webXMPP

Check-in [a93fd62e0f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add whitelist support, while generalising and keeping blacklist support too.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:a93fd62e0fbc718675afbc78636450856917e2ca179fda592cd5a1b42391fbe0
User & Date: web 2019-04-12 23:12:00
Context
2019-04-28
18:47
Add MMS support check-in: df0f18ff49 user: web tags: master, trunk
2019-04-12
23:12
Add whitelist support, while generalising and keeping blacklist support too. check-in: a93fd62e0f user: web tags: master, trunk
23:11
Set font size; especially good for FxOS which ended up with some bad defaults. check-in: feade2b803 user: web tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.py.

81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
...
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174


175

















176
177
178
179
180
181
182
	c.ints.add( (f,) )
    for f in ("pollslop",):
	c.floats.add( (f,) )

    # Messaging key from Google for Firebase Cloud Messaging
    c.onearg.add( ("fcmkey",) )

    # Lists of SMS peers, also a blacklist
    c.noarg.add( ("sms",) )
    c.args.add( ("sms", "peers") )
    c.mults.add( ("sms", "peers") )
    c.onearg.add( ("sms", "blacklist") )


    # Multiple of these, with sub-config
    c.onearg.add( ("user",) )
    c.mults.add( ("user",) )

    # Sub-config of "user", XMPP account(s)
    c.args.add( ("user", "account") )
................................................................................
	# List of tuples; (expires-tm, call-fn, call-arg)
	self.timeouts = []

	# Possibly restrict REST SMS submission by IP
	# SMS source filters, if any
	self.smsok = []

	# List of bad phone #'s (SMS spam) and file which we
	#  refresh from on demand
	self.smsbad = []
	self.smsblack = None
	self.smsblatest = 0.0

	if "sms" in cfg:
	    subs = cfg["sms"][1]
	    for tup in subs.get("peers"):
		for a in tup:
		    self.smsok.append(chore.net.parseaddr(a))


	    self.smsblack = subs.get("blacklist")


















	# Static/local authentication config?  Can't mix with
	#  an authentication server.
	if any(("password" in acct[1]) for acct in cfg["user"]):
	    self.authentication.append(WebXMPP.auth_local)
	else:
	    # Account server to get logged in & get cookie







|




>







 







|

|
|
|
>





>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
	c.ints.add( (f,) )
    for f in ("pollslop",):
	c.floats.add( (f,) )

    # Messaging key from Google for Firebase Cloud Messaging
    c.onearg.add( ("fcmkey",) )

    # Lists of SMS peers, also a blacklist/whitelist
    c.noarg.add( ("sms",) )
    c.args.add( ("sms", "peers") )
    c.mults.add( ("sms", "peers") )
    c.onearg.add( ("sms", "blacklist") )
    c.onearg.add( ("sms", "whitelist") )

    # Multiple of these, with sub-config
    c.onearg.add( ("user",) )
    c.mults.add( ("user",) )

    # Sub-config of "user", XMPP account(s)
    c.args.add( ("user", "account") )
................................................................................
	# List of tuples; (expires-tm, call-fn, call-arg)
	self.timeouts = []

	# Possibly restrict REST SMS submission by IP
	# SMS source filters, if any
	self.smsok = []

	# List of good/bad phone #'s (SMS spam) and file which we
	#  refresh from on demand
	self.smslnums = []
	self.smsisblack = None
	self.smslfn = None
	self.smsllatest = None
	if "sms" in cfg:
	    subs = cfg["sms"][1]
	    for tup in subs.get("peers"):
		for a in tup:
		    self.smsok.append(chore.net.parseaddr(a))

	    # Black/white list
	    smsblist = subs.get("blacklist")
	    smswlist = subs.get("whitelist")
	    if smsblist or smswlist:
		if smsblist and smswlist:
		    raise Exception, "Can't have both SMS whitelist and blacklist"

		# The numbers on the list
		self.smslnums = []

		# What kind?  Blacklist (else whitelist)
		self.smsisblack = smsblist

		# Filename
		self.smslfn = smsblist or smswlist

		# Timestamp, to tell us when to reload it because
		#  somebody edited it
		self.smsllatest = 0.0

	# Static/local authentication config?  Can't mix with
	#  an authentication server.
	if any(("password" in acct[1]) for acct in cfg["user"]):
	    self.authentication.append(WebXMPP.auth_local)
	else:
	    # Account server to get logged in & get cookie

Changes to post.py.

19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52



53

54
55




56
57
58
59
60
61
62
..
73
74
75
76
77
78
79

80
81
82
83
84
85
86
	self.dispatchers.append( ("POST", self.post_sms) )
	self.dispatchers.append( ("POST", self.post_mast) )

    # Does SMS blacklisting apply to this message?
    def filtered(self, msg):
	approot = self.server.approot

	# No blacklist
	if approot.smsblack is None:
	    return False

	# Refresh?

	try:
	    st = os.stat(approot.smsblack)
	except:
	    sys.stderr.write("SMS blacklist %s missing\n" %
		(approot.smsblack,))
	    return False
	if st.st_mtime > approot.smsblatest:
	    sys.stderr.write("Reload SMS blacklist\n")
	    approot.smsbad = []
	    f = open(approot.smsblack, "r")
	    for l in f:
		l = l.strip()
		if not l:
		    continue
		approot.smsbad.append(l)
	    f.close()
	    sys.stderr.write(" %d entries\n" % (len(approot.smsbad),))
	    approot.smsblatest = st.st_mtime

	# See if any blacklist pattern is found within sender
	mf = msg.get("from", "")

	res = any( (a in mf) for a in approot.smsbad )



	if res:

	    sys.stderr.write("SMS blacklist %s\n" % (mf,))
	return res





    # An SMS has arrived for us
    def post_sms(self, buf):
	# /sms.json
	if not self.path_match("sms.json"):
	    return False,None

................................................................................

	# Decode message payload
	msg = json.loads(buf)
	sys.stderr.write(" JSON result %s\n" % (msg,))

	# Pre-filter
	if self.filtered(msg):

	    return True,self.send_result("", "text/html")

	# Hand it off
	acct_sms.incoming(msg)

	# If we error, they just re-deliver more times, so always
	#  accept it, even if we have to log an issue with handling it.







|
|



>

|

|
|

|
|
|
|




|

|
|

|

>
|
>
>
>
|
>
|
<
>
>
>
>







 







>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	self.dispatchers.append( ("POST", self.post_sms) )
	self.dispatchers.append( ("POST", self.post_mast) )

    # Does SMS blacklisting apply to this message?
    def filtered(self, msg):
	approot = self.server.approot

	# No list at all
	if not approot.smslfn:
	    return False

	# Refresh?
	ltype = "black" if approot.smsisblack else "white"
	try:
	    st = os.stat(approot.smslfn)
	except:
	    sys.stderr.write("SMS %slist %s missing\n" %
		(ltype, approot.smsblack))
	    return False
	if st.st_mtime > approot.smsllatest:
	    sys.stderr.write("Reload SMS %slist\n" % (ltype,))
	    approot.smslnums = []
	    f = open(approot.smslfn, "r")
	    for l in f:
		l = l.strip()
		if not l:
		    continue
		approot.smslnums.append(l)
	    f.close()
	    sys.stderr.write(" %d entries\n" % (len(approot.smslnums),))
	    approot.smsllatest = st.st_mtime

	# See if any list pattern is found within sender
	mf = msg.get("from", "")
	res = False
	for a in approot.smslnums:
	    if a in mf:
		sys.stderr.write("Match %slist %s on %s\n" %
		    (ltype, a, mf))
		res = True
		break
	sys.stderr.write("SMS %slist %s\n" % (ltype, mf))


	# So we reject on match for blacklist; we reject
	#  on non-match for whitelist
	return res if approot.smsisblack else (not res)

    # An SMS has arrived for us
    def post_sms(self, buf):
	# /sms.json
	if not self.path_match("sms.json"):
	    return False,None

................................................................................

	# Decode message payload
	msg = json.loads(buf)
	sys.stderr.write(" JSON result %s\n" % (msg,))

	# Pre-filter
	if self.filtered(msg):
	    sys.stderr.write(" filtered\n")
	    return True,self.send_result("", "text/html")

	# Hand it off
	acct_sms.incoming(msg)

	# If we error, they just re-deliver more times, so always
	#  accept it, even if we have to log an issue with handling it.