wiclear-2007-07-19/inc/classes/auth.class.php

<?php
# ***** BEGIN LICENSE BLOCK *****
# This file is part of WiClear.
# Copyright (c) 2004-2007 David Jobet. All rights
# reserved.
#
# WiClear is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# WiClear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with DotClear; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
#
# ***** END LICENSE BLOCK *****

/**
 * \brief authentification related functions
 */
class auth
{
  /**
   * \brief return user info from cookie or session
   *
   * \return array(user_id, MD5 encoded user_password)
   */
  function getUserInfoFromCookieOrSession()
  {
    $user_id = 0;
    $user_password = '';

    // session has priority over cookie
    if (existVarSession('user_id') && existVarSession('user_password'))
    {
      $user_id       = varSession('user_id');
      $user_password = varSession('user_password');
    }
    else
    if (existVarCookie('login'))
    {
      $login_info = &varCookie('login');
      $user_id       = $login_info['user_id'];
      $user_password = $login_info['user_password'];
      setVarSession('user_id',       $user_id);
      setVarSession('user_password', $user_password);
    }

    return array($user_id, $user_password);
  }

  /**
   * \brief return a user from session variables (user is logged) or anonymous user
   *
   * \param wiki the wiki controller object
   * \return user
   */
  function checkRights($wiki)
  {
    list($user_id, $user_password) = auth::getUserInfoFromCookieOrSession();

    if ($user_id == '0' && $user_password == '')
    {
      return $wiki->anonymousUser();
    }
    else
    {
      return $wiki->getUser($user_id, $user_password);
    }
  }

  /**
   * \brief check if an ip is in a network/mask
   *
   * \param ip the ip to check
   * \param network the network to compare against
   * \param mask the mask to apply on network for comparison
   *
   * \return true if match
   */
  function isIPInNet($ip, $network, $mask)
  {
    if ($mask == 0)
    {
      return $ip == $network;
    }

    $lnet = ip2long($network);
    $lip  = ip2long($ip);

    $binnet    = str_pad(decbin($lnet), 32, '0', 'STR_PAD_LEFT');
    $firstpart = substr($binnet, 0, $mask);
    $binip     = str_pad(decbin($lip), 32, '0', 'STR_PAD_LEFT');
    $firstip   = substr($binip, 0, $mask);

    return strcmp($firstpart, $firstip) == 0;
  }

  /**
   * \brief check if an ip is in a list of network/mask
   *
   * \param ip the ip to check
   * \param network_array a list of network/mask
   *
   * \return true if found
   */
  function isIpInNetArray($ip, $network_array)
  {
    foreach ($network_array as $subnet)
    {
      list($network, $mask) = split('/', $subnet);
      if (auth::isIPInNet($ip, $network, $mask))
      {
        return true;
      }
    }

    return false;
  }

  /**
   * \brief parse a comma separated list of ips and add it to ips
   *
   * \param ips the array of ip to complete
   * \param str the string to parse
   */
  function collectIpsFromString(&$ips, $str)
  {
    $new_ips = explode(',', $str);
    foreach ($new_ips as $ip)
    {
      if (!in_array($ip, $ips))
      {
        $ips[] = $ip;
      }
    }
  }

  /**
   * \brief return a list of filtered IP (private ips are taken out)
   *
   * \param ips ips to filter
   *
   * \return filtered ips
   */
  function filterOutPrivateIps($ips)
  {
    $ip_private_list = array(
      '127.0.0.1/0',
      '10.0.0.0/8',
      '172.16.0.0/12',
      '192.168.0.0/16'
    );

    $result = array();
    foreach ($ips as $ip)
    {
      if (!auth::isIpInNetArray($ip, $ip_private_list))
      {
        // not a private ip : keep this one
        $result[] = $ip;
      }
    }

    return $result;
  }

  /**
   * \brief return list of IP from currently connected browser
   *
   * \param $filter_out_private_ips indicates if we need to filter out private ips
   *
   * \return IP array
   */
  function getIPs($filter_out_private_ips = false)
  {
    $ips = array();

    if (isset($_SERVER['HTTP_CLIENT_IP']))
    {
      auth::collectIpsFromString($ips, $_SERVER['HTTP_CLIENT_IP']);
    }

    if (isset($_SERVER['HTTP_X_REAL_IP']))
    {
      auth::collectIpsFromString($ips, $_SERVER['HTTP_X_REAL_IP']);
    }

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
      auth::collectIpsFromString($ips, $_SERVER['HTTP_X_FORWARDED_FOR']);
    }

    auth::collectIpsFromString($ips, $_SERVER['REMOTE_ADDR']);

    if ($filter_out_private_ips)
    {
      $ips = auth::filterOutPrivateIps($ips);
    }

    return $ips;
  }

  /**
  * \brief randomly generates a text
  *
  * \param $textLen length of text
  * \return random text
  */
  function generateRandomText($textLen)
  {
    $text = '';

    for ($i = 0; $i < $textLen; ++$i)
    {
      switch(rand(1, 4))
      {
        case 1:
          // 25% probability to generate a number
          $text .= chr(rand(48, 57));
        break;

        default:
          // 75% probability to generate a letter
          $text .= chr(rand(97, 122));
        break;
      }
    }

    return $text;
  }

  /**
   * \brief is it possible for this user to do an action on this node based on acls and an acl_type
   *
   * \param default_global_action the default parameter for the whole wiki
   * \param acl_type the acl_type to check
   * \param user the user to check
   * \param node the node to check ACL
   * \return true if the user can edit the node, false otherwise
   */
  function aclMatch($default_global_action, $acl_type, $user, $node)
  {
    // if the user is admin or moderator
    if ($user->isAdmin() || $user->isModerator())
    {
      return true;
    }

    // if the node is empty or if there are no acls
    if (empty($node) || empty($node->groups[$acl_type]))
    {
      if ($user->isAnonymous() && !$default_global_action)
      {
        // if user is anonymous and this very acl right is denied by global configuration for anonymous
        return false;
      }
      else
      {
        return true;
      }
    }

    global $wiki;
    $anonymousUser =  $wiki->anonymousUser();

    // else browse groups and try to find one that match the user
    $matchAcl = empty($node->groups[$acl_type]);
    foreach ($node->groups[$acl_type] as $group)
    {
      // if group validates current user, or if anonymous is allowed (which means everybody's allowed)
      if ($group->validates($user) || $group->validates($anonymousUser))
      {
        $matchAcl = true;
        break;
      }
    }

    return $matchAcl;
  }

  /**
   * \brief is it possible for this user to edit this node
   *
   * \param user the user to check
   * \param node the node to check ACL
   * \return true if the user can edit the node, false otherwise
   */
  function canEdit($user, $node)
  {
    return auth::aclMatch(wc_wiki_accept_anonymous_content == 'true', acl_write, $user, $node);
  }

  /**
   * \brief is it possible for this user to read this node
   *
   * \param user the user to check
   * \param node the node to check ACL
   * \return true if the user can edit the node, false otherwise
   */
  function canRead($user, $node)
  {
    return auth::aclMatch(true, acl_read, $user, $node);
  }

  /**
   * \brief is it possible for this user to comment
   *
   * \param user the user to check
   * \param node the node to check ACL
   * \return true if the user can comment, false otherwise
   */
  function canComment($user, $node)
  {
    return auth::aclMatch(wc_wiki_accept_anonymous_comment == 'true', acl_comment, $user, $node);
  }

  /**
   * \brief look into the table of banned ip and returns true if ip of current user was banned
   */
  function banned()
  {
    global $wiki;
    $ips = auth::getIPs();

    return $wiki->containsBannedIp($ips);
  }
}

?>