home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / common / favicons.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  7.1 KB  |  228 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from threading import RLock, currentThread
  6. from time import time
  7. import wx
  8. from util.primitives.funcs import WeakDelegate
  9. from util.cacheable import get_cache_root
  10. from common import netcall
  11. import common.asynchttp as asynchttp
  12. from logging import getLogger
  13. log = getLogger('favicons')
  14. __all__ = ('favicon',)
  15. FETCHING = object()
  16. EMPTY = object()
  17. FAVICON_EXPIRE_SECS = 2592000
  18. FAVICON_EXPIRE_ERROR_SECS = 86400
  19. FAVICON_CACHE_DIR = 'favicons'
  20. ICON_EXT = '.ico'
  21. LINK_EXT = '.redirect'
  22. MAX_SUBDOMAIN_CHECK = 5
  23. _favicons_lru = { }
  24. _domain_lru = { }
  25. manual_redirects = {
  26.     'gmail.com': 'mail.google.com',
  27.     'facebookmail.com': 'www.facebook.com',
  28.     'papajohns-specials.com': 'papajohns.com',
  29.     'papajohnsonline.com': 'papajohns.com' }
  30.  
  31. def favicon(domain):
  32.     cached = get_cached(domain)
  33.     if cached in (FETCHING, EMPTY):
  34.         return None
  35.     if cached is not None:
  36.         return cached
  37.     fetch_favicon(domain)
  38.  
  39. on_icon = WeakDelegate()
  40.  
  41. def cache_path():
  42.     p = get_cache_root() / FAVICON_CACHE_DIR
  43.     if not p.isdir():
  44.         p.makedirs()
  45.     
  46.     return p
  47.  
  48.  
  49. def clear_cache():
  50.     cache_path().rmtree()
  51.  
  52.  
  53. def get_icon_domain(domain):
  54.     domain = manual_redirects.get(domain, domain)
  55.     if domain in _domain_lru:
  56.         return _domain_lru[domain]
  57.     root = cache_path()
  58.     p = root / (domain + LINK_EXT)
  59.     if p.isfile():
  60.         result = p.bytes()
  61.     else:
  62.         result = domain
  63.     _domain_lru[domain] = result
  64.     return result
  65.  
  66.  
  67. def get_cached(domain, done_fetching = False):
  68.     domain = get_icon_domain(domain)
  69.     if domain in _favicons_lru:
  70.         return _favicons_lru[domain]
  71.     if not done_fetching and is_fetching(domain):
  72.         return FETCHING
  73.     cache_file = cache_path() / domain + ICON_EXT
  74.     if not cache_file.isfile():
  75.         return None
  76.     age = time() - cache_file.mtime
  77.     if cache_file.size == 0:
  78.         if age > FAVICON_EXPIRE_ERROR_SECS:
  79.             log.info('expiring empty favicon cache file for %s' % domain)
  80.             cache_file.remove()
  81.             return None
  82.         log.debug('%s has an empty cache file', domain)
  83.         _favicons_lru[domain] = EMPTY
  84.         return EMPTY
  85.     
  86.     try:
  87.         log.debug('loading favicon cache file for %s', domain)
  88.         bitmap = wx.Bitmap(cache_file)
  89.         if not bitmap.IsOk():
  90.             raise Exception('bitmap.IsOk() != True')
  91.         bitmap.IsOk()
  92.     except Exception:
  93.         cache_file.size == 0
  94.         e = cache_file.size == 0
  95.         is_fetching(domain) if not done_fetching else cache_file.isfile()
  96.         log.warning('Error loading image file: %s' % e)
  97.         cache_file.remove()
  98.     except:
  99.         domain in _favicons_lru
  100.  
  101.     _favicons_lru[domain] = bitmap
  102.     on_icon(domain)
  103.     return bitmap
  104.  
  105.  
  106. def cache_icon(domain, linked_domains, data):
  107.     cp = cache_path()
  108.     icon_file = cp / domain + ICON_EXT
  109.     if icon_file.isfile():
  110.         log.warning('caching file to %s but it already exists', icon_file)
  111.     
  112.     icon_file.write_bytes(data)
  113.     for d in linked_domains:
  114.         (cp / d + LINK_EXT).write_bytes(domain)
  115.     
  116.     _domain_lru.clear()
  117.     wx.CallAfter(get_cached, domain, done_fetching = True)
  118.     log.debug('cached %d bytes of data for %r (linked: %s)', len(data), domain, ', '.join(linked_domains))
  119.  
  120.  
  121. def cache_noicon(domain, linked_domains):
  122.     return cache_icon(domain, linked_domains, '')
  123.  
  124.  
  125. def link_tag_url(html):
  126.     HTML = HTML
  127.     import lxml.etree
  128.     doc = HTML(html)
  129.     link_tag = doc.find('.//link[@rel="shortcut icon"]')
  130.     if link_tag is not None:
  131.         favicon_url = link_tag.get('href', '')
  132.         if favicon_url:
  133.             return favicon_url
  134.     
  135.  
  136.  
  137. def fetch_favicon(domain, linked_domains = None):
  138.     start_domain = domain
  139.     real_domain = get_icon_domain(domain)
  140.     if linked_domains is None:
  141.         linked_domains = []
  142.     
  143.     if real_domain != domain:
  144.         linked_domains.append(domain)
  145.     
  146.     domain = real_domain
  147.     wwwdomain = 'www.' + domain
  148.     if not domain.startswith('www') or wwwdomain in linked_domains:
  149.         linked_domains.append(domain)
  150.         domain = wwwdomain
  151.     
  152.     log.info('Using %r for %r (linked = %r)', domain, start_domain, linked_domains)
  153.     url = 'http://' + domain + '/favicon.ico'
  154.     
  155.     def on_success(req, resp):
  156.         data = resp.read()
  157.         log.info('httpopen(%s): received %d bytes of data', url, len(data))
  158.         log.info('%r', resp)
  159.         cache_icon(domain, linked_domains, data)
  160.         unset_fetching([
  161.             domain])
  162.  
  163.     
  164.     def on_error(req = (None, None, None), resp = (None, None)):
  165.         log.error('on_error for domain=%r, linked_domains=%r', domain, linked_domains)
  166.         if domain.count('.') < domain.count('.'):
  167.             pass
  168.         elif domain.count('.') < MAX_SUBDOMAIN_CHECK:
  169.             new_domain = '.'.join(domain.split('.')[1:])
  170.             wx.CallAfter(fetch_favicon, new_domain, linked_domains + [
  171.                 domain])
  172.             return None
  173.         log.error('No more subdomains to try for %r. Error response was: %r', domain, resp)
  174.         cache_noicon(domain, linked_domains)
  175.         unset_fetching(linked_domains + [
  176.             domain])
  177.  
  178.     
  179.     def on_redirect(req):
  180.         return req
  181.  
  182.     fetch_lock.__enter__()
  183.     
  184.     try:
  185.         if domain in currently_fetching:
  186.             log.info('already fetching %r', url)
  187.             return None
  188.         log.info('getting %r', url)
  189.         currently_fetching.add(domain)
  190.     finally:
  191.         pass
  192.  
  193.     (None, fetch_lock, fetch_lock.__exit__, netcall)((lambda : asynchttp.httpopen(url, success = on_success, error = on_error, on_redirect = on_redirect)))
  194.  
  195. fetch_lock = RLock()
  196. currently_fetching = set()
  197.  
  198. def set_fetching(domain):
  199.     fetch_lock.__enter__()
  200.     
  201.     try:
  202.         currently_fetching.add(domain)
  203.     finally:
  204.         pass
  205.  
  206.  
  207.  
  208. def unset_fetching(domains):
  209.     global currently_fetching
  210.     fetch_lock.__enter__()
  211.     
  212.     try:
  213.         currently_fetching -= set(domains)
  214.     finally:
  215.         pass
  216.  
  217.  
  218.  
  219. def is_fetching(domain):
  220.     fetch_lock.__enter__()
  221.     
  222.     try:
  223.         return domain in currently_fetching
  224.     finally:
  225.         pass
  226.  
  227.  
  228.