Enigma2 plugin to to play various online streams (mostly Latvian).

openload_resolver.py 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. # -*- coding: utf-8 -*-
  2. """
  3. openload.io urlresolver plugin
  4. Copyright (C) 2015 tknorris
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. """
  16. import urllib
  17. import re
  18. import urllib2
  19. from HTMLParser import HTMLParser
  20. import requests
  21. #from lib.net import Net
  22. #from urlresolver import common
  23. #from urlresolver.resolver import ResolverError
  24. #net = Net() #III
  25. SIZE_LIMIT = 32 * 1024 * 1024
  26. def caesar_shift(s, shift=13):
  27. s2 = ''
  28. for c in s:
  29. if c.isalpha():
  30. limit = 90 if c <= 'Z' else 122
  31. new_code = ord(c) + shift
  32. if new_code > limit:
  33. new_code -= 26
  34. s2 += chr(new_code)
  35. else:
  36. s2 += c
  37. return s2
  38. def unpack(html):
  39. strings = re.findall('{\s*var\s+a\s*=\s*"([^"]+)', html)
  40. shifts = re.findall('\)\);}\((\d+)\)', html)
  41. for s, shift in zip(strings, shifts):
  42. s = caesar_shift(s, int(shift))
  43. s = urllib.unquote(s)
  44. for i, replace in enumerate(['j', '_', '__', '___']):
  45. s = s.replace(str(i), replace)
  46. html += '<script>%s</script>' % (s)
  47. return html
  48. def get_media_url(url):
  49. try:
  50. HTTP_HEADER = {
  51. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0',
  52. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  53. 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
  54. 'Accept-Encoding': 'none',
  55. 'Accept-Language': 'en-US,en;q=0.8',
  56. 'Referer': url} # 'Connection': 'keep-alive'
  57. #html = net.http_GET(url, headers=HTTP_HEADER).content
  58. html = requests.get(url, headers=HTTP_HEADER).content
  59. try: html = html.encode('utf-8')
  60. except: pass
  61. html = unpack(html)
  62. match = re.search('''>([^<]+)</span>\s*<span\s+id="streamurl"''', html, re.DOTALL | re.IGNORECASE)
  63. if not match:
  64. raise Exception('Stream Url Not Found. Deleted?')
  65. hiddenurl = HTMLParser().unescape(match.group(1))
  66. decodes = []
  67. for match in re.finditer('<script[^>]*>(.*?)</script>', html, re.DOTALL):
  68. encoded = match.group(1)
  69. match = re.search("(゚ω゚ノ.*?\('_'\);)", encoded, re.DOTALL)
  70. if match:
  71. decodes.append(AADecoder(match.group(1)).decode())
  72. match = re.search('(.=~\[\].*\(\);)', encoded, re.DOTALL)
  73. if match:
  74. decodes.append(JJDecoder(match.group(1)).decode())
  75. if not decodes:
  76. raise ResolverError('No Encoded Section Found. Deleted?')
  77. magic_number = 0
  78. for decode in decodes:
  79. match = re.search('charCodeAt\(\d+\)\s*\+\s*(\d+)\)', decode, re.DOTALL | re.I)
  80. if match:
  81. magic_number = match.group(1)
  82. break
  83. s = []
  84. for idx, i in enumerate(hiddenurl):
  85. j = ord(i)
  86. if (j >= 33 & j <= 126):
  87. j = 33 + ((j + 14) % 94)
  88. if idx == len(hiddenurl) - 1:
  89. j += int(magic_number)
  90. s.append(chr(j))
  91. res = ''.join(s)
  92. videoUrl = 'https://openload.co/stream/{0}?mime=true'.format(res)
  93. dtext = videoUrl.replace('https', 'http')
  94. headers = {'User-Agent': HTTP_HEADER['User-Agent']}
  95. req = urllib2.Request(dtext, None, headers)
  96. res = urllib2.urlopen(req)
  97. videourl = res.geturl()
  98. if int(res.headers['Content-Length']) < SIZE_LIMIT:
  99. raise ResolverError('Openload.co resolve failed. Pigeons?')
  100. res.close()
  101. return videourl
  102. except Exception as e:
  103. print 'Exception during openload resolve parse: %s' % e
  104. # -*- coding: utf-8 -*-
  105. # ------------------------------------------------------------
  106. # pelisalacarta - XBMC Plugin
  107. # Conector for openload.io
  108. # http://blog.tvalacarta.info/plugin-xbmc/pelisalacarta/
  109. # by DrZ3r0
  110. # ------------------------------------------------------------
  111. # Modified by Shani
  112. import re
  113. #from urlresolver import common
  114. #import common
  115. class AADecoder(object):
  116. def __init__(self, aa_encoded_data):
  117. self.encoded_str = aa_encoded_data.replace('/*´∇`*/', '')
  118. self.b = ["(c^_^o)", "(゚Θ゚)", "((o^_^o) - (゚Θ゚))", "(o^_^o)",
  119. "(゚ー゚)", "((゚ー゚) + (゚Θ゚))", "((o^_^o) +(o^_^o))", "((゚ー゚) + (o^_^o))",
  120. "((゚ー゚) + (゚ー゚))", "((゚ー゚) + (゚ー゚) + (゚Θ゚))", "(゚Д゚) .゚ω゚ノ", "(゚Д゚) .゚Θ゚ノ",
  121. "(゚Д゚) ['c']", "(゚Д゚) .゚ー゚ノ", "(゚Д゚) .゚Д゚ノ", "(゚Д゚) [゚Θ゚]"]
  122. def is_aaencoded(self):
  123. idx = self.encoded_str.find("゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); ")
  124. if idx == -1:
  125. return False
  126. is_encoded = self.encoded_str.find("(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');", idx) != -1
  127. return is_encoded
  128. def base_repr(self, number, base=2, padding=0):
  129. digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  130. if base > len(digits):
  131. base = len(digits)
  132. num = abs(number)
  133. res = []
  134. while num:
  135. res.append(digits[num % base])
  136. num //= base
  137. if padding:
  138. res.append('0' * padding)
  139. if number < 0:
  140. res.append('-')
  141. return ''.join(reversed(res or '0'))
  142. def decode_char(self, enc_char, radix):
  143. end_char = "+ "
  144. str_char = ""
  145. while enc_char != '':
  146. found = False
  147. # for i in range(len(self.b)):
  148. # print self.b[i], enc_char.find(self.b[i])
  149. # if enc_char.find(self.b[i]) == 0:
  150. # str_char += self.base_repr(i, radix)
  151. # enc_char = enc_char[len(self.b[i]):]
  152. # found = True
  153. # break
  154. # print 'found', found, enc_char
  155. if not found:
  156. for i in range(len(self.b)):
  157. enc_char = enc_char.replace(self.b[i], str(i))
  158. # enc_char = enc_char.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3')
  159. # print 'enc_char', enc_char
  160. startpos = 0
  161. findClose = True
  162. balance = 1
  163. result = []
  164. if enc_char.startswith('('):
  165. l = 0
  166. for t in enc_char[1:]:
  167. l += 1
  168. # print 'looping', findClose, startpos, t, balance
  169. if findClose and t == ')':
  170. balance -= 1
  171. if balance == 0:
  172. result += [enc_char[startpos:l + 1]]
  173. findClose = False
  174. continue
  175. elif not findClose and t == '(':
  176. startpos = l
  177. findClose = True
  178. balance = 1
  179. continue
  180. elif t == '(':
  181. balance += 1
  182. if result is None or len(result) == 0:
  183. return ""
  184. else:
  185. for r in result:
  186. value = self.decode_digit(r, radix)
  187. # print 'va', value
  188. str_char += value
  189. if value == "":
  190. return ""
  191. return str_char
  192. enc_char = enc_char[len(end_char):]
  193. return str_char
  194. def parseJSString(self, s):
  195. try:
  196. # print s
  197. # offset = 1 if s[0] == '+' else 0
  198. tmp = (s.replace('!+[]', '1').replace('!![]', '1').replace('[]', '0')) # .replace('(','str(')[offset:])
  199. val = int(eval(tmp))
  200. return val
  201. except:
  202. pass
  203. def decode_digit(self, enc_int, radix):
  204. # enc_int = enc_int.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3')
  205. # print 'enc_int before', enc_int
  206. # for i in range(len(self.b)):
  207. # print self.b[i], enc_char.find(self.b[i])
  208. # if enc_char.find(self.b[i]) > 0:
  209. # str_char += self.base_repr(i, radix)
  210. # enc_char = enc_char[len(self.b[i]):]
  211. # found = True
  212. # break
  213. # enc_int=enc_int.replace(self.b[i], str(i))
  214. # print 'enc_int before', enc_int
  215. try:
  216. return str(eval(enc_int))
  217. except: pass
  218. rr = '(\(.+?\)\))\+'
  219. rerr = enc_int.split('))+') # re.findall(rr, enc_int)
  220. v = ""
  221. # print rerr
  222. for c in rerr:
  223. if len(c) > 0:
  224. # print 'v', c
  225. if c.strip().endswith('+'):
  226. c = c.strip()[:-1]
  227. # print 'v', c
  228. startbrackets = len(c) - len(c.replace('(', ''))
  229. endbrackets = len(c) - len(c.replace(')', ''))
  230. if startbrackets > endbrackets:
  231. c += ')' * (startbrackets - endbrackets)
  232. if '[' in c:
  233. v += str(self.parseJSString(c))
  234. else:
  235. # print c
  236. v += str(eval(c))
  237. return v
  238. # unreachable code
  239. # mode 0=+, 1=-
  240. # mode = 0
  241. # value = 0
  242. # while enc_int != '':
  243. # found = False
  244. # for i in range(len(self.b)):
  245. # if enc_int.find(self.b[i]) == 0:
  246. # if mode == 0:
  247. # value += i
  248. # else:
  249. # value -= i
  250. # enc_int = enc_int[len(self.b[i]):]
  251. # found = True
  252. # break
  253. # if not found:
  254. # return ""
  255. # enc_int = re.sub('^\s+|\s+$', '', enc_int)
  256. # if enc_int.find("+") == 0:
  257. # mode = 0
  258. # else:
  259. # mode = 1
  260. # enc_int = enc_int[1:]
  261. # enc_int = re.sub('^\s+|\s+$', '', enc_int)
  262. # return self.base_repr(value, radix)
  263. def decode(self):
  264. self.encoded_str = re.sub('^\s+|\s+$', '', self.encoded_str)
  265. # get data
  266. pattern = (r"\(゚Д゚\)\[゚o゚\]\+ (.+?)\(゚Д゚\)\[゚o゚\]\)")
  267. result = re.search(pattern, self.encoded_str, re.DOTALL)
  268. if result is None:
  269. #common.log_utils.log_debug("AADecoder: data not found")
  270. print "AADecoder: data not foun"
  271. return False
  272. data = result.group(1)
  273. # hex decode string
  274. begin_char = "(゚Д゚)[゚ε゚]+"
  275. alt_char = "(o゚ー゚o)+ "
  276. out = ''
  277. # print data
  278. while data != '':
  279. # Check new char
  280. if data.find(begin_char) != 0:
  281. common.log_utils.log_debug("AADecoder: data not found")
  282. return False
  283. data = data[len(begin_char):]
  284. # Find encoded char
  285. enc_char = ""
  286. if data.find(begin_char) == -1:
  287. enc_char = data
  288. data = ""
  289. else:
  290. enc_char = data[:data.find(begin_char)]
  291. data = data[len(enc_char):]
  292. radix = 8
  293. # Detect radix 16 for utf8 char
  294. if enc_char.find(alt_char) == 0:
  295. enc_char = enc_char[len(alt_char):]
  296. radix = 16
  297. # print repr(enc_char), radix
  298. # print enc_char.replace('(゚Θ゚)', '1').replace('(゚ー゚)', '4').replace('(c^_^o)', '0').replace('(o^_^o)', '3')
  299. # print 'The CHAR', enc_char, radix
  300. str_char = self.decode_char(enc_char, radix)
  301. if str_char == "":
  302. #common.log_utils.log_debug("no match : "),
  303. print "no match : "
  304. #common.log_utils.log_debug(data + "\nout = " + out + "\n")
  305. print data + "\nout = " + out + "\n"
  306. return False
  307. # print 'sofar', str_char, radix,out
  308. out += chr(int(str_char, radix))
  309. # print 'sfar', chr(int(str_char, radix)), out
  310. if out == "":
  311. #common.log_utils.log_debug("no match : " + data)
  312. print "no match : " + data
  313. return False
  314. return out
  315. #
  316. # Python version of the jjdecode function written by Syed Zainudeen
  317. # http://csc.cs.utm.my/syed/images/files/jjdecode/jjdecode.html
  318. #
  319. # +NCR/CRC! [ReVeRsEr] - crackinglandia@gmail.com
  320. # Thanks to Jose Miguel Esparza (@EternalTodo) for the final push to make it work!
  321. #
  322. class JJDecoder(object):
  323. def __init__(self, jj_encoded_data):
  324. self.encoded_str = jj_encoded_data
  325. def clean(self):
  326. return re.sub('^\s+|\s+$', '', self.encoded_str)
  327. def checkPalindrome(self, Str):
  328. startpos = -1
  329. endpos = -1
  330. gv, gvl = -1, -1
  331. index = Str.find('"\'\\"+\'+",')
  332. if index == 0:
  333. startpos = Str.find('$$+"\\""+') + 8
  334. endpos = Str.find('"\\"")())()')
  335. gv = Str[Str.find('"\'\\"+\'+",') + 9:Str.find('=~[]')]
  336. gvl = len(gv)
  337. else:
  338. gv = Str[0:Str.find('=')]
  339. gvl = len(gv)
  340. startpos = Str.find('"\\""+') + 5
  341. endpos = Str.find('"\\"")())()')
  342. return (startpos, endpos, gv, gvl)
  343. def decode(self):
  344. self.encoded_str = self.clean()
  345. startpos, endpos, gv, gvl = self.checkPalindrome(self.encoded_str)
  346. if startpos == endpos:
  347. raise Exception('No data!')
  348. data = self.encoded_str[startpos:endpos]
  349. b = ['___+', '__$+', '_$_+', '_$$+', '$__+', '$_$+', '$$_+', '$$$+', '$___+', '$__$+', '$_$_+', '$_$$+', '$$__+', '$$_$+', '$$$_+', '$$$$+']
  350. str_l = '(![]+"")[' + gv + '._$_]+'
  351. str_o = gv + '._$+'
  352. str_t = gv + '.__+'
  353. str_u = gv + '._+'
  354. str_hex = gv + '.'
  355. str_s = '"'
  356. gvsig = gv + '.'
  357. str_quote = '\\\\\\"'
  358. str_slash = '\\\\\\\\'
  359. str_lower = '\\\\"+'
  360. str_upper = '\\\\"+' + gv + '._+'
  361. str_end = '"+'
  362. out = ''
  363. while data != '':
  364. # l o t u
  365. if data.find(str_l) == 0:
  366. data = data[len(str_l):]
  367. out += 'l'
  368. continue
  369. elif data.find(str_o) == 0:
  370. data = data[len(str_o):]
  371. out += 'o'
  372. continue
  373. elif data.find(str_t) == 0:
  374. data = data[len(str_t):]
  375. out += 't'
  376. continue
  377. elif data.find(str_u) == 0:
  378. data = data[len(str_u):]
  379. out += 'u'
  380. continue
  381. # 0123456789abcdef
  382. if data.find(str_hex) == 0:
  383. data = data[len(str_hex):]
  384. for i in range(len(b)):
  385. if data.find(b[i]) == 0:
  386. data = data[len(b[i]):]
  387. out += '%x' % i
  388. break
  389. continue
  390. # start of s block
  391. if data.find(str_s) == 0:
  392. data = data[len(str_s):]
  393. # check if "R
  394. if data.find(str_upper) == 0: # r4 n >= 128
  395. data = data[len(str_upper):] # skip sig
  396. ch_str = ''
  397. for i in range(2): # shouldn't be more than 2 hex chars
  398. # gv + "."+b[ c ]
  399. if data.find(gvsig) == 0:
  400. data = data[len(gvsig):]
  401. for k in range(len(b)): # for every entry in b
  402. if data.find(b[k]) == 0:
  403. data = data[len(b[k]):]
  404. ch_str = '%x' % k
  405. break
  406. else:
  407. break
  408. out += chr(int(ch_str, 16))
  409. continue
  410. elif data.find(str_lower) == 0: # r3 check if "R // n < 128
  411. data = data[len(str_lower):] # skip sig
  412. ch_str = ''
  413. ch_lotux = ''
  414. temp = ''
  415. b_checkR1 = 0
  416. for j in range(3): # shouldn't be more than 3 octal chars
  417. if j > 1: # lotu check
  418. if data.find(str_l) == 0:
  419. data = data[len(str_l):]
  420. ch_lotux = 'l'
  421. break
  422. elif data.find(str_o) == 0:
  423. data = data[len(str_o):]
  424. ch_lotux = 'o'
  425. break
  426. elif data.find(str_t) == 0:
  427. data = data[len(str_t):]
  428. ch_lotux = 't'
  429. break
  430. elif data.find(str_u) == 0:
  431. data = data[len(str_u):]
  432. ch_lotux = 'u'
  433. break
  434. # gv + "."+b[ c ]
  435. if data.find(gvsig) == 0:
  436. temp = data[len(gvsig):]
  437. for k in range(8): # for every entry in b octal
  438. if temp.find(b[k]) == 0:
  439. if int(ch_str + str(k), 8) > 128:
  440. b_checkR1 = 1
  441. break
  442. ch_str += str(k)
  443. data = data[len(gvsig):] # skip gvsig
  444. data = data[len(b[k]):]
  445. break
  446. if b_checkR1 == 1:
  447. if data.find(str_hex) == 0: # 0123456789abcdef
  448. data = data[len(str_hex):]
  449. # check every element of hex decode string for a match
  450. for i in range(len(b)):
  451. if data.find(b[i]) == 0:
  452. data = data[len(b[i]):]
  453. ch_lotux = '%x' % i
  454. break
  455. break
  456. else:
  457. break
  458. out += chr(int(ch_str, 8)) + ch_lotux
  459. continue
  460. else: # "S ----> "SR or "S+
  461. # if there is, loop s until R 0r +
  462. # if there is no matching s block, throw error
  463. match = 0
  464. n = None
  465. # searching for matching pure s block
  466. while True:
  467. n = ord(data[0])
  468. if data.find(str_quote) == 0:
  469. data = data[len(str_quote):]
  470. out += '"'
  471. match += 1
  472. continue
  473. elif data.find(str_slash) == 0:
  474. data = data[len(str_slash):]
  475. out += '\\'
  476. match += 1
  477. continue
  478. elif data.find(str_end) == 0: # reached end off S block ? +
  479. if match == 0:
  480. raise '+ no match S block: ' + data
  481. data = data[len(str_end):]
  482. break # step out of the while loop
  483. elif data.find(str_upper) == 0: # r4 reached end off S block ? - check if "R n >= 128
  484. if match == 0:
  485. raise 'no match S block n>128: ' + data
  486. data = data[len(str_upper):] # skip sig
  487. ch_str = ''
  488. ch_lotux = ''
  489. for j in range(10): # shouldn't be more than 10 hex chars
  490. if j > 1: # lotu check
  491. if data.find(str_l) == 0:
  492. data = data[len(str_l):]
  493. ch_lotux = 'l'
  494. break
  495. elif data.find(str_o) == 0:
  496. data = data[len(str_o):]
  497. ch_lotux = 'o'
  498. break
  499. elif data.find(str_t) == 0:
  500. data = data[len(str_t):]
  501. ch_lotux = 't'
  502. break
  503. elif data.find(str_u) == 0:
  504. data = data[len(str_u):]
  505. ch_lotux = 'u'
  506. break
  507. # gv + "."+b[ c ]
  508. if data.find(gvsig) == 0:
  509. data = data[len(gvsig):] # skip gvsig
  510. for k in range(len(b)): # for every entry in b
  511. if data.find(b[k]) == 0:
  512. data = data[len(b[k]):]
  513. ch_str += '%x' % k
  514. break
  515. else:
  516. break # done
  517. out += chr(int(ch_str, 16))
  518. break # step out of the while loop
  519. elif data.find(str_lower) == 0: # r3 check if "R // n < 128
  520. if match == 0:
  521. raise 'no match S block n<128: ' + data
  522. data = data[len(str_lower):] # skip sig
  523. ch_str = ''
  524. ch_lotux = ''
  525. temp = ''
  526. b_checkR1 = 0
  527. for j in range(3): # shouldn't be more than 3 octal chars
  528. if j > 1: # lotu check
  529. if data.find(str_l) == 0:
  530. data = data[len(str_l):]
  531. ch_lotux = 'l'
  532. break
  533. elif data.find(str_o) == 0:
  534. data = data[len(str_o):]
  535. ch_lotux = 'o'
  536. break
  537. elif data.find(str_t) == 0:
  538. data = data[len(str_t):]
  539. ch_lotux = 't'
  540. break
  541. elif data.find(str_u) == 0:
  542. data = data[len(str_u):]
  543. ch_lotux = 'u'
  544. break
  545. # gv + "."+b[ c ]
  546. if data.find(gvsig) == 0:
  547. temp = data[len(gvsig):]
  548. for k in range(8): # for every entry in b octal
  549. if temp.find(b[k]) == 0:
  550. if int(ch_str + str(k), 8) > 128:
  551. b_checkR1 = 1
  552. break
  553. ch_str += str(k)
  554. data = data[len(gvsig):] # skip gvsig
  555. data = data[len(b[k]):]
  556. break
  557. if b_checkR1 == 1:
  558. if data.find(str_hex) == 0: # 0123456789abcdef
  559. data = data[len(str_hex):]
  560. # check every element of hex decode string for a match
  561. for i in range(len(b)):
  562. if data.find(b[i]) == 0:
  563. data = data[len(b[i]):]
  564. ch_lotux = '%x' % i
  565. break
  566. else:
  567. break
  568. out += chr(int(ch_str, 8)) + ch_lotux
  569. break # step out of the while loop
  570. elif (0x21 <= n and n <= 0x2f) or (0x3A <= n and n <= 0x40) or (0x5b <= n and n <= 0x60) or (0x7b <= n and n <= 0x7f):
  571. out += data[0]
  572. data = data[1:]
  573. match += 1
  574. continue
  575. print 'No match : ' + data
  576. break
  577. return out