Sexy system trac icon instead of ugly console, Total received/sent stat, List all site peer, Dont sent passive peers over pex, Dont store passive peers on trackers, Dont monkey patch thread at all, Allow main command plugins

This commit is contained in:
HelloZeroNet 2015-04-15 02:54:10 +02:00
parent 804fed2659
commit 30281c8fb5
14 changed files with 1170 additions and 207 deletions

View File

@ -53,12 +53,14 @@ class UiRequestPlugin(object):
# Memory
try:
yield "Ip external: %s | " % config.ip_external
yield "Port opened: %s | " % main.file_server.port_opened
yield "IP external: %s | " % config.ip_external
yield "Opened: %s | " % main.file_server.port_opened
yield "Recv: %.2fMB, Sent: %.2fMB | " % (float(main.file_server.bytes_recv)/1024/1024, float(main.file_server.bytes_sent)/1024/1024)
yield "Peerid: %s | " % main.file_server.peer_id
import psutil
process = psutil.Process(os.getpid())
mem = process.get_memory_info()[0] / float(2 ** 20)
yield "Memory usage: %.2fMB | " % mem
yield "Mem: %.2fMB | " % mem
yield "Threads: %s | " % len(process.threads())
yield "CPU: usr %.2fs sys %.2fs | " % process.cpu_times()
yield "Open files: %s | " % len(process.open_files())
@ -69,7 +71,7 @@ class UiRequestPlugin(object):
yield "<br>"
# Connections
yield "<b>Connections</b> (%s):<br>" % len(main.file_server.connections)
yield "<b>Connections</b> (%s, total made: %s):<br>" % (len(main.file_server.connections), main.file_server.last_connection_id)
yield "<table><tr> <th>id</th> <th>protocol</th> <th>type</th> <th>ip</th> <th>open</th> <th>ping</th> <th>buff</th>"
yield "<th>idle</th> <th>open</th> <th>delay</th> <th>sent</th> <th>received</th> <th>last sent</th> <th>waiting</th> <th>version</th> <th>peerid</th> </tr>"
for connection in main.file_server.connections:
@ -100,11 +102,15 @@ class UiRequestPlugin(object):
yield "<tr><th>address</th> <th>connected</th> <th>peers</th> <th>content.json</th> </tr>"
for site in self.server.sites.values():
yield self.formatTableRow([
("%s", site.address),
("<a href='#ShowPeers' onclick='document.getElementById(\"peers_%s\").style.display=\"initial\"; return false'>%s</a>", (site.address, site.address)),
("%s", [peer.connection.id for peer in site.peers.values() if peer.connection and peer.connection.connected]),
("%s/%s", ( len([peer for peer in site.peers.values() if peer.connection and peer.connection.connected]), len(site.peers) ) ),
("%s", len(site.content_manager.contents)),
])
yield "<tr><td id='peers_%s' style='display: none'>" % site.address
for key, peer in site.peers.items():
yield "(%s) %s -<br>" % (peer.connection, key)
yield "<br></td></tr>"
yield "</table>"

View File

@ -0,0 +1,91 @@
import re, time, cgi, os, sys
from Plugin import PluginManager
from Config import config
import atexit
allow_reload = False # No reload supported
@PluginManager.registerTo("Actions")
class ActionsPlugin(object):
def main(self):
global notificationicon, winfolders
from lib import notificationicon, winfolders
import gevent.threadpool
self.main = sys.modules["main"]
icon = notificationicon.NotificationIcon(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'trayicon.ico'), "ZeroNet %s" % config.version)
self.icon = icon
if not config.debug: # Hide console if not in debug mode
notificationicon.hideConsole()
self.console = False
else:
self.console = True
@atexit.register
def hideIcon():
icon.die()
icon.items = (
(self.titleIp, False),
(self.titleConnections, False),
(self.titleTransfer, False),
(self.titleConsole, self.toggleConsole),
"--",
("ZeroNet Twitter", lambda: self.opensite("https://twitter.com/HelloZeroNet") ),
("ZeroNet Reddit", lambda: self.opensite("http://www.reddit.com/r/zeronet/") ),
("ZeroNet Github", lambda: self.opensite("https://github.com/HelloZeroNet/ZeroNet") ),
("Report bug/request feature", lambda: self.opensite("https://github.com/HelloZeroNet/ZeroNet/issues") ),
"--",
("!Open ZeroNet", lambda: self.opensite("http://%s:%s" % (config.ui_ip, config.ui_port)) ),
#"--",
#("Start ZeroNet when Windows starts", quit),
"--",
("Quit", self.quit),
)
icon.clicked = lambda: self.opensite("http://%s:%s" % (config.ui_ip, config.ui_port))
gevent.threadpool.start_new_thread(icon._run, ()) # Start in real thread (not gevent compatible)
super(ActionsPlugin, self).main()
icon._die = True
def quit(self):
self.icon.die()
time.sleep(0.1)
self.main.ui_server.stop()
self.main.file_server.stop()
#sys.exit()
def opensite(self, url):
import webbrowser
webbrowser.open(url, new=2)
def titleIp(self):
title = "!IP: %s" % config.ip_external
if self.main.file_server.port_opened:
title += " (active)"
else:
title += " (passive)"
return title
def titleConnections(self):
title = "Connections: %s" % len(self.main.file_server.connections)
return title
def titleTransfer(self):
title = "Received: %.2f MB | Sent: %.2f MB" % (float(self.main.file_server.bytes_recv)/1024/1024, float(self.main.file_server.bytes_sent)/1024/1024)
return title
def titleConsole(self):
if self.console: return "+Show console window"
else: return "Show console window"
def toggleConsole(self):
if self.console:
notificationicon.hideConsole()
self.console = False
else:
notificationicon.showConsole()
self.console = True

View File

@ -0,0 +1,4 @@
import sys
if sys.platform == 'win32':
import TrayiconPlugin

View File

View File

@ -0,0 +1,800 @@
# Pure ctypes windows taskbar notification icon
# via https://gist.github.com/jasonbot/5759510
# Modified for ZeroNet
import ctypes
import ctypes.wintypes
import os
#import threading
#import Queue
import uuid
import time
import gevent
__all__ = ['NotificationIcon']
# Create popup menu
CreatePopupMenu = ctypes.windll.user32.CreatePopupMenu
CreatePopupMenu.restype = ctypes.wintypes.HMENU
CreatePopupMenu.argtypes = []
MF_BYCOMMAND = 0x0
MF_BYPOSITION = 0x400
MF_BITMAP = 0x4
MF_CHECKED = 0x8
MF_DISABLED = 0x2
MF_ENABLED = 0x0
MF_GRAYED = 0x1
MF_MENUBARBREAK = 0x20
MF_MENUBREAK = 0x40
MF_OWNERDRAW = 0x100
MF_POPUP = 0x10
MF_SEPARATOR = 0x800
MF_STRING = 0x0
MF_UNCHECKED = 0x0
InsertMenu = ctypes.windll.user32.InsertMenuW
InsertMenu.restype = ctypes.wintypes.BOOL
InsertMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.LPCWSTR]
AppendMenu = ctypes.windll.user32.AppendMenuW
AppendMenu.restype = ctypes.wintypes.BOOL
AppendMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.LPCWSTR]
SetMenuDefaultItem = ctypes.windll.user32.SetMenuDefaultItem
SetMenuDefaultItem.restype = ctypes.wintypes.BOOL
SetMenuDefaultItem.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT]
#class MENUITEMINFO(ctypes.Structure):
# UINT cbSize;
# UINT fMask;
# UINT fType;
# UINT fState;
# UINT wID;
# HMENU hSubMenu;
# HBITMAP hbmpChecked;
# HBITMAP hbmpUnchecked;
# ULONG_PTR dwItemData;
# LPTSTR dwTypeData;
# UINT cch;
# HBITMAP hbmpItem;
#
#BOOL WINAPI InsertMenuItem(
# __in HMENU hMenu,
# __in UINT uItem,
# __in BOOL fByPosition,
# __in LPCMENUITEMINFO lpmii
#);
#
class POINT(ctypes.Structure):
_fields_ = [ ('x', ctypes.wintypes.LONG),
('y', ctypes.wintypes.LONG)]
GetCursorPos = ctypes.windll.user32.GetCursorPos
GetCursorPos.argtypes = [ctypes.POINTER(POINT)]
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow
SetForegroundWindow.argtypes = [ctypes.wintypes.HWND]
TPM_LEFTALIGN = 0x0
TPM_CENTERALIGN = 0x4
TPM_RIGHTALIGN = 0x8
TPM_TOPALIGN = 0x0
TPM_VCENTERALIGN = 0x10
TPM_BOTTOMALIGN = 0x20
TPM_NONOTIFY = 0x80
TPM_RETURNCMD = 0x100
TPM_LEFTBUTTON = 0x0
TPM_RIGHTBUTTON = 0x2
TPM_HORNEGANIMATION = 0x800
TPM_HORPOSANIMATION = 0x400
TPM_NOANIMATION = 0x4000
TPM_VERNEGANIMATION = 0x2000
TPM_VERPOSANIMATION = 0x1000
TrackPopupMenu = ctypes.windll.user32.TrackPopupMenu
TrackPopupMenu.restype = ctypes.wintypes.BOOL
TrackPopupMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.wintypes.HWND, ctypes.c_void_p]
PostMessage = ctypes.windll.user32.PostMessageW
PostMessage.restype = ctypes.wintypes.BOOL
PostMessage.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM]
DestroyMenu = ctypes.windll.user32.DestroyMenu
DestroyMenu.restype = ctypes.wintypes.BOOL
DestroyMenu.argtypes = [ctypes.wintypes.HMENU]
# Create notification icon
GUID = ctypes.c_ubyte * 16
class TimeoutVersionUnion(ctypes.Union):
_fields_ = [('uTimeout', ctypes.wintypes.UINT),
('uVersion', ctypes.wintypes.UINT),]
NIS_HIDDEN = 0x1
NIS_SHAREDICON = 0x2
class NOTIFYICONDATA(ctypes.Structure):
def __init__(self, *args, **kwargs):
super(NOTIFYICONDATA, self).__init__(*args, **kwargs)
self.cbSize = ctypes.sizeof(self)
_fields_ = [
('cbSize', ctypes.wintypes.DWORD),
('hWnd', ctypes.wintypes.HWND),
('uID', ctypes.wintypes.UINT),
('uFlags', ctypes.wintypes.UINT),
('uCallbackMessage', ctypes.wintypes.UINT),
('hIcon', ctypes.wintypes.HICON),
('szTip', ctypes.wintypes.WCHAR * 64),
('dwState', ctypes.wintypes.DWORD),
('dwStateMask', ctypes.wintypes.DWORD),
('szInfo', ctypes.wintypes.WCHAR * 256),
('union', TimeoutVersionUnion),
('szInfoTitle', ctypes.wintypes.WCHAR * 64),
('dwInfoFlags', ctypes.wintypes.DWORD),
('guidItem', GUID),
('hBalloonIcon', ctypes.wintypes.HICON),
]
NIM_ADD = 0
NIM_MODIFY = 1
NIM_DELETE = 2
NIM_SETFOCUS = 3
NIM_SETVERSION = 4
NIF_MESSAGE = 1
NIF_ICON = 2
NIF_TIP = 4
NIF_STATE = 8
NIF_INFO = 16
NIF_GUID = 32
NIF_REALTIME = 64
NIF_SHOWTIP = 128
NIIF_NONE = 0
NIIF_INFO = 1
NIIF_WARNING = 2
NIIF_ERROR = 3
NIIF_USER = 4
NOTIFYICON_VERSION = 3
NOTIFYICON_VERSION_4 = 4
Shell_NotifyIcon = ctypes.windll.shell32.Shell_NotifyIconW
Shell_NotifyIcon.restype = ctypes.wintypes.BOOL
Shell_NotifyIcon.argtypes = [ctypes.wintypes.DWORD, ctypes.POINTER(NOTIFYICONDATA)]
# Load icon/image
IMAGE_BITMAP = 0
IMAGE_ICON = 1
IMAGE_CURSOR = 2
LR_CREATEDIBSECTION = 0x00002000
LR_DEFAULTCOLOR = 0x00000000
LR_DEFAULTSIZE = 0x00000040
LR_LOADFROMFILE = 0x00000010
LR_LOADMAP3DCOLORS = 0x00001000
LR_LOADTRANSPARENT = 0x00000020
LR_MONOCHROME = 0x00000001
LR_SHARED = 0x00008000
LR_VGACOLOR = 0x00000080
OIC_SAMPLE = 32512
OIC_HAND = 32513
OIC_QUES = 32514
OIC_BANG = 32515
OIC_NOTE = 32516
OIC_WINLOGO = 32517
OIC_WARNING = OIC_BANG
OIC_ERROR = OIC_HAND
OIC_INFORMATION = OIC_NOTE
LoadImage = ctypes.windll.user32.LoadImageW
LoadImage.restype = ctypes.wintypes.HANDLE
LoadImage.argtypes = [ctypes.wintypes.HINSTANCE, ctypes.wintypes.LPCWSTR, ctypes.wintypes.UINT, ctypes.c_int, ctypes.c_int, ctypes.wintypes.UINT]
# CreateWindow call
WNDPROC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.wintypes.HWND, ctypes.c_uint, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
DefWindowProc = ctypes.windll.user32.DefWindowProcW
DefWindowProc.restype = ctypes.c_int
DefWindowProc.argtypes = [ctypes.wintypes.HWND, ctypes.c_uint, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM]
WS_OVERLAPPED = 0x00000000L
WS_POPUP = 0x80000000L
WS_CHILD = 0x40000000L
WS_MINIMIZE = 0x20000000L
WS_VISIBLE = 0x10000000L
WS_DISABLED = 0x08000000L
WS_CLIPSIBLINGS = 0x04000000L
WS_CLIPCHILDREN = 0x02000000L
WS_MAXIMIZE = 0x01000000L
WS_CAPTION = 0x00C00000L
WS_BORDER = 0x00800000L
WS_DLGFRAME = 0x00400000L
WS_VSCROLL = 0x00200000L
WS_HSCROLL = 0x00100000L
WS_SYSMENU = 0x00080000L
WS_THICKFRAME = 0x00040000L
WS_GROUP = 0x00020000L
WS_TABSTOP = 0x00010000L
WS_MINIMIZEBOX = 0x00020000L
WS_MAXIMIZEBOX = 0x00010000L
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX)
SM_XVIRTUALSCREEN = 76
SM_YVIRTUALSCREEN = 77
SM_CXVIRTUALSCREEN = 78
SM_CYVIRTUALSCREEN = 79
SM_CMONITORS = 80
SM_SAMEDISPLAYFORMAT = 81
WM_NULL = 0x0000
WM_CREATE = 0x0001
WM_DESTROY = 0x0002
WM_MOVE = 0x0003
WM_SIZE = 0x0005
WM_ACTIVATE = 0x0006
WM_SETFOCUS = 0x0007
WM_KILLFOCUS = 0x0008
WM_ENABLE = 0x000A
WM_SETREDRAW = 0x000B
WM_SETTEXT = 0x000C
WM_GETTEXT = 0x000D
WM_GETTEXTLENGTH = 0x000E
WM_PAINT = 0x000F
WM_CLOSE = 0x0010
WM_QUERYENDSESSION = 0x0011
WM_QUIT = 0x0012
WM_QUERYOPEN = 0x0013
WM_ERASEBKGND = 0x0014
WM_SYSCOLORCHANGE = 0x0015
WM_ENDSESSION = 0x0016
WM_SHOWWINDOW = 0x0018
WM_CTLCOLOR = 0x0019
WM_WININICHANGE = 0x001A
WM_SETTINGCHANGE = 0x001A
WM_DEVMODECHANGE = 0x001B
WM_ACTIVATEAPP = 0x001C
WM_FONTCHANGE = 0x001D
WM_TIMECHANGE = 0x001E
WM_CANCELMODE = 0x001F
WM_SETCURSOR = 0x0020
WM_MOUSEACTIVATE = 0x0021
WM_CHILDACTIVATE = 0x0022
WM_QUEUESYNC = 0x0023
WM_GETMINMAXINFO = 0x0024
WM_PAINTICON = 0x0026
WM_ICONERASEBKGND = 0x0027
WM_NEXTDLGCTL = 0x0028
WM_SPOOLERSTATUS = 0x002A
WM_DRAWITEM = 0x002B
WM_MEASUREITEM = 0x002C
WM_DELETEITEM = 0x002D
WM_VKEYTOITEM = 0x002E
WM_CHARTOITEM = 0x002F
WM_SETFONT = 0x0030
WM_GETFONT = 0x0031
WM_SETHOTKEY = 0x0032
WM_GETHOTKEY = 0x0033
WM_QUERYDRAGICON = 0x0037
WM_COMPAREITEM = 0x0039
WM_GETOBJECT = 0x003D
WM_COMPACTING = 0x0041
WM_COMMNOTIFY = 0x0044
WM_WINDOWPOSCHANGING = 0x0046
WM_WINDOWPOSCHANGED = 0x0047
WM_POWER = 0x0048
WM_COPYDATA = 0x004A
WM_CANCELJOURNAL = 0x004B
WM_NOTIFY = 0x004E
WM_INPUTLANGCHANGEREQUEST = 0x0050
WM_INPUTLANGCHANGE = 0x0051
WM_TCARD = 0x0052
WM_HELP = 0x0053
WM_USERCHANGED = 0x0054
WM_NOTIFYFORMAT = 0x0055
WM_CONTEXTMENU = 0x007B
WM_STYLECHANGING = 0x007C
WM_STYLECHANGED = 0x007D
WM_DISPLAYCHANGE = 0x007E
WM_GETICON = 0x007F
WM_SETICON = 0x0080
WM_NCCREATE = 0x0081
WM_NCDESTROY = 0x0082
WM_NCCALCSIZE = 0x0083
WM_NCHITTEST = 0x0084
WM_NCPAINT = 0x0085
WM_NCACTIVATE = 0x0086
WM_GETDLGCODE = 0x0087
WM_SYNCPAINT = 0x0088
WM_NCMOUSEMOVE = 0x00A0
WM_NCLBUTTONDOWN = 0x00A1
WM_NCLBUTTONUP = 0x00A2
WM_NCLBUTTONDBLCLK = 0x00A3
WM_NCRBUTTONDOWN = 0x00A4
WM_NCRBUTTONUP = 0x00A5
WM_NCRBUTTONDBLCLK = 0x00A6
WM_NCMBUTTONDOWN = 0x00A7
WM_NCMBUTTONUP = 0x00A8
WM_NCMBUTTONDBLCLK = 0x00A9
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
WM_CHAR = 0x0102
WM_DEADCHAR = 0x0103
WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
WM_SYSCHAR = 0x0106
WM_SYSDEADCHAR = 0x0107
WM_KEYLAST = 0x0108
WM_IME_STARTCOMPOSITION = 0x010D
WM_IME_ENDCOMPOSITION = 0x010E
WM_IME_COMPOSITION = 0x010F
WM_IME_KEYLAST = 0x010F
WM_INITDIALOG = 0x0110
WM_COMMAND = 0x0111
WM_SYSCOMMAND = 0x0112
WM_TIMER = 0x0113
WM_HSCROLL = 0x0114
WM_VSCROLL = 0x0115
WM_INITMENU = 0x0116
WM_INITMENUPOPUP = 0x0117
WM_MENUSELECT = 0x011F
WM_MENUCHAR = 0x0120
WM_ENTERIDLE = 0x0121
WM_MENURBUTTONUP = 0x0122
WM_MENUDRAG = 0x0123
WM_MENUGETOBJECT = 0x0124
WM_UNINITMENUPOPUP = 0x0125
WM_MENUCOMMAND = 0x0126
WM_CTLCOLORMSGBOX = 0x0132
WM_CTLCOLOREDIT = 0x0133
WM_CTLCOLORLISTBOX = 0x0134
WM_CTLCOLORBTN = 0x0135
WM_CTLCOLORDLG = 0x0136
WM_CTLCOLORSCROLLBAR = 0x0137
WM_CTLCOLORSTATIC = 0x0138
WM_MOUSEMOVE = 0x0200
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_LBUTTONDBLCLK = 0x0203
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
WM_RBUTTONDBLCLK = 0x0206
WM_MBUTTONDOWN = 0x0207
WM_MBUTTONUP = 0x0208
WM_MBUTTONDBLCLK = 0x0209
WM_MOUSEWHEEL = 0x020A
WM_PARENTNOTIFY = 0x0210
WM_ENTERMENULOOP = 0x0211
WM_EXITMENULOOP = 0x0212
WM_NEXTMENU = 0x0213
WM_SIZING = 0x0214
WM_CAPTURECHANGED = 0x0215
WM_MOVING = 0x0216
WM_DEVICECHANGE = 0x0219
WM_MDICREATE = 0x0220
WM_MDIDESTROY = 0x0221
WM_MDIACTIVATE = 0x0222
WM_MDIRESTORE = 0x0223
WM_MDINEXT = 0x0224
WM_MDIMAXIMIZE = 0x0225
WM_MDITILE = 0x0226
WM_MDICASCADE = 0x0227
WM_MDIICONARRANGE = 0x0228
WM_MDIGETACTIVE = 0x0229
WM_MDISETMENU = 0x0230
WM_ENTERSIZEMOVE = 0x0231
WM_EXITSIZEMOVE = 0x0232
WM_DROPFILES = 0x0233
WM_MDIREFRESHMENU = 0x0234
WM_IME_SETCONTEXT = 0x0281
WM_IME_NOTIFY = 0x0282
WM_IME_CONTROL = 0x0283
WM_IME_COMPOSITIONFULL = 0x0284
WM_IME_SELECT = 0x0285
WM_IME_CHAR = 0x0286
WM_IME_REQUEST = 0x0288
WM_IME_KEYDOWN = 0x0290
WM_IME_KEYUP = 0x0291
WM_MOUSEHOVER = 0x02A1
WM_MOUSELEAVE = 0x02A3
WM_CUT = 0x0300
WM_COPY = 0x0301
WM_PASTE = 0x0302
WM_CLEAR = 0x0303
WM_UNDO = 0x0304
WM_RENDERFORMAT = 0x0305
WM_RENDERALLFORMATS = 0x0306
WM_DESTROYCLIPBOARD = 0x0307
WM_DRAWCLIPBOARD = 0x0308
WM_PAINTCLIPBOARD = 0x0309
WM_VSCROLLCLIPBOARD = 0x030A
WM_SIZECLIPBOARD = 0x030B
WM_ASKCBFORMATNAME = 0x030C
WM_CHANGECBCHAIN = 0x030D
WM_HSCROLLCLIPBOARD = 0x030E
WM_QUERYNEWPALETTE = 0x030F
WM_PALETTEISCHANGING = 0x0310
WM_PALETTECHANGED = 0x0311
WM_HOTKEY = 0x0312
WM_PRINT = 0x0317
WM_PRINTCLIENT = 0x0318
WM_HANDHELDFIRST = 0x0358
WM_HANDHELDLAST = 0x035F
WM_AFXFIRST = 0x0360
WM_AFXLAST = 0x037F
WM_PENWINFIRST = 0x0380
WM_PENWINLAST = 0x038F
WM_APP = 0x8000
WM_USER = 0x0400
WM_REFLECT = WM_USER + 0x1c00
class WNDCLASSEX(ctypes.Structure):
def __init__(self, *args, **kwargs):
super(WNDCLASSEX, self).__init__(*args, **kwargs)
self.cbSize = ctypes.sizeof(self)
_fields_ = [("cbSize", ctypes.c_uint),
("style", ctypes.c_uint),
("lpfnWndProc", WNDPROC),
("cbClsExtra", ctypes.c_int),
("cbWndExtra", ctypes.c_int),
("hInstance", ctypes.wintypes.HANDLE),
("hIcon", ctypes.wintypes.HANDLE),
("hCursor", ctypes.wintypes.HANDLE),
("hBrush", ctypes.wintypes.HANDLE),
("lpszMenuName", ctypes.wintypes.LPCWSTR),
("lpszClassName", ctypes.wintypes.LPCWSTR),
("hIconSm", ctypes.wintypes.HANDLE)]
UpdateWindow = ctypes.windll.user32.UpdateWindow
UpdateWindow.argtypes = [ctypes.wintypes.HWND]
SW_HIDE = 0
SW_SHOWNORMAL = 1
SW_SHOW = 5
ShowWindow = ctypes.windll.user32.ShowWindow
ShowWindow.argtypes = [ctypes.wintypes.HWND, ctypes.c_int]
CS_VREDRAW = 0x0001
CS_HREDRAW = 0x0002
CS_KEYCVTWINDOW = 0x0004
CS_DBLCLKS = 0x0008
CS_OWNDC = 0x0020
CS_CLASSDC = 0x0040
CS_PARENTDC = 0x0080
CS_NOKEYCVT = 0x0100
CS_NOCLOSE = 0x0200
CS_SAVEBITS = 0x0800
CS_BYTEALIGNCLIENT = 0x1000
CS_BYTEALIGNWINDOW = 0x2000
CS_GLOBALCLASS = 0x4000
COLOR_SCROLLBAR = 0
COLOR_BACKGROUND = 1
COLOR_ACTIVECAPTION = 2
COLOR_INACTIVECAPTION = 3
COLOR_MENU = 4
COLOR_WINDOW = 5
COLOR_WINDOWFRAME = 6
COLOR_MENUTEXT = 7
COLOR_WINDOWTEXT = 8
COLOR_CAPTIONTEXT = 9
COLOR_ACTIVEBORDER = 10
COLOR_INACTIVEBORDER = 11
COLOR_APPWORKSPACE = 12
COLOR_HIGHLIGHT = 13
COLOR_HIGHLIGHTTEXT = 14
COLOR_BTNFACE = 15
COLOR_BTNSHADOW = 16
COLOR_GRAYTEXT = 17
COLOR_BTNTEXT = 18
COLOR_INACTIVECAPTIONTEXT = 19
COLOR_BTNHIGHLIGHT = 20
LoadCursor = ctypes.windll.user32.LoadCursorW
def GenerateDummyWindow(callback, uid):
newclass = WNDCLASSEX()
newclass.lpfnWndProc = callback
newclass.style = CS_VREDRAW | CS_HREDRAW
newclass.lpszClassName = uid.replace("-", "")
newclass.hBrush = COLOR_BACKGROUND
newclass.hCursor = LoadCursor(0, 32512)
ATOM = ctypes.windll.user32.RegisterClassExW(ctypes.byref(newclass))
#print "ATOM", ATOM
#print "CLASS", newclass.lpszClassName
hwnd = ctypes.windll.user32.CreateWindowExW(0,
newclass.lpszClassName,
u"Dummy Window",
WS_OVERLAPPEDWINDOW | WS_SYSMENU,
ctypes.windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN),
ctypes.windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN),
800, 600, 0, 0, 0, 0)
ShowWindow(hwnd, SW_SHOW)
UpdateWindow(hwnd)
ShowWindow(hwnd, SW_HIDE)
return hwnd
# Message loop calls
TIMERCALLBACK = ctypes.WINFUNCTYPE(None,
ctypes.wintypes.HWND,
ctypes.wintypes.UINT,
ctypes.POINTER(ctypes.wintypes.UINT),
ctypes.wintypes.DWORD)
SetTimer = ctypes.windll.user32.SetTimer
SetTimer.restype = ctypes.POINTER(ctypes.wintypes.UINT)
SetTimer.argtypes = [ctypes.wintypes.HWND,
ctypes.POINTER(ctypes.wintypes.UINT),
ctypes.wintypes.UINT,
TIMERCALLBACK]
KillTimer = ctypes.windll.user32.KillTimer
KillTimer.restype = ctypes.wintypes.BOOL
KillTimer.argtypes = [ctypes.wintypes.HWND,
ctypes.POINTER(ctypes.wintypes.UINT)]
class MSG(ctypes.Structure):
_fields_ = [ ('HWND', ctypes.wintypes.HWND),
('message', ctypes.wintypes.UINT),
('wParam', ctypes.wintypes.WPARAM),
('lParam', ctypes.wintypes.LPARAM),
('time', ctypes.wintypes.DWORD),
('pt', POINT)]
GetMessage = ctypes.windll.user32.GetMessageW
GetMessage.restype = ctypes.wintypes.BOOL
GetMessage.argtypes = [ctypes.POINTER(MSG), ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.UINT]
TranslateMessage = ctypes.windll.user32.TranslateMessage
TranslateMessage.restype = ctypes.wintypes.ULONG
TranslateMessage.argtypes = [ctypes.POINTER(MSG)]
DispatchMessage = ctypes.windll.user32.DispatchMessageW
DispatchMessage.restype = ctypes.wintypes.ULONG
DispatchMessage.argtypes = [ctypes.POINTER(MSG)]
def LoadIcon(iconfilename, small=False):
return LoadImage(0,
unicode(iconfilename),
IMAGE_ICON,
16 if small else 0,
16 if small else 0,
LR_LOADFROMFILE)
class NotificationIcon(object):
def __init__(self, iconfilename, tooltip=None):
assert os.path.isfile(unicode(iconfilename)), "{} doesn't exist".format(iconfilename)
self._iconfile = unicode(iconfilename)
self._hicon = LoadIcon(self._iconfile, True)
assert self._hicon, "Failed to load {}".format(iconfilename)
#self._pumpqueue = Queue.Queue()
self._die = False
self._timerid = None
self._uid = uuid.uuid4()
self._tooltip = unicode(tooltip) if tooltip else u''
#self._thread = threading.Thread(target=self._run)
#self._thread.start()
self._info_bubble = None
self.items = []
def _bubble(self, iconinfo):
if self._info_bubble:
info_bubble = self._info_bubble
self._info_bubble = None
message = unicode(self._info_bubble)
iconinfo.uFlags |= NIF_INFO
iconinfo.szInfo = message
iconinfo.szInfoTitle = message
iconinfo.dwInfoFlags = NIIF_INFO
iconinfo.union.uTimeout = 10000
Shell_NotifyIcon(NIM_MODIFY, ctypes.pointer(iconinfo))
def _run(self):
self._windowproc = WNDPROC(self._callback)
self._hwnd = GenerateDummyWindow(self._windowproc, str(self._uid))
iconinfo = NOTIFYICONDATA()
iconinfo.hWnd = self._hwnd
iconinfo.uID = 100
iconinfo.uFlags = NIF_ICON | NIF_SHOWTIP | NIF_MESSAGE | (NIF_TIP if self._tooltip else 0)
iconinfo.uCallbackMessage = WM_MENUCOMMAND
iconinfo.hIcon = self._hicon
iconinfo.szTip = self._tooltip
iconinfo.dwState = NIS_SHAREDICON
iconinfo.dwInfoFlags = NIIF_INFO
# iconinfo.dwStateMask = NIS_SHAREDICON
iconinfo.szInfo = "Application Title"
iconinfo.union.uTimeout = 5000
Shell_NotifyIcon(NIM_ADD, ctypes.pointer(iconinfo))
iconinfo.union.uVersion = NOTIFYICON_VERSION
self.iconinfo = iconinfo
Shell_NotifyIcon(NIM_SETVERSION, ctypes.pointer(iconinfo))
PostMessage(self._hwnd, WM_NULL, 0, 0)
#self._timerid = SetTimer(self._hwnd, self._timerid, 25, TIMERCALLBACK())
message = MSG()
last_time = -1
ret = None
while not self._die:
ret = GetMessage(ctypes.pointer(message), 0, 0, 0)
TranslateMessage(ctypes.pointer(message))
DispatchMessage(ctypes.pointer(message))
time.sleep(0.125)
#KillTimer(self._hwnd, self._timerid)
Shell_NotifyIcon(NIM_DELETE, ctypes.pointer(iconinfo))
ctypes.windll.user32.DestroyWindow(self._hwnd)
ctypes.windll.user32.DestroyIcon(self._hicon)
def _menu(self):
if not hasattr(self, 'items'):
return
menu = CreatePopupMenu()
func = None
try:
iidx = 1000
defaultitem = -1
item_map = {}
for fs in self.items:
iidx += 1
if isinstance(fs, basestring):
if fs and not fs.strip('-_='):
AppendMenu(menu, MF_SEPARATOR, iidx, fs)
else:
AppendMenu(menu, MF_STRING | MF_GRAYED, iidx, fs)
elif isinstance(fs, tuple):
if callable(fs[0]):
itemstring = fs[0]()
else:
itemstring = unicode(fs[0])
flags = MF_STRING
if itemstring.startswith("!"):
itemstring = itemstring[1:]
defaultitem = iidx
if itemstring.startswith("+"):
itemstring = itemstring[1:]
flags = flags | MF_CHECKED
itemcallable = fs[1]
item_map[iidx] = itemcallable
if itemcallable is False:
flags = flags | MF_DISABLED
elif not callable(itemcallable):
flags = flags | MF_GRAYED
AppendMenu(menu, flags, iidx, itemstring)
if defaultitem != -1:
SetMenuDefaultItem(menu, defaultitem, 0)
pos = POINT()
GetCursorPos(ctypes.pointer(pos))
PostMessage(self._hwnd, WM_NULL, 0, 0)
SetForegroundWindow(self._hwnd)
ti = TrackPopupMenu(menu, TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, pos.x, pos.y, 0, self._hwnd, None)
if ti in item_map:
func = item_map[ti]
PostMessage(self._hwnd, WM_NULL, 0, 0)
finally:
DestroyMenu(menu)
if func: func()
def clicked(self):
self._menu()
def _callback(self, hWnd, msg, wParam, lParam):
# Check if the main thread is still alive
if msg == WM_TIMER:
if not any(thread.getName() == 'MainThread' and thread.isAlive()
for thread in threading.enumerate()):
self._die = True
elif msg == WM_MENUCOMMAND and lParam == WM_LBUTTONUP:
self.clicked()
elif msg == WM_MENUCOMMAND and lParam == WM_RBUTTONUP:
self._menu()
else:
return DefWindowProc(hWnd, msg, wParam, lParam)
return 1
def die(self):
try:
Shell_NotifyIcon(NIM_DELETE, ctypes.pointer(self.iconinfo))
except:
pass
ctypes.windll.user32.DestroyWindow(self._hwnd)
ctypes.windll.user32.DestroyIcon(self._hicon)
self._die = True
def pump(self):
try:
while not self._pumpqueue.empty():
callable = self._pumpqueue.get(False)
callable()
except Queue.Empty:
pass
def announce(self, text):
self._info_bubble = text
def hideConsole():
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
def showConsole():
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 1)
if __name__ == "__main__":
import time
def greet():
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
print "Hello"
def quit():
ni._die = True
#sys.exit()
def announce():
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 1)
ni.announce("Hello there")
def clicked():
ni.announce("Hello")
def dynamicTitle():
return "!The time is: %s" % time.time()
ni = NotificationIcon(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../trayicon.ico'), "ZeroNet 0.2.9")
ni.items = [
(dynamicTitle, False),
('Hello', greet),
('Title', False),
('!Default', greet),
('+Popup bubble', announce),
'Nothing',
'--',
('Quit', quit)
]
ni.clicked = clicked
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
ni._run()

View File

@ -0,0 +1,48 @@
''' Get windows special folders without pythonwin
Example:
import specialfolders
start_programs = specialfolders.get(specialfolders.PROGRAMS)
Code is public domain, do with it what you will.
Luke Pinner - Environment.gov.au, 2010 February 10
'''
#Imports use _syntax to mask them from autocomplete IDE's
import ctypes as _ctypes
from ctypes.wintypes import HWND as _HWND, HANDLE as _HANDLE,DWORD as _DWORD,LPCWSTR as _LPCWSTR,MAX_PATH as _MAX_PATH, create_unicode_buffer as _cub
_SHGetFolderPath = _ctypes.windll.shell32.SHGetFolderPathW
#public special folder constants
DESKTOP= 0
PROGRAMS= 2
MYDOCUMENTS= 5
FAVORITES= 6
STARTUP= 7
RECENT= 8
SENDTO= 9
STARTMENU= 11
MYMUSIC= 13
MYVIDEOS= 14
NETHOOD= 19
FONTS= 20
TEMPLATES= 21
ALLUSERSSTARTMENU= 22
ALLUSERSPROGRAMS= 23
ALLUSERSSTARTUP= 24
ALLUSERSDESKTOP= 25
APPLICATIONDATA= 26
PRINTHOOD= 27
LOCALSETTINGSAPPLICATIONDATA= 28
ALLUSERSFAVORITES= 31
LOCALSETTINGSTEMPORARYINTERNETFILES=32
COOKIES= 33
LOCALSETTINGSHISTORY= 34
ALLUSERSAPPLICATIONDATA= 35
def get(intFolder):
_SHGetFolderPath.argtypes = [_HWND, _ctypes.c_int, _HANDLE, _DWORD, _LPCWSTR]
auPathBuffer = _cub(_MAX_PATH)
exit_code=_SHGetFolderPath(0, intFolder, 0, 0, auPathBuffer)
return auPathBuffer.value

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -162,6 +162,7 @@ class Connection:
self.last_recv_time = time.time()
self.incomplete_buff_recv += 1
self.bytes_recv += len(buff)
self.server.bytes_recv += len(buff)
if not self.unpacker:
self.unpacker = msgpack.Unpacker()
self.unpacker.feed(buff)
@ -198,13 +199,19 @@ class Connection:
if config.debug_socket: self.log("Got handshake response: %s, ping: %s" % (message, ping))
self.last_ping_delay = ping
self.handshake = message
self.port = message["fileserver_port"] # Set peer fileserver port
if self.handshake.get("port_opened", None) == False: # Not connectable
self.port = 0
else:
self.port = message["fileserver_port"] # Set peer fileserver port
else:
self.log("Unknown response: %s" % message)
elif message.get("cmd"): # Handhsake request
if message["cmd"] == "handshake":
self.handshake = message["params"]
self.port = self.handshake["fileserver_port"] # Set peer fileserver port
if self.handshake.get("port_opened", None) == False: # Not connectable
self.port = 0
else:
self.port = self.handshake["fileserver_port"] # Set peer fileserver port
if config.debug_socket: self.log("Handshake request: %s" % message)
data = self.handshakeInfo()
data["cmd"] = "response"
@ -242,6 +249,7 @@ class Connection:
else: # Normal connection
data = msgpack.packb(message)
self.bytes_sent += len(data)
self.server.bytes_sent += len(data)
self.sock.sendall(data)
self.last_sent_time = time.time()
return True

View File

@ -22,6 +22,9 @@ class ConnectionServer:
self.running = True
self.thread_checker = gevent.spawn(self.checkConnections)
self.bytes_recv = 0
self.bytes_sent = 0
self.zmq_running = False
self.zmq_last_connection = None # Last incoming message client
@ -82,6 +85,8 @@ class ConnectionServer:
return connection
# No connection found
if port == 0:
raise Exception("This peer is not connectable")
try:
connection = Connection(self, ip, port)
self.ips[ip] = connection

View File

@ -131,10 +131,10 @@ class FileRequest:
address = self.unpackAddress(peer)
got_peer_keys.append("%s:%s" % address)
if (site.addPeer(*address)): added += 1
# Send back peers that is not in the sent list
# Send back peers that is not in the sent list and connectable (not port 0)
peers = site.peers.values()
random.shuffle(peers)
packed_peers = [peer.packAddress() for peer in peers if peer.key not in got_peer_keys][0:params["need"]]
packed_peers = [peer.packAddress() for peer in peers if not peer.key.endswith(":0") and peer.key not in got_peer_keys][0:params["need"]]
if added:
self.log.debug("Added %s peers to %s using pex, sending back %s" % (added, site, len(packed_peers)))
self.response({"peers": packed_peers})

View File

@ -150,7 +150,7 @@ class Peer:
if not site: site = self.site # If no site definied request peers for this site
peers = self.site.peers.values()
random.shuffle(peers)
packed_peers = [peer.packAddress() for peer in peers][0:need_num]
packed_peers = [peer.packAddress() for peer in peers if not peer.key.endswith(":0")][0:need_num]
response = self.request("pex", {"site": site.address, "peers": packed_peers, "need": need_num})
if not response or "error" in response:
return False

View File

@ -319,11 +319,10 @@ class Site:
address_hash = hashlib.sha1(self.address).hexdigest()
my_peer_id = sys.modules["main"].file_server.peer_id
# Later, if we have peer exchange
"""if sys.modules["main"].file_server.port_opened:
if sys.modules["main"].file_server.port_opened:
fileserver_port = config.fileserver_port
else: # Port not opened, report port 0
fileserver_port = 0"""
fileserver_port = 0
fileserver_port = config.fileserver_port
s = time.time()

View File

@ -112,9 +112,11 @@ class UiServer:
def stop(self):
self.log.debug("Stopping...")
# Close WS sockets
for client in self.server.clients.values():
client.ws.close()
if "clients" in dir(self.server):
for client in self.server.clients.values():
client.ws.close()
# Close http sockets
sock_closed = 0
for sock in self.server.sockets.values():

View File

@ -35,11 +35,10 @@ logging.getLogger('').name = "-" # Remove root prefix
from Debug import DebugHook
if config.debug:
console_log.setLevel(logging.DEBUG) # Display everything to console
from gevent import monkey; monkey.patch_all(thread=False) # thread=False because of pyfilesystem
else:
console_log.setLevel(logging.INFO) # Display only important info to console
from gevent import monkey; monkey.patch_all() # Make time, thread, socket gevent compatible
from gevent import monkey; monkey.patch_all(thread=False) # Make time, socket gevent compatible
import gevent
import time
@ -64,195 +63,196 @@ PluginManager.plugin_manager.loadPlugins()
# -- Actions --
@PluginManager.acceptPlugins
class Actions:
# Default action: Start serving UiServer and FileServer
def main(self):
logging.info("Version: %s, Python %s, Gevent: %s" % (config.version, sys.version, gevent.__version__))
global ui_server, file_server
from File import FileServer
from Ui import UiServer
logging.info("Creating UiServer....")
ui_server = UiServer()
logging.info("Creating FileServer....")
file_server = FileServer()
logging.info("Starting servers....")
gevent.joinall([gevent.spawn(ui_server.start), gevent.spawn(file_server.start)])
# Site commands
def siteCreate(self):
logging.info("Generating new privatekey...")
from Crypt import CryptBitcoin
privatekey = CryptBitcoin.newPrivatekey()
logging.info("----------------------------------------------------------------------")
logging.info("Site private key: %s" % privatekey)
logging.info(" !!! ^ Save it now, required to modify the site ^ !!!")
address = CryptBitcoin.privatekeyToAddress(privatekey)
logging.info("Site address: %s" % address)
logging.info("----------------------------------------------------------------------")
while True:
if raw_input("? Have you secured your private key? (yes, no) > ").lower() == "yes": break
else: logging.info("Please, secure it now, you going to need it to modify your site!")
logging.info("Creating directory structure...")
from Site import Site
os.mkdir("data/%s" % address)
open("data/%s/index.html" % address, "w").write("Hello %s!" % address)
logging.info("Creating content.json...")
site = Site(address)
site.content_manager.sign(privatekey=privatekey)
site.settings["own"] = True
site.saveSettings()
logging.info("Site created!")
def siteSign(self, address, privatekey=None, inner_path="content.json"):
from Site import Site
logging.info("Signing site: %s..." % address)
site = Site(address, allow_create = False)
if not privatekey: # If no privatekey in args then ask it now
import getpass
privatekey = getpass.getpass("Private key (input hidden):")
site.content_manager.sign(inner_path=inner_path, privatekey=privatekey, update_changed_files=True)
def siteVerify(self, address):
from Site import Site
logging.info("Verifing site: %s..." % address)
site = Site(address)
for content_inner_path in site.content_manager.contents:
logging.info("Verifing %s signature..." % content_inner_path)
if site.content_manager.verifyFile(content_inner_path, site.storage.open(content_inner_path, "rb"), ignore_same=False) == True:
logging.info("[OK] %s signed by address %s!" % (content_inner_path, address))
else:
logging.error("[ERROR] %s not signed by address %s!" % (content_inner_path, address))
logging.info("Verifying site files...")
bad_files = site.storage.verifyFiles()
if not bad_files:
logging.info("[OK] All file sha512sum matches!")
else:
logging.error("[ERROR] Error during verifying site files!")
def dbRebuild(self, address):
from Site import Site
logging.info("Rebuilding site sql cache: %s..." % address)
site = Site(address)
s = time.time()
site.storage.rebuildDb()
logging.info("Done in %.3fs" % (time.time()-s))
def dbQuery(self, address, query):
from Site import Site
import json
site = Site(address)
result = []
for row in site.storage.query(query):
result.append(dict(row))
print json.dumps(result, indent=4)
def siteAnnounce(self, address):
from Site.Site import Site
logging.info("Announcing site %s to tracker..." % address)
site = Site(address)
s = time.time()
site.announce()
print "Response time: %.3fs" % (time.time()-s)
print site.peers
def siteNeedFile(self, address, inner_path):
from Site import Site
site = Site(address)
site.announce()
print site.needFile(inner_path, update=True)
def sitePublish(self, address, peer_ip=None, peer_port=15441, inner_path="content.json"):
global file_server
from Site import Site
from File import FileServer # We need fileserver to handle incoming file requests
logging.info("Creating FileServer....")
file_server = FileServer()
file_server_thread = gevent.spawn(file_server.start, check_sites=False) # Dont check every site integrity
file_server.openport()
if file_server.port_opened == False:
logging.info("Port not opened, passive publishing not supported yet :(")
return
site = file_server.sites[address]
site.settings["serving"] = True # Serving the site even if its disabled
if peer_ip: # Announce ip specificed
site.addPeer(peer_ip, peer_port)
else: # Just ask the tracker
logging.info("Gathering peers from tracker")
site.announce() # Gather peers
site.publish(20, inner_path) # Push to 20 peers
time.sleep(3)
logging.info("Serving files...")
gevent.joinall([file_server_thread])
logging.info("Done.")
# Crypto commands
def cryptoPrivatekeyToAddress(self, privatekey=None):
from Crypt import CryptBitcoin
if not privatekey: # If no privatekey in args then ask it now
import getpass
privatekey = getpass.getpass("Private key (input hidden):")
print CryptBitcoin.privatekeyToAddress(privatekey)
# Peer
def peerPing(self, peer_ip, peer_port):
logging.info("Opening a simple connection server")
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer("127.0.0.1", 1234)
from Peer import Peer
logging.info("Pinging 5 times peer: %s:%s..." % (peer_ip, int(peer_port)))
peer = Peer(peer_ip, peer_port)
for i in range(5):
s = time.time()
print peer.ping(),
print "Response time: %.3fs" % (time.time()-s)
time.sleep(1)
def peerGetFile(self, peer_ip, peer_port, site, filename):
logging.info("Opening a simple connection server")
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer()
from Peer import Peer
logging.info("Getting %s/%s from peer: %s:%s..." % (site, filename, peer_ip, peer_port))
peer = Peer(peer_ip, peer_port)
s = time.time()
print peer.getFile(site, filename).read()
print "Response time: %.3fs" % (time.time()-s)
actions = Actions()
# Starts here when running zeronet.py
def start():
action_func = globals()[config.action] # Function reference
action_kwargs = config.getActionArguments() # non-config arguments when calling zeronet.py
action_func(**action_kwargs)
# Start serving UiServer and PeerServer
def main():
logging.info("Version: %s, Python %s, Gevent: %s" % (config.version, sys.version, gevent.__version__))
global ui_server, file_server
from File import FileServer
from Ui import UiServer
logging.info("Creating UiServer....")
ui_server = UiServer()
logging.info("Creating FileServer....")
file_server = FileServer()
logging.info("Starting servers....")
gevent.joinall([gevent.spawn(ui_server.start), gevent.spawn(file_server.start)])
# Site commands
def siteCreate():
logging.info("Generating new privatekey...")
from Crypt import CryptBitcoin
privatekey = CryptBitcoin.newPrivatekey()
logging.info("----------------------------------------------------------------------")
logging.info("Site private key: %s" % privatekey)
logging.info(" !!! ^ Save it now, required to modify the site ^ !!!")
address = CryptBitcoin.privatekeyToAddress(privatekey)
logging.info("Site address: %s" % address)
logging.info("----------------------------------------------------------------------")
while True:
if raw_input("? Have you secured your private key? (yes, no) > ").lower() == "yes": break
else: logging.info("Please, secure it now, you going to need it to modify your site!")
logging.info("Creating directory structure...")
from Site import Site
os.mkdir("data/%s" % address)
open("data/%s/index.html" % address, "w").write("Hello %s!" % address)
logging.info("Creating content.json...")
site = Site(address)
site.content_manager.sign(privatekey=privatekey)
site.settings["own"] = True
site.saveSettings()
logging.info("Site created!")
def siteSign(address, privatekey=None, inner_path="content.json"):
from Site import Site
logging.info("Signing site: %s..." % address)
site = Site(address, allow_create = False)
if not privatekey: # If no privatekey in args then ask it now
import getpass
privatekey = getpass.getpass("Private key (input hidden):")
site.content_manager.sign(inner_path=inner_path, privatekey=privatekey, update_changed_files=True)
def siteVerify(address):
from Site import Site
logging.info("Verifing site: %s..." % address)
site = Site(address)
for content_inner_path in site.content_manager.contents:
logging.info("Verifing %s signature..." % content_inner_path)
if site.content_manager.verifyFile(content_inner_path, site.storage.open(content_inner_path, "rb"), ignore_same=False) == True:
logging.info("[OK] %s signed by address %s!" % (content_inner_path, address))
else:
logging.error("[ERROR] %s not signed by address %s!" % (content_inner_path, address))
logging.info("Verifying site files...")
bad_files = site.storage.verifyFiles()
if not bad_files:
logging.info("[OK] All file sha512sum matches!")
else:
logging.error("[ERROR] Error during verifying site files!")
def dbRebuild(address):
from Site import Site
logging.info("Rebuilding site sql cache: %s..." % address)
site = Site(address)
s = time.time()
site.storage.rebuildDb()
logging.info("Done in %.3fs" % (time.time()-s))
def dbQuery(address, query):
from Site import Site
import json
site = Site(address)
result = []
for row in site.storage.query(query):
result.append(dict(row))
print json.dumps(result, indent=4)
def siteAnnounce(address):
from Site.Site import Site
logging.info("Announcing site %s to tracker..." % address)
site = Site(address)
s = time.time()
site.announce()
print "Response time: %.3fs" % (time.time()-s)
print site.peers
def siteNeedFile(address, inner_path):
from Site import Site
site = Site(address)
site.announce()
print site.needFile(inner_path, update=True)
def sitePublish(address, peer_ip=None, peer_port=15441, inner_path="content.json"):
global file_server
from Site import Site
from File import FileServer # We need fileserver to handle incoming file requests
logging.info("Creating FileServer....")
file_server = FileServer()
file_server_thread = gevent.spawn(file_server.start, check_sites=False) # Dont check every site integrity
file_server.openport()
if file_server.port_opened == False:
logging.info("Port not opened, passive publishing not supported yet :(")
return
site = file_server.sites[address]
site.settings["serving"] = True # Serving the site even if its disabled
if peer_ip: # Announce ip specificed
site.addPeer(peer_ip, peer_port)
else: # Just ask the tracker
logging.info("Gathering peers from tracker")
site.announce() # Gather peers
site.publish(20, inner_path) # Push to 20 peers
time.sleep(3)
logging.info("Serving files...")
gevent.joinall([file_server_thread])
logging.info("Done.")
# Crypto commands
def cryptoPrivatekeyToAddress(privatekey=None):
from Crypt import CryptBitcoin
if not privatekey: # If no privatekey in args then ask it now
import getpass
privatekey = getpass.getpass("Private key (input hidden):")
print CryptBitcoin.privatekeyToAddress(privatekey)
# Peer
def peerPing(peer_ip, peer_port):
logging.info("Opening a simple connection server")
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer("127.0.0.1", 1234)
from Peer import Peer
logging.info("Pinging 5 times peer: %s:%s..." % (peer_ip, int(peer_port)))
peer = Peer(peer_ip, peer_port)
for i in range(5):
s = time.time()
print peer.ping(),
print "Response time: %.3fs" % (time.time()-s)
time.sleep(1)
def peerGetFile(peer_ip, peer_port, site, filename):
logging.info("Opening a simple connection server")
global file_server
from Connection import ConnectionServer
file_server = ConnectionServer()
from Peer import Peer
logging.info("Getting %s/%s from peer: %s:%s..." % (site, filename, peer_ip, peer_port))
peer = Peer(peer_ip, peer_port)
s = time.time()
print peer.getFile(site, filename).read()
print "Response time: %.3fs" % (time.time()-s)
# Call function
func = getattr(actions, config.action, None)
action_kwargs = config.getActionArguments()
func(**action_kwargs)