1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2010-2013 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #ifndef LICQDAEMON_USERMANAGER_H
21 #define LICQDAEMON_USERMANAGER_H
22 
23 #include <licq/contactlist/usermanager.h>
24 
25 #include <map>
26 #include <set>
27 
28 #include <licq/thread/readwritemutex.h>
29 #include <licq/userid.h>
30 
31 
32 namespace LicqDaemon
33 {
34 class Group;
35 
36 typedef std::map<Licq::UserId, Licq::User*> UserMap;
37 typedef std::map<int, Group*> GroupMap;
38 typedef std::map<Licq::UserId, Licq::Owner*> OwnerMap;
39 
40 class UserManager : public Licq::UserManager
41 {
42 public:
43   UserManager();
44   ~UserManager();
45 
46   /**
47    * Shut down the user manager
48    */
49   void shutdown();
50 
51   bool Load();
52   void writeToUserHistory(Licq::User* user, const std::string& text);
53 
54   /**
55    * Load owners and users for a protocol
56    * Called by ProtocolManager when protocol is loaded
57    *
58    * @param protocolId Protocol to load contacts for
59    */
60   void loadProtocol(unsigned long protocolId);
61 
62   /**
63    * Check if protocol unloading should be allowed
64    * Called by ProtocolManager before protocol is unloaded
65    *
66    * @param protocolId Id of protocol to be unloaded
67    * @return False if unloading should be aborted
68    */
69   bool allowUnloadProtocol(unsigned long protocolId);
70 
71   /**
72    * Prepare to unload a protocol
73    * Called by ProtocolManager when protocol is unloaded
74    *
75    * @param protocolId Protocol to be unloaded
76    */
77   void unloadProtocol(unsigned long protocolId);
78 
79   /**
80    * Fetch and lock the user list map
81    *
82    * @return The internal map with all users
83    */
84   const UserMap& lockUserList();
85 
86   /**
87    * Free lock on user list map
88    */
89   void unlockUserList();
90 
91   /**
92    * Fetch and lock the owner list map
93    *
94    * @return The internal map with all owners
95    */
96   const OwnerMap& lockOwnerList();
97 
98   /**
99    * Free lock on group list map
100    */
101   void unlockOwnerList();
102 
103   /**
104    * Fetch and lock the group list map
105    *
106    * @return The internal map with all groups
107    */
108   const GroupMap& lockGroupList();
109 
110   /**
111    * Free lock on group list map
112    */
113   void unlockGroupList();
114 
115   /**
116    * Fetch and lock a group
117    *
118    * @param groupId Id of group to get
119    * @param writeLock True to lock group for writing, false for read lock
120    * @return Requested group if exist, otherwise NULL
121    */
122   Group* fetchGroup(int groupId, bool writeLock = false);
123 
124   /**
125    * Find and lock an user object
126    *
127    * @param userId User id
128    * @param writeLock True to lock user for writing, false for read lock
129    * @param addUser True if user should be added (as temporary) if not found
130    * @param retWasAdded If not null, will be set to true if user was added
131    * @return The locked user object if user exist or was created, otherwise NULL
132    */
133   Licq::User* fetchUser(const Licq::UserId& userId, bool writeLock = false,
134       bool addUser = false, bool* retWasAdded = NULL);
135 
136   /**
137    * Fetch and lock an owner object based on protocolId
138    *
139    * @param userId Id of owner to get
140    * @param writeLock True to lock owner for writing, false for read lock
141    * @return The locked owner object if owner exists, otherwise NULL
142    */
143   Licq::Owner* fetchOwner(const Licq::UserId& userId, bool writeLock = false);
144 
145   // From Licq::UserManager
146   void addOwner(const Licq::UserId& userId);
147   bool removeOwner(const Licq::UserId& userId);
148   bool userExists(const Licq::UserId& userId);
149   void notifyUserUpdated(const Licq::UserId& userId, unsigned long subSignal);
150   bool addUser(const Licq::UserId& userId, bool permanent = true,
151       bool addToServer = true, unsigned short groupId = 0);
152   void removeUser(const Licq::UserId& userId);
153   void removeLocalUser(const Licq::UserId& userId);
154   bool groupExists(int groupId);
155   int AddGroup(const std::string& name);
156   void RemoveGroup(int groupId);
157   bool RenameGroup(int groupId, const std::string& name, const Licq::UserId& skipOwnerId = Licq::UserId());
158   void ModifyGroupSorting(int groupId, int newIndex);
159   void setGroupServerId(int groupId, const Licq::UserId& ownerId, unsigned long serverId);
160   int getGroupFromServerId(const Licq::UserId& ownerId, unsigned long serverId);
161   int GetGroupFromName(const std::string& name);
162   std::string GetGroupNameFromGroup(int groupId);
163   void setUserInGroup(const Licq::UserId& userId, int groupId,
164       bool inGroup, bool updateServer = true);
165   void SaveAllUsers();
166   const std::string& defaultUserEncoding();
167   void setDefaultUserEncoding(const std::string& defaultEncoding);
168   unsigned short NumUsers();
169   unsigned short NumOwners();
170   unsigned int NumGroups();
171 
172 private:
173   /**
174    * Load user list from configuration file
175    *
176    * @param ownerId Owner to load users for
177    */
178   void loadUserList(const Licq::UserId& ownerId);
179 
180   void saveOwnerList();
181 
182   /**
183    * Save user list to configuration file
184    * Note: This function assumes that the user list is already locked.
185    *
186    * @param ownerId Owner to save user list for
187    */
188   void saveUserList(const Licq::UserId& ownerId);
189 
190   void SaveGroups();
191 
192   /**
193    * Create a user object, either Licq::User or protocol subclass
194    *
195    * @param id User id
196    * @param temporary True if user isn't premanently added to contact list
197    * @return A created Licq::User
198    */
199   Licq::User* createUser(const Licq::UserId& id, bool temporary = false);
200 
201   /**
202    * Create an owner object, either Licq::Owner or protocol subclass
203    *
204    * @param id Owner user id
205    * @return a created Licq::Owner
206    */
207   Licq::Owner* createOwner(const Licq::UserId& id);
208 
209   Licq::ReadWriteMutex myGroupListMutex;
210   Licq::ReadWriteMutex myUserListMutex;
211   Licq::ReadWriteMutex myOwnerListMutex;
212 
213   GroupMap myGroups;
214   UserMap myUsers;
215   OwnerMap myOwners;
216   std::set<Licq::UserId> myConfiguredOwners;
217   bool m_bAllowSave;
218   std::string myDefaultEncoding;
219 };
220 
221 extern UserManager gUserManager;
222 
223 } // namespace LicqDaemon
224 
225 #endif
226