summaryrefslogtreecommitdiff
path: root/Presence/Presence.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/Presence.hs')
-rw-r--r--Presence/Presence.hs213
1 files changed, 128 insertions, 85 deletions
diff --git a/Presence/Presence.hs b/Presence/Presence.hs
index 15775857..9b91dc1d 100644
--- a/Presence/Presence.hs
+++ b/Presence/Presence.hs
@@ -32,7 +32,7 @@ import System.IO.Error (isDoesNotExistError)
32import System.Posix.User (getUserEntryForID,userName) 32import System.Posix.User (getUserEntryForID,userName)
33import qualified Data.ByteString.Lazy.Char8 as L 33import qualified Data.ByteString.Lazy.Char8 as L
34import qualified ConfigFiles 34import qualified ConfigFiles
35import Data.Maybe (maybeToList,listToMaybe,mapMaybe) 35import Data.Maybe
36import Data.Bits 36import Data.Bits
37import Data.Int (Int8) 37import Data.Int (Int8)
38import Data.XML.Types (Event) 38import Data.XML.Types (Event)
@@ -56,10 +56,12 @@ isPeerKey k = case k of { PeerKey {} -> True ; _ -> False }
56isClientKey :: ConnectionKey -> Bool 56isClientKey :: ConnectionKey -> Bool
57isClientKey k = case k of { ClientKey {} -> True ; _ -> False } 57isClientKey k = case k of { ClientKey {} -> True ; _ -> False }
58 58
59localJID :: Text -> Text -> IO Text 59localJID :: Text -> Text -> Text -> IO Text
60localJID user resource = do 60localJID user "." resource = do
61 hostname <- textHostName 61 hostname <- textHostName
62 return $ user <> "@" <> hostname <> "/" <> resource 62 return $ user <> "@" <> hostname <> "/" <> resource
63localJID user profile resource =
64 return $ user <> "@" <> profile <> "/" <> resource
63 65
64data PresenceState = forall status. PresenceState 66data PresenceState = forall status. PresenceState
65 { clients :: TVar (Map ConnectionKey ClientState) 67 { clients :: TVar (Map ConnectionKey ClientState)
@@ -72,6 +74,9 @@ data PresenceState = forall status. PresenceState
72 } 74 }
73 75
74 76
77newPresenceState :: Maybe ConsoleWriter
78 -> TMVar (XMPPServer, Connection.Manager status Text)
79 -> IO PresenceState
75newPresenceState cw xmpp = atomically $ do 80newPresenceState cw xmpp = atomically $ do
76 clients <- newTVar Map.empty 81 clients <- newTVar Map.empty
77 clientsByUser <- newTVar Map.empty 82 clientsByUser <- newTVar Map.empty
@@ -87,6 +92,7 @@ newPresenceState cw xmpp = atomically $ do
87 } 92 }
88 93
89 94
95presenceHooks :: PresenceState -> Int -> XMPPServerParameters
90presenceHooks state verbosity = XMPPServerParameters 96presenceHooks state verbosity = XMPPServerParameters
91 { xmppChooseResourceName = chooseResourceName state 97 { xmppChooseResourceName = chooseResourceName state
92 , xmppTellClientHisName = tellClientHisName state 98 , xmppTellClientHisName = tellClientHisName state
@@ -165,21 +171,25 @@ identifyTTY' ttypids uid inode = ttypid
165 textify (tty,pid) = (fmap lazyByteStringToText tty, pid) 171 textify (tty,pid) = (fmap lazyByteStringToText tty, pid)
166 172
167chooseResourceName :: PresenceState 173chooseResourceName :: PresenceState
168 -> ConnectionKey -> SockAddr -> t -> IO Text 174 -> ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text
169chooseResourceName state k addr desired = do 175chooseResourceName state k addr clientsNameForMe desired = do
170 muid <- getLocalPeerCred' addr 176 muid <- getLocalPeerCred' addr
171 (mtty,pid) <- getTTYandPID muid 177 (mtty,pid) <- getTTYandPID muid
172 user <- getJabberUserForId muid 178 user <- getJabberUserForId muid
173 status <- atomically $ newTVar Nothing 179 status <- atomically $ newTVar Nothing
174 flgs <- atomically $ newTVar 0 180 flgs <- atomically $ newTVar 0
181 profile <- fmap (fromMaybe ".") $ forM clientsNameForMe $ \wanted_profile -> do
182 -- TODO: allow user to select profile
183 return "."
175 let client = ClientState { clientResource = maybe "fallback" id mtty 184 let client = ClientState { clientResource = maybe "fallback" id mtty
176 , clientUser = user 185 , clientUser = user
177 , clientPid = pid 186 , clientProfile = profile
178 , clientStatus = status 187 , clientPid = pid
179 , clientFlags = flgs } 188 , clientStatus = status
189 , clientFlags = flgs }
180 190
181 do -- forward-lookup of the buddies so that it is cached for reversing. 191 do -- forward-lookup of the buddies so that it is cached for reversing.
182 buds <- configText ConfigFiles.getBuddies (clientUser client) 192 buds <- configText ConfigFiles.getBuddies (clientUser client) (clientProfile client)
183 forM_ buds $ \bud -> do 193 forM_ buds $ \bud -> do
184 let (_,h,_) = splitJID bud 194 let (_,h,_) = splitJID bud
185 forkIO $ void $ resolvePeer h 195 forkIO $ void $ resolvePeer h
@@ -191,7 +201,7 @@ chooseResourceName state k addr desired = do
191 (pcInsertNetworkClient k client) 201 (pcInsertNetworkClient k client)
192 mb 202 mb
193 203
194 localJID (clientUser client) (clientResource client) 204 localJID (clientUser client) (clientProfile client) (clientResource client)
195 205
196 where 206 where
197 getTTYandPID muid = do 207 getTTYandPID muid = do
@@ -226,8 +236,8 @@ forClient state k fallback f = do
226tellClientHisName :: PresenceState -> ConnectionKey -> IO Text 236tellClientHisName :: PresenceState -> ConnectionKey -> IO Text
227tellClientHisName state k = forClient state k fallback go 237tellClientHisName state k = forClient state k fallback go
228 where 238 where
229 fallback = localJID "nobody" "fallback" 239 fallback = localJID "nobody" "." "fallback"
230 go client = localJID (clientUser client) (clientResource client) 240 go client = localJID (clientUser client) (clientProfile client) (clientResource client)
231 241
232toMapUnit :: Ord k => [k] -> Map k () 242toMapUnit :: Ord k => [k] -> Map k ()
233toMapUnit xs = Map.fromList $ map (,()) xs 243toMapUnit xs = Map.fromList $ map (,()) xs
@@ -237,11 +247,11 @@ resolveAllPeers hosts = fmap (toMapUnit . concat) $ Prelude.mapM (fmap (take 1)
237 247
238 248
239rosterGetStuff 249rosterGetStuff
240 :: (L.ByteString -> IO [L.ByteString]) 250 :: (ConfigFiles.User -> ConfigFiles.Profile -> IO [L.ByteString])
241 -> PresenceState -> ConnectionKey -> IO [Text] 251 -> PresenceState -> ConnectionKey -> IO [Text]
242rosterGetStuff what state k = forClient state k (return []) 252rosterGetStuff what state k = forClient state k (return [])
243 $ \client -> do 253 $ \client -> do
244 jids <- configText what (clientUser client) 254 jids <- configText what (clientUser client) (clientProfile client)
245 let hosts = map ((\(_,h,_)->h) . splitJID) jids 255 let hosts = map ((\(_,h,_)->h) . splitJID) jids
246 case state of 256 case state of
247 PresenceState { server = svVar } -> do 257 PresenceState { server = svVar } -> do
@@ -267,13 +277,16 @@ data Conn = Conn { connChan :: TChan Stanza
267 , auxAddr :: SockAddr } 277 , auxAddr :: SockAddr }
268 278
269configText :: Functor f => 279configText :: Functor f =>
270 (L.ByteString -> f [L.ByteString]) -> Text -> f [Text] 280 (ConfigFiles.User -> ConfigFiles.Profile -> f [L.ByteString])
271configText what u = fmap (map lazyByteStringToText) 281 -> Text -- user
272 $ what (textToLazyByteString u) 282 -> Text -- profile
273 283 -> f [Text] -- items
274getBuddies' :: Text -> IO [Text] 284configText what u p = fmap (map lazyByteStringToText)
285 $ what (textToLazyByteString u) (Text.unpack p)
286
287getBuddies' :: Text -> Text -> IO [Text]
275getBuddies' = configText ConfigFiles.getBuddies 288getBuddies' = configText ConfigFiles.getBuddies
276getSolicited' :: Text -> IO [Text] 289getSolicited' :: Text -> Text -> IO [Text]
277getSolicited' = configText ConfigFiles.getSolicited 290getSolicited' = configText ConfigFiles.getSolicited
278 291
279sendProbesAndSolicitations :: PresenceState 292sendProbesAndSolicitations :: PresenceState
@@ -282,10 +295,11 @@ sendProbesAndSolicitations state k laddr chan = do
282 -- get all buddies & solicited matching k for all users 295 -- get all buddies & solicited matching k for all users
283 xs <- runTraversableT $ do 296 xs <- runTraversableT $ do
284 cbu <- lift $ atomically $ readTVar $ clientsByUser state 297 cbu <- lift $ atomically $ readTVar $ clientsByUser state
285 user <- liftT $ Map.keys cbu 298 (user,LocalPresence cmap) <- liftT $ Map.toList cbu
299 profile <- liftT $ nub $ map clientProfile $ Map.elems cmap
286 (isbud,getter) <- liftT [(True ,getBuddies' ) 300 (isbud,getter) <- liftT [(True ,getBuddies' )
287 ,(False,getSolicited')] 301 ,(False,getSolicited')]
288 bud <- liftMT $ getter user 302 bud <- liftMT $ getter user profile
289 let (u,h,r) = splitJID bud 303 let (u,h,r) = splitJID bud
290 addr <- liftMT $ nub `fmap` resolvePeer h 304 addr <- liftMT $ nub `fmap` resolvePeer h
291 liftT $ guard (PeerKey addr == k) 305 liftT $ guard (PeerKey addr == k)
@@ -294,10 +308,10 @@ sendProbesAndSolicitations state k laddr chan = do
294 -- is a bad idea. Perhaps due to laziness and an 308 -- is a bad idea. Perhaps due to laziness and an
295 -- unforced list? Instead, we will return a list 309 -- unforced list? Instead, we will return a list
296 -- of (Bool,Text) for processing outside. 310 -- of (Bool,Text) for processing outside.
297 return (isbud,u,if isbud then "" else user) 311 return (isbud,u,user,profile)
298 -- XXX: The following O(n²) nub may be a little 312 -- XXX: The following O(n²) nub may be a little
299 -- too onerous. 313 -- too onerous.
300 forM_ (nub xs) $ \(isbud,u,user) -> do 314 forM_ (nub xs) $ \(isbud,u,user,profile) -> do
301 let make = if isbud then presenceProbe 315 let make = if isbud then presenceProbe
302 else presenceSolicitation 316 else presenceSolicitation
303 toh = peerKeyToText k 317 toh = peerKeyToText k
@@ -378,13 +392,17 @@ rewriteJIDForClient laddr jid buds = do
378 else peerKeyToResolvedName buds (PeerKey addr) 392 else peerKeyToResolvedName buds (PeerKey addr)
379 return (mine,(n,h',r)) 393 return (mine,(n,h',r))
380 394
395-- This attempts to reverse resolve a peers address to give the human-friendly
396-- domain name as it appears in the roster. It prefers host names that occur
397-- in the given list of JIDs, but will fall back to any reverse-resolved name
398-- and if it was unable to reverse the address, it will yield an ip address.
381peerKeyToResolvedName :: [Text] -> ConnectionKey -> IO Text 399peerKeyToResolvedName :: [Text] -> ConnectionKey -> IO Text
382peerKeyToResolvedName buds k@(ClientKey { localAddress=addr }) = return "ErrorClIeNt1" 400peerKeyToResolvedName buds k@(ClientKey { localAddress=addr }) = return "ErrorClIeNt1"
383peerKeyToResolvedName buds pk = do 401peerKeyToResolvedName buds pk = do
384 ns <- peerKeyToResolvedNames pk 402 ns <- peerKeyToResolvedNames pk
385 let hs = map (\jid -> let (_,h,_)=splitJID jid in h) buds 403 let hs = map (\jid -> let (_,h,_)=splitJID jid in h) buds
386 ns' = sortBy (comparing $ not . flip elem hs) ns 404 ns' = sortBy (comparing $ not . flip elem hs) ns
387 return $ maybe (peerKeyToText pk) id (listToMaybe ns') 405 return $ fromMaybe (peerKeyToText pk) (listToMaybe ns')
388 406
389 407
390multiplyJIDForClient :: SockAddr -> Text -> IO (Bool,[(Maybe Text,Text,Maybe Text)]) 408multiplyJIDForClient :: SockAddr -> Text -> IO (Bool,[(Maybe Text,Text,Maybe Text)])
@@ -468,33 +486,46 @@ deliverMessage state fail msg =
468 if not mine then fail else do 486 if not mine then fail else do
469 let to' = unsplitJID (n,h,r) 487 let to' = unsplitJID (n,h,r)
470 cmap <- atomically . readTVar $ clientsByUser state 488 cmap <- atomically . readTVar $ clientsByUser state
471 (from',chans,ks) <- do 489 chans <- fmap (fromMaybe []) $ do
472 flip (maybe $ return (Nothing,[],[])) n $ \n -> do 490 forM (n >>= flip Map.lookup cmap) $ \presence_container -> do
473 buds <- configText ConfigFiles.getBuddies n 491 let ks = Map.keys (networkClients presence_container)
492 chans = do
493 (k,client) <- Map.toList $ networkClients presence_container
494 chan <- maybeToList $ Map.lookup k key_to_chan
495 return (clientProfile client, chan)
496 forM chans $ \(profile,chan) -> do
497 buds <- configText ConfigFiles.getBuddies (fromJust n) profile
474 from' <- do 498 from' <- do
475 flip (maybe $ return Nothing) (stanzaFrom msg) $ \from -> do 499 flip (maybe $ return Nothing) (stanzaFrom msg) $ \from -> do
476 (_,trip) <- rewriteJIDForClient laddr from buds 500 (_,trip) <- rewriteJIDForClient laddr from buds
477 return . Just $ unsplitJID trip 501 return . Just $ unsplitJID trip
478 let nope = return (from',[],[]) 502 return (from',chan)
479 flip (maybe nope) (Map.lookup n cmap) $ \presence_container -> do
480 let ks = Map.keys (networkClients presence_container)
481 chans = mapMaybe (flip Map.lookup key_to_chan) ks
482 return (from',chans,ks)
483 putStrLn $ "chan count: " ++ show (length chans) 503 putStrLn $ "chan count: " ++ show (length chans)
484 let msg' = msg { stanzaTo=Just to' 504 if null chans then do
485 , stanzaFrom=from' } 505 forM_ (stanzaFrom msg) $ \from -> do
486 if null chans then deliverToConsole state fail msg' else do 506 from' <- do
487 forM_ chans $ \Conn { connChan=chan} -> do 507 -- Fallback to "." profile when no clients.
488 putStrLn $ "sending "++show (stanzaId msg)++" to clients "++show ks 508 buds <- maybe (return [])
489 -- TODO: Cloning isn't really neccessary unless there are multiple 509 (\n -> configText ConfigFiles.getBuddies n ".")
490 -- destinations and we should probably transition to minimal cloning, 510 n
491 -- or else we should distinguish between announcable stanzas and 511 (_,trip) <- rewriteJIDForClient laddr from buds
492 -- consumable stanzas and announcables use write-only broadcast 512 return . Just $ unsplitJID trip
493 -- channels that must be cloned in order to be consumed. 513 let msg' = msg { stanzaTo=Just to'
494 -- For now, we are doing redundant cloning. 514 , stanzaFrom=from' }
495 dup <- cloneStanza msg' 515 deliverToConsole state fail msg'
496 sendModifiedStanzaToClient dup 516 else do
497 chan 517 forM_ chans $ \(from',Conn { connChan=chan}) -> do
518 -- TODO: Cloning isn't really neccessary unless there are multiple
519 -- destinations and we should probably transition to minimal cloning,
520 -- or else we should distinguish between announcable stanzas and
521 -- consumable stanzas and announcables use write-only broadcast
522 -- channels that must be cloned in order to be consumed.
523 -- For now, we are doing redundant cloning.
524 let msg' = msg { stanzaTo=Just to'
525 , stanzaFrom=from' }
526 dup <- cloneStanza msg'
527 sendModifiedStanzaToClient dup
528 chan
498 529
499 530
500setClientFlag :: PresenceState -> ConnectionKey -> Int8 -> IO () 531setClientFlag :: PresenceState -> ConnectionKey -> Int8 -> IO ()
@@ -513,9 +544,9 @@ informSentRoster state k = do
513 setClientFlag state k cf_interested 544 setClientFlag state k cf_interested
514 545
515 546
516subscribedPeers :: Text -> IO [SockAddr] 547subscribedPeers :: Text -> Text -> IO [SockAddr]
517subscribedPeers user = do 548subscribedPeers user profile = do
518 jids <- configText ConfigFiles.getSubscribers user 549 jids <- configText ConfigFiles.getSubscribers user profile
519 let hosts = map ((\(_,h,_)->h) . splitJID) jids 550 let hosts = map ((\(_,h,_)->h) . splitJID) jids
520 fmap Map.keys $ resolveAllPeers hosts 551 fmap Map.keys $ resolveAllPeers hosts
521 552
@@ -546,7 +577,7 @@ informClientPresence0 state mbk client stanza = do
546 when (not is_avail) $ do 577 when (not is_avail) $ do
547 atomically $ setClientFlag0 client cf_available 578 atomically $ setClientFlag0 client cf_available
548 maybe (return ()) (sendCachedPresence state) mbk 579 maybe (return ()) (sendCachedPresence state) mbk
549 addrs <- subscribedPeers (clientUser client) 580 addrs <- subscribedPeers (clientUser client) (clientProfile client)
550 ktc <- atomically $ readTVar (keyToChan state) 581 ktc <- atomically $ readTVar (keyToChan state)
551 let connected = mapMaybe (flip Map.lookup ktc . PeerKey) addrs 582 let connected = mapMaybe (flip Map.lookup ktc . PeerKey) addrs
552 forM_ connected $ \con -> do 583 forM_ connected $ \con -> do
@@ -649,7 +680,7 @@ answerProbe state mto k chan = do
649 680
650 flip (maybe $ return ()) muser $ \(u,conn,ch) -> do 681 flip (maybe $ return ()) muser $ \(u,conn,ch) -> do
651 682
652 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers u 683 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers u (_todo {- profile -})
653 let gaddrs = groupBy (\a b -> snd a == snd b) (sort resolved_subs) 684 let gaddrs = groupBy (\a b -> snd a == snd b) (sort resolved_subs)
654 whitelist = do 685 whitelist = do
655 xs <- gaddrs 686 xs <- gaddrs
@@ -693,7 +724,7 @@ sendCachedPresence :: PresenceState -> ConnectionKey -> IO ()
693sendCachedPresence state k = do 724sendCachedPresence state k = do
694 forClient state k (return ()) $ \client -> do 725 forClient state k (return ()) $ \client -> do
695 rbp <- atomically $ readTVar (remotesByPeer state) 726 rbp <- atomically $ readTVar (remotesByPeer state)
696 jids <- configText ConfigFiles.getBuddies (clientUser client) 727 jids <- configText ConfigFiles.getBuddies (clientUser client) (clientProfile client)
697 let hosts = map ((\(_,h,_)->h) . splitJID) jids 728 let hosts = map ((\(_,h,_)->h) . splitJID) jids
698 addrs <- resolveAllPeers hosts 729 addrs <- resolveAllPeers hosts
699 let onlines = rbp `Map.intersection` Map.mapKeys PeerKey addrs 730 let onlines = rbp `Map.intersection` Map.mapKeys PeerKey addrs
@@ -714,7 +745,7 @@ sendCachedPresence state k = do
714 sendModifiedStanzaToClient (dup { stanzaFrom=Just from' }) 745 sendModifiedStanzaToClient (dup { stanzaFrom=Just from' })
715 (connChan con) 746 (connChan con)
716 747
717 pending <- configText ConfigFiles.getPending (clientUser client) 748 pending <- configText ConfigFiles.getPending (clientUser client) (clientProfile client)
718 hostname <- textHostName 749 hostname <- textHostName
719 forM_ pending $ \pending_jid -> do 750 forM_ pending $ \pending_jid -> do
720 let cjid = unsplitJID ( Just $ clientUser client 751 let cjid = unsplitJID ( Just $ clientUser client
@@ -728,27 +759,39 @@ sendCachedPresence state k = do
728 return () 759 return ()
729 760
730addToRosterFile :: (MonadPlus t, Traversable t) => 761addToRosterFile :: (MonadPlus t, Traversable t) =>
731 (L.ByteString -> (L.ByteString -> IO (t L.ByteString)) 762 (ConfigFiles.User
763 -> ConfigFiles.Profile
764 -> (L.ByteString -> IO (t L.ByteString))
732 -> Maybe L.ByteString 765 -> Maybe L.ByteString
733 -> t1) 766 -> t1)
734 -> Text -> Text -> [SockAddr] -> t1 767 -> Text -- user
735addToRosterFile doit whose to addrs = 768 -> Text -- profile
736 modifyRosterFile doit whose to addrs True 769 -> Text -> [SockAddr] -> t1
770addToRosterFile doit whose profile to addrs =
771 modifyRosterFile doit whose profile to addrs True
737 772
738removeFromRosterFile :: (MonadPlus t, Traversable t) => 773removeFromRosterFile :: (MonadPlus t, Traversable t) =>
739 (L.ByteString -> (L.ByteString -> IO (t L.ByteString)) 774 (ConfigFiles.User
775 -> ConfigFiles.Profile
776 -> (L.ByteString -> IO (t L.ByteString))
740 -> Maybe L.ByteString 777 -> Maybe L.ByteString
741 -> t1) 778 -> t1)
742 -> Text -> Text -> [SockAddr] -> t1 779 -> Text -- user
743removeFromRosterFile doit whose to addrs = 780 -> Text -- profile
744 modifyRosterFile doit whose to addrs False 781 -> Text -> [SockAddr] -> t1
782removeFromRosterFile doit whose profile to addrs =
783 modifyRosterFile doit whose profile to addrs False
745 784
746modifyRosterFile :: (Traversable t, MonadPlus t) => 785modifyRosterFile :: (Traversable t, MonadPlus t) =>
747 (L.ByteString -> (L.ByteString -> IO (t L.ByteString)) 786 (ConfigFiles.User
787 -> ConfigFiles.Profile
788 -> (L.ByteString -> IO (t L.ByteString))
748 -> Maybe L.ByteString 789 -> Maybe L.ByteString
749 -> t1) 790 -> t1)
750 -> Text -> Text -> [SockAddr] -> Bool -> t1 791 -> Text -- user
751modifyRosterFile doit whose to addrs bAdd = do 792 -> Text -- profile
793 -> Text -> [SockAddr] -> Bool -> t1
794modifyRosterFile doit whose profile to addrs bAdd = do
752 let (mu,_,_) = splitJID to 795 let (mu,_,_) = splitJID to
753 cmp jid = runTraversableT $ do 796 cmp jid = runTraversableT $ do
754 let (msu,stored_h,mr) = splitJID (lazyByteStringToText jid) 797 let (msu,stored_h,mr) = splitJID (lazyByteStringToText jid)
@@ -767,7 +810,7 @@ modifyRosterFile doit whose to addrs bAdd = do
767 if null (stored_addrs \\ addrs) then mzero else do 810 if null (stored_addrs \\ addrs) then mzero else do
768 -- keep 811 -- keep
769 return jid 812 return jid
770 doit (textToLazyByteString whose) 813 doit (textToLazyByteString whose) (Text.unpack profile)
771 cmp 814 cmp
772 (guard bAdd >> Just (textToLazyByteString to)) 815 (guard bAdd >> Just (textToLazyByteString to))
773 816
@@ -781,9 +824,9 @@ clientSubscriptionRequest state fail k stanza chan = do
781 flip (maybe fail) mu $ \u -> do 824 flip (maybe fail) mu $ \u -> do
782 -- add to-address to from's solicited 825 -- add to-address to from's solicited
783 addrs <- resolvePeer h 826 addrs <- resolvePeer h
784 addToRosterFile ConfigFiles.modifySolicited (clientUser client) to addrs 827 addToRosterFile ConfigFiles.modifySolicited (clientUser client) (clientProfile client) to addrs
785 removeFromRosterFile ConfigFiles.modifyBuddies (clientUser client) to addrs 828 removeFromRosterFile ConfigFiles.modifyBuddies (clientUser client) (clientProfile client) to addrs
786 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers (clientUser client) 829 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers (clientUser client) (clientProfile client)
787 let is_subscribed = not . null $ intersect (map ((mu,).PeerKey) addrs) resolved_subs 830 let is_subscribed = not . null $ intersect (map ((mu,).PeerKey) addrs) resolved_subs
788 -- subscribers: "from" 831 -- subscribers: "from"
789 -- buddies: "to" 832 -- buddies: "to"
@@ -831,10 +874,10 @@ clientSubscriptionRequest state fail k stanza chan = do
831 874
832 875
833resolvedFromRoster 876resolvedFromRoster
834 :: (L.ByteString -> IO [L.ByteString]) 877 :: (ConfigFiles.User -> ConfigFiles.Profile -> IO [L.ByteString])
835 -> UserName -> IO [(Maybe UserName, ConnectionKey)] 878 -> UserName -> Text -> IO [(Maybe UserName, ConnectionKey)]
836resolvedFromRoster doit u = do 879resolvedFromRoster doit u profile = do
837 subs <- configText doit u 880 subs <- configText doit u profile
838 runTraversableT $ do 881 runTraversableT $ do
839 (mu,h,_) <- liftT $ splitJID `fmap` subs 882 (mu,h,_) <- liftT $ splitJID `fmap` subs
840 addr <- liftMT $ fmap nub $ resolvePeer h 883 addr <- liftMT $ fmap nub $ resolvePeer h
@@ -870,7 +913,7 @@ peerSubscriptionRequest state fail k stanza chan = do
870 (_,fromtup) <- rewriteJIDForClient laddr from [] 913 (_,fromtup) <- rewriteJIDForClient laddr from []
871 flip (maybe fail) mto_u $ \u -> do 914 flip (maybe fail) mto_u $ \u -> do
872 flip (maybe fail) mfrom_u $ \from_u -> do 915 flip (maybe fail) mfrom_u $ \from_u -> do
873 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers u 916 resolved_subs <- resolvedFromRoster ConfigFiles.getSubscribers u (_todo {- profile -})
874 let already_subscribed = elem (mfrom_u,k) resolved_subs 917 let already_subscribed = elem (mfrom_u,k) resolved_subs
875 is_wanted = case stanzaType stanza of 918 is_wanted = case stanzaType stanza of
876 PresenceRequestSubscription b -> b 919 PresenceRequestSubscription b -> b
@@ -900,9 +943,9 @@ peerSubscriptionRequest state fail k stanza chan = do
900 943
901 already_pending <- 944 already_pending <-
902 if is_wanted then 945 if is_wanted then
903 addToRosterFile ConfigFiles.modifyPending u from' addrs 946 addToRosterFile ConfigFiles.modifyPending u (_todo {- profile -}) from' addrs
904 else do 947 else do
905 removeFromRosterFile ConfigFiles.modifySubscribers u from' addrs 948 removeFromRosterFile ConfigFiles.modifySubscribers u (_todo {- profile -}) from' addrs
906 reply <- makeInformSubscription "jabber:server" to from is_wanted 949 reply <- makeInformSubscription "jabber:server" to from is_wanted
907 sendModifiedStanzaToPeer reply chan 950 sendModifiedStanzaToPeer reply chan
908 return False 951 return False
@@ -933,9 +976,9 @@ clientInformSubscription state fail k stanza = do
933 let (mu,h,mr) = splitJID to 976 let (mu,h,mr) = splitJID to
934 addrs <- resolvePeer h 977 addrs <- resolvePeer h
935 -- remove from pending 978 -- remove from pending
936 buds <- resolvedFromRoster ConfigFiles.getBuddies (clientUser client) 979 buds <- resolvedFromRoster ConfigFiles.getBuddies (clientUser client) (clientProfile client)
937 let is_buddy = not . null $ map ((mu,) . PeerKey) addrs `intersect` buds 980 let is_buddy = not . null $ map ((mu,) . PeerKey) addrs `intersect` buds
938 removeFromRosterFile ConfigFiles.modifyPending (clientUser client) to addrs 981 removeFromRosterFile ConfigFiles.modifyPending (clientUser client) (clientProfile client) to addrs
939 let (relationship,addf,remf) = 982 let (relationship,addf,remf) =
940 case stanzaType stanza of 983 case stanzaType stanza of
941 PresenceInformSubscription True -> 984 PresenceInformSubscription True ->
@@ -947,8 +990,8 @@ clientInformSubscription state fail k stanza = do
947 else "none" ) 990 else "none" )
948 , ConfigFiles.modifyOthers 991 , ConfigFiles.modifyOthers
949 , ConfigFiles.modifySubscribers ) 992 , ConfigFiles.modifySubscribers )
950 addToRosterFile addf (clientUser client) to addrs 993 addToRosterFile addf (clientUser client) (clientProfile client) to addrs
951 removeFromRosterFile remf (clientUser client) to addrs 994 removeFromRosterFile remf (clientUser client) (clientProfile client) to addrs
952 995
953 do 996 do
954 cbu <- atomically $ readTVar (clientsByUser state) 997 cbu <- atomically $ readTVar (clientsByUser state)
@@ -1009,8 +1052,8 @@ peerInformSubscription state fail k stanza = do
1009 -- This would allow us to answer anonymous probes with 'unsubscribed'. 1052 -- This would allow us to answer anonymous probes with 'unsubscribed'.
1010 flip (maybe fail) muser $ \user -> do 1053 flip (maybe fail) muser $ \user -> do
1011 addrs <- resolvePeer from_h 1054 addrs <- resolvePeer from_h
1012 was_solicited <- removeFromRosterFile ConfigFiles.modifySolicited user from'' addrs 1055 was_solicited <- removeFromRosterFile ConfigFiles.modifySolicited user (_todo {- profile -}) from'' addrs
1013 subs <- resolvedFromRoster ConfigFiles.getSubscribers user 1056 subs <- resolvedFromRoster ConfigFiles.getSubscribers user (_todo {- profile -})
1014 let is_sub = not . null $ map ((from_u,) . PeerKey) addrs `intersect` subs 1057 let is_sub = not . null $ map ((from_u,) . PeerKey) addrs `intersect` subs
1015 let (relationship,addf,remf) = 1058 let (relationship,addf,remf) =
1016 case stanzaType stanza of 1059 case stanzaType stanza of
@@ -1023,8 +1066,8 @@ peerInformSubscription state fail k stanza = do
1023 else "none") 1066 else "none")
1024 , ConfigFiles.modifyOthers 1067 , ConfigFiles.modifyOthers
1025 , ConfigFiles.modifyBuddies ) 1068 , ConfigFiles.modifyBuddies )
1026 addToRosterFile addf user from'' addrs 1069 addToRosterFile addf user (_todo {- profile -}) from'' addrs
1027 removeFromRosterFile remf user from'' addrs 1070 removeFromRosterFile remf user (_todo {- profile -}) from'' addrs
1028 1071
1029 hostname <- textHostName 1072 hostname <- textHostName
1030 let to' = unsplitJID (Just user, hostname, Nothing) 1073 let to' = unsplitJID (Just user, hostname, Nothing)