1 /* Copyright (C) 2000-2005 Thomas Bopp, Thorsten Hampel, Ludger Merkens
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * $Id: home.pike,v 1.2 2008/04/18 10:02:46 exodusd Exp $
19 inherit "/kernel/module";
23 #include <exception.h>
24 #include <attributes.h>
25 #include <configure.h>
26 //! The home module must be located in the root-room and resolves
27 //! any user or group name parsed and gets the appropriate workarea
28 //! for it. Queried users/groups can be seen in this modules inventory
29 //! afterwards. This way emacs and other tools may be able to resolve
30 //! path, even though actually no object is really places in this container.
31 class home : public module{
38 bool mount_users = true;
39 bool mount_groups = true;
46 void create(object g, object h) {
49 THROW("GroupWrapper: Group is no proxy !", E_ERROR);
51 THROW("Group "+g->get_group_name() + " missing workroom!", E_ERROR);
54 THROW("GroupWrapper: Home is no proxy !", E_ERROR);
57 string get_identifier() { return grp->get_identifier(); }
58 int get_object_class() { return CLASS_ROOM|CLASS_CONTAINER; }
59 int status() { if ( !objectp(home) ) return 3; return home->status(); }
60 int get_object_id() { return home->get_object_id(); }
62 final mixed `->(string func)
64 if ( func == "get_identifier" )
65 return get_identifier;
66 else if ( func == "create" )
68 else if ( func == "get_object_class" )
69 return get_object_class;
70 else if ( func == "status" )
72 else if ( func == "get_object_id" )
75 return home->get_object()[func];
80 mapping directoryCache = ([ ]);
82 string get_identifier() { return "home"; }
83 void update_identifier(string name) {};
85 int get_object_class()
87 return ::get_object_class() | CLASS_CONTAINER | CLASS_ROOM;
91 bool insert_obj(object obj)
93 return true; //THROW("No Insert in home !", E_ACCESS);
96 bool remove_obj(object obj)
98 return true; // THROW("No Remove in home !", E_ACCESS);
101 /** Checks whether a user can be mounted. If user mounting is switched off
102 * in the config, then only system users ("restricted" users) will be mounted.
103 * @param identifier identifier of the user to check
104 * @return true if the user can be mounted, false if not
106 bool can_mount_user ( string identifier ) {
107 if ( mount_users ) return true;
108 if ( _Persistence->user_restricted( identifier ) ) return true;
112 /** Checks whether a group can be mounted. If group mounting is switched off
113 * in the config, then only system groups ("restricted" groups) will be
115 * @param identifier identifier of the group to check
116 * @return true if the group can be mounted, false if not
118 bool can_mount_group ( string identifier ) {
119 if ( mount_groups ) return true;
120 if ( _Persistence->group_restricted( identifier ) ) return true;
124 array get_inventory()
126 array groups = this_user()->get_groups();
127 foreach(groups, object grp) {
128 string id = grp->get_identifier();
129 if ( !can_mount_group(id) )
131 if ( !directoryCache[id] ) {
133 directoryCache[id] = GroupWrapper(grp,
134 grp->query_attribute(GROUP_WORKROOM));
137 FATAL("Failed to mount GROUP in home-Module: %O\n%O\n%O",
138 grp, err[0], err[1]);
142 if ( can_mount_user(this_user()->get_identifier()) )
143 mount( this_user() );
144 return values(directoryCache);
147 array get_inventory_by_class(int cl)
149 if ( can_mount_user(this_user()->get_identifier()) )
150 mount( this_user() );
152 if ( cl & CLASS_GROUP )
153 return values(directoryCache);
154 else if ( cl & CLASS_ROOM )
155 return values(directoryCache);
165 * Get the object by its name. This function is overloaded to allow
166 * the /home syntax to all directories, without having the workrooms
167 * environments point there. This means the Container is actually empty,
168 * but you can do cd /home/user and get somewhere.
170 * @param string obj_name - the object to resolve
173 object get_object_byname(string obj_name)
177 LOG("Getting "+ obj_name);
178 if ( objectp(directoryCache[obj_name]) ) {
179 if ( directoryCache[obj_name]->status() >= 0 &&
180 directoryCache[obj_name]->status() != PSTAT_DELETED )
181 return directoryCache[obj_name];
183 m_delete(directoryCache, obj_name);
186 obj = MODULE_GROUPS->lookup(obj_name);
187 if ( objectp(obj) && can_mount_group(obj_name) ) {
188 LOG("Found group - returning workroom !");
189 res = obj->query_attribute(GROUP_WORKROOM);
192 obj = MODULE_USERS->lookup(obj_name);
193 if ( objectp(obj) && can_mount_user(obj_name) ) {
194 if ( obj->status() >= 0 )
195 res = obj->query_attribute(USER_WORKROOM);
199 directoryCache[obj_name] = GroupWrapper(obj, res);
201 return directoryCache[obj_name];
204 object mount(object grp)
208 string name = grp->get_identifier();
210 if ( objectp(directoryCache[name]) )
211 return directoryCache[name]->home;
213 if ( grp->get_object_class() & CLASS_GROUP ) {
214 if ( ! can_mount_group(name) )
216 wr = grp->query_attribute(GROUP_WORKROOM);
218 else if ( grp->get_object_class() & CLASS_USER ) {
219 if ( ! can_mount_user(name) )
221 wr = grp->query_attribute(USER_WORKROOM);
226 directoryCache[name] = GroupWrapper(grp, wr);
231 void unmount ( object grp )
233 // allow unmounting only for group and user factory and for admins:
234 if ( CALLER != get_factory(CLASS_GROUP) &&
235 CALLER != get_factory(CLASS_USER) &&
236 ! _ADMIN->is_member( this_user() ) )
237 steam_error("Invalid caller for unmount: %O !", CALLER);
239 string name = grp->get_identifier();
240 if ( !objectp( directoryCache[ name ] ) )
242 m_delete( directoryCache, name );
245 int is_mounted ( object grp )
247 string name = grp->get_identifier();
248 return objectp( directoryCache[ name ] );
251 string contains_virtual(object obj)
253 object creatorGroup = obj->get_creator();
254 string id = creatorGroup->get_identifier();
255 if ( creatorGroup->get_object_class() & CLASS_GROUP ) {
256 if ( ! can_mount_group(id) )
260 else if ( creatorGroup->get_object_class() & CLASS_USER ) {
261 if ( ! can_mount_user(id) )
263 if ( creatorGroup->query_attribute(USER_WORKROOM) == obj )
264 return creatorGroup->get_user_name();
274 * Called after the object is loaded. Move the object to the workroom !
279 if ( MODULE_OBJECTS && objectp(_ROOTROOM) && oEnvironment != _ROOTROOM ) {
280 set_attribute(OBJ_NAME, "home");
285 // load config mapping only locally to conserve memory:
286 mapping config = Config.read_config_file( _Server.get_config_dir()+"/modules/home.cfg", "home" );
287 mount_users = !Config.bool_value( config["dont_mount_users"] );
288 if ( !mount_users ) MESSAGE( "home: not mounting users" );
289 mount_groups = !Config.bool_value( config["dont_mount_groups"] );
290 if ( !mount_groups ) MESSAGE( "home: not mounting groups" );
294 * Get the content size of this object which does not make really
295 * sense for containers.
297 * @return the content size: -2 as the container can be seen as an inventory
300 int get_content_size()
306 * This function returns the stat() of this object. This has the
307 * same format as statting a file.
309 * @return status array as in file_stat()
310 * @see get_content_size
314 int creator_id = objectp(get_creator())?get_creator()->get_object_id():0;
317 return ({ 16877, get_content_size(), time(), time(), time(),
318 creator_id, creator_id, "httpd/unix-directory" });