diff options
| author | 2015-08-09 00:50:54 +0200 | |
|---|---|---|
| committer | 2015-08-09 00:50:54 +0200 | |
| commit | b0ef3f1673e1930916604bb1264ca3a38414bc8d (patch) | |
| tree | c97936e4d2a4cd6eb1072c65c8a08a7d18816b18 /module/plugins/captcha | |
| parent | [XFileSharingPro][XFileSharingProFolder] Added default __pattern__ (diff) | |
| parent | Fix https://github.com/pyload/pyload/issues/1707 (diff) | |
| download | pyload-b0ef3f1673e1930916604bb1264ca3a38414bc8d.tar.xz | |
Merge pull request #1 from pyload/stable
sync with stable
Diffstat (limited to 'module/plugins/captcha')
| -rw-r--r-- | module/plugins/captcha/AdYouLike.py | 92 | ||||
| -rw-r--r-- | module/plugins/captcha/AdsCaptcha.py | 64 | ||||
| -rw-r--r-- | module/plugins/captcha/CircleCaptcha.py | 707 | ||||
| -rw-r--r-- | module/plugins/captcha/GigasizeCom.py | 11 | ||||
| -rw-r--r-- | module/plugins/captcha/LinksaveIn.py | 29 | ||||
| -rw-r--r-- | module/plugins/captcha/NetloadIn.py | 11 | ||||
| -rw-r--r-- | module/plugins/captcha/OCR.py | 319 | ||||
| -rw-r--r-- | module/plugins/captcha/ReCaptcha.py | 197 | ||||
| -rw-r--r-- | module/plugins/captcha/ShareonlineBiz.py | 17 | ||||
| -rw-r--r-- | module/plugins/captcha/SolveMedia.py | 105 | 
10 files changed, 848 insertions, 704 deletions
| diff --git a/module/plugins/captcha/AdYouLike.py b/module/plugins/captcha/AdYouLike.py new file mode 100644 index 000000000..f91b5805c --- /dev/null +++ b/module/plugins/captcha/AdYouLike.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +import re + +from module.common.json_layer import json_loads +from module.plugins.internal.CaptchaService import CaptchaService + + +class AdYouLike(CaptchaService): +    __name__    = "AdYouLike" +    __type__    = "captcha" +    __version__ = "0.07" +    __status__  = "testing" + +    __description__ = """AdYouLike captcha service plugin""" +    __license__     = "GPLv3" +    __authors__     = [("Walter Purcaro", "vuolter@gmail.com")] + + +    AYL_PATTERN      = r'Adyoulike\.create\s*\((.+?)\)' +    CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' + + +    def detect_key(self, data=None): +        html = data or self.retrieve_data() + +        m = re.search(self.AYL_PATTERN, html) +        n = re.search(self.CALLBACK_PATTERN, html) +        if m and n: +            self.key = (m.group(1).strip(), n.group(1).strip()) +            self.log_debug("Ayl: %s | Callback: %s" % self.key) +            return self.key   #: Key is the tuple(ayl, callback) +        else: +            self.log_warning(_("Ayl or callback pattern not found")) +            return None + + +    def challenge(self, key=None, data=None): +        ayl, callback = key or self.retrieve_key(data) + +        #: {'adyoulike':{'key':"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, +        #: 'all':{'element_id':"ayl_private_cap_92300",'lang':"fr",'env':"prod"}} +        ayl = json_loads(ayl) + +        html = self.plugin.load("http://api-ayl.appspot.com/challenge", +                                    get={'key'     : ayl['adyoulike']['key'], +                                         'env'     : ayl['all']['env'], +                                         'callback': callback}) +        try: +            challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) + +        except AttributeError: +            self.fail(_("AdYouLike challenge pattern not found")) + +        self.log_debug("Challenge: %s" % challenge) + +        return self.result(ayl, challenge), challenge + + +    def result(self, server, challenge): +        #: Adyoulike.g._jsonp_5579316662423138 +        #: ({'translations':{'fr':{'instructions_visual':"Recopiez « Soonnight » ci-dessous :"}}, +        #: 'site_under':true,'clickable':true,'pixels':{'VIDEO_050':[],'DISPLAY':[],'VIDEO_000':[],'VIDEO_100':[], +        #: 'VIDEO_025':[],'VIDEO_075':[]},'medium_type':"image/adyoulike", +        #: 'iframes':{'big':"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" +        #: height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},'shares':{},'id':256, +        #: 'token':"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1",'formats':{'small':{'y':300,'x':0,'w':300,'h':60}, +        #: 'big':{'y':0,'x':0,'w':300,'h':250},'hover':{'y':440,'x':0,'w':300,'h':60}}, +        #: 'tid':"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) + +        if isinstance(server, basestring): +            server = json_loads(server) + +        if isinstance(challenge, basestring): +            challenge = json_loads(challenge) + +        try: +            instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] +            result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() + +        except AttributeError: +            self.fail(_("AdYouLike result not found")) + +        result = {'_ayl_captcha_engine' : "adyoulike", +                  '_ayl_env'            : server['all']['env'], +                  '_ayl_tid'            : challenge['tid'], +                  '_ayl_token_challenge': challenge['token'], +                  '_ayl_response'       : response} + +        self.log_debug("Result: %s" % result) + +        return result diff --git a/module/plugins/captcha/AdsCaptcha.py b/module/plugins/captcha/AdsCaptcha.py new file mode 100644 index 000000000..613283e53 --- /dev/null +++ b/module/plugins/captcha/AdsCaptcha.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +import random +import re + +from module.plugins.internal.CaptchaService import CaptchaService + + +class AdsCaptcha(CaptchaService): +    __name__    = "AdsCaptcha" +    __type__    = "captcha" +    __version__ = "0.10" +    __status__  = "testing" + +    __description__ = """AdsCaptcha captcha service plugin""" +    __license__     = "GPLv3" +    __authors__     = [("pyLoad Team", "admin@pyload.org")] + + +    CAPTCHAID_PATTERN  = r'api\.adscaptcha\.com/Get\.aspx\?.*?CaptchaId=(\d+)' +    PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' + + +    def detect_key(self, data=None): +        html = data or self.retrieve_data() + +        m = re.search(self.PUBLICKEY_PATTERN, html) +        n = re.search(self.CAPTCHAID_PATTERN, html) +        if m and n: +            self.key = (m.group(1).strip(), n.group(1).strip())  #: Key is the tuple(PublicKey, CaptchaId) +            self.log_debug("Key: %s | ID: %s" % self.key) +            return self.key +        else: +            self.log_warning(_("Key or id pattern not found")) +            return None + + +    def challenge(self, key=None, data=None): +        PublicKey, CaptchaId = key or self.retrieve_key(data) + +        html = self.plugin.load("http://api.adscaptcha.com/Get.aspx", +                                    get={'CaptchaId': CaptchaId, +                                         'PublicKey': PublicKey}) +        try: +            challenge = re.search("challenge: '(.+?)',", html).group(1) +            server    = re.search("server: '(.+?)',", html).group(1) + +        except AttributeError: +            self.fail(_("AdsCaptcha challenge pattern not found")) + +        self.log_debug("Challenge: %s" % challenge) + +        return self.result(server, challenge), challenge + + +    def result(self, server, challenge): +        result = self.decrypt("%sChallenge.aspx" % server, +                                    get={'cid': challenge, 'dummy': random.random()}, +                                    cookies=True, +                                    input_type="jpg") + +        self.log_debug("Result: %s" % result) + +        return result diff --git a/module/plugins/captcha/CircleCaptcha.py b/module/plugins/captcha/CircleCaptcha.py index d4f08018d..dc04a04c8 100644 --- a/module/plugins/captcha/CircleCaptcha.py +++ b/module/plugins/captcha/CircleCaptcha.py @@ -1,4 +1,6 @@  # -*- coding: utf-8 -*- +# +#@TODO: Recheck all  from __future__ import division @@ -9,7 +11,7 @@ import math  import operator  import urllib -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR  class ImageSequence: @@ -29,7 +31,8 @@ class ImageSequence:  class CircleCaptcha(OCR):      __name__    = "CircleCaptcha"      __type__    = "ocr" -    __version__ = "1.00" +    __version__ = "1.04" +    __status__  = "testing"      __description__ = """Circle captcha ocr plugin"""      __license__     = "GPLv3" @@ -43,11 +46,11 @@ class CircleCaptcha(OCR):      BLACKCOLOR = 5 -    def cleanImage(self, im, pix): +    def clean_image(self, im, pix):          cleandeep = 1 -        imageheight = range(1,int(im.size[1])) -        imagewidth = range(1,int(im.size[0])) +        imageheight = xrange(1, int(im.size[1])) +        imagewidth = xrange(1, int(im.size[0]))          howmany = 0          curcolor = self.BACKGROUND @@ -55,184 +58,184 @@ class CircleCaptcha(OCR):              jump = True              howmany = 0              for x in imagewidth: -                curpix = pix[x,y] +                curpix = pix[x, y]                  if curpix > self.BACKGROUND:                      if howmany <= cleandeep and howmany > 0: -                        # clean pixel -                        for ic in range(1,cleandeep+1): +                        #: Clean pixel +                        for ic in xrange(1, cleandeep+1):                              if x -ic > 0: -                                pix[x-ic,y] = self.BACKGROUND +                                pix[x-ic, y] = self.BACKGROUND                      jump = False                      howmany = 0                      curcolor = curpix -                    # print (x, y), jump,2 +                    # self.log_debug(x, y, jump, 2)                  else:                      if howmany == 0: -                        # found pixel +                        #: Found pixel                          jump = True                          howmany = howmany + 1                          curcolor = curpix -                        # print (x, y), jump,2 +                        # self.log_debug(x, y, jump, 2)                      else:                          howmany = howmany + 1              if howmany == 1: -                # clean pixel -                pix[x-1,y] = self.BACKGROUND +                #: Clean pixel +                pix[x-1, y] = self.BACKGROUND          curcolor = self.BACKGROUND          for x in imagewidth:              jump = True              howmany = 0              for y in imageheight: -                curpix = pix[x,y] -                # if jump == True: +                curpix = pix[x, y] +                # if jump is True:                  if curpix > self.BACKGROUND:                      if howmany <= cleandeep and howmany > 0: -                        # clean pixel -                        for ic in range(1,cleandeep+1): -                            # raw_input('2'+str(ic)) +                        #: Clean pixel +                        for ic in xrange(1, cleandeep+1): +                            #: raw_input('2'+str(ic))                              if y-ic > 0: -                                pix[x,y-ic] = self.BACKGROUND +                                pix[x, y-ic] = self.BACKGROUND                      jump = False                      howmany = 0                      curcolor = curpix -                    # print (x, y), jump +                    # self.log_debug(x, y, jump)                  else:                      if howmany == 0: -                        # found pixel +                        #: Found pixel                          jump = True                          howmany = howmany + 1                          curcolor = curpix -                        # print (x, y), jump +                        # self.log_debug(x, y, jump)                      else:                          howmany = howmany + 1              if howmany == 1: -                # clean pixel -                pix[x-1,y] = self.BACKGROUND +                #: Clean pixel +                pix[x-1, y] = self.BACKGROUND -        # return -1 +        #: return -1 -    def findFirstPixelX(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): -        imageheight = range(1,int(im.size[1])) -        imagewidth = range(curx+1,int(im.size[0])) +    def find_first_pixel_x(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): +        imageheight = xrange(1, int(im.size[1])) +        imagewidth = xrange(curx+1, int(im.size[0]))          jump = True -        newx = (-1,-1) +        newx = (-1, -1)          blackfound = 0          for x in imagewidth: -            curpix = pix[x,cury] +            curpix = pix[x, cury]              if curpix < self.BLACKCOLOR:                  blackfound = blackfound + 1 -                if ExitWithBlack == True and blackfound >= 3: -                    break;    #exit if found black +                if ExitWithBlack is True and blackfound >= 3: +                    break  #: Exit if found black                  else: -                    continue; +                    continue              if curpix >= self.BACKGROUND: -                # found first pixel white +                #: Found first pixel white                  jump = False -                continue; +                continue -            if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): -                if jump == False: -                    # found pixel +            if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): +                if jump is False: +                    #: Found pixel                      curcolor = curpix                      newx = x, curcolor -                    break; +                    break          return newx -    def findLastPixelX(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): -        imageheight = range(1,int(im.size[1])) -        imagewidth = range(curx+1,int(im.size[0])) -        newx = (-1,-1) +    def find_last_pixel_x(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): +        imageheight = xrange(1, int(im.size[1])) +        imagewidth = xrange(curx+1, int(im.size[0])) +        newx = (-1, -1)          blackfound = 0          for x in imagewidth: -            curpix = pix[x,cury] +            curpix = pix[x, cury]              if curpix < self.BLACKCOLOR:                  blackfound = blackfound + 1 -                if ExitWithBlack == True and blackfound >= 3: -                    break;    #exit if found black +                if ExitWithBlack is True and blackfound >= 3: +                    break  #: Exit if found black                  else: -                    continue; +                    continue              if curpix >= self.BACKGROUND: -                if newx != (-1,-1): -                    # found last pixel and the first white -                    break; +                if newx != (-1, -1): +                    #: Found last pixel and the first white +                    break -            if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): -                # found pixel +            if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): +                #: Found pixel                  curcolor = curpix                  newx = x, curcolor          return newx -    def findLastPixelY(self, im, pix, curx, cury, DownToUp, color = -1, ExitWithBlack = False): -        if DownToUp == False: -            imageheight = range(int(cury)+1,int(im.size[1])-1) +    def find_last_pixel_y(self, im, pix, curx, cury, DownToUp, color = -1, ExitWithBlack = False): +        if DownToUp is False: +            imageheight = xrange(int(cury)+1, int(im.size[1])-1)          else: -            imageheight = range(int(cury)-1,1,-1) -        imagewidth = range(int(curx),int(im.size[0])) -        newy = (-1,-1) +            imageheight = xrange(int(cury)-1, 1, -1) +        imagewidth = xrange(int(curx), int(im.size[0])) +        newy = (-1, -1)          blackfound = 0          for y in imageheight: -            curpix = pix[curx,y] +            curpix = pix[curx, y]              if curpix < self.BLACKCOLOR:                  blackfound = blackfound + 1 -                if ExitWithBlack == True and blackfound >= 3: -                    break;    #exit if found black +                if ExitWithBlack is True and blackfound >= 3: +                    break  #: Exit if found black                  else: -                    continue; +                    continue              if curpix >= self.BACKGROUND: -                if newy != (-1,-1): -                    # found last pixel and the first white -                    break; +                if newy != (-1, -1): +                    #: Found last pixel and the first white +                    break -            if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): -                # found pixel +            if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): +                #: Found pixel                  curcolor = curpix                  newy = y, color          return newy -    def findCircle(self, pix, x1, y1, x2, y2, x3, y3): -        # trasposizione coordinate -        # A(0,0) B(x2-x1,y2-y1) C(x3-x1,y3-y1) -        # x**2+y**2+ax+bx+c=0 -        p1 = (0,0) -        p2 = (x2-x1,y2-y1) -        p3 = (x3-x1,y3-y1) +    def find_circle(self, pix, x1, y1, x2, y2, x3, y3): +        #: Trasposizione coordinate +        #: A(0, 0) B(x2-x1, y2-y1) C(x3-x1, y3-y1) +        #: x**2+y**2+ax+bx+c=0 +        p1 = (0, 0) +        p2 = (x2-x1, y2-y1) +        p3 = (x3-x1, y3-y1) -        # 1 +        #: 1          c=0 -        # 2 -        # p2[0]**2+a*p2[0]+c=0 -        # a*p2[0]=-1*(p2[0]**2-c) -        # a=(-1*(p2[0]**2-c))/p2[0] +        #: 2 +        #: p2[0]**2+a*p2[0]+c=0 +        #: a*p2[0]=-1*(p2[0]**2-c) +        #: a=(-1*(p2[0]**2-c))/p2[0]          a=(-1*(p2[0]**2-c))/p2[0] -        # 3 -        # p3[0]**2+p3[1]**2+a*p3[0]+b*p3[1]+c=0 -        # b*p3[1]=-(p3[0]**2+p3[1]**2+a*p3[0]+c) -        # b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1] +        #: 3 +        #: p3[0]**2+p3[1]**2+a*p3[0]+b*p3[1]+c=0 +        #: b*p3[1]=-(p3[0]**2+p3[1]**2+a*p3[0]+c) +        #: b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1]          b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1]          r=math.floor(math.sqrt((-1*(a/2))**2+(-1*(b/2))**2))          cx=math.floor((-1*(a/2))+x1)          cy=math.floor((-1*(b/2))+y1) -        return cx,cy,r +        return cx, cy, r -    def verifyCircleNew(self, im, pix, c): +    def verify_circle_new(self, im, pix, c):          """              This is the MAIN function to recognize the circle              returns: @@ -241,9 +244,8 @@ class CircleCaptcha(OCR):                  -1 -> Not found circle                  -2 -> Found black position then leave position          """ - -        imageheight = range(int(c[1]-c[2]),int(c[1]+c[2])) -        imagewidth = range(int(c[0]-c[2]),int(c[0]+c[2])) +        imageheight = xrange(int(c[1]-c[2]), int(c[1]+c[2])) +        imagewidth = xrange(int(c[0]-c[2]), int(c[0]+c[2]))          min_ray = 15          max_ray = 30 @@ -253,68 +255,73 @@ class CircleCaptcha(OCR):          missing = 0          missingconsecutive = 0          missinglist = [] -        minX = 0; maxX = 0; minY = 0; maxY = 0 + +        minX = 0 +        maxX = 0 +        minY = 0 +        maxY = 0 +          pointsofcircle = []          if (c[2] < min_ray) or (c[2] > max_ray):              return -1 -        # check cardinal points (at least 3) (if found i have to leave this position) -        if pix[c[0] + c[2],c[1]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0] - c[2],c[1]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0],c[1] + c[2]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0],c[1] - c[2]] < self.BLACKCOLOR: -            return -2; +        #: Check cardinal points (at least 3) (if found i have to leave this position) +        if pix[c[0] + c[2], c[1]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0] - c[2], c[1]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0], c[1] + c[2]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0], c[1] - c[2]] < self.BLACKCOLOR: +            return -2          cardinalpoints = 0 -        if self.verifyPoint(im, pix,c[0] + c[2],c[1],True) == 1: +        if self.verify_point(im, pix, c[0] + c[2], c[1], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0] + c[2],c[1],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0] - c[2],c[1],True) == 1: +        if self.verify_point(im, pix, c[0] + c[2], c[1], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0] - c[2], c[1], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0] - c[2],c[1],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0],c[1] + c[2],True) == 1: +        if self.verify_point(im, pix, c[0] - c[2], c[1], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0], c[1] + c[2], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0],c[1] + c[2],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0],c[1] - c[2],True) == 1: +        if self.verify_point(im, pix, c[0], c[1] + c[2], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0], c[1] - c[2], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0],c[1] - c[2],False) == -1: -            return -2; +        if self.verify_point(im, pix, c[0], c[1] - c[2], False) == -1: +            return -2          if cardinalpoints < 3: -            return -1; +            return -1          for x in imagewidth: -            # Pitagora +            #: Pitagora              y = int(round(c[1]- math.sqrt(c[2]**2-(c[0]-x)**2)))              y2= int(round(c[1]+ math.sqrt(c[2]**2-(c[0]-x)**2)))              howmany = howmany + 2 -            if self.verifyPoint(im, pix, x,y,exactfind) == 0: +            if self.verify_point(im, pix, x, y, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x,y)) +                missinglist.append((x, y))              else: -                pointsofcircle.append((x,y)) +                pointsofcircle.append((x, y)) -            if self.verifyPoint(im, pix, x,y,False) == -1: -                return -2; +            if self.verify_point(im, pix, x, y, False) == -1: +                return -2 -            if self.verifyPoint(im, pix, x,y2,exactfind) == 0: +            if self.verify_point(im, pix, x, y2, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x,y2)) +                missinglist.append((x, y2))              else: -                pointsofcircle.append((x,y2)) +                pointsofcircle.append((x, y2)) -            if self.verifyPoint(im, pix, x,y2,False) == -1: -                return -2; +            if self.verify_point(im, pix, x, y2, False) == -1: +                return -2 -    def verifyCircle(self, im, pix, c): +    def verify_circle(self, im, pix, c):          """              This is the MAIN function to recognize the circle              returns: @@ -323,9 +330,8 @@ class CircleCaptcha(OCR):                  -1 -> Not found circle                  -2 -> Found black position then leave position          """ - -        imageheight = range(int(c[1]-c[2]),int(c[1]+c[2])) -        imagewidth = range(int(c[0]-c[2]),int(c[0]+c[2])) +        imageheight = xrange(int(c[1]-c[2]), int(c[1]+c[2])) +        imagewidth = xrange(int(c[0]-c[2]), int(c[0]+c[2]))          min_ray = 15          max_ray = 30 @@ -335,119 +341,124 @@ class CircleCaptcha(OCR):          missing = 0          missingconsecutive = 0          missinglist = [] -        minX = 0; maxX = 0; minY = 0; maxY = 0 + +        minX = 0 +        maxX = 0 +        minY = 0 +        maxY = 0 +          pointsofcircle = []          if (c[2] < min_ray) or (c[2] > max_ray):              return -1 -        # check cardinal points (at least 3) (if found i have to leave this position) -        if pix[c[0] + c[2],c[1]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0] - c[2],c[1]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0],c[1] + c[2]] < self.BLACKCOLOR: -            return -2; -        if pix[c[0],c[1] - c[2]] < self.BLACKCOLOR: -            return -2; +        #: Check cardinal points (at least 3) (if found i have to leave this position) +        if pix[c[0] + c[2], c[1]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0] - c[2], c[1]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0], c[1] + c[2]] < self.BLACKCOLOR: +            return -2 +        if pix[c[0], c[1] - c[2]] < self.BLACKCOLOR: +            return -2          cardinalpoints = 0 -        if self.verifyPoint(im, pix,c[0] + c[2],c[1],True) == 1: +        if self.verify_point(im, pix, c[0] + c[2], c[1], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0] + c[2],c[1],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0] - c[2],c[1],True) == 1: +        if self.verify_point(im, pix, c[0] + c[2], c[1], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0] - c[2], c[1], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0] - c[2],c[1],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0],c[1] + c[2],True) == 1: +        if self.verify_point(im, pix, c[0] - c[2], c[1], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0], c[1] + c[2], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0],c[1] + c[2],False) == -1: -            return -2; -        if self.verifyPoint(im, pix,c[0],c[1] - c[2],True) == 1: +        if self.verify_point(im, pix, c[0], c[1] + c[2], False) == -1: +            return -2 +        if self.verify_point(im, pix, c[0], c[1] - c[2], True) == 1:              cardinalpoints = cardinalpoints + 1 -        if self.verifyPoint(im, pix,c[0],c[1] - c[2],False) == -1: -            return -2; +        if self.verify_point(im, pix, c[0], c[1] - c[2], False) == -1: +            return -2          if cardinalpoints < 3: -            return -1; +            return -1          for x in imagewidth: -            # Pitagora +            #: Pitagora              y = int(round(c[1]- math.sqrt(c[2]**2-(c[0]-x)**2)))              y2= int(round(c[1]+ math.sqrt(c[2]**2-(c[0]-x)**2)))              howmany = howmany + 2 -            if self.verifyPoint(im, pix, x,y,exactfind) == 0: +            if self.verify_point(im, pix, x, y, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x,y)) +                missinglist.append((x, y))              else: -                pointsofcircle.append((x,y)) +                pointsofcircle.append((x, y)) -            if self.verifyPoint(im, pix, x,y,False) == -1: -                return -2; +            if self.verify_point(im, pix, x, y, False) == -1: +                return -2 -            if self.verifyPoint(im, pix, x,y2,exactfind) == 0: +            if self.verify_point(im, pix, x, y2, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x,y2)) +                missinglist.append((x, y2))              else: -                pointsofcircle.append((x,y2)) +                pointsofcircle.append((x, y2)) -            if self.verifyPoint(im, pix, x,y2,False) == -1: -                return -2; +            if self.verify_point(im, pix, x, y2, False) == -1: +                return -2          for y in imageheight: -            # Pitagora +            #: Pitagora              x = int(round(c[0]- math.sqrt(c[2]**2-(c[1]-y)**2)))              x2= int(round(c[0]+ math.sqrt(c[2]**2-(c[1]-y)**2)))              howmany = howmany + 2 -            if self.verifyPoint(im, pix, x,y,exactfind) == 0: +            if self.verify_point(im, pix, x, y, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x,y)) +                missinglist.append((x, y))              else: -                pointsofcircle.append((x,y)) +                pointsofcircle.append((x, y)) -            if self.verifyPoint(im, pix, x,y,False) == -1: -                return -2; +            if self.verify_point(im, pix, x, y, False) == -1: +                return -2 -            if self.verifyPoint(im, pix, x2,y,exactfind) == 0: +            if self.verify_point(im, pix, x2, y, exactfind) == 0:                  missing = missing + 1 -                missinglist.append((x2,y)) +                missinglist.append((x2, y))              else: -                pointsofcircle.append((x2,y)) +                pointsofcircle.append((x2, y)) -            if self.verifyPoint(im, pix, x2,y,exactfind) == -1: -                return -2; +            if self.verify_point(im, pix, x2, y, exactfind) == -1: +                return -2          for p in missinglist: -                # left and bottom -            if (self.verifyPoint(im, pix, p[0]-1, p[1],exactfind) == 1 and \ -                self.verifyPoint(im, pix, p[0], p[1]+1,exactfind) == 1): +                #: Left and bottom +            if (self.verify_point(im, pix, p[0]-1, p[1], exactfind) == 1 +                and self.verify_point(im, pix, p[0], p[1]+1, exactfind) == 1):                  missing = missing - 1 -            elif (self.verifyPoint(im, pix, p[0]-1, p[1],exactfind) == 1 and \ -                self.verifyPoint(im, pix, p[0], p[1]-1,exactfind) == 1): +            elif (self.verify_point(im, pix, p[0]-1, p[1], exactfind) == 1 +                  and self.verify_point(im, pix, p[0], p[1]-1, exactfind) == 1):                  missing = missing - 1 -                # right and bottom -            elif (self.verifyPoint(im, pix, p[0]+1, p[1],exactfind) == 1 and \ -                self.verifyPoint(im, pix, p[0], p[1]+1,exactfind) == 1): +                #: Right and bottom +            elif (self.verify_point(im, pix, p[0]+1, p[1], exactfind) == 1 +                  and self.verify_point(im, pix, p[0], p[1]+1, exactfind) == 1):                  missing = missing - 1 -                # right and up -            elif (self.verifyPoint(im, pix, p[0]+1, p[1],exactfind) == 1 and \ -                self.verifyPoint(im, pix, p[0], p[1]-1,exactfind) == 1): +                #: Right and up +            elif (self.verify_point(im, pix, p[0]+1, p[1], exactfind) == 1 +                  and self.verify_point(im, pix, p[0], p[1]-1, exactfind) == 1):                  missing = missing - 1 -            if (p[0], p[1]+1) in missinglist or \ -                (p[0], p[1]-1) in missinglist or \ -                (p[0]+1, p[1]) in missinglist or \ -                (p[0]-1, p[1]) in missinglist or \ -                (p[0]+1, p[1]+1) in missinglist or \ -                (p[0]-1, p[1]+1) in missinglist or \ -                (p[0]+1, p[1]-1) in missinglist or \ -                (p[0]-1, p[1]-1) in missinglist or \ -                self.verifyPoint(im, pix, p[0], p[1],False) == 1: +            if ((p[0], p[1]+1) in missinglist +                or (p[0], p[1]-1) in missinglist +                or (p[0]+1, p[1]) in missinglist +                or (p[0]-1, p[1]) in missinglist +                or (p[0]+1, p[1]+1) in missinglist +                or (p[0]-1, p[1]+1) in missinglist +                or (p[0]+1, p[1]-1) in missinglist +                or (p[0]-1, p[1]-1) in missinglist +                or self.verify_point(im, pix, p[0], p[1], False) == 1):                  missingconsecutive = missingconsecutive + 1              # else: -            #    pix[p[0], p[1]] = 0 +            #     pix[p[0], p[1]] = 0          if missing / howmany > 0:              indice = c[2] * (missing / howmany) @@ -461,80 +472,79 @@ class CircleCaptcha(OCR):              minY = min(missinglist, key=operator.itemgetter(1))[1]              maxY = max(missinglist, key=operator.itemgetter(1))[1] -        # Assial Simmetric -        if self._DEBUG == True: -            print "Center: " + str(c) -            print "Missing: " + str(missing) -            print "Howmany: " + str(howmany) -            print "Ratio: " + str(missing / howmany) -            print "Missing consecutives: " + str(missingconsecutive) -            print "Missing X lenght: " + str(minX) + ":" + str(maxX) -            print "Missing Y lenght: " + str(minY) + ":" + str(maxY) -            print "Ratio without consecutives: " + str((missing - missingconsecutive) / howmany) -            print "List missing: " + str(missinglist) +        #: Assial Simmetric +        if self.pyload.debug: +            self.log_debug("Center: " + str(c), +                           "Missing: " + str(missing), +                           "Howmany: " + str(howmany), +                           "Ratio: " + str(missing / howmany), +                           "Missing consecutives: " + str(missingconsecutive), +                           "Missing X lenght: " + str(minX) + ":" + str(maxX), +                           "Missing Y lenght: " + str(minY) + ":" + str(maxY), +                           "Ratio without consecutives: " + str((missing - missingconsecutive) / howmany), +                           "List missing: " + str(missinglist)) -        # Lenght of missing cannot be over 75% of diameter +        #: Lenght of missing cannot be over 75% of diameter          if maxX - minX >= c[2] * 2 * 0.75: -            return -1; +            return -1          if maxY - minY >= c[2] * 2 * 0.75: -            # raw_input('tro') -            return -1; +            #: raw_input('tro') +            return -1          """ -        # Lenght of missing cannot be less 10% of diameter +        #: Lenght of missing cannot be less 10% of diameter          if maxX - minX < c[2] * 2 * 0.10 and maxY - minY < c[2] * 2 * 0.10: -            return -1; +            return -1          """ -          if missing / howmany > 0.25 or \              missingconsecutive >= (howmany / 4) * 2 or \              howmany < 80: -            return -1; +            return -1          # elif missing / howmany < 0.10:          elif missing == 0:              self.pointsofcirclefound.extend(pointsofcircle) -            return 1; +            return 1          elif (missing - missingconsecutive) / howmany < 0.20: -            return 0; +            return 0          else:              self.pointsofcirclefound.extend(pointsofcircle) -            return 1; +            return 1 -    def verifyPoint(self, im, pix, x,y,exact,color = -1): -        # Verify point +    def verify_point(self, im, pix, x, y, exact, color = -1): +        #: Verify point          result = 0          if x < 0 or x >= im.size[0]: -            return result; +            return result          if y < 0 or y >= im.size[1]: -            return result; +            return result -        curpix = pix[x,y] -        if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): +        curpix = pix[x, y] +        if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1):              if curpix > self.BLACKCOLOR:                  result = 1              else:                  result = -1 -        # Verify around -        if (exact == False): +        #: Verify around +        if exact is False:              if x + 1 < im.size[0]: -                curpix = pix[x+1,y] -                if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): +                curpix = pix[x+1, y] +                if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1):                      if curpix > self.BLACKCOLOR:                          result = 1                  if curpix <= self.BLACKCOLOR:                      result = -1              if x > 0: -                curpix = pix[x-1,y] -                if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): +                curpix = pix[x-1, y] +                if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1):                      if curpix > self.BLACKCOLOR:                          result = 1                  if curpix <= self.BLACKCOLOR:                      result = -1 -        # print str((x,y)) + " = " + str(result); +        # self.log_debug(str((x, y)) + " = " + str(result))          return result @@ -543,22 +553,23 @@ class CircleCaptcha(OCR):          mypalette = None          for im in ImageSequence(img):              im.save("orig.png", "png") -            if mypalette != None: +            if mypalette is not None:                  im.putpalette(mypalette)              mypalette = im.getpalette()              im = im.convert('L') -            if self._DEBUG == True: +            if self.pyload.debug:                  iDebugSaveFile = iDebugSaveFile + 1 -                # if iDebugSaveFile < 7: continue; +                # if iDebugSaveFile < 7: +                    # continue                  im.save("output" + str(iDebugSaveFile) + ".png", "png")                  raw_input('frame: '+ str(im))              pix = im.load() -            stepheight = range(1,im.size[1],2) -            # stepheight = range(45,47) -            imagewidth = range(1,im.size[0]) +            stepheight = xrange(1, im.size[1], 2) +            #: stepheight = xrange(45, 47) +            imagewidth = xrange(1, im.size[0])              lstPoints = [] # Declares an empty list for the points              lstX = [] # CoordinateX              lstY = [] # CoordinateY @@ -566,209 +577,211 @@ class CircleCaptcha(OCR):              min_distance = 10              max_diameter = 70 -            if self._DEBUG == True: +            if self.pyload.debug:                  imdebug = im.copy()                  draw = ImageDraw.Draw(imdebug)                  pixcopy = imdebug.load() -            # Clean image for powerfull search -            self.cleanImage(im, pix) +            #: Clean image for powerfull search +            self.clean_image(im, pix)              im.save("cleaned" + str(iDebugSaveFile) + ".png", "png")              found = set()              findnewcircle = True -            # finding all the circles +            #: Finding all the circles              for y1 in stepheight:                  x1 = 1                  curcolor = -1 -                for k in range(1,100): +                for k in xrange(1, 100):                      findnewcircle = False -                    retval = self.findFirstPixelX(im, pix, x1, y1, -1, False) +                    retval = self.find_first_pixel_x(im, pix, x1, y1, -1, False)                      x1 = retval[0]                      curcolor = retval[1]                      if x1 == -2: -                        break; +                        break                      if x1 == -1: -                        break; -                    if self._DEBUG == True: print "x1, y1 -> " + str((x1,y1)) + ": " + str(pix[x1,y1]) - -                    if (x1,y1) in self.pointsofcirclefound: -                        if self._DEBUG == True: print 'found ' + str((x1,y1)) -                        continue; - -                    if self._DEBUG == True: pixcopy[x1,y1] = 45 #(255,0,0,255) -                    # found 1 pixel, seeking x2,y2 +                        break +                    if self.pyload.debug: +                        self.log_debug("x1, y1 -> " + str((x1, y1)) + ": " + str(pix[x1, y1])) + +                    if (x1, y1) in self.pointsofcirclefound: +                        if self.pyload.debug: +                            self.log_debug("Found " + str((x1, y1))) +                        continue + +                    if self.pyload.debug: +                        pixcopy[x1, y1] = 45 #(255, 0, 0, 255) +                    #: found 1 pixel, seeking x2, y2                      x2 = x1                      y2 = y1 -                    for i in range(1,100): -                        retval = self.findLastPixelX(im, pix, x2, y2, -1, True) +                    for i in xrange(1, 100): +                        retval = self.find_last_pixel_x(im, pix, x2, y2, -1, True)                          x2 = retval[0]                          if x1 == -2:                              findnewcircle = True -                            break; +                            break                          if x2 == -1: -                            break; -                        if self._DEBUG == True: print "x2, y2 -> " + str((x2,y1)) + ": " + str(pix[x2,y1]) +                            break +                        if self.pyload.debug: +                            self.log_debug("x2, y2 -> " + str((x2, y1)) + ": " + str(pix[x2, y1]))                          if abs(x2 - x1) < min_distance: -                            continue; +                            continue                          if abs(x2 - x1) > (im.size[1] * 2 / 3): -                            break; +                            break                          if abs(x2 - x1) > max_diameter: -                            break; +                            break -                        if self._DEBUG == True: pixcopy[x2,y2] = 65 #(0,255,0,255) -                        # found 2 pixel, seeking x3,y3 -                        # verify cord +                        if self.pyload.debug: +                            pixcopy[x2, y2] = 65 #(0, 255, 0, 255) +                        #: found 2 pixel, seeking x3, y3 +                        #: Verify cord -                        for invert in range(0,2): +                        for invert in xrange(0, 2):                              x3 = math.floor(x2 - ((x2 - x1) / 2))                              y3 = y1 -                            for j in range(1,50): -                                retval = self.findLastPixelY(im, pix, x3, y3, True if invert == 1 else False, -1, True) -                                # print (x3, y3,retval[0],invert) +                            for j in xrange(1, 50): +                                retval = self.find_last_pixel_y(im, pix, x3, y3, True if invert == 1 else False, -1, True) +                                # self.log_debug(x3, y3, retval[0], invert)                                  y3 = retval[0]                                  if y3 == -2:                                      findnewcircle = True -                                    break; +                                    break                                  if y3 == -1: -                                    break; +                                    break -                                if self._DEBUG == True: print "x3, y3 -> " + str((x3,y3)) + ": " + str(pix[x3,y3]) -                                # verify cord +                                if self.pyload.debug: +                                    self.log_debug("x3, y3 -> " + str((x3, y3)) + ": " + str(pix[x3, y3])) +                                #: Verify cord                                  if abs(y3 - y2) < min_distance: -                                    continue; +                                    continue                                  if abs(y3 - y2) > (im.size[1] * 2 / 3): -                                    break; +                                    break                                  if abs(y3 - y2) > max_diameter: -                                    break; +                                    break -                                if self._DEBUG == True: pixcopy[x3,y3] = 85 -                                # found 3 pixel. try circle -                                c = self.findCircle(pix, x1,y1,x2,y2,x3,y3) +                                if self.pyload.debug: +                                    pixcopy[x3, y3] = 85 +                                #: found 3 pixel. try circle +                                c = self.find_circle(pix, x1, y1, x2, y2, x3, y3)                                  if c[0] + c[2] >= im.size[0] or c[1] + c[2] >= im.size[1] or c[0] - c[2] <= 0 or c[1] - c[2] <= 0: -                                    continue; +                                    continue -                                if self._DEBUG == True: pixcopy[c[0],c[1]] = 0 -                                # (x-r, y-r, x+r, y+r) -                                verified = self.verifyCircle(im, pix, c) +                                if self.pyload.debug: +                                    pixcopy[c[0], c[1]] = 0 +                                #: (x-r, y-r, x+r, y+r) +                                verified = self.verify_circle(im, pix, c)                                  if verified == -1:                                      verified = -1                                  elif verified == 0: -                                    found.add(((c[0],c[1],c[2]),verified)) +                                    found.add(((c[0], c[1], c[2]), verified))                                      findnewcircle = True                                  elif verified == 1: -                                    found.add(((c[0],c[1],c[2]),verified)) +                                    found.add(((c[0], c[1], c[2]), verified))                                      findnewcircle = True -                                if self._DEBUG == True: +                                if self.pyload.debug:                                      _pause = ""                                      # if verified == -1: -                                        # draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=0) +                                        # draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=0)                                          # _pause = "NOTDOUND"                                          # imdebug.save("debug.png", "png")                                      if verified == 0: -                                        draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=120) +                                        draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=120)                                          _pause = "OPENED"                                      if verified == 1: -                                        draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=65) +                                        draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=65)                                          _pause = "CLOSED"                                      imdebug.save("debug.png", "png")                                      if _pause != "":                                          valore = raw_input('Found ' + _pause + ' CIRCLE circle press [Enter] = continue / [q] for Quit: ' + str(verified)) -                                        if valore == 'q': -                                            sys.exit(); +                                        if valore == "q": +                                            sys.exit() -                                if findnewcircle == True: -                                    break; -                            if findnewcircle == True: -                                break; -                        if findnewcircle == True: -                            break; +                                if findnewcircle is True: +                                    break +                            if findnewcircle is True: +                                break +                        if findnewcircle is True: +                            break -            if self._DEBUG == True: -                print 'Howmany opened circle? ' + str(len(found)) + ' ' + str(found) +            if self.pyload.debug: +                self.log_debug('Howmany opened circle? ' + str(len(found)) + ' ' + str(found)) -            # clean results +            #: Clean results              for c in found:                  verify = c[1]                  if verify == 0:                      p = c[0] -                    if ( -                        ((p[0], p[1]+1,p[2]),1) in found or \ -                        ((p[0], p[1]-1,p[2]),1) in found or \ -                        ((p[0]+1, p[1],p[2]),1) in found or \ -                        ((p[0]-1, p[1],p[2]),1) in found or \ -                        ((p[0]+1, p[1]+1,p[2]),1) in found or \ -                        ((p[0]-1, p[1]+1,p[2]),1) in found or \ -                        ((p[0]+1, p[1]-1,p[2]),1) in found or \ -                        ((p[0]-1, p[1]-1,p[2]),1) in found \ -                        ): - -                        # delete nearly circle +                    if (((p[0], p[1]+1, p[2]), 1) in found +                        or ((p[0], p[1]-1, p[2]), 1) in found +                        or ((p[0]+1, p[1], p[2]), 1) in found +                        or ((p[0]-1, p[1], p[2]), 1) in found +                        or ((p[0]+1, p[1]+1, p[2]), 1) in found +                        or ((p[0]-1, p[1]+1, p[2]), 1) in found +                        or ((p[0]+1, p[1]-1, p[2]), 1) in found +                        or ((p[0]-1, p[1]-1, p[2]), 1) in found): + +                        #: Delete nearly circle                          verify = -1 -                    if ( -                        ((p[0], p[1]+1,p[2]+1),1) in found or \ -                        ((p[0], p[1]-1,p[2]+1),1) in found or \ -                        ((p[0]+1, p[1],p[2]+1),1) in found or \ -                        ((p[0]-1, p[1],p[2]+1),1) in found or \ -                        ((p[0]+1, p[1]+1,p[2]+1),1) in found or \ -                        ((p[0]-1, p[1]+1,p[2]+1),1) in found or \ -                        ((p[0]+1, p[1]-1,p[2]+1),1) in found or \ -                        ((p[0]-1, p[1]-1,p[2]+1),1) in found \ -                        ): - -                        # delete nearly circle +                    if (((p[0], p[1]+1, p[2]+1), 1) in found +                        or ((p[0], p[1]-1, p[2]+1), 1) in found +                        or ((p[0]+1, p[1], p[2]+1), 1) in found +                        or ((p[0]-1, p[1], p[2]+1), 1) in found +                        or ((p[0]+1, p[1]+1, p[2]+1), 1) in found +                        or ((p[0]-1, p[1]+1, p[2]+1), 1) in found +                        or ((p[0]+1, p[1]-1, p[2]+1), 1) in found +                        or ((p[0]-1, p[1]-1, p[2]+1), 1) in found): + +                        #: Delete nearly circle                          verify = -1 -                    if ( -                        ((p[0], p[1]+1,p[2]-1),1) in found or \ -                        ((p[0], p[1]-1,p[2]-1),1) in found or \ -                        ((p[0]+1, p[1],p[2]-1),1) in found or \ -                        ((p[0]-1, p[1],p[2]-1),1) in found or \ -                        ((p[0]+1, p[1]+1,p[2]-1),1) in found or \ -                        ((p[0]-1, p[1]+1,p[2]-1),1) in found or \ -                        ((p[0]+1, p[1]-1,p[2]-1),1) in found or \ -                        ((p[0]-1, p[1]-1,p[2]-1),1) in found \ -                        ): - -                        # delete nearly circle +                    if (((p[0], p[1]+1, p[2]-1), 1) in found +                        or ((p[0], p[1]-1, p[2]-1), 1) in found +                        or ((p[0]+1, p[1], p[2]-1), 1) in found +                        or ((p[0]-1, p[1], p[2]-1), 1) in found +                        or ((p[0]+1, p[1]+1, p[2]-1), 1) in found +                        or ((p[0]-1, p[1]+1, p[2]-1), 1) in found +                        or ((p[0]+1, p[1]-1, p[2]-1), 1) in found +                        or ((p[0]-1, p[1]-1, p[2]-1), 1) in found): + +                        #: Delete nearly circle                          verify = -1                  # if verify == 0: -                    # if self._DEBUG == True: -                    # pix[c[0][0],c[0][1]] = 90 #(255,255,0) +                    # if self.pyload.debug: +                    # pix[c[0][0], c[0][1]] = 90 #(255, 255, 0)                      # im.save("output.png", "png") -                    # return c[0][0],c[0][1] +                    # return c[0][0], c[0][1]                  # elif verify == 1: -                    # if self._DEBUG == True: -                        # pix[c[0][0],c[0][1]] = 40 #(255,0,0) +                    # if self.pyload.debug: +                        # pix[c[0][0], c[0][1]] = 40 #(255, 0, 0)                          # im.save("output.png", "png")                  # else: -                    # if self._DEBUG == True: -                        # pix[c[0][0],c[0][1]] = 180 #(0,0,255) +                    # if self.pyload.debug: +                        # pix[c[0][0], c[0][1]] = 180 #(0, 0, 255)                          # im.save("output.png", "png") -        if self._DEBUG == True: +        if self.pyload.debug:              im.save("output.png", "png") -    # Return coordinates of opened circle (eg (x,y)) +    #: Return coordinates of opened circle (eg (x, y))      def decrypt_from_web(self, url):          file = cStringIO.StringIO(urllib.urlopen(url).read())          img = Image.open(file) -        coords = self.decrypt(img); -        print "Coords: " + str(coords) +        coords = self.decrypt(img) +        self.log_info(_("Coords: %s") % coords) -    # Return coordinates of opened circle (eg (x,y)) +    #: Return coordinates of opened circle (eg (x, y))      def decrypt_from_file(self, filename): -        coords = self.decrypt(Image.open(filename)); #Can be many different formats. -        print "Coords: " + str(coords) +        coords = self.decrypt(Image.open(filename))  #: Can be many different formats. +        self.log_info(_("Coords: %s") % coords)  ##DEBUG @@ -778,4 +791,4 @@ class CircleCaptcha(OCR):  # coords = x.decrypt_from_file("decripter/captx.html2.gif")  # coords = x.decrypt_from_web("http://ncrypt.in/classes/captcha/circlecaptcha.php")  # b = datetime.datetime.now() -# print 'Elapsed time: ' + str((b-a).seconds) + ' seconds' +# self.log_debug("Elapsed time: %s seconds" % (b-a).seconds) diff --git a/module/plugins/captcha/GigasizeCom.py b/module/plugins/captcha/GigasizeCom.py index 52c41729b..12f123c41 100644 --- a/module/plugins/captcha/GigasizeCom.py +++ b/module/plugins/captcha/GigasizeCom.py @@ -1,23 +1,20 @@  # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR  class GigasizeCom(OCR):      __name__    = "GigasizeCom"      __type__    = "ocr" -    __version__ = "0.11" +    __version__ = "0.14" +    __status__  = "testing"      __description__ = """Gigasize.com ocr plugin"""      __license__     = "GPLv3"      __authors__     = [("pyLoad Team", "admin@pyload.org")] -    def __init__(self): -        OCR.__init__(self) - - -    def get_captcha(self, image): +    def recognize(self, image):          self.load_image(image)          self.threshold(2.8)          self.run_tesser(True, False, False, True) diff --git a/module/plugins/captcha/LinksaveIn.py b/module/plugins/captcha/LinksaveIn.py index 95b107977..4d2e2bc34 100644 --- a/module/plugins/captcha/LinksaveIn.py +++ b/module/plugins/captcha/LinksaveIn.py @@ -2,27 +2,28 @@  try:      from PIL import Image +  except ImportError:      import Image  import glob  import os -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR  class LinksaveIn(OCR):      __name__    = "LinksaveIn"      __type__    = "ocr" -    __version__ = "0.11" +    __version__ = "0.14" +    __status__  = "testing"      __description__ = """Linksave.in ocr plugin"""      __license__     = "GPLv3"      __authors__     = [("pyLoad Team", "admin@pyload.org")] -    def __init__(self): -        OCR.__init__(self) +    def init(self):          self.data_dir = os.path.dirname(os.path.abspath(__file__)) + os.sep + "LinksaveIn" + os.sep @@ -31,7 +32,7 @@ class LinksaveIn(OCR):          frame_nr = 0          lut = im.resize((256, 1)) -        lut.putdata(range(256)) +        lut.putdata(xrange(256))          lut = list(lut.convert("RGB").getdata())          new = Image.new("RGB", im.size) @@ -51,7 +52,7 @@ class LinksaveIn(OCR):          new.save(self.data_dir+"unblacked.png")          self.image = new.copy()          self.pixels = self.image.load() -        self.result_captcha = '' +        self.result_captcha = ""      def get_bg(self): @@ -63,11 +64,11 @@ class LinksaveIn(OCR):              bg = Image.open(bgpath)              bglut = bg.resize((256, 1)) -            bglut.putdata(range(256)) +            bglut.putdata(xrange(256))              bglut = list(bglut.convert("RGB").getdata())              lut = img.resize((256, 1)) -            lut.putdata(range(256)) +            lut.putdata(xrange(256))              lut = list(lut.convert("RGB").getdata())              bgpix = bg.load() @@ -80,11 +81,11 @@ class LinksaveIn(OCR):                          cstat[rgb_c] += 1                      except Exception:                          cstat[rgb_c] = 1 -                    if rgb_bg == rgb_c: +                    if rgb_bg is rgb_c:                          stat[bgpath] += 1          max_p = 0          bg = "" -        for bgpath, value in stat.iteritems(): +        for bgpath, value in stat.items():              if max_p < value:                  bg = bgpath                  max_p = value @@ -96,11 +97,11 @@ class LinksaveIn(OCR):          img = self.image.convert("P")          bglut = bg.resize((256, 1)) -        bglut.putdata(range(256)) +        bglut.putdata(xrange(256))          bglut = list(bglut.convert("RGB").getdata())          lut = img.resize((256, 1)) -        lut.putdata(range(256)) +        lut.putdata(xrange(256))          lut = list(lut.convert("RGB").getdata())          bgpix = bg.load() @@ -110,7 +111,7 @@ class LinksaveIn(OCR):              for y in xrange(bg.size[1]):                  rgb_bg = bglut[bgpix[x, y]]                  rgb_c = lut[pix[x, y]] -                if rgb_c == rgb_bg: +                if rgb_c is rgb_bg:                      orgpix[x, y] = (255, 255, 255) @@ -136,7 +137,7 @@ class LinksaveIn(OCR):          self.pixels = self.image.load() -    def get_captcha(self, image): +    def recognize(self, image):          self.load_image(image)          bg = self.get_bg()          self.substract_bg(bg) diff --git a/module/plugins/captcha/NetloadIn.py b/module/plugins/captcha/NetloadIn.py index 1fb258c47..50174684d 100644 --- a/module/plugins/captcha/NetloadIn.py +++ b/module/plugins/captcha/NetloadIn.py @@ -1,23 +1,20 @@  # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR  class NetloadIn(OCR):      __name__    = "NetloadIn"      __type__    = "ocr" -    __version__ = "0.11" +    __version__ = "0.14" +    __status__  = "testing"      __description__ = """Netload.in ocr plugin"""      __license__     = "GPLv3"      __authors__     = [("pyLoad Team", "admin@pyload.org")] -    def __init__(self): -        OCR.__init__(self) - - -    def get_captcha(self, image): +    def recognize(self, image):          self.load_image(image)          self.to_greyscale()          self.clean(3) diff --git a/module/plugins/captcha/OCR.py b/module/plugins/captcha/OCR.py deleted file mode 100644 index 1874ba07d..000000000 --- a/module/plugins/captcha/OCR.py +++ /dev/null @@ -1,319 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -try: -    from PIL import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin - -except ImportError: -    import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin - -import logging -import os -import subprocess -#import tempfile - -from module.utils import save_join - - -class OCR(object): -    __name__    = "OCR" -    __type__    = "ocr" -    __version__ = "0.11" - -    __description__ = """OCR base plugin""" -    __license__     = "GPLv3" -    __authors__     = [("pyLoad Team", "admin@pyload.org")] - - -    def __init__(self): -        self.logger = logging.getLogger("log") - - -    def load_image(self, image): -        self.image = Image.open(image) -        self.pixels = self.image.load() -        self.result_captcha = '' - - -    def unload(self): -        """delete all tmp images""" -        pass - - -    def threshold(self, value): -        self.image = self.image.point(lambda a: a * value + 10) - - -    def run(self, command): -        """Run a command""" - -        popen = subprocess.Popen(command, bufsize = -1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -        popen.wait() -        output = popen.stdout.read() +" | "+ popen.stderr.read() -        popen.stdout.close() -        popen.stderr.close() -        self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output)) - - -    def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True): -        #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") -        try: -            tmpTif = open(save_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") -            tmpTif.close() - -            #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") -            tmpTxt = open(save_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") -            tmpTxt.close() - -        except IOError, e: -            self.logError(e) -            return - -        self.logger.debug("save tiff") -        self.image.save(tmpTif.name, 'TIFF') - -        if os.name == "nt": -            tessparams = [os.path.join(pypath, "tesseract", "tesseract.exe")] -        else: -            tessparams = ["tesseract"] - -        tessparams.extend( [os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] ) - -        if subset and (digits or lowercase or uppercase): -            #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") -            with open(save_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub: -                tmpSub.write("tessedit_char_whitelist ") - -                if digits: -                    tmpSub.write("0123456789") -                if lowercase: -                    tmpSub.write("abcdefghijklmnopqrstuvwxyz") -                if uppercase: -                    tmpSub.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ") - -                tmpSub.write("\n") -                tessparams.append("nobatch") -                tessparams.append(os.path.abspath(tmpSub.name)) - -        self.logger.debug("run tesseract") -        self.run(tessparams) -        self.logger.debug("read txt") - -        try: -            with open(tmpTxt.name, 'r') as f: -                self.result_captcha = f.read().replace("\n", "") -        except Exception: -            self.result_captcha = "" - -        self.logger.debug(self.result_captcha) -        try: -            os.remove(tmpTif.name) -            os.remove(tmpTxt.name) -            if subset and (digits or lowercase or uppercase): -                os.remove(tmpSub.name) -        except Exception: -            pass - - -    def get_captcha(self, name): -        raise NotImplementedError - - -    def to_greyscale(self): -        if self.image.mode != 'L': -            self.image = self.image.convert('L') - -        self.pixels = self.image.load() - - -    def eval_black_white(self, limit): -        self.pixels = self.image.load() -        w, h = self.image.size -        for x in xrange(w): -            for y in xrange(h): -                if self.pixels[x, y] > limit: -                    self.pixels[x, y] = 255 -                else: -                    self.pixels[x, y] = 0 - - -    def clean(self, allowed): -        pixels = self.pixels - -        w, h = self.image.size - -        for x in xrange(w): -            for y in xrange(h): -                if pixels[x, y] == 255: -                    continue -                # No point in processing white pixels since we only want to remove black pixel -                count = 0 - -                try: -                    if pixels[x-1, y-1] != 255: -                        count += 1 -                    if pixels[x-1, y] != 255: -                        count += 1 -                    if pixels[x-1, y + 1] != 255: -                        count += 1 -                    if pixels[x, y + 1] != 255: -                        count += 1 -                    if pixels[x + 1, y + 1] != 255: -                        count += 1 -                    if pixels[x + 1, y] != 255: -                        count += 1 -                    if pixels[x + 1, y-1] != 255: -                        count += 1 -                    if pixels[x, y-1] != 255: -                        count += 1 -                except Exception: -                    pass - -        # not enough neighbors are dark pixels so mark this pixel -            # to be changed to white -                if count < allowed: -                    pixels[x, y] = 1 - -            # second pass: this time set all 1's to 255 (white) -        for x in xrange(w): -            for y in xrange(h): -                if pixels[x, y] == 1: -                    pixels[x, y] = 255 - -        self.pixels = pixels - - -    def derotate_by_average(self): -        """rotate by checking each angle and guess most suitable""" - -        w, h = self.image.size -        pixels = self.pixels - -        for x in xrange(w): -            for y in xrange(h): -                if pixels[x, y] == 0: -                    pixels[x, y] = 155 - -        highest = {} -        counts = {} - -        for angle in xrange(-45, 45): - -            tmpimage = self.image.rotate(angle) - -            pixels = tmpimage.load() - -            w, h = self.image.size - -            for x in xrange(w): -                for y in xrange(h): -                    if pixels[x, y] == 0: -                        pixels[x, y] = 255 - - -            count = {} - -            for x in xrange(w): -                count[x] = 0 -                for y in xrange(h): -                    if pixels[x, y] == 155: -                        count[x] += 1 - -            sum = 0 -            cnt = 0 - -            for x in count.values(): -                if x != 0: -                    sum += x -                    cnt += 1 - -            avg = sum / cnt -            counts[angle] = cnt -            highest[angle] = 0 -            for x in count.values(): -                if x > highest[angle]: -                    highest[angle] = x - -            highest[angle] = highest[angle] - avg - -        hkey = 0 -        hvalue = 0 - -        for key, value in highest.iteritems(): -            if value > hvalue: -                hkey = key -                hvalue = value - -        self.image = self.image.rotate(hkey) -        pixels = self.image.load() - -        for x in xrange(w): -            for y in xrange(h): -                if pixels[x, y] == 0: -                    pixels[x, y] = 255 - -                if pixels[x, y] == 155: -                    pixels[x, y] = 0 - -        self.pixels = pixels - - -    def split_captcha_letters(self): -        captcha = self.image -        started = False -        letters = [] -        width, height = captcha.size -        bottomY, topY = 0, height -        pixels = captcha.load() - -        for x in xrange(width): -            black_pixel_in_col = False -            for y in xrange(height): -                if pixels[x, y] != 255: -                    if not started: -                        started = True -                        firstX = x -                        lastX = x - -                    if y > bottomY: -                        bottomY = y -                    if y < topY: -                        topY = y -                    if x > lastX: -                        lastX = x - -                    black_pixel_in_col = True - -            if black_pixel_in_col is False and started is True: -                rect = (firstX, topY, lastX, bottomY) -                new_captcha = captcha.crop(rect) - -                w, h = new_captcha.size -                if w > 5 and h > 5: -                    letters.append(new_captcha) - -                started = False -                bottomY, topY = 0, height - -        return letters - - -    def correct(self, values, var=None): -        if var: -            result = var -        else: -            result = self.result_captcha - -        for key, item in values.iteritems(): - -            if key.__class__ == str: -                result = result.replace(key, item) -            else: -                for expr in key: -                    result = result.replace(expr, item) - -        if var: -            return result -        else: -            self.result_captcha = result diff --git a/module/plugins/captcha/ReCaptcha.py b/module/plugins/captcha/ReCaptcha.py new file mode 100644 index 000000000..5931159c5 --- /dev/null +++ b/module/plugins/captcha/ReCaptcha.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- + +import random +import re +import time +import urlparse + +from base64 import b64encode + +from module.plugins.internal.CaptchaService import CaptchaService + + +class ReCaptcha(CaptchaService): +    __name__    = "ReCaptcha" +    __type__    = "captcha" +    __version__ = "0.18" +    __status__  = "testing" + +    __description__ = """ReCaptcha captcha service plugin""" +    __license__     = "GPLv3" +    __authors__     = [("pyLoad Team", "admin@pyload.org"), +                       ("Walter Purcaro", "vuolter@gmail.com"), +                       ("zapp-brannigan", "fuerst.reinje@web.de")] + + +    KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' +    KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' + + +    def detect_key(self, data=None): +        html = data or self.retrieve_data() + +        m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) +        if m: +            self.key = m.group(1).strip() +            self.log_debug("Key: %s" % self.key) +            return self.key +        else: +            self.log_warning(_("Key pattern not found")) +            return None + + +    def challenge(self, key=None, data=None, version=None): +        key = key or self.retrieve_key(data) + +        if version in (1, 2): +            return getattr(self, "_challenge_v%s" % version)(key) + +        else: +            return self.challenge(key, +                                  version=2 if re.search(self.KEY_V2_PATTERN, data or self.retrieve_data()) else 1) + + +    def _challenge_v1(self, key): +        html = self.plugin.load("http://www.google.com/recaptcha/api/challenge", +                                    get={'k': key}) +        try: +            challenge = re.search("challenge : '(.+?)',", html).group(1) +            server    = re.search("server : '(.+?)',", html).group(1) + +        except AttributeError: +            self.fail(_("ReCaptcha challenge pattern not found")) + +        self.log_debug("Challenge: %s" % challenge) + +        return self.result(server, challenge, key) + + +    def result(self, server, challenge, key): +        self.plugin.load("http://www.google.com/recaptcha/api/js/recaptcha.js") +        html = self.plugin.load("http://www.google.com/recaptcha/api/reload", +                                    get={'c'     : challenge, +                                         'k'     : key, +                                         'reason': "i", +                                         'type'  : "image"}) + +        try: +            challenge = re.search('\(\'(.+?)\',',html).group(1) + +        except AttributeError: +            self.fail(_("ReCaptcha second challenge pattern not found")) + +        self.log_debug("Second challenge: %s" % challenge) +        result = self.decrypt(urlparse.urljoin(server, "image"), +                              get={'c': challenge}, +                              cookies=True, +                              input_type="jpg") + +        self.log_debug("Result: %s" % result) + +        return result, challenge + + +    def _collect_api_info(self): +        html = self.plugin.load("http://www.google.com/recaptcha/api.js") +        a    = re.search(r'po.src = \'(.*?)\';', html).group(1) +        vers = a.split("/")[5] + +        self.log_debug("API version: %s" % vers) + +        language = a.split("__")[1].split(".")[0] + +        self.log_debug("API language: %s" % language) + +        html = self.plugin.load("https://apis.google.com/js/api.js") +        b    = re.search(r'"h":"(.*?)","', html).group(1) +        jsh  = b.decode('unicode-escape') + +        self.log_debug("API jsh-string: %s" % jsh) + +        return vers, language, jsh + + +    def _prepare_time_and_rpc(self): +        self.plugin.load("http://www.google.com/recaptcha/api2/demo") + +        millis = int(round(time.time() * 1000)) + +        self.log_debug("Time: %s" % millis) + +        rand = random.randint(1, 99999999) +        a    = "0.%s" % str(rand * 2147483647) +        rpc  = int(100000000 * float(a)) + +        self.log_debug("Rpc-token: %s" % rpc) + +        return millis, rpc + + +    def _challenge_v2(self, key, parent=None): +        if parent is None: +            try: +                parent = urlparse.urljoin("http://", urlparse.urlparse(self.plugin.pyfile.url).netloc) + +            except Exception: +                parent = "" + +        botguardstring      = "!A" +        vers, language, jsh = self._collect_api_info() +        millis, rpc         = self._prepare_time_and_rpc() + +        html = self.plugin.load("https://www.google.com/recaptcha/api2/anchor", +                                    get={'k'       : key, +                                         'hl'      : language, +                                         'v'       : vers, +                                         'usegapi' : "1", +                                         'jsh'     : "%s#id=IO_%s" % (jsh, millis), +                                         'parent'  : parent, +                                         'pfname'  : "", +                                         'rpctoken': rpc}) + +        token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) +        self.log_debug("Token #1: %s" % token1.group(1)) + +        html = self.plugin.load("https://www.google.com/recaptcha/api2/frame", +                                get={'c'      : token1.group(1), +                                     'hl'     : language, +                                     'v'      : vers, +                                     'bg'     : botguardstring, +                                     'k'      : key, +                                     'usegapi': "1", +                                     'jsh'    : jsh}, +                                decode="unicode-escape") + +        token2 = re.search(r'"finput","(.*?)",', html) +        self.log_debug("Token #2: %s" % token2.group(1)) + +        token3 = re.search(r'"rresp","(.*?)",', html) +        self.log_debug("Token #3: %s" % token3.group(1)) + +        millis_captcha_loading = int(round(time.time() * 1000)) +        captcha_response = self.decrypt("https://www.google.com/recaptcha/api2/payload", +                                              get={'c':token3.group(1), 'k':key}, +                                              cookies=True, +                                              ocr=False, +                                              timeout=30) +        response = b64encode('{"response":"%s"}' % captcha_response) + +        self.log_debug("Result: %s" % response) + +        timeToSolve     = int(round(time.time() * 1000)) - millis_captcha_loading +        timeToSolveMore = timeToSolve + int(float("0." + str(random.randint(1, 99999999))) * 500) + +        html = self.plugin.load("https://www.google.com/recaptcha/api2/userverify", +                                    post={'k'       : key, +                                          'c'       : token3.group(1), +                                          'response': response, +                                          't'       : timeToSolve, +                                          'ct'      : timeToSolveMore, +                                          'bg'      : botguardstring}) + +        token4 = re.search(r'"uvresp","(.*?)",', html) +        self.log_debug("Token #4: %s" % token4.group(1)) + +        result = token4.group(1) + +        return result, None diff --git a/module/plugins/captcha/ShareonlineBiz.py b/module/plugins/captcha/ShareonlineBiz.py index 6fad66600..edf14df87 100644 --- a/module/plugins/captcha/ShareonlineBiz.py +++ b/module/plugins/captcha/ShareonlineBiz.py @@ -1,30 +1,27 @@  # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR  class ShareonlineBiz(OCR):      __name__    = "ShareonlineBiz"      __type__    = "ocr" -    __version__ = "0.11" +    __version__ = "0.14" +    __status__  = "testing"      __description__ = """Shareonline.biz ocr plugin"""      __license__     = "GPLv3"      __authors__     = [("RaNaN", "RaNaN@pyload.org")] -    def __init__(self): -        OCR.__init__(self) - - -    def get_captcha(self, image): +    def recognize(self, image):          self.load_image(image)          self.to_greyscale()          self.image = self.image.resize((160, 50))          self.pixels = self.image.load()          self.threshold(1.85) -        #self.eval_black_white(240) -        #self.derotate_by_average() +        # self.eval_black_white(240) +        # self.derotate_by_average()          letters = self.split_captcha_letters() @@ -36,4 +33,4 @@ class ShareonlineBiz(OCR):          return final -        #tesseract at 60% +        #: Tesseract at 60% diff --git a/module/plugins/captcha/SolveMedia.py b/module/plugins/captcha/SolveMedia.py new file mode 100644 index 000000000..870b5fc10 --- /dev/null +++ b/module/plugins/captcha/SolveMedia.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.internal.Plugin import Fail +from module.plugins.internal.CaptchaService import CaptchaService + + +class SolveMedia(CaptchaService): +    __name__    = "SolveMedia" +    __type__    = "captcha" +    __version__ = "0.15" +    __status__  = "testing" + +    __description__ = """SolveMedia captcha service plugin""" +    __license__     = "GPLv3" +    __authors__     = [("pyLoad Team", "admin@pyload.org")] + + +    KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' + + +    def detect_key(self, data=None): +        html = data or self.retrieve_data() + +        m = re.search(self.KEY_PATTERN, html) +        if m: +            self.key = m.group(1).strip() +            self.log_debug("Key: %s" % self.key) +            return self.key +        else: +            self.log_warning(_("Key pattern not found")) +            return None + + +    def challenge(self, key=None, data=None): +        key = key or self.retrieve_key(data) + +        html = self.plugin.load("http://api.solvemedia.com/papi/challenge.noscript", +                                    get={'k': key}) + +        for i in xrange(1, 11): +            try: +                magic = re.search(r'name="magic" value="(.+?)"', html).group(1) + +            except AttributeError: +                self.log_warning(_("Magic pattern not found")) +                magic = None + +            try: +                challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="(.+?)">', +                                      html).group(1) + +            except AttributeError: +                self.fail(_("SolveMedia challenge pattern not found")) + +            else: +                self.log_debug("Challenge: %s" % challenge) + +            try: +                result = self.result("http://api.solvemedia.com/papi/media", challenge) + +            except Fail, e: +                self.log_warning(e) +                self.plugin.invalidCaptcha() +                result = None + +            html = self.plugin.load("http://api.solvemedia.com/papi/verify.noscript", +                                        post={'adcopy_response' : result, +                                              'k'               : key, +                                              'l'               : "en", +                                              't'               : "img", +                                              's'               : "standard", +                                              'magic'           : magic, +                                              'adcopy_challenge': challenge, +                                              'ref'             : self.plugin.pyfile.url}) +            try: +                redirect = re.search(r'URL=(.+?)">', html).group(1) + +            except AttributeError: +                self.fail(_("SolveMedia verify pattern not found")) + +            else: +                if "error" in html: +                    self.log_warning(_("Captcha code was invalid")) +                    self.log_debug("Retry #%d" % i) +                    html = self.plugin.load(redirect) +                else: +                    break + +        else: +            self.fail(_("SolveMedia max retries exceeded")) + +        return result, challenge + + +    def result(self, server, challenge): +        result = self.decrypt(server, +                                    get={'c': challenge}, +                                    cookies=True, +                                    input_type="gif") + +        self.log_debug("Result: %s" % result) + +        return result | 
