common_operations.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. # -*- coding: utf-8 -*-
  2. u"""
  3. 基本操作
  4. """
  5. import os
  6. import sys
  7. import traceback
  8. import wx
  9. import chardet
  10. import urllib
  11. import re
  12. import threading
  13. import httplib
  14. import urlparse
  15. if os.name == "posix":
  16. if sys.platform != "darwin":
  17. # Linux
  18. try:
  19. import pynotify
  20. except ImportError:
  21. pynotify = None
  22. else:
  23. # Mac
  24. import gntp.notifier
  25. growl = gntp.notifier.GrowlNotifier(
  26. applicationName="SwitchHosts!",
  27. notifications=["New Updates", "New Messages"],
  28. defaultNotifications=["New Messages"],
  29. hostname = "127.0.0.1", # Defaults to localhost
  30. # password = "" # Defaults to a blank password
  31. )
  32. growl.register()
  33. from icons import ICONS, ICONS2, ICONS_ICO
  34. def GetMondrianData(i=0, fn=None):
  35. if not fn:
  36. idx = i if 0 <= i < len(ICONS) else 0
  37. return ICONS_ICO[idx]
  38. else:
  39. return ICONS2[fn]
  40. def GetMondrianBitmap(i=0, fn=None):
  41. return wx.BitmapFromImage(GetMondrianImage(i, fn))
  42. def GetMondrianImage(i=0, fn=None):
  43. import cStringIO
  44. stream = cStringIO.StringIO(GetMondrianData(i, fn))
  45. return wx.ImageFromStream(stream)
  46. def GetMondrianIcon(i=0, fn=None):
  47. icon = wx.EmptyIcon()
  48. icon.CopyFromBitmap(GetMondrianBitmap(i, fn))
  49. return icon
  50. def macNotify(msg, title):
  51. # print("mac nofity!")
  52. growl.notify(
  53. noteType="New Messages",
  54. title=title,
  55. description=msg,
  56. sticky=False,
  57. priority=1,
  58. )
  59. def notify(frame, msg="", title=u"消息"):
  60. if os.name == "posix":
  61. if sys.platform != "darwin":
  62. # linux 系统
  63. pynotify.Notification(title, msg).show()
  64. else:
  65. # Mac 系统
  66. macNotify(msg, title)
  67. return
  68. import ToasterBox as TB
  69. sw, sh = wx.GetDisplaySize()
  70. width, height = 210, 50
  71. px = sw - 230
  72. py = sh - 100
  73. tb = TB.ToasterBox(frame)
  74. tb.SetPopupText(msg)
  75. tb.SetPopupSize((width, height))
  76. tb.SetPopupPosition((px, py))
  77. tb.Play()
  78. frame.SetFocus()
  79. def switchHost(obj, fn):
  80. u"""切换 hosts 为 fn 的内容"""
  81. from cls_Hosts import Hosts
  82. if not os.path.isfile(fn):
  83. wx.MessageBox(u"hosts 文件 '%s' 不存在!" % fn, "Error!")
  84. ohosts = Hosts(path=fn)
  85. sys_hosts_fn = getSysHostsPath()
  86. try:
  87. a = open(fn, "rb").read().split("\n")
  88. a = [ln.rstrip() for ln in a]
  89. if sys_hosts_fn:
  90. open(sys_hosts_fn, "wb").write(os.linesep.join(a))
  91. else:
  92. wx.MessageBox(u"无效的系统 hosts 路径!")
  93. obj.current_hosts = fn
  94. title = ohosts.getTitle()
  95. obj.SetIcon(GetMondrianIcon(), "Hosts: %s" % title)
  96. notify(obj.frame, u"Hosts 已切换为 %s。" % title)
  97. ohosts = obj.frame.getOHostsFromFn(fn)
  98. obj.SetIcon(GetMondrianIcon(ohosts.icon_idx), u"当前 hosts 方案:%s" % ohosts.getTitle())
  99. obj.frame.SetIcon(GetMondrianIcon(ohosts.icon_idx))
  100. obj.frame.current_use_hosts_index = ohosts.index
  101. except Exception:
  102. err_msg = traceback.format_exc()
  103. if "Permission denied" in err_msg:
  104. err_msg = u"权限不足!"
  105. wx.MessageBox(err_msg, u"hosts 未能成功切换!")
  106. def getSysHostsPath():
  107. u"""取得系统 host 文件的路径"""
  108. if os.name == "nt":
  109. path = "C:\\Windows\\System32\\drivers\\etc\\hosts"
  110. else:
  111. path = "/etc/hosts"
  112. return path if os.path.isfile(path) else None
  113. def encode(s):
  114. # print("--")
  115. # print(chardet.detect(s))
  116. return unicode(s).encode("UTF-8") if s else ""
  117. def decode(s):
  118. if not s:
  119. return ""
  120. cd = {}
  121. try:
  122. cd = chardet.detect(s)
  123. except Exception:
  124. # print(traceback.format_exc())
  125. pass
  126. encoding = cd.get("encoding") if cd.get("confidence", 0) > 0.65 else None
  127. if not encoding:
  128. encoding = "GB18030" if os.name == "nt" else "UTF-8"
  129. # print s, cd, encoding, s.decode(encoding)
  130. return s.decode(encoding)
  131. def checkLatestStableVersion(obj):
  132. def _f(obj):
  133. url = "https://github.com/oldj/SwitchHosts/blob/master/README.md"
  134. ver = None
  135. try:
  136. c = urllib.urlopen(url).read()
  137. v = re.search(r"\bLatest Stable:\s?(?P<version>[\d\.]+)\b", c)
  138. if v:
  139. ver = v.group("version")
  140. except Exception:
  141. pass
  142. obj.setLatestStableVersion(ver)
  143. return ver
  144. t = threading.Thread(target=_f, args=(obj,))
  145. t.setDaemon(True)
  146. t.start()
  147. def httpExists(url):
  148. host, path = urlparse.urlsplit(url)[1:3]
  149. found = 0
  150. try:
  151. connection = httplib.HTTPConnection(host) ## Make HTTPConnection Object
  152. connection.request("HEAD", path)
  153. responseOb = connection.getresponse() ## Grab HTTPResponse Object
  154. if responseOb.status == 200:
  155. found = 1
  156. elif responseOb.status == 302:
  157. found = httpExists(urlparse.urljoin(url, responseOb.getheader('location', '')))
  158. else:
  159. print "Status %d %s : %s" % (responseOb.status, responseOb.reason, url)
  160. except Exception, e:
  161. print e.__class__, e, url
  162. return found