<pid>PyMSNt.pid</pid>
<!-- If set, the transport will background itself when run -->
<background/>
+<!-- The Twisted reactor to choose. Pick poll or epoll on Linux, kqueue on BSD. Or leave as default (select) -->
+<!-- <reactor>poll</reactor> -->
<!-- The IP address of the main Jabber server to connect to -->
<mainServer>127.0.0.1</mainServer>
-<!-- The website of the Jabber service -->
-<website>http://host.com</website>
<!-- The TCP port to connect to the Jabber server on (this is the default for Jabberd2) -->
<port>5347</port>
<!-- The authentication token to use when connecting to the Jabber server -->
<secret>secret</secret>
-<!-- The Twisted reactor to choose. Pick poll or epoll on Linux, kqueue on BSD. Or leave as default (select) -->
-<!-- <reactor>poll</reactor> -->
+<!-- Use Jabber.com's XCP component protocol extensions. -->
+<!-- <useXCP/> -->
<!-- The default language to use -->
<lang>en</lang>
+<!-- The website of the Jabber service -->
+<website>http://host.com</website>
<!-- Comment out the following options to disable them, or uncomment them to enable them -->
<allowRegister/>
<!-- Get all avatars. If this is set to true then avatars are grabbed for all your contacts immediately. If false then avatars are only grabbed when you're in a chat with a contact -->
<getAllAvatars/>
-<!-- Use Jabber.com's XCP component protocol extensions. -->
-<!-- <useXCP/> -->
<!-- File transfer settings -->
<!-- <debugLevel>0</debugLevel> -->
<!-- The file to log to. Leave this disabled for stdout -->
-<!-- <debugFile>debug.log</debugLog> -->
+<!-- <debugFile>debug.log</debugFile> -->
</pymsnt>
if ptype and (ptype.startswith("subscribe") or ptype.startswith("unsubscribe")):
LogEvent(INFO, self.jabberID, "Parsed subscription presence packet")
self.subscriptionReceived(toj.userhost(), ptype)
- elif ptype == "probe":
- LogEvent(INFO, self.jabberID, "Parsed presence probe")
- self.contactList.getContact(toj.userhost()).sendPresence(fro)
else:
status = None
show = None
# Copyright 2004-2005 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
+import os.path
import utils
from twisted.internet import task
from tlib.xmlw import Element
from tlib import msn
from debug import LogEvent, INFO, WARN, ERROR
import disco
-import sha
import groupchat
import ft
import avatar
# Load the default avatars
-f = open("src/legacy/defaultJabberAvatar.png")
+f = open(os.path.join("data", "defaultJabberAvatar.png"))
defaultJabberAvatarData = f.read()
f.close()
-f = open("src/legacy/defaultAvatar.png")
+f = open(os.path.join("data", "defaultMSNAvatar.png"))
defaultAvatarData = f.read()
f.close()
defaultAvatar = avatar.AvatarCache().setAvatar(defaultAvatarData)
def reloadConfig():
- msn.GETALLAVATARS = config.getAllAvatars
+ msn.MSNConnection.GETALLAVATARS = config.getAllAvatars
def isGroupJID(jid):
""" Returns True if the JID passed is a valid groupchat JID (for MSN, does not contain '%') """
import xmlconfig
configFile = "config.xml"
configOptions = {}
-opts, args = getopt.getopt(sys.argv[1:], "bc:o:dDgtl:h", ["background", "config=", "option=", "debug", "Debug", "garbage", "traceback", "log=", "help"])
+opts, args = getopt.getopt(sys.argv[1:], "bc:o:dDgtlp:h", ["background", "config=", "option=", "debug", "Debug", "garbage", "traceback", "log=", "pid=", "help"])
for o, v in opts:
if o in ("-c", "--config"):
configFile = v
config.debugLevel = "1"
elif o in ("-l", "--log"):
config.debugFile = v
+ elif o in ("-p", "--pid"):
+ config.pid = v
elif o in ("-o", "--option"):
var, setting = v.split("=", 2)
configOptions[var] = setting
print " -g print garbage collection output"
print " -t print debugging only on traceback"
print " -l <file> write debugging output to file"
+ print " -p <file> write process ID to file"
print " -o <var>=<setting> set config var to setting"
sys.exit(0)
class App:
def __init__(self):
# Check for any other instances
+ if config.pid and os.name != "posix":
+ config.pid = ""
if config.pid:
- self.checkPID()
+ twistd.checkPID(config.pid)
# Do any auto-update stuff
housekeep.init()
# Daemonise the process and write the PID file
- if config.background:
- self.daemonise()
+ if config.background and os.name == "posix":
+ twistd.daemonize()
if config.pid:
self.writePID()
self.c.startService()
reactor.addSystemEventTrigger('before', 'shutdown', self.shuttingDown)
- def checkPID(self):
- # Check that we're not already running
- if os.path.isfile(config.pid):
- if os.name == "posix":
- pf = open(config.pid)
- pid = int(str(pf.readline().strip()))
- pf.close()
- try:
- os.kill(pid, signal.SIGHUP)
- self.alreadyRunning()
- except OSError:
- pass
- else:
- self.alreadyRunning()
-
def writePID(self):
# Create a PID file
pid = str(os.getpid())
sys.__stdout__.write("There is already a transport instance running with this configuration.\nExiting...\n\n")
sys.exit(1)
- def daemonise(self):
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0)
- except OSError, e:
- sys.stderr.write("Daemonise failed: (%d) %s\n" % (e.errno, e.strerror))
- sys.exit(1)
-
def shuttingDown(self):
self.transportSvc.removeMe()
# Keep the transport running for another 3 seconds
def cb(ignored=None):
if config.pid:
- os.remove(config.pid)
+ twistd.removePID(config.pid)
d = Deferred()
d.addCallback(cb)
reactor.callLater(3.0, d.callback, None)
def SIGHUPstuff(*args):
global configFile, configOptions
xmlconfig.reloadConfig(configFile, configOptions)
+ if config.pid and os.name != "posix":
+ config.pid = ""
debug.reloadConfig()
legacy.reloadConfig()
import signal
# Set SIGHUP to reload the config file & close & open debug file
signal.signal(signal.SIGHUP, SIGHUPstuff)
+ # Load some scripts for PID and daemonising
+ from twisted.scripts import twistd
def main():
groupchat = legacy.LegacyGroupchat(self, resource, gcID) # Creates an empty groupchat
groupchat.userJoined(tor)
+ elif ptype == "probe":
+ LogEvent(INFO, self.jabberID, "Responding to presence probe")
+ self.contactList.getContact(toj.userhost()).sendPresence(fro)
else:
# Not for groupchat
self.handleResourcePresence(source, resource, to, tor, priority, ptype, show, status)
-from msnw import MSNConnection, MultiSwitchboardSession, GETALLAVATARS
+from msnw import MSNConnection, MultiSwitchboardSession
from msn import FORWARD_LIST, ALLOW_LIST, BLOCK_LIST, REVERSE_LIST, PENDING_LIST
from msn import STATUS_ONLINE, STATUS_OFFLINE, STATUS_HIDDEN, STATUS_IDLE, STATUS_AWAY, STATUS_BUSY, STATUS_BRB, STATUS_PHONE, STATUS_LUNCH
from msn import MSNContact, MSNContactList
self.gotMSNAlert(bodytext, actionurl, subscrurl)
def _gotUBX(self, message):
+ msnContact = self.factory.contacts.getContact(message.userHandle)
+ if not msnContact: return
lm = message.message.lower()
p1 = lm.find("<psm>") + 5
p2 = lm.find("</psm>")
if p1 >= 0 and p2 >= 0:
personal = unescapeFromXml(message.message[p1:p2])
- msnContact = self.factory.contacts.getContact(message.userHandle)
- if not msnContact: return
msnContact.personal = personal
self.contactPersonalChanged(message.userHandle, personal)
else:
+ msnContact.personal = ''
self.contactPersonalChanged(message.userHandle, '')
def checkMessage(self, message):
self.currentMessage = MSNMessage(length=messageLen, userHandle=params[0], screenName="UBX", specialMessage=True)
self.setRawMode()
else:
- self.contactPersonalChanged(params[0], '')
+ self._gotUBX(MSNMessage(userHandle=params[0]))
def handle_UUX(self, params):
checkParamLen(len(params), 2, 'UUX')
from tlib.msn import msn
-MAXMESSAGESIZE = 1400
-SWITCHBOARDTIMEOUT = 30.0*60.0
-GETALLAVATARS = False
-
"""
All interaction should be with the MSNConnection and MultiSwitchboardSession classes.
class MSNConnection:
""" Manages all the Twisted factories, etc """
+ MAXMESSAGESIZE = 1400
+ SWITCHBOARDTIMEOUT = 30.0*60.0
+ GETALLAVATARS = False
+
def __init__(self, username, password, ident):
""" Connects to the MSN servers.
@param username: the MSN passport to connect with.
LogEvent(INFO, self.ident)
if not self.notificationClient: return
- if GETALLAVATARS:
+ if MSNConnection.GETALLAVATARS:
self._ensureSwitchboardSession(userHandle)
sb = self.switchboardSessions.get(userHandle)
if sb: return sb.sendAvatarRequest()
if not noerror:
self.failedMessage(text)
- if len(text) < MAXMESSAGESIZE:
+ if len(text) < MSNConnection.MAXMESSAGESIZE:
message = msn.MSNMessage(message=str(text.replace("\n", "\r\n").encode("utf-8")))
message.setHeader("Content-Type", "text/plain; charset=UTF-8")
message.ack = msn.MSNMessage.MESSAGE_NACK
d.addCallback(failedMessage)
else:
- chunks = int(math.ceil(len(text) / float(MAXMESSAGESIZE)))
+ chunks = int(math.ceil(len(text) / float(MSNConnection.MAXMESSAGESIZE)))
chunk = 0
guid = msn.random_guid()
while chunk < chunks:
- offset = chunk * MAXMESSAGESIZE
- text = message[offset : offset + MAXMESSAGESIZE]
+ offset = chunk * MSNConnection.MAXMESSAGESIZE
+ text = message[offset : offset + MSNConnection.MAXMESSAGESIZE]
message = msn.MSNMessage(message=str(text.replace("\n", "\r\n").encode("utf-8")))
message.ack = msn.MSNMessage.MESSAGE_NACK
if chunk == 0: