Пример #1
0
	def dealWithUnencryptedMessage(message):
		'''Decide what to do with the given unencrypted message'''
		if message.messageType == Message.TYPE_CONTACT_REQUEST:
			print("Received a contact request from", message.senderId)
			# Check config to see whether we accept these or not
			if Config.getProperty(Config.KEY_ALLOW_FRIEND_REQUESTS) \
			  and MessageShuffler._isProfileStatusOk(message.senderId, [None, 'requested', 'untrusted', 'trusted']):
				# Call DbClient to store new message in inbox
				rowToStore = {"messageType":"contactrequest", "fromId":message.senderId,
					"fromName":message.senderName, "messageBody":message.message,
					"publicKey":message.publicKey, "timestamp":message.timestamp,
					"messageRead":False, "messageReplied":False}
				DbClient.addMessageToInbox(rowToStore)
		elif message.messageType == Message.TYPE_CONTACT_RESPONSE:
			print("It's an unencrypted contact response, so it must be a refusal")
			sender = DbClient.getProfile(message.senderId, False)
			if MessageShuffler._isProfileStatusOk(message.senderId, ['requested']):
				senderName = sender.get("displayName") if sender else ""
				ContactMaker.handleReceiveDeny(message.senderId)
				# Call DbClient to store new message in inbox
				rowToStore = {"messageType":"contactresponse", "fromId":message.senderId,
					"fromName":senderName, "messageBody":"", "accepted":False,
					"messageRead":False, "messageReplied":False, "timestamp":message.timestamp,
					"recipients":MessageShuffler.getOwnTorId()}
				DbClient.addMessageToInbox(rowToStore)
		else:
			print("Hä?  It's unencrypted but the message type is", message.messageType)
Пример #2
0
 def dealWithUnencryptedMessage(message):
     '''Decide what to do with the given unencrypted message'''
     if message.messageType == Message.TYPE_CONTACT_REQUEST:
         print("Received a contact request from", message.senderId)
         # Check config to see whether we accept these or not
         if Config.getProperty(Config.KEY_ALLOW_FRIEND_REQUESTS) \
           and MessageShuffler._isProfileStatusOk(message.senderId, [None, 'requested', 'untrusted', 'trusted']):
             # Store new message in inbox
             rowToStore = {
                 "messageType": "contactrequest",
                 "fromId": message.senderId,
                 "fromName": message.senderName,
                 "messageBody": message.message,
                 "publicKey": message.publicKey,
                 "timestamp": message.timestamp,
                 "messageRead": False,
                 "messageReplied": False
             }
             DbI.addToInbox(rowToStore)
     elif message.messageType == Message.TYPE_CONTACT_RESPONSE:
         print(
             "It's an unencrypted contact response, so it must be a refusal"
         )
         sender = DbI.getProfile(message.senderId)
         if MessageShuffler._isProfileStatusOk(message.senderId,
                                               ['requested']):
             senderName = sender.get("displayName") if sender else ""
             ContactMaker.handleReceiveDeny(message.senderId)
             # Store new message in inbox
             rowToStore = {
                 "messageType": "contactresponse",
                 "fromId": message.senderId,
                 "fromName": senderName,
                 "messageBody": "",
                 "accepted": False,
                 "messageRead": False,
                 "messageReplied": False,
                 "timestamp": message.timestamp,
                 "recipients": DbI.getOwnTorid()
             }
             DbI.addToInbox(rowToStore)
     else:
         print("Hä?  It's unencrypted but the message type is",
               message.messageType)
Пример #3
0
	def testSharedContacts(self):
		# Delete whole profiles table
		DbClient._getProfileTable().remove({})
		self.assertEqual(DbClient._getProfileTable().count(), 0, "Profiles table should be empty")
		# Add own profile
		myTorId = "ABC123DEF456GH78"
		myprofile = {"name" : "Constantin Taylor", "keyid" : "someKeyId", "displayName" : "Me",
					"status" : "self", "ownprofile" : True}
		DbClient.updateContact(myTorId, myprofile)
		# Add friend who doesn't list any contacts
		person1TorId = "DEF123GHI456JK78"
		person1profile = {"name" : "Jeremy Flintstone", "keyid" : "someKeyId", "displayName" : "Uncle Jez",
					"status" : "trusted"}
		DbClient.updateContact(person1TorId, person1profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertFalse(shared, "person1 shouldn't have any shared contacts")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts")
		# Add second friend who lists first one as contact
		person2TorId = "GHI123JKL456MN78"
		person2profile = {"name" : "Karen Millhouse", "keyid" : "someKeyId", "displayName" : "Mum",
					"status" : "trusted", "contactlist":"DEF123GHI456JK78Jeremy,ABC123DEF456GH78Constantin,"}
		DbClient.updateContact(person2TorId, person2profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should have exactly one shared contact now")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact now")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts from p1")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 1, "person2 should have exactly one shared contact now")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact now")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
		self.assertFalse(possIdsForMe, "I shouldn't have any possible contacts from p2")
		# Person 2 gets a new friend
		DbClient.updateContact(person2TorId, {"contactlist":"DEF123GHI456JK78Jeremy,ABC123DEF456GH78Constantin,MNO123PQR456ST78Scarlet Pimpernel"})
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should still have one shared contact")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact")
		self.assertFalse(possIdsForThem, "person1 shouldn't have any possible contacts")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 1, "person2 should still have one shared contact")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
		# We now make friends with MNO
		person3TorId = "MNO123PQR456ST78"
		person3profile = {"name" : "Scarlet Pimpernel", "keyid" : "someKeyId", "displayName" : "Stranger",
					"status" : "trusted"}
		DbClient.updateContact(person3TorId, person3profile)
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person1TorId)
		self.assertEqual(len(shared), 1, "person1 should still have one shared contact")
		self.assertTrue(person2TorId in shared, "person1 should have p2 as shared contact")
		self.assertEqual(len(possIdsForThem), 1, "person1 should have one possible contact now")
		self.assertTrue(person3TorId in possIdsForThem, "person1 should have p3 as possible contact")
		(shared, possIdsForThem, possIdsForMe, _) = ContactMaker.getSharedAndPossibleContacts(person2TorId)
		self.assertEqual(len(shared), 2, "person2 should now have 2 shared contacts")
		self.assertTrue(person1TorId in shared, "person2 should have p1 as shared contact")
		self.assertTrue(person3TorId in shared, "person2 should have p3 as shared contact")
		self.assertFalse(possIdsForThem, "person2 shouldn't have any possible contacts")
Пример #4
0
    def __init__(self, *args):
        self.logPanel = LogWindow()
        GuiWindow.__init__(self, lowerItem=self.logPanel)
        self.clearWebCache()
        self.postmen = None
        self.toolbar = self.makeToolbar([
            ("images/toolbar-home.png", self.onHomeClicked,
             "mainwindow.toolbar.home"),
            ("images/toolbar-people.png", self.onContactsClicked,
             "mainwindow.toolbar.contacts"),
            ("images/toolbar-messages.png", self.onMessagesClicked,
             "mainwindow.toolbar.messages"),
            ("images/toolbar-messages-highlight.png", self.onMessagesClicked,
             "mainwindow.toolbar.messages"),
            ("images/toolbar-calendar.png", self.onCalendarClicked,
             "mainwindow.toolbar.calendar"),
            ("images/toolbar-settings.png", self.onSettingsClicked,
             "mainwindow.toolbar.settings")
        ])
        self.addToolBar(self.toolbar)
        self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        # status bar
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.setWindowTitle(I18nManager.getText("mainwindow.title"))

        self.setStatusTip("Murmeli")
        self.setPageServer(PageServer())
        self.navigateTo("/")
        # we want to be notified of Config changes
        Config.registerSubscriber(self)
        self.postmen = [
            postmen.IncomingPostman(self),
            postmen.OutgoingPostman(self)
        ]
        self.postmen[1].messageSentSignal.connect(self.logPanel.notifyLogEvent)
        MessageShuffler.getTannoy().updateSignal.connect(
            self.logPanel.notifyLogEvent)
        # Make sure Tor client is started
        if not TorClient.isStarted():
            TorClient.startTor()
        # Create database instance if not already set
        if not DbI.hasDbSet():
            DbI.setDb(MurmeliDb(Config.getSsDatabaseFile()))
        # Make sure the status of the contacts matches our keyring
        missingKeyNames = ContactMaker.checkAllContactsKeys()
        if missingKeyNames:
            warningTexts = [I18nManager.getText("warning.keysnotfoundfor")
                            ] + missingKeyNames
            QtWidgets.QMessageBox.warning(self, "Murmeli",
                                          "\n   ".join(warningTexts))
Пример #5
0
	def generateListPage(self, doEdit=False, userid=None, extraParams=None):
		self.requirePageResources(['avatar-none.jpg', 'status-self.png', 'status-requested.png', 'status-untrusted.png', 'status-trusted.png'])
		# List of contacts, and show details for the selected one (or self if userid=None)
		selectedprofile = DbClient.getProfile(userid)
		if selectedprofile is None:
			selectedprofile = DbClient.getProfile()
		userid = selectedprofile['torid']
		ownPage = userid == DbClient.getOwnTorId()

		# Build list of contacts
		userboxes = []
		for p in DbClient.getContactList():
			box = Bean()
			box.dispName = p['displayName']
			box.torid = p['torid']
			box.tilestyle = "contacttile" + ("selected" if p['torid'] == userid else "")
			box.status = p['status']
			box.isonline = Contacts.isOnline(box.torid)
			userboxes.append(box)
		# expand templates using current details
		lefttext = self.listtemplate.getHtml({'webcachedir' : Config.getWebCacheDir(), 'contacts' : userboxes})
		pageProps = {"webcachedir" : Config.getWebCacheDir(), 'person':selectedprofile}
		# Add extra parameters if necessary
		if extraParams:
			pageProps.update(extraParams)

		# See which contacts we have in common with this person
		(sharedContactIds, possIdsForThem, possIdsForMe, nameMap) = ContactMaker.getSharedAndPossibleContacts(userid)
		sharedContacts = self._makeIdAndNameBeanList(sharedContactIds, nameMap)
		pageProps.update({"sharedcontacts" : sharedContacts})
		possibleContacts = self._makeIdAndNameBeanList(possIdsForThem, nameMap)
		pageProps.update({"possiblecontactsforthem" : possibleContacts})
		possibleContacts = self._makeIdAndNameBeanList(possIdsForMe, nameMap)
		pageProps.update({"possiblecontactsforme" : possibleContacts})

		# Which template to use depends on whether we're just showing or also editing
		if doEdit:
			# Use two different details templates, one for self and one for others
			detailstemplate = self.editowndetailstemplate if ownPage else self.editdetailstemplate
			righttext = detailstemplate.getHtml(pageProps)
		else:
			detailstemplate = self.detailstemplate  # just show
			righttext = detailstemplate.getHtml(pageProps)

		contents = self.buildTwoColumnPage({'pageTitle' : I18nManager.getText("contacts.title"),
			'leftColumn' : lefttext,
			'rightColumn' : righttext,
			'pageFooter' : "<p>Footer</p>"})
		return contents
Пример #6
0
 def dealWithAsymmetricMessage(message):
     '''Decide what to do with the given asymmetric message'''
     if message.senderId == DbI.getOwnTorid():
         print("*** Shouldn't receive a message from myself!")
         return
     # Sort message according to type
     if message.messageType == Message.TYPE_CONTACT_RESPONSE:
         print("Received a contact accept from", message.senderId, "name",
               message.senderName)
         if MessageShuffler._isProfileStatusOk(
                 message.senderId, ['pending', 'requested', 'untrusted']):
             print(message.senderName, "'s public key is",
                   message.senderKey)
             ContactMaker.handleReceiveAccept(message.senderId,
                                              message.senderName,
                                              message.senderKey)
             # Store new message in inbox
             rowToStore = {
                 "messageType": "contactresponse",
                 "fromId": message.senderId,
                 "fromName": message.senderName,
                 "messageBody": message.introMessage,
                 "accepted": True,
                 "messageRead": False,
                 "messageReplied": False,
                 "timestamp": message.timestamp,
                 "recipients": DbI.getOwnTorid()
             }
             DbI.addToInbox(rowToStore)
         elif MessageShuffler._isProfileStatusOk(message.senderId,
                                                 [None, 'blocked']):
             print(
                 "Received a contact response but I didn't send them a request!"
             )
             print("Encrypted contents are:", message.encryptedContents)
             rowToStore = {
                 "messageType": "contactresponse",
                 "fromId": message.senderId,
                 "fromName": message.senderName,
                 "messageBody": message.introMessage,
                 "accepted": True,
                 "timestamp": message.timestamp,
                 "encryptedMsg": message.encryptedContents
             }
             DbI.addMessageToPendingContacts(rowToStore)
     elif message.messageType == Message.TYPE_STATUS_NOTIFY:
         if message.online:
             print("One of our contacts has just come online- ",
                   message.senderId, "and hash is", message.profileHash)
             prof = DbI.getProfile(message.senderId)
             if prof:
                 storedHash = prof.get("profileHash", "empty")
                 if message.profileHash != storedHash:
                     reply = InfoRequestMessage(
                         infoType=InfoRequestMessage.INFO_PROFILE)
                     reply.recipients = [message.senderId]
                     DbI.addToOutbox(reply)
                 if message.ping:
                     print("Now sending back a pong, too")
                     reply = StatusNotifyMessage(online=True,
                                                 ping=False,
                                                 profileHash=None)
                     reply.recipients = [message.senderId]
                     DbI.addToOutbox(reply)
                 else:
                     print("It's already a pong so I won't reply")
             Contacts.instance().comeOnline(message.senderId)
         else:
             print("One of our contacts is going offline -",
                   message.senderId)
             Contacts.instance().goneOffline(message.senderId)
     elif message.messageType == Message.TYPE_INFO_REQUEST:
         print("I've received an info request message for type",
               message.infoType)
         if MessageShuffler._isProfileStatusOk(message.senderId,
                                               ['trusted']):
             reply = InfoResponseMessage(message.messageType)
             reply.recipients = [message.senderId]
             DbI.addToOutbox(reply)
     elif message.messageType == Message.TYPE_INFO_RESPONSE:
         if message.profile and MessageShuffler._isProfileStatusOk(
                 message.senderId, ['trusted', 'untrusted']):
             if message.profileHash:
                 message.profile['profileHash'] = message.profileHash
             DbI.updateProfile(message.senderId, message.profile,
                               Config.getWebCacheDir())
     elif message.messageType == Message.TYPE_FRIEND_REFERRAL:
         print("I've received a friend referral message from:",
               message.senderId, "for:", message.friendName)
         if MessageShuffler._isProfileStatusOk(message.senderId,
                                               ['trusted']):
             # Store new referral message in inbox
             rowToStore = {
                 "messageType": "contactrefer",
                 "fromId": message.senderId,
                 "friendId": message.friendId,
                 "friendName": message.friendName,
                 "messageBody": message.message,
                 "publicKey": message.publicKey,
                 "timestamp": message.timestamp,
                 "messageRead": False,
                 "messageReplied": False
             }
             DbI.addToInbox(rowToStore)
     elif message.messageType == Message.TYPE_FRIENDREFER_REQUEST:
         print("I've received a friend referral request from:",
               message.senderId, "who wants me to refer:", message.friendId)
         if MessageShuffler._isProfileStatusOk(message.senderId,
                                               ['trusted']):
             # Store message in the inbox
             rowToStore = {
                 "messageType": "referrequest",
                 "fromId": message.senderId,
                 "friendId": message.friendId,
                 "friendName": message.friendName,
                 "messageBody": message.message,
                 "publicKey": message.publicKey,
                 "timestamp": message.timestamp,
                 "messageRead": False,
                 "messageReplied": False
             }
             DbI.addToInbox(rowToStore)
     elif message.messageType == Message.TYPE_ASYM_MESSAGE:
         print(
             "It's a general kind of message, this should go in the Inbox, right?"
         )
         if MessageShuffler._isProfileStatusOk(message.senderId,
                                               ['trusted', 'untrusted']):
             rowToStore = {
                 "messageType": "normal",
                 "fromId": message.senderId,
                 "messageBody": message.messageBody,
                 "timestamp": message.timestamp,
                 "messageRead": False,
                 "messageReplied": False,
                 "recipients": message.sendTo,
                 "parentHash": message.replyToHash
             }
             DbI.addToInbox(rowToStore)
             Contacts.instance().comeOnline(message.senderId)
     else:
         # It's another asymmetric message type
         print("Hä?  What kind of asymmetric message type is that? ",
               message.messageType)
Пример #7
0
	def dealWithAsymmetricMessage(message):
		'''Decide what to do with the given asymmetric message'''
		if message.senderId == MessageShuffler.getOwnTorId():
			print("*** Shouldn't receive a message from myself!")
			return
		# Sort message according to type
		if message.messageType == Message.TYPE_CONTACT_RESPONSE:
			print("Received a contact accept from", message.senderId, "name", message.senderName)
			if MessageShuffler._isProfileStatusOk(message.senderId, ['pending', 'requested', 'untrusted']):
				print(message.senderName, "'s public key is", message.senderKey)
				ContactMaker.handleReceiveAccept(message.senderId, message.senderName, message.senderKey)
				# Call DbClient to store new message in inbox
				rowToStore = {"messageType":"contactresponse", "fromId":message.senderId,
					"fromName":message.senderName, "messageBody":message.introMessage, "accepted":True,
					"messageRead":False, "messageReplied":False, "timestamp":message.timestamp,
					"recipients":MessageShuffler.getOwnTorId()}
				DbClient.addMessageToInbox(rowToStore)
			elif MessageShuffler._isProfileStatusOk(message.senderId, [None, 'blocked']):
				print("Received a contact response but I didn't send them a request!")
				print("Encrypted contents are:", message.encryptedContents)
				rowToStore = {"messageType":"contactresponse", "fromId":message.senderId,
					"fromName":message.senderName, "messageBody":message.introMessage, "accepted":True,
					"timestamp":message.timestamp, "encryptedMsg":message.encryptedContents}
				DbClient.addMessageToPendingContacts(rowToStore)
		elif message.messageType == Message.TYPE_STATUS_NOTIFY:
			if message.online:
				print("One of our contacts has just come online- ", message.senderId,
					"and hash is", message.profileHash)
				prof = DbClient.getProfile(userid=message.senderId, extend=False)
				if prof:
					storedHash = prof.get("profileHash", "empty")
					if message.profileHash != storedHash:
						reply = InfoRequestMessage(infoType=InfoRequestMessage.INFO_PROFILE)
						reply.recipients = [message.senderId]
						DbClient.addMessageToOutbox(reply)
					if message.ping:
						print("Now sending back a pong, too")
						reply = StatusNotifyMessage(online=True, ping=False, profileHash=None)
						reply.recipients = [message.senderId]
						DbClient.addMessageToOutbox(reply)
					else:
						print("It's already a pong so I won't reply")
				Contacts.comeOnline(message.senderId)
			else:
				print("One of our contacts is going offline -", message.senderId)
				Contacts.goneOffline(message.senderId)
		elif message.messageType == Message.TYPE_INFO_REQUEST:
			print("I've received an info request message for type", message.infoType)
			if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted']):
				reply = InfoResponseMessage(message.messageType)
				reply.recipients = [message.senderId]
				DbClient.addMessageToOutbox(reply)
		elif message.messageType == Message.TYPE_INFO_RESPONSE:
			if message.profile and MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']):
				if message.profileHash:
					message.profile['profileHash'] = message.profileHash
				DbClient.updateContact(message.senderId, message.profile)
		elif message.messageType == Message.TYPE_ASYM_MESSAGE:
			print("It's a general kind of message, this should go in the Inbox, right?")
			if MessageShuffler._isProfileStatusOk(message.senderId, ['trusted', 'untrusted']):
				Contacts.comeOnline(message.senderId)
		else:
			# It's another asymmetric message type
			print("Hä?  What kind of asymmetric message type is that? ", message.messageType)
Пример #8
0
	def servePage(self, view, url, params):
		self.requirePageResources(['button-addperson.png', 'button-drawgraph.png', 'avatar-none.jpg'])
		DbClient.exportAvatars(Config.getWebCacheDir())
		if url == "/add" or url == "/add/":
			contents = self.generateAddPage()
			view.setHtml(contents)
			return
		elif url == "/submitaddrequest":
			print("Submit add request!:", url)
			if len(params) > 0:
				# request to add a new friend
				recipientid  = params.get('murmeliid', '')
				dispname     = params.get('displayname', '')
				intromessage = params.get('intromessage', '')
				if len(recipientid) == 16:
					# TODO: How to react if: person already added (untrusted/trusted); request already sent (requested)
					# update the database accordingly
					ContactMaker.handleInitiate(recipientid, dispname)
					print("I should send an add request to '%s' now." % recipientid)
					outmsg = message.ContactRequestMessage(introMessage=intromessage)
					outmsg.recipients = [recipientid]
					DbClient.addMessageToOutbox(outmsg)
				else:
					print("Hmm, show an error message here?")
				# in any case, go back to contact list
				url = "/" + recipientid
				# ensure that picture is generated for new id
				DbClient.exportAvatars(Config.getWebCacheDir())
		contents = None
		userid   = None
		pageParams = {}
		# Split url into components /userid/command
		command = [i for i in url.split("/") if i != ""]
		if len(command) > 0 and len(command[0]) == 16 and re.match("([a-zA-Z0-9]+)$", command[0]):
			userid = command[0]
			# check for command edit or submit-edit
			if len(command) == 2:
				if command[1] == "edit":
					contents = self.generateListPage(doEdit=True, userid=userid) # show edit fields
				elif command[1] == "submitedit":
					DbClient.updateContact(userid, params)
					# don't generate contents, go back to details
				elif command[1] == "delete":
					ContactMaker.handleDeleteContact(userid)
					userid = None
				elif command[1] == "checkfingerprint":
					contents = self.generateFingerprintsPage(userid)
				elif command[1] == "checkedfingerprint":
					givenAnswer = int(params.get('answer', -1))
					fc = self._makeFingerprintChecker(userid)
					expectedAnswer = fc.getCorrectAnswer()
					if expectedAnswer == givenAnswer:
						ContactMaker.keyFingerprintChecked(userid)
						# Show page again
						contents = self.generateFingerprintsPage(userid)
					else:
						# Add a message to show when the list page is re-generated
						pageParams['fingerprint_check_failed'] = True

		# If we haven't got any contents yet, then do a show details
		if not contents:
			# Show details for selected userid (or for self if userid is None)
			contents = self.generateListPage(doEdit=False, userid=userid, extraParams=pageParams)

		view.setHtml(contents)
Пример #9
0
    def servePage(self, view, url, params):
        self.requirePageResources(
            ['button-compose.png', 'default.css', 'jquery-3.1.1.js'])
        DbI.exportAllAvatars(Config.getWebCacheDir())

        messageList = None
        if url == "/send":
            print("send message of type '%(messageType)s' to id '%(sendTo)s'" %
                  params)
            if params['messageType'] == "contactresponse":
                torId = params['sendTo']
                if params.get("accept", "0") == "1":
                    ContactMaker.handleAccept(torId)
                    # Make sure this new contact has an empty avatar
                    DbI.exportAllAvatars(Config.getWebCacheDir())
                    outmsg = message.ContactResponseMessage(
                        message=params['messageBody'])
                else:
                    ContactMaker.handleDeny(torId)
                    outmsg = message.ContactDenyMessage()
                # Construct a ContactResponse message object for sending
                outmsg.recipients = [params['sendTo']]
                DbI.addToOutbox(outmsg)
        elif url.startswith("/delete/"):
            DbI.deleteFromInbox(params.get("msgId", ""))
        elif url in ["/search", "/search/"]:
            messageList = DbI.searchInboxMessages(params.get("searchTerm"))

        # Make dictionary to convert ids to names
        contactNames = {
            c['torid']: c['displayName']
            for c in DbI.getProfiles()
        }
        unknownSender = I18nManager.getText("messages.sender.unknown")
        unknownRecpt = I18nManager.getText("messages.recpt.unknown")
        # Get contact requests, responses and mails from inbox
        conreqs = []
        conresps = []
        mailTree = MessageTree()
        if messageList is None:
            messageList = DbI.getInboxMessages()
        # TODO: Paging options?
        for m in messageList:
            if not m:
                continue
            m['msgId'] = str(m.get("_id", ""))
            if m['messageType'] == "contactrequest":
                conreqs.append(m)
            elif m['messageType'] == "contactrefer":
                senderId = m.get('fromId', None)
                m['senderName'] = contactNames.get(senderId, unknownSender)
                conreqs.append(m)
            elif m['messageType'] == "contactresponse":
                if not m.get('accepted', False):
                    m['messageBody'] = I18nManager.getText(
                        "messages.contactrequest.refused")
                    m['fromName'] = DbI.getProfile(m['fromId'])["displayName"]
                elif not m.get('messageBody', False):
                    m['messageBody'] = I18nManager.getText(
                        "messages.contactrequest.accepted")
                conresps.append(m)
            else:
                senderId = m.get('fromId', None)
                if not senderId and m.get('signatureKeyId', None):
                    senderId = DbI.findUserIdFromKeyId(m['signatureKeyId'])
                m['senderName'] = contactNames.get(senderId, unknownSender)
                m['sentTimeStr'] = self.makeLocalTimeString(m['timestamp'])
                # Split m['recipients'] by commas, and look up each id with contactNames
                recpts = m.get('recipients', '')
                if recpts:
                    replyAll = recpts.split(",")
                    m['recipients'] = ", ".join(
                        [contactNames.get(i, unknownRecpt) for i in replyAll])
                    replyAll.append(senderId)
                    m['replyAll'] = ",".join(replyAll)
                else:
                    m['recipients'] = unknownRecpt
                    m['replyAll'] = ""
                mailTree.addMsg(m)
        mails = mailTree.build()
        bodytext = self.messagestemplate.getHtml({
            "contactrequests":
            conreqs,
            "contactresponses":
            conresps,
            "mails":
            mails,
            "nummessages":
            len(conreqs) + len(conresps) + len(mails),
            "webcachedir":
            Config.getWebCacheDir()
        })
        contents = self.buildPage({
            'pageTitle':
            I18nManager.getText("messages.title"),
            'pageBody':
            bodytext,
            'pageFooter':
            "<p>Footer</p>"
        })
        view.setHtml(contents)
Пример #10
0
    def generateListPage(self, doEdit=False, userid=None, extraParams=None):
        self.requirePageResources([
            'avatar-none.jpg', 'status-self.png', 'status-requested.png',
            'status-untrusted.png', 'status-trusted.png', 'status-pending.png'
        ])
        # List of contacts, and show details for the selected one (or self if userid=None)
        selectedprofile = DbI.getProfile(userid)
        if not selectedprofile:
            selectedprofile = DbI.getProfile()
        userid = selectedprofile['torid']
        ownPage = userid == DbI.getOwnTorid()

        # Build list of contacts
        userboxes = []
        currTime = datetime.datetime.now()
        for p in DbI.getProfiles():
            box = Bean()
            box.dispName = p['displayName']
            box.torid = p['torid']
            box.tilestyle = "contacttile" + ("selected"
                                             if p['torid'] == userid else "")
            box.status = p['status']
            isonline = Contacts.instance().isOnline(box.torid)
            lastSeen = Contacts.instance().lastSeen(box.torid)
            lastSeenTime = str(lastSeen.timetz())[:5] if lastSeen and (
                currTime - lastSeen).total_seconds() < 18000 else None
            if lastSeenTime:
                box.lastSeen = I18nManager.getText(
                    "contacts.onlinesince"
                    if isonline else "contacts.offlinesince") % lastSeenTime
            elif isonline:
                box.lastSeen = I18nManager.getText("contacts.online")
            else:
                box.lastSeen = None
            userboxes.append(box)

        # expand templates using current details
        lefttext = self.listtemplate.getHtml({
            'webcachedir':
            Config.getWebCacheDir(),
            'contacts':
            userboxes
        })
        pageProps = {
            "webcachedir": Config.getWebCacheDir(),
            'person': selectedprofile
        }
        # Add extra parameters if necessary
        if extraParams:
            pageProps.update(extraParams)

        # See which contacts we have in common with this person
        (sharedContactIds, possIdsForThem, possIdsForMe,
         nameMap) = ContactMaker.getSharedAndPossibleContacts(userid)
        sharedContacts = self._makeIdAndNameBeanList(sharedContactIds, nameMap)
        pageProps.update({"sharedcontacts": sharedContacts})
        possibleContacts = self._makeIdAndNameBeanList(possIdsForThem, nameMap)
        pageProps.update({"possiblecontactsforthem": possibleContacts})
        possibleContacts = self._makeIdAndNameBeanList(possIdsForMe, nameMap)
        pageProps.update({"possiblecontactsforme": possibleContacts})

        # Which template to use depends on whether we're just showing or also editing
        if doEdit:
            # Use two different details templates, one for self and one for others
            detailstemplate = self.editowndetailstemplate if ownPage else self.editdetailstemplate
            righttext = detailstemplate.getHtml(pageProps)
        else:
            detailstemplate = self.detailstemplate  # just show
            righttext = detailstemplate.getHtml(pageProps)

        contents = self.buildTwoColumnPage({
            'pageTitle':
            I18nManager.getText("contacts.title"),
            'leftColumn':
            lefttext,
            'rightColumn':
            righttext,
            'pageFooter':
            "<p>Footer</p>"
        })
        return contents
Пример #11
0
    def servePage(self, view, url, params):
        self.requirePageResources([
            'button-addperson.png', 'button-drawgraph.png', 'avatar-none.jpg'
        ])
        DbI.exportAllAvatars(Config.getWebCacheDir())
        if url == "/add" or url == "/add/":
            contents = self.generateAddPage()
            view.setHtml(contents)
            return
        elif url == "/submitaddrequest":
            print("Submit add request!:", url)
            if len(params) > 0:
                # request to add a new friend
                recipientid = params.get('murmeliid', '')
                dispname = params.get('displayname', '')
                intromessage = params.get('intromessage', '')
                if len(recipientid) == 16:
                    # TODO: How to react if: person already added (untrusted/trusted); request already sent (requested)
                    # update the database accordingly
                    ContactMaker.handleInitiate(recipientid, dispname)
                    print("I should send an add request to '%s' now." %
                          recipientid)
                    outmsg = message.ContactRequestMessage(
                        introMessage=intromessage)
                    outmsg.recipients = [recipientid]
                    DbI.addToOutbox(outmsg)
                else:
                    print("Hmm, show an error message here?")
                # in any case, go back to contact list
                url = "/" + recipientid
                # ensure that picture is generated for new id
                DbI.exportAllAvatars(Config.getWebCacheDir())
        contents = None
        userid = None
        pageParams = {}
        # Split url into components /userid/command
        command = [i for i in url.split("/") if i != ""]
        if len(command) > 0 and len(command[0]) == 16 and re.match(
                "([a-zA-Z0-9]+)$", command[0]):
            userid = command[0]
            # check for command edit or submit-edit
            if len(command) == 2:
                if command[1] == "edit":
                    contents = self.generateListPage(
                        doEdit=True, userid=userid)  # show edit fields
                elif command[1] == "submitedit":
                    DbI.updateProfile(userid, params, Config.getWebCacheDir())
                    # TODO: If we've updated our own details, can we trigger a broadcast?
                    # don't generate contents, go back to details
                elif command[1] == "delete":
                    ContactMaker.handleDeleteContact(userid)
                    userid = None
                elif command[1] == "checkfingerprint":
                    contents = self.generateFingerprintsPage(userid)
                elif command[1] == "checkedfingerprint":
                    givenAnswer = int(params.get('answer', -1))
                    fc = self._makeFingerprintChecker(userid)
                    expectedAnswer = fc.getCorrectAnswer()
                    if expectedAnswer == givenAnswer:
                        ContactMaker.keyFingerprintChecked(userid)
                        # Show page again
                        contents = self.generateFingerprintsPage(userid)
                    else:
                        # Add a message to show when the list page is re-generated
                        pageParams['fingerprint_check_failed'] = True
            elif len(command) == 3 and command[1] == "refer" and len(
                    command[2]) == 16:
                intro = str(params.get('introMessage', ""))
                ContactMaker.sendReferralMessages(command[0], command[2],
                                                  intro)
                pageParams['message_sent'] = True
                # go back to details page
            elif len(command) == 3 and command[1] == "requestrefer" and len(
                    command[2]) == 16:
                intro = str(params.get('introMessage', ""))
                ContactMaker.sendReferRequestMessage(command[0], command[2],
                                                     intro)
                pageParams['message_sent'] = True
                # go back to details page

        # If we haven't got any contents yet, then do a show details
        if not contents:
            # Show details for selected userid (or for self if userid is None)
            contents = self.generateListPage(doEdit=False,
                                             userid=userid,
                                             extraParams=pageParams)

        view.setHtml(contents)