def testBasics(self): '''Testing the basics of the interface with a super-simple db''' # Create new, empty database without file-storage db = supersimpledb.MurmeliDb() DbI.setDb(db) # Lists should be empty self.assertEqual(len(DbI.getMessageableProfiles()), 0, "Should be 0 messageables") self.assertEqual(len(DbI.getTrustedProfiles()), 0, "Should be 0 trusted") self.assertFalse(DbI.hasFriends(), "Shouldn't have any friends") # Store some profiles DbI.updateProfile("abc123", {"keyid":"ZYXW987", "status":"self", "name":"That's me"}) DbI.updateProfile("def123", {"keyid":"JKLM987", "status":"trusted", "name":"Jimmy"}) DbI.updateProfile("ghi123", {"keyid":"TUVWX987", "status":"untrusted", "name":"Dave"}) # Get my ids self.assertEqual(DbI.getOwnTorid(), "abc123", "Should find correct tor id") self.assertEqual(DbI.getOwnKeyid(), "ZYXW987", "Should find correct key id") # Get all profiles self.assertEqual(len(DbI.getProfiles()), 3, "Should be three profiles in total") self.assertEqual(len(DbI.getMessageableProfiles()), 2, "Should be two messageables") self.assertEqual(len(DbI.getTrustedProfiles()), 1, "Should be one trusted") self.assertEqual(DbI.getTrustedProfiles()[0]['displayName'], "Jimmy", "Jimmy should be trusted") self.assertTrue(DbI.hasFriends(), "Should have friends") # Update an existing profile DbI.updateProfile("def123", {"displayName":"Slippin' Jimmy"}) self.assertEqual(len(DbI.getTrustedProfiles()), 1, "Should still be one trusted") self.assertEqual(DbI.getTrustedProfiles()[0]['displayName'], "Slippin' Jimmy", "Slippin' Jimmy should be trusted") # Finished DbI.releaseDb()
def getSharedAndPossibleContacts(torid): '''Check which contacts we share with the given torid and which ones we could recommend to each other''' nameMap = {} ourContactIds = set() trustedContactIds = set() theirContactIds = set() # Get our id so we can exclude it from the sets myTorId = DbI.getOwnTorid() if torid == myTorId: return (None, None, None, None) # Find the contacts of the specified person selectedProfile = DbI.getProfile(torid) selectedContacts = selectedProfile.get( 'contactlist', None) if selectedProfile else None if selectedContacts: for s in selectedContacts.split(","): if s and len(s) >= 16: foundid = s[0:16] if foundid != myTorId: foundName = s[16:] theirContactIds.add(foundid) nameMap[foundid] = foundName foundTheirContacts = len(theirContactIds) > 0 # Now get information about our contacts for c in DbI.getMessageableProfiles(): foundid = c['torid'] ourContactIds.add(foundid) if c['status'] == 'trusted' and foundid != torid: trustedContactIds.add(foundid) nameMap[foundid] = c['displayName'] # Should we check the contact information too? if not foundTheirContacts: foundContacts = c.get('contactlist', None) if foundContacts: for s in foundContacts.split(","): if s[0:16] == torid: theirContactIds.add(foundid) # Now we have three sets of torids: our contacts, our trusted contacts, and their contacts. sharedContactIds = ourContactIds.intersection( theirContactIds) # might be empty suggestionsForThem = trustedContactIds.difference(theirContactIds) possibleForMe = theirContactIds.difference(ourContactIds) # TODO: Maybe subtract requested contacts from the "possibleForMe" set? # Some or all of these sets may be empty, but we still return the map so we can look up names return (sharedContactIds, suggestionsForThem, possibleForMe, nameMap)
def checkAllContactsKeys(): '''Return a list of names for which the key can't be found''' nameList = [] for c in DbI.getMessageableProfiles(): torId = c['torid'] if c else None if torId: keyId = c['keyid'] if not keyId: print("No keyid found for torid", torId) nameList.append(c['displayName']) elif not CryptoClient.getPublicKey(keyId): print("CryptoClient hasn't got a public key for torid", torId) nameList.append(c['displayName']) if not keyId or not CryptoClient.getPublicKey(keyId): # We haven't got their key in our keyring! DbI.updateProfile(torId, {"status": "requested"}) return nameList
def servePage(self, view, url, params): print("Compose: %s, params %s" % (url, repr(params))) if url == "/start": self.requirePageResources(['default.css', 'jquery-3.1.1.js']) DbI.exportAllAvatars(Config.getWebCacheDir()) parentHash = params.get("reply", None) recpts = params.get("sendto", None) # Build list of contacts to whom we can send userboxes = [] for p in DbI.getMessageableProfiles(): box = Bean() box.dispName = p['displayName'] box.torid = p['torid'] userboxes.append(box) pageParams = { "contactlist": userboxes, "parenthash": parentHash if parentHash else "", "webcachedir": Config.getWebCacheDir(), "recipientids": recpts } contents = self.buildPage({ 'pageTitle': I18nManager.getText("composemessage.title"), 'pageBody': self.composetemplate.getHtml(pageParams), 'pageFooter': "<p>Footer</p>" }) view.setHtml(contents) # If we've got no friends, then warn, can't send to anyone if not DbI.hasFriends(): view.page().mainFrame().evaluateJavaScript( "window.alert('No friends :(');") elif url == "/send": print("Submit new message with params:", params) msgBody = params[ 'messagebody'] # TODO: check body isn't empty, throw an exception? parentHash = params.get("parenthash", None) recpts = params['sendto'] # Make a corresponding message object and pass it on msg = message.RegularMessage(sendTo=recpts, messageBody=msgBody, replyToHash=parentHash) msg.recipients = recpts.split(",") DbI.addToOutbox(msg) # Save a copy of the sent message sentMessage = { "messageType": "normal", "fromId": DbI.getOwnTorid(), "messageBody": msgBody, "timestamp": msg.timestamp, "messageRead": True, "messageReplied": False, "recipients": recpts, "parentHash": parentHash } DbI.addToInbox(sentMessage) # Close window after successful send contents = self.buildPage({ 'pageTitle': I18nManager.getText("messages.title"), 'pageBody': self.closingtemplate.getHtml(), 'pageFooter': "<p>Footer</p>" }) view.setHtml(contents)
def servePage(self, view, url, params): print("Special function:", url) if url == "/selectprofilepic": # Get home directory for file dialog homedir = os.path.expanduser("~/") fname = QFileDialog.getOpenFileName( view, I18nManager.getText("gui.dialogtitle.openimage"), homedir, I18nManager.getText("gui.fileselection.filetypes.jpg")) if fname: view.page().mainFrame().evaluateJavaScript( "updateProfilePic('" + fname + "');") elif url == "/friendstorm": if not DbI.hasFriends(): view.page().mainFrame().evaluateJavaScript( "window.alert('No friends :(');") return # Launch a storm self.bs = Brainstorm(I18nManager.getText("contacts.storm.title")) self.bs.show() storm = Storm() # Build up Nodes and Edges using our contact list and if possible our friends' contact lists myTorId = DbI.getOwnTorid() friends = {} friendsOfFriends = {} for c in DbI.getMessageableProfiles(): # print("Contact: id:'%s' name:'%s'" % (c['torid'], c['displayName'])) nodeid = storm.getUnusedNodeId() torid = c['torid'] friends[torid] = nodeid storm.addNode(Node(None, nodeid, c['displayName'])) friendsOfFriends[torid] = c.get('contactlist', "") # Also add ourselves c = DbI.getProfile() nodeid = storm.getUnusedNodeId() friends[c['torid']] = nodeid storm.addNode(Node(None, nodeid, c['displayName'])) # Add edges for torid in friends: if torid != myTorId: storm.addEdge(friends[torid], friends[myTorId]) for torid in friendsOfFriends: if torid != myTorId: ffList = friendsOfFriends[torid] if ffList: for ff in ffList.split(","): if ff and len(ff) > 16: ffTorid = ff[:16] ffName = ff[16:] if ffTorid != myTorId: if not friends.get(ffTorid, None): # Friend's friend is not in the list yet - add it nodeid = storm.getUnusedNodeId() friends[ffTorid] = nodeid storm.addNode( Node(None, nodeid, ffName)) # Add edge from torid to ffTorid storm.addEdge(friends[torid], friends[ffTorid]) self.bs.setStorm(storm)