|
0
|
1 |
#!/usr/bin/python3
|
|
|
2 |
# coding=utf8
|
|
|
3 |
|
|
|
4 |
import os, argparse, subprocess, socket
|
|
|
5 |
|
|
|
6 |
class Parms():
|
|
|
7 |
|
|
|
8 |
positiv = ('1', 'Y', 'YES', 'ON')
|
|
|
9 |
negativ = ('0', 'N', 'NO', 'OFF')
|
|
|
10 |
|
|
|
11 |
@classmethod
|
|
|
12 |
def setup(cls):
|
|
|
13 |
cls.applName = "dejsem"
|
|
|
14 |
cls.version = 1.00
|
|
|
15 |
|
|
|
16 |
cls.defaultsFile = os.path.join("/etc/default", cls.applName)
|
|
|
17 |
cls.parsedflts()
|
|
|
18 |
cls.parsecmdl()
|
|
|
19 |
|
|
|
20 |
cls.clientMode = False # řídí chování při ABENDu: client po ABENDu sys.exit(), server pokračuje
|
|
|
21 |
|
|
|
22 |
cls.debugLevel = cls.cmdl("debugLevel", int(cls.env("DEB", cls.dflt("DEB", 0))))
|
|
|
23 |
cls.random_seed= int(cls.env('RS', 0))
|
|
|
24 |
|
|
|
25 |
cls.action = cls.cmdl("action", cls.env("ACT", "")).upper()
|
|
|
26 |
cls.clientMode = cls.action != "SRV"
|
|
|
27 |
|
|
|
28 |
cls.ssl = True
|
|
|
29 |
|
|
|
30 |
cls.sslchannel = int(cls.cmdl("sslchannel", cls.env("CHAN", cls.dflt("CHAN", 2))))
|
|
|
31 |
cls.sslPath = cls.cmdl("sslPath", cls.env("SSLP", cls.dflt("SSLP", os.path.join("/usr/share", cls.applName, "ssl"))))
|
|
|
32 |
cls.sslCAPath = os.path.join(cls.sslPath, "dejCA.crt")
|
|
|
33 |
cls.sslCert = os.path.join(cls.sslPath, "{:02d}.pem".format(cls.sslchannel))
|
|
|
34 |
|
|
|
35 |
cls.srvhost = cls.cmdl("srvhost", cls.env("HOST", cls.dflt("HOST", "dejsem.org")))
|
|
|
36 |
cls.filedir = "files"
|
|
|
37 |
cls.exposed = ".exposed_to_http"
|
|
|
38 |
cls.clipfile = "clipboard"
|
|
|
39 |
cls.histdir = "history" # cliboard history dir
|
|
|
40 |
cls.srv_wwwhomedir = os.path.join("/var/www/html", cls.applName)
|
|
|
41 |
cls.srv_homedir = os.path.join("/usr/local/", cls.applName)
|
|
|
42 |
cls.client_homedir = cls.env("HOME", os.path.join("/home", "{}".format(os.getlogin)))
|
|
|
43 |
cls.client_appldir = os.path.join(cls.client_homedir, ".local/share", cls.applName)
|
|
|
44 |
cls.client_histdir = os.path.join(cls.client_appldir, cls.histdir)
|
|
|
45 |
|
|
|
46 |
cls.bindhost = cls.env("BINDHOST", cls.dflt("BINDHOST", cls.getbindhost()))
|
|
|
47 |
# cls.bindhost = cls.env("BINDHOST", "")
|
|
|
48 |
# cls.broadcast = cls.env("BROADCAST", cls.getbroadcast(cls.bindhost))
|
|
|
49 |
cls.broadcast = cls.env("BROADCAST", "255.255.255.255")
|
|
|
50 |
cls.baseport = int(cls.env("BASEPORT", cls.dflt("BASEPORT", 42000)))
|
|
|
51 |
cls.udpport = 4242 if cls.applName == "dejsem" else 4224
|
|
|
52 |
cls.pullPeerIface = None
|
|
|
53 |
|
|
|
54 |
cls.bufSize = 256 * 1024
|
|
|
55 |
cls.connThreshold = 77
|
|
|
56 |
cls.connTimeout = 0.01
|
|
|
57 |
cls.blockTimeout = 20
|
|
|
58 |
cls.accept_timeout = 60 # seconds
|
|
|
59 |
cls.long_run_accept_timeout = 60 # seconds
|
|
|
60 |
cls.peer_accept_timeout = 60 # seconds
|
|
|
61 |
|
|
|
62 |
cls.datapaths = cls.args["datapaths"] # data paths from cmdline
|
|
|
63 |
cls.orig = cls.cmdl("datapaths", list(cls.env("ORIG", ""))) # origin data path
|
|
|
64 |
cls.dest = cls.env("DEST", "") # destination data path from ENV
|
|
|
65 |
|
|
|
66 |
@classmethod
|
|
|
67 |
def parsecmdl(cls):
|
|
|
68 |
parser = argparse.ArgumentParser(description='sdílení clipboardu a filů přes server, přenos filů peer-to-peer')
|
|
|
69 |
cmds = parser.add_mutually_exclusive_group()
|
|
|
70 |
cmds.add_argument('--push', dest='action',
|
|
|
71 |
action='store_const', const='PUSHCLIP',
|
|
|
72 |
help='copy from local clipboard to shared clipboard')
|
|
|
73 |
cmds.add_argument('--pull', dest='action',
|
|
|
74 |
action='store_const', const='PULLCLIP',
|
|
|
75 |
help='copy from shared clipboard to local clipboard')
|
|
|
76 |
cmds.add_argument('--pullhist', dest='action',
|
|
|
77 |
action='store_const', const='PULLHIST',
|
|
|
78 |
help='synchronize local clipboard history from shared clipboard')
|
|
|
79 |
cmds.add_argument('--pushsrv', '--pushfile', '--puf', dest='action',
|
|
|
80 |
action='store_const', const='PUSHFILE',
|
|
|
81 |
help='copy local file to server')
|
|
|
82 |
cmds.add_argument('--pullsrv', '--pullfile', '--plf', dest='action',
|
|
|
83 |
action='store_const', const='PULLFILE',
|
|
|
84 |
help='copy server file to local')
|
|
|
85 |
cmds.add_argument('--pulllist', dest='action',
|
|
|
86 |
action='store_const', const='PULLLIST',
|
|
|
87 |
help='list files on server')
|
|
|
88 |
cmds.add_argument('--pushpeer', '--pup', dest='action',
|
|
|
89 |
action='store_const', const='PUSHPEER',
|
|
|
90 |
help='copy from local file to LAN peer')
|
|
|
91 |
cmds.add_argument('--pullpeer', '--plp', dest='action',
|
|
|
92 |
action='store_const', const='PULLPEER',
|
|
|
93 |
help='copy from LAN peer to local dir')
|
|
|
94 |
options = parser.add_argument_group(title='options')
|
|
|
95 |
options.add_argument('-d', dest='debugLevel', type=int,
|
|
|
96 |
metavar='<debug level>', help='debug level 0-5, ENV DEB')
|
|
|
97 |
options.add_argument('-s', dest='srvhost',
|
|
|
98 |
metavar='<srvhost>', help='server domain name or ip, ENV HOST')
|
|
|
99 |
options.add_argument('-c', dest='sslchannel', type=int,
|
|
|
100 |
metavar='<channel#>', help='ssl channel NN, ENV CHAN')
|
|
|
101 |
options.add_argument('-x', dest='sslPath',
|
|
|
102 |
metavar='<sslhome>', help='ssl keys store directory, ENV SSL')
|
|
|
103 |
options.add_argument('-i', dest='pullPeerIface',
|
|
|
104 |
metavar='<iface>', help='copy from LAN peer via <iface>')
|
|
|
105 |
parser.add_argument('datapaths', nargs='*', metavar='datapath')
|
|
|
106 |
cls.args = vars(parser.parse_args())
|
|
|
107 |
|
|
|
108 |
@classmethod
|
|
|
109 |
def parsedflts(cls):
|
|
|
110 |
cls.defaults = dict()
|
|
|
111 |
with open(cls.defaultsFile) as df:
|
|
|
112 |
for line in df:
|
|
|
113 |
key, value = line.split('=')
|
|
|
114 |
cls.defaults[key] = value[:-1]
|
|
|
115 |
|
|
|
116 |
@classmethod
|
|
|
117 |
def dflt(cls, key, wired):
|
|
|
118 |
return cls.defaults[key] if key in cls.defaults else wired
|
|
|
119 |
|
|
|
120 |
@classmethod
|
|
|
121 |
def env(cls, key, default):
|
|
|
122 |
return os.environ[key] if key in os.environ else default
|
|
|
123 |
|
|
|
124 |
@classmethod
|
|
|
125 |
def cmdl(cls, arg, default):
|
|
|
126 |
return cls.args[arg] if (arg in cls.args and cls.args[arg]) else default
|
|
|
127 |
|
|
|
128 |
@classmethod
|
|
|
129 |
def getbindhost(cls):
|
|
|
130 |
return socket.getfqdn()
|
|
|
131 |
|
|
|
132 |
"""
|
|
|
133 |
p = subprocess.Popen(["host", "-t", "A", socket.gethostname()], stdout=subprocess.PIPE)
|
|
|
134 |
p.wait()
|
|
|
135 |
if p.returncode == 0:
|
|
|
136 |
return p.stdout.readlines()[0].decode().split()[3]
|
|
|
137 |
else:
|
|
|
138 |
return ''
|
|
|
139 |
"""
|
|
|
140 |
|
|
|
141 |
@classmethod
|
|
|
142 |
def getbroadcast(cls, bindhost):
|
|
|
143 |
return '255.255.255.255'
|
|
|
144 |
|
|
|
145 |
"""zatím mimo použití, je to hodně nejasné
|
|
|
146 |
p = subprocess.Popen(("ip", "-o", "addr", "list"), stdout=subprocess.PIPE)
|
|
|
147 |
p.wait()
|
|
|
148 |
if p.returncode == 0:
|
|
|
149 |
return subprocess.check_output(("grep", bindhost), stdin=p.stdout).decode().split()[5]
|
|
|
150 |
else:
|
|
|
151 |
return '255.255.255.255'
|
|
|
152 |
"""
|
|
|
153 |
|
|
|
154 |
|