|
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 |