webXMPP

Check-in [93ec53def7]
Login

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

Overview
Comment:Blacklist in its own file, update from it on demand.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:93ec53def7bcb79717be4eb4228be79c2b485953499e0ef012d3b1f8ffdf3c44
User & Date: ajv-899-334-8894@vsta.org 2018-03-13 02:29:10
Context
2018-03-13
03:59
Support more subtleties of XMPP presence; "type" field basically means you're offline. Seem to be tracking Jane/Amri along with the n910's XMPP stack behavior. check-in: 6e2093a529 user: ajv-899-334-8894@vsta.org tags: master, trunk
02:29
Blacklist in its own file, update from it on demand. check-in: 93ec53def7 user: ajv-899-334-8894@vsta.org tags: master, trunk
2018-03-12
14:59
Fix typo. Include our own input in user history. check-in: a9af2b1f5e user: ajv-899-334-8894@vsta.org tags: master, trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to main.py.

    75     75       # Messaging key from Google for Firebase Cloud Messaging
    76     76       c.onearg.add( ("fcmkey",) )
    77     77   
    78     78       # Lists of SMS peers, also a blacklist
    79     79       c.noarg.add( ("sms",) )
    80     80       c.args.add( ("sms", "peers") )
    81     81       c.mults.add( ("sms", "peers") )
    82         -    c.args.add( ("sms", "blacklist") )
    83         -    c.mults.add( ("sms", "blacklist") )
           82  +    c.onearg.add( ("sms", "blacklist") )
    84     83   
    85     84       # Multiple of these, with sub-config
    86     85       c.onearg.add( ("user",) )
    87     86       c.mults.add( ("user",) )
    88     87   
    89     88       # Sub-config of "user", XMPP account(s)
    90     89       c.args.add( ("user", "account") )
................................................................................
   145    144   	# Our timeout service thread
   146    145   	self.timer = None
   147    146   
   148    147   	# Callbacks when time expires
   149    148   	# List of tuples; (expires-tm, call-fn, call-arg)
   150    149   	self.timeouts = []
   151    150   
          151  +	# Possibly restrict REST SMS submission by IP
   152    152   	# SMS source filters, if any
   153    153   	self.smsok = []
          154  +
          155  +	# List of bad phone #'s (SMS spam) and file which we
          156  +	#  refresh from on demand
   154    157   	self.smsbad = []
          158  +	self.smsblack = None
          159  +	self.smsblatest = 0.0
   155    160   	if "sms" in cfg:
   156         -	    for tup in cfg["sms"][1].get("peers"):
          161  +	    subs = cfg["sms"][1]
          162  +	    for tup in subs.get("peers"):
   157    163   		for a in tup:
   158    164   		    self.smsok.append(chore.net.parseaddr(a))
   159         -	    for tup in cfg["sms"][1].get("blacklist"):
   160         -		for a in tup:
   161         -		    self.smsbad.append(a)
          165  +	    self.smsblack = subs.get("blacklist")
   162    166   
   163    167   	# Static/local authentication config?  Can't mix with
   164    168   	#  an authentication server.
   165    169   	if any(("password" in acct[1]) for acct in cfg["user"]):
   166    170   	    self.authentication.append(WebXMPP.auth_local)
   167    171   	else:
   168    172   	    # Account server to get logged in & get cookie

Changes to post.py.

     3      3   #	HTML POST/PUT handling
     4      4   #
     5      5   # POST's put state back to us--usually a text to send.
     6      6   #
     7      7   # /msg.json - JSON of a message to send
     8      8   # /sms.json - JSON of a Flowroute-style SMS delivery
     9      9   #
    10         -import sys, json
           10  +import sys, json, os
    11     11   from chore.utils import toascii
    12     12   import chore
    13     13   import acct_sms
    14     14   
    15     15   class POST_mixin(object):
    16     16       def __init__(self):
    17     17   	self.dispatchers.append( ("POST", self.post_msg) )
    18     18   	self.dispatchers.append( ("POST", self.post_sms) )
           19  +
           20  +    # Does SMS blacklisting apply to this message?
           21  +    def filtered(self, msg):
           22  +	approot = self.server.approot
           23  +
           24  +	# No blacklist
           25  +	if approot.smsblack is None:
           26  +	    return False
           27  +
           28  +	# Refresh?
           29  +	try:
           30  +	    st = os.stat(approot.smsblack)
           31  +	except:
           32  +	    sys.stderr.write("SMS blacklist %s missing\n" %
           33  +		(approot.smsblack,))
           34  +	    return False
           35  +	if st.st_mtime > approot.smsblatest:
           36  +	    sys.stderr.write("Reload SMS blacklist\n")
           37  +	    approot.smsbad = []
           38  +	    f = open(approot.smsblack, "r")
           39  +	    for l in f:
           40  +		l = l.strip()
           41  +		if not l:
           42  +		    continue
           43  +		approot.smsbad.append(l)
           44  +	    f.close()
           45  +	    sys.stderr.write(" %d entries\n" % (len(approot.smsbad),))
           46  +	    approot.smsblatest = st.st_mtime
           47  +
           48  +	# See if any blacklist pattern is found within sender
           49  +	mf = msg.get("from", "")
           50  +	res = any( (a in mf) for a in approot.smsbad )
           51  +	if res:
           52  +	    sys.stderr.write("SMS blacklist %s\n" % (mf,))
           53  +	return res
    19     54   
    20     55       # An SMS has arrived for us
    21     56       def post_sms(self, buf):
    22     57   	# /sms.json
    23     58   	if not self.path_match("sms.json"):
    24     59   	    return False,None
    25     60   
................................................................................
    35     70   		sys.exit(0)
    36     71   
    37     72   	# Decode message payload
    38     73   	msg = json.loads(buf)
    39     74   	sys.stderr.write(" JSON result %s\n" % (msg,))
    40     75   
    41     76   	# Pre-filter
    42         -	for a in approot.smsbad:
    43         -	    if a in msg.get("from", ""):
    44         -		sys.stderr.write("Blacklist SMS from %s\n" %
    45         -		    (msg["from"],))
    46         -		return True,self.send_result("", "text/html")
           77  +	if self.filtered(msg):
           78  +	    return True,self.send_result("", "text/html")
    47     79   
    48     80   	# Hand it off
    49     81   	acct_sms.incoming(msg)
    50     82   
    51     83   	# If we error, they just re-deliver more times, so always
    52     84   	#  accept it, even if we have to log an issue with handling it.
    53     85   	return True,self.send_result("", "text/html")