home._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2005 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
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.
7  *
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.
12  *
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
16  *
17  * $Id: home.pike,v 1.2 2008/04/18 10:02:46 exodusd Exp $
18  */
19 inherit "/kernel/module";
20 #include <macros.h>
21 #include <classes.h>
22 #include <database.h>
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{
32 public:
33 
34 
35 
36 
37 
38  bool mount_users = true;
39  bool mount_groups = true;
40 
41 
42 
43 class GroupWrapper {
44 public:
45  object grp, home;
46  void create(object g, object h) {
47 
48  if ( !IS_PROXY(g) )
49  THROW("GroupWrapper: Group is no proxy !", E_ERROR);
50  if ( !objectp(h) ) {
51  THROW("Group "+g->get_group_name() + " missing workroom!", E_ERROR);
52  }
53  if ( !IS_PROXY(h) )
54  THROW("GroupWrapper: Home is no proxy !", E_ERROR);
55  grp = g; home = h;
56  }
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(); }
61 
62  final mixed `->(string func)
63  {
64  if ( func == "get_identifier" )
65  return get_identifier;
66  else if ( func == "create" )
67  return create;
68  else if ( func == "get_object_class" )
69  return get_object_class;
70  else if ( func == "status" )
71  return status;
72  else if ( func == "get_object_id" )
73  return get_object_id;
74 
75  return home->get_object()[func];
76  }
77 };
78 
79 
80  mapping directoryCache = ([ ]);
81 
82 string get_identifier() { return "home"; }
83  void update_identifier(string name) {};
84 
85 int get_object_class()
86 {
87  return ::get_object_class() | CLASS_CONTAINER | CLASS_ROOM;
88 }
89 
90 
91 bool insert_obj(object obj)
92 {
93  return true; //THROW("No Insert in home !", E_ACCESS);
94 }
95 
96 bool remove_obj(object obj)
97 {
98  return true; // THROW("No Remove in home !", E_ACCESS);
99 }
100 
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
105  */
106 bool can_mount_user ( string identifier ) {
107  if ( mount_users ) return true;
108  if ( _Persistence->user_restricted( identifier ) ) return true;
109  return false;
110 }
111 
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
114  * mounted.
115  * @param identifier identifier of the group to check
116  * @return true if the group can be mounted, false if not
117  */
118 bool can_mount_group ( string identifier ) {
119  if ( mount_groups ) return true;
120  if ( _Persistence->group_restricted( identifier ) ) return true;
121  return false;
122 }
123 
124 array get_inventory()
125 {
126  array groups = this_user()->get_groups();
127  foreach(groups, object grp) {
128  string id = grp->get_identifier();
129  if ( !can_mount_group(id) )
130  continue;
131  if ( !directoryCache[id] ) {
132  mixed err = catch {
133  directoryCache[id] = GroupWrapper(grp,
134  grp->query_attribute(GROUP_WORKROOM));
135  };
136  if (err) {
137  FATAL("Failed to mount GROUP in home-Module: %O\n%O\n%O",
138  grp, err[0], err[1]);
139  }
140  }
141  }
142  if ( can_mount_user(this_user()->get_identifier()) )
143  mount( this_user() );
144  return values(directoryCache);
145 }
146 
147 array get_inventory_by_class(int cl)
148 {
149  if ( can_mount_user(this_user()->get_identifier()) )
150  mount( this_user() );
151 
152  if ( cl & CLASS_GROUP )
153  return values(directoryCache);
154  else if ( cl & CLASS_ROOM )
155  return values(directoryCache);
156  return ({ });
157 }
158 
159 array get_users()
160 {
161  return ({ });
162 }
163 
164 /*
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.
169  *
170  * @param string obj_name - the object to resolve
171  * @return the object
172  */
173 object get_object_byname(string obj_name)
174 {
175  object obj, res;
176 
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];
182  else
183  m_delete(directoryCache, obj_name);
184  }
185 
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);
190  }
191  else {
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);
196  }
197  }
198  if ( objectp(res) )
199  directoryCache[obj_name] = GroupWrapper(obj, res);
200 
201  return directoryCache[obj_name];
202 }
203 
204 object mount(object grp)
205 {
206  object wr;
207 
208  string name = grp->get_identifier();
209 
210  if ( objectp(directoryCache[name]) )
211  return directoryCache[name]->home;
212 
213  if ( grp->get_object_class() & CLASS_GROUP ) {
214  if ( ! can_mount_group(name) )
215  return UNDEFINED;
216  wr = grp->query_attribute(GROUP_WORKROOM);
217  }
218  else if ( grp->get_object_class() & CLASS_USER ) {
219  if ( ! can_mount_user(name) )
220  return UNDEFINED;
221  wr = grp->query_attribute(USER_WORKROOM);
222  }
223  else
224  return UNDEFINED;
225 
226  directoryCache[name] = GroupWrapper(grp, wr);
227 
228  return wr;
229 }
230 
231 void unmount ( object grp )
232 {
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);
238 
239  string name = grp->get_identifier();
240  if ( !objectp( directoryCache[ name ] ) )
241  return;
242  m_delete( directoryCache, name );
243 }
244 
245 int is_mounted ( object grp )
246 {
247  string name = grp->get_identifier();
248  return objectp( directoryCache[ name ] );
249 }
250 
251 string contains_virtual(object obj)
252 {
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) )
257  return UNDEFINED;
258  return id;
259  }
260  else if ( creatorGroup->get_object_class() & CLASS_USER ) {
261  if ( ! can_mount_user(id) )
262  return UNDEFINED;
263  if ( creatorGroup->query_attribute(USER_WORKROOM) == obj )
264  return creatorGroup->get_user_name();
265  }
266  return UNDEFINED;
267 }
268 
269 void add_paths()
270 {
271 }
272 
273 /**
274  * Called after the object is loaded. Move the object to the workroom !
275  *
276  */
277 void load_module()
278 {
279  if ( MODULE_OBJECTS && objectp(_ROOTROOM) && oEnvironment != _ROOTROOM ) {
280  set_attribute(OBJ_NAME, "home");
281  move(_ROOTROOM);
282  }
283  call(add_paths, 0);
284 
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" );
291 }
292 
293 /**
294  * Get the content size of this object which does not make really
295  * sense for containers.
296  *
297  * @return the content size: -2 as the container can be seen as an inventory
298  * @see stat
299  */
300 int get_content_size()
301 {
302  return -2;
303 }
304 
305 /**
306  * This function returns the stat() of this object. This has the
307  * same format as statting a file.
308  *
309  * @return status array as in file_stat()
310  * @see get_content_size
311  */
312 array stat()
313 {
314  int creator_id = objectp(get_creator())?get_creator()->get_object_id():0;
315 
316 
317  return ({ 16877, get_content_size(), time(), time(), time(),
318  creator_id, creator_id, "httpd/unix-directory" });
319 }
320 
321 
322 };