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" });