mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-08 00:54:50 +01:00
Move password functions to auth class; Add support for new encryption types in setup
and implement password checking and creation for these new types
This commit is contained in:
parent
037369b6e6
commit
77fd8f4882
@ -38,7 +38,7 @@
|
||||
|
||||
function accounts_()
|
||||
{
|
||||
$this->db = $GLOBALS['phpgw']->db;
|
||||
copyobj($GLOBALS['phpgw']->db,$this->db);
|
||||
}
|
||||
|
||||
function list_methods($_type='xmlrpc')
|
||||
@ -344,11 +344,15 @@
|
||||
|
||||
function create($account_info,$default_prefs=True)
|
||||
{
|
||||
if(!@is_object($GLOBALS['phpgw']->auth))
|
||||
{
|
||||
$GLOBALS['phpgw']->auth = CreateObject('phpgwapi.auth');
|
||||
}
|
||||
$this->db->query('INSERT INTO phpgw_accounts (account_lid,account_type,account_pwd,'
|
||||
. 'account_firstname,account_lastname,account_status,account_expires,person_id,'
|
||||
. "account_primary_group) VALUES ('".$this->db->db_addslashes($account_info['account_lid'])
|
||||
. "','" . $this->db->db_addslashes($account_info['account_type'])
|
||||
. "','" . md5($account_info['account_passwd'])
|
||||
. "','" . $GLOBALS['phpgw']->auth->encrypt_password($account_info['account_passwd'], True)
|
||||
. "', '" . $this->db->db_addslashes($account_info['account_firstname'])
|
||||
. "','" . $this->db->db_addslashes($account_info['account_lastname'])
|
||||
. "','" . $this->db->db_addslashes($account_info['account_status'])
|
||||
|
@ -1,7 +1,189 @@
|
||||
<?php
|
||||
if (empty($GLOBALS['phpgw_info']['server']['auth_type']))
|
||||
/**************************************************************************\
|
||||
* eGroupWare API - Password auth and crypt functions *
|
||||
* This file written by Miles Lott <milos@groupwhere.org> *
|
||||
* Copyright (C) 2004 Miles Lott *
|
||||
* Most functions based on code from http://www.thomas-alfeld.de/frank/ *
|
||||
* Other code taken from class.common.inc.php originally from phpGroupWare *
|
||||
* ------------------------------------------------------------------------ *
|
||||
* This library is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as published by *
|
||||
* the Free Software Foundation; either version 2.1 of the License, *
|
||||
* or any later version. *
|
||||
* This library 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 Lesser General Public License for more details. *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this library; if not, write to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
if(empty($GLOBALS['phpgw_info']['server']['auth_type']))
|
||||
{
|
||||
$GLOBALS['phpgw_info']['server']['auth_type'] = 'sql';
|
||||
}
|
||||
include(PHPGW_API_INC.'/class.auth_'.$GLOBALS['phpgw_info']['server']['auth_type'].'.inc.php');
|
||||
|
||||
class auth extends auth_
|
||||
{
|
||||
var $seeded = False;
|
||||
var $error = '';
|
||||
|
||||
/*!
|
||||
@function randomstring
|
||||
@abstract return a random string of size $size
|
||||
@param $size int-size of random string to return
|
||||
*/
|
||||
function randomstring($size)
|
||||
{
|
||||
$s = '';
|
||||
$random_char = array(
|
||||
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
|
||||
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
|
||||
'w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L',
|
||||
'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
|
||||
);
|
||||
|
||||
if(!$this->seeded && phpversion() < '4.2.0')
|
||||
{
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
mt_srand((float)$sec + ((float)$usec * 100000));
|
||||
$this->seeded = True;
|
||||
}
|
||||
|
||||
for ($i=0; $i<$size; $i++)
|
||||
{
|
||||
$s .= $random_char[mt_rand(1,61)];
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function encrypt_password
|
||||
@abstract encrypt password
|
||||
@abstract uses the encryption type set in setup and calls the appropriate encryption functions
|
||||
@param $password password to encrypt
|
||||
*/
|
||||
function encrypt_password($password,$sql=False)
|
||||
{
|
||||
if($sql)
|
||||
{
|
||||
return $this->encrypt_sql($password);
|
||||
}
|
||||
return $this->encrypt_ldap($password);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function encrypt_ldap
|
||||
@abstract encrypt password for ldap
|
||||
@abstract uses the encryption type set in setup and calls the appropriate encryption functions
|
||||
@param $password password to encrypt
|
||||
*/
|
||||
function encrypt_ldap($password)
|
||||
{
|
||||
$type = strtolower($GLOBALS['phpgw_info']['server']['ldap_encryption_type']);
|
||||
$salt = '';
|
||||
switch($type)
|
||||
{
|
||||
case 'des':
|
||||
$salt = $this->randomstring(2);
|
||||
$_password = crypt($password, $salt);
|
||||
$e_password = sprintf('%s%s', '{crypt}', $_password);
|
||||
break;
|
||||
case 'md5':
|
||||
/* New method taken from the openldap-software list as recommended by
|
||||
* Kervin L. Pierre" <kervin@blueprint-tech.com>
|
||||
*/
|
||||
$e_password = '{md5}' . base64_encode(pack("H*",md5($password)));
|
||||
break;
|
||||
case 'sha':
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$e_password = '{SHA}' . base64_encode(mhash(MHASH_SHA1, $userpass));
|
||||
break;
|
||||
case 'ssha':
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$salt = $this->randomstring(8);
|
||||
$hash = mhash(MHASH_SHA1, $password . $salt);
|
||||
$e_password = '{SSHA}' . base64_encode($hash . $salt);
|
||||
break;
|
||||
default:
|
||||
return False;
|
||||
}
|
||||
return $e_password;
|
||||
}
|
||||
|
||||
/* Create a password for storage in the phpgw_accounts table */
|
||||
function encrypt_sql($password)
|
||||
{
|
||||
$type = @$GLOBALS['phpgw_info']['server']['sql_encryption_type']
|
||||
? strtolower($GLOBALS['phpgw_info']['server']['sql_encryption_type'])
|
||||
: 'md5';
|
||||
switch($type)
|
||||
{
|
||||
case 'crypt':
|
||||
if(@defined('CRYPT_STD_DES') && CRYPT_STD_DES == 1)
|
||||
{
|
||||
$salt = $this->randomstring(2);
|
||||
return crypt($password,$salt);
|
||||
}
|
||||
$this->error = 'no std crypt';
|
||||
break;
|
||||
case 'blowfish_crypt':
|
||||
if(@defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH == 1)
|
||||
{
|
||||
$salt = '$2$' . $this->randomstring(13);
|
||||
return crypt($password,$salt);
|
||||
}
|
||||
$this->error = 'no blowfish crypt';
|
||||
break;
|
||||
case 'md5_crypt':
|
||||
if(@defined('CRYPT_MD5') && CRYPT_MD5 == 1)
|
||||
{
|
||||
$salt = '$1$' . $this->randomstring(9);
|
||||
return crypt($password,$salt);
|
||||
}
|
||||
$this->error = 'no md5 crypt';
|
||||
break;
|
||||
case 'ext_crypt':
|
||||
if(@defined('CRYPT_EXT_DES') && CRYPT_EXT_DES == 1)
|
||||
{
|
||||
$salt = $this->randomstring(9);
|
||||
return crypt($password,$salt);
|
||||
}
|
||||
$this->error = 'no ext crypt';
|
||||
break;
|
||||
case 'sha':
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
$this->error = 'no sha';
|
||||
return False;
|
||||
}
|
||||
return '{SHA}' . base64_encode(mhash(MHASH_SHA1,$passwd));
|
||||
case 'ssha':
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
$this->error = 'no ssha';
|
||||
return False;
|
||||
}
|
||||
$salt = $this->randomstring(8);
|
||||
$hash = mhash(MHASH_SHA1, $password . $salt);
|
||||
return '{SSHA}' . base64_encode($hash . $salt);
|
||||
case 'md5':
|
||||
default:
|
||||
/* This is the old standard for password storage in SQL */
|
||||
return md5($password);
|
||||
}
|
||||
$this->error = $this->error ? $this->error : 'no valid encryption available';
|
||||
return False;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
var $previous_login = -1;
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
var $previous_login = -1;
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
$sri = ldap_search($ds, $GLOBALS['phpgw_info']['server']['ldap_context'], "uidnumber=$_account_id");
|
||||
$allValues = ldap_get_entries($ds, $sri);
|
||||
|
||||
$entry['userpassword'] = $GLOBALS['phpgw']->common->encrypt_password($new_passwd);
|
||||
$entry['userpassword'] = $this->encrypt_password($new_passwd);
|
||||
$dn = $allValues[0]['dn'];
|
||||
|
||||
if (!@ldap_modify($ds, $dn, $entry))
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
var $previous_login = -1;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* phpGroupWare API - Auth from NIS *
|
||||
* eGroupWare API - Auth from NIS *
|
||||
* Authentication based on NIS maps *
|
||||
* by Dylan Adams <dadams@jhu.edu> *
|
||||
* Copyright (C) 2001 Dylan Adams *
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
function authenticate($username, $passwd)
|
||||
{
|
||||
|
@ -3,11 +3,11 @@
|
||||
* phpGroupWare API - Auth from SQL *
|
||||
* This file written by Dan Kuykendall <seek3r@phpgroupware.org> *
|
||||
* and Joseph Engo <jengo@phpgroupware.org> *
|
||||
* Encryption types other than md5() added by *
|
||||
* Miles Lott <milos@groupwhere.org> based on code from *
|
||||
* http://www.thomas-alfeld.de/frank/ *
|
||||
* Authentication based on SQL table *
|
||||
* Copyright (C) 2000, 2001 Dan Kuykendall *
|
||||
* -------------------------------------------------------------------------*
|
||||
* This library is part of the phpGroupWare API *
|
||||
* http://www.phpgroupware.org/api *
|
||||
* ------------------------------------------------------------------------ *
|
||||
* This library is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as published by *
|
||||
@ -24,49 +24,185 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
var $db = '';
|
||||
var $previous_login = -1;
|
||||
var $xmlrpc_methods = array();
|
||||
|
||||
function auth()
|
||||
function auth_()
|
||||
{
|
||||
$this->xmlrpc_methods[] = array(
|
||||
'name' => 'change_password',
|
||||
'decription' => 'Change the current users password'
|
||||
);
|
||||
copyobj($GLOBALS['phpgw']->db,$this->db);
|
||||
}
|
||||
|
||||
function authenticate($username, $passwd, $passwd_type)
|
||||
{
|
||||
$db = $GLOBALS['phpgw']->db;
|
||||
|
||||
if ($passwd_type == 'text')
|
||||
if($passwd_type == 'text')
|
||||
{
|
||||
$_passwd = md5($passwd);
|
||||
}
|
||||
|
||||
if ($passwd_type == 'md5')
|
||||
{
|
||||
$_passwd = $passwd;
|
||||
}
|
||||
|
||||
$db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. "account_pwd='" . $_passwd . "' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($db->f('account_lid') != $username)
|
||||
/* normal web form login */
|
||||
$type = @$GLOBALS['phpgw_info']['server']['sql_encryption_type']
|
||||
? strtolower($GLOBALS['phpgw_info']['server']['sql_encryption_type'])
|
||||
: 'md5';
|
||||
switch($type)
|
||||
{
|
||||
return false;
|
||||
case 'sha':
|
||||
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($this->db->f('account_lid') != $username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
/* Start with the first char after {SHA} */
|
||||
$hash = base64_decode(substr($this->db->f('account_pwd'),5));
|
||||
$new_hash = mhash(MHASH_SHA1, $passwd);
|
||||
// echo '<br> DB: ' . base64_encode($orig_hash) . '<br>FORM: ' . base64_encode($new_hash);
|
||||
|
||||
if(strcmp($hash,$new_hash) == 0)
|
||||
{
|
||||
$this->previous_login = $this->db->f('account_lastlogin');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'ssha':
|
||||
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($this->db->f('account_lid') != $username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
/* Start with the first char after {SSHA} */
|
||||
$hash = base64_decode(substr($this->db->f('account_pwd'), 6));
|
||||
|
||||
// SHA-1 hashes are 160 bits long
|
||||
$orig_hash = substr($hash, 0, 20);
|
||||
$salt = substr($hash, 20);
|
||||
$new_hash = mhash(MHASH_SHA1, $passwd . $salt);
|
||||
// echo '<br> DB: ' . base64_encode($orig_hash) . '<br>FORM: ' . base64_encode($new_hash);exit;
|
||||
|
||||
if(strcmp($orig_hash,$new_hash) == 0)
|
||||
{
|
||||
$this->previous_login = $this->db->f('account_lastlogin');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'md5_crypt':
|
||||
case 'blowfish_crypt':
|
||||
case 'ext_crypt':
|
||||
case 'crypt':
|
||||
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($this->db->f('account_lid') != $username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
$saltlen = array(
|
||||
'blowfish_crypt' => 16,
|
||||
'md5_crypt' => 12,
|
||||
'ext_crypt' => 9,
|
||||
'crypt' => 2
|
||||
);
|
||||
$hash = $this->db->f('account_pwd');
|
||||
|
||||
// PHP's crypt(): salt + hash
|
||||
// notice: "The encryption type is triggered by the salt argument."
|
||||
$salt = substr($hash, 0, (int)$saltlen[$type]);
|
||||
$new_hash = crypt($passwd, $salt);
|
||||
// echo "$hash<br>" . $new_hash;
|
||||
|
||||
if(strcmp($hash,$new_hash) == 0)
|
||||
{
|
||||
$this->previous_login = $this->db->f('account_lastlogin');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'md5':
|
||||
default:
|
||||
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. " account_type='u' AND "
|
||||
. "account_pwd='" . md5($passwd) . "' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($this->db->f('account_lid') != $username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($this->db->f('account_lid'))
|
||||
{
|
||||
$this->previous_login = $this->db->f('account_lastlogin');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($db->f('account_lid'))
|
||||
elseif($passwd_type == 'md5')
|
||||
{
|
||||
$this->previous_login = $db->f('account_lastlogin');
|
||||
return True;
|
||||
/* Where is this used? */
|
||||
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
// . " account_type='u' AND "
|
||||
. "account_pwd='" . $passwd . "' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
if($this->db->f('account_lid') != $username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($this->db->f('account_lid'))
|
||||
{
|
||||
$this->previous_login = $this->db->f('account_lastlogin');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -76,34 +212,148 @@
|
||||
|
||||
function change_password($old_passwd, $new_passwd, $account_id = '')
|
||||
{
|
||||
// Don't allow passwords changes for other accounts when using XML-RPC
|
||||
if (! $account_id || $GLOBALS['phpgw_info']['flags']['currentapp'] == 'login')
|
||||
// Don't allow password changes for other accounts when using XML-RPC
|
||||
if(!$account_id || $GLOBALS['phpgw_info']['flags']['currentapp'] == 'login')
|
||||
{
|
||||
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
||||
$pwd_check = " and account_pwd='" . md5($old_passwd) . "'";
|
||||
}
|
||||
$encrypted_passwd = $this->encrypt_sql($new_passwd);
|
||||
echo 'old: ' . $old_passwd . 'new: ' . $new_passwd . ' ' . $account_id;
|
||||
echo $encrypted_passwd;exit;
|
||||
|
||||
$encrypted_passwd = md5($new_passwd);
|
||||
|
||||
$GLOBALS['phpgw']->db->query("update phpgw_accounts set account_pwd='" . md5($new_passwd) . "',"
|
||||
. "account_lastpwd_change='" . time() . "' where account_id='" . $account_id . "'" . $pwd_check,__LINE__,__FILE__);
|
||||
|
||||
if ($GLOBALS['phpgw']->db->affected_rows())
|
||||
$type = @$GLOBALS['phpgw_info']['server']['sql_encryption_type']
|
||||
? strtolower($GLOBALS['phpgw_info']['server']['sql_encryption_type'])
|
||||
: 'md5';
|
||||
switch($type)
|
||||
{
|
||||
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
|
||||
return $encrypted_passwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
case 'sha':
|
||||
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
|
||||
. "' AND " // . " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
/* Start with the first char after {SHA} */
|
||||
$hash = base64_decode(substr($this->db->f('account_pwd'),5));
|
||||
$new_hash = mhash(MHASH_SHA1, $old_passwd);
|
||||
if(strcmp($orig_hash,$new_hash) == 0)
|
||||
{
|
||||
/* old password ok */
|
||||
$this->db->query("UPDATE phpgw_accounts SET account_pwd='" . $encrypted_passwd . "',"
|
||||
. "account_lastpwd_change='" . time()
|
||||
. "' WHERE account_id=" . (int)$account_id,__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->affected_rows())
|
||||
{
|
||||
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
|
||||
return $encrypted_passwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'ssha':
|
||||
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
|
||||
. "' AND " // . " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
/* Start with the first char after {SSHA} */
|
||||
$hash = base64_decode(substr($this->db->f('account_pwd'), 6));
|
||||
|
||||
// SHA-1 hashes are 160 bits long
|
||||
$orig_hash = substr($hash, 0, 20);
|
||||
$salt = substr($hash, 20);
|
||||
$new_hash = mhash(MHASH_SHA1, $old_passwd . $salt);
|
||||
if(strcmp($orig_hash,$new_hash) == 0)
|
||||
{
|
||||
/* old password ok */
|
||||
$this->db->query("UPDATE phpgw_accounts SET account_pwd='" . $encrypted_passwd . "',"
|
||||
. "account_lastpwd_change='" . time()
|
||||
. "' WHERE account_id=" . (int)$account_id,__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->affected_rows())
|
||||
{
|
||||
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
|
||||
return $encrypted_passwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'crypt':
|
||||
case 'ext_crypt':
|
||||
case 'md5_crypt':
|
||||
case 'blowfish_crypt':
|
||||
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
|
||||
. "' AND " // . " account_type='u' AND "
|
||||
. " account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->f('account_pwd'))
|
||||
{
|
||||
$saltlen = array(
|
||||
'blowfish_crypt' => 16,
|
||||
'md5_crypt' => 12,
|
||||
'ext_crypt' => 9,
|
||||
'crypt' => 2
|
||||
);
|
||||
$hash = $this->db->f('account_pwd');
|
||||
|
||||
// PHP's crypt(): salt + hash
|
||||
// notice: "The encryption type is triggered by the salt argument."
|
||||
$salt = substr($hash, 0, (int)$saltlen[$type]);
|
||||
$new_hash = crypt($old_passwd, $salt);
|
||||
// echo "$hash<br>" . $new_hash;
|
||||
|
||||
if(strcmp($hash,$new_hash) == 0)
|
||||
{
|
||||
/* old password ok */
|
||||
$this->db->query("UPDATE phpgw_accounts SET account_pwd='" . $encrypted_passwd . "',"
|
||||
. "account_lastpwd_change='" . time()
|
||||
. "' WHERE account_id=" . (int)$account_id,__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->affected_rows())
|
||||
{
|
||||
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
|
||||
return $encrypted_passwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
return False;
|
||||
case 'md5':
|
||||
default:
|
||||
$pwd_check = " AND account_pwd='" . $GLOBALS['phpgw']->common->sql_encrypt_password($old_passwd) . "'";
|
||||
$this->db->query("UPDATE phpgw_accounts SET account_pwd='" . $encrypted_passwd . "',"
|
||||
. "account_lastpwd_change='" . time() . "' WHERE account_id='" . $account_id . "'" . $pwd_check,__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if($this->db->affected_rows())
|
||||
{
|
||||
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
|
||||
return $encrypted_passwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update_lastlogin($account_id, $ip)
|
||||
{
|
||||
$GLOBALS['phpgw']->db->query("update phpgw_accounts set account_lastloginfrom='"
|
||||
$GLOBALS['phpgw']->db->query("UPDATE phpgw_accounts SET account_lastloginfrom='"
|
||||
. "$ip', account_lastlogin='" . time()
|
||||
. "' where account_id='$account_id'",__LINE__,__FILE__);
|
||||
. "' WHERE account_id='$account_id'",__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -23,14 +23,18 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class auth
|
||||
class auth_
|
||||
{
|
||||
var $db = '';
|
||||
var $previous_login = -1;
|
||||
|
||||
function auth_()
|
||||
{
|
||||
copyobj($GLOBALS['phpgw']->db,$this->db);
|
||||
}
|
||||
|
||||
function authenticate($username, $passwd)
|
||||
{
|
||||
$db = $GLOBALS['phpgw']->db;
|
||||
|
||||
$local_debug = False;
|
||||
|
||||
if($local_debug)
|
||||
@ -41,18 +45,18 @@
|
||||
# Apache + mod_ssl provide the data in the environment
|
||||
# Certificate (chain) verification occurs inside mod_ssl
|
||||
# see http://www.modssl.org/docs/2.8/ssl_howto.html#ToC6
|
||||
if(!isset($GLOBALS['HTTP_SERVER_VARS']['SSL_CLIENT_S_DN']))
|
||||
if(!isset($_SERVER['SSL_CLIENT_S_DN']))
|
||||
{
|
||||
# if we're not doing SSL authentication, behave like auth_sql
|
||||
$db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
|
||||
. "account_pwd='" . md5($passwd) . "' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$db->next_record();
|
||||
$this->db->next_record();
|
||||
}
|
||||
else
|
||||
{
|
||||
# use username only for authentication, ignore X.509 subject in $passwd for now
|
||||
$db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$db->next_record();
|
||||
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND account_status ='A'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
}
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
|
||||
@ -62,7 +66,7 @@
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($db->f('account_lid'))
|
||||
if($this->db->f('account_lid'))
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Copyright (C) 2003 Lars Kneschke *
|
||||
* -------------------------------------------------------------------------*
|
||||
* This library is part of the phpGroupWare API *
|
||||
* http://www.phpgroupware.org/api *
|
||||
* http://www.phpgroupware.org/api *
|
||||
* ------------------------------------------------------------------------ *
|
||||
* This library is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as published by *
|
||||
@ -128,7 +128,8 @@
|
||||
{
|
||||
if (count($array))
|
||||
{
|
||||
while ($t = each($array)) {
|
||||
while ($t = each($array))
|
||||
{
|
||||
$s .= ',' . $t[1];
|
||||
}
|
||||
$s .= ',';
|
||||
@ -146,7 +147,7 @@
|
||||
@function sql_search
|
||||
@abstract this function is used for searching the access fields
|
||||
@param $table
|
||||
@param $owner
|
||||
@param $owner
|
||||
*/
|
||||
function sql_search($table,$owner=0)
|
||||
{
|
||||
@ -176,7 +177,7 @@
|
||||
function getInstalledLanguages()
|
||||
{
|
||||
$GLOBALS['phpgw']->db->query('SELECT DISTINCT lang FROM phpgw_lang');
|
||||
while (@$GLOBALS['phpgw']->db->next_record())
|
||||
while (@$GLOBALS['phpgw']->db->next_record())
|
||||
{
|
||||
$installedLanguages[$GLOBALS['phpgw']->db->f('lang')] = $GLOBALS['phpgw']->db->f('lang');
|
||||
}
|
||||
@ -261,7 +262,7 @@
|
||||
printf("<b>Error: Can't connect to LDAP server %s!</b><br>",$host);
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
if($GLOBALS['phpgw_info']['server']['ldap_version3'])
|
||||
{
|
||||
if(!ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3))
|
||||
@ -459,7 +460,7 @@
|
||||
$name .= implode(', ',$a);
|
||||
break;
|
||||
case 'firstall':
|
||||
if ($lid)
|
||||
if ($lid)
|
||||
{
|
||||
$name = ' ['.$lid.']';
|
||||
}
|
||||
@ -579,7 +580,7 @@
|
||||
@function get_app_dir
|
||||
@abstract get directory of application
|
||||
@discussion $appname can either be passed or derived from $phpgw_info['flags']['currentapp'];
|
||||
@param $appname name of application
|
||||
@param $appname name of application
|
||||
*/
|
||||
function get_app_dir($appname = '')
|
||||
{
|
||||
@ -613,7 +614,7 @@
|
||||
@function get_inc_dir
|
||||
@abstract get inc (include dir) of application
|
||||
@discussion $appname can either be passed or derived from $phpgw_info['flags']['currentapp'];
|
||||
@param $appname name of application
|
||||
@param $appname name of application
|
||||
*/
|
||||
function get_inc_dir($appname = '')
|
||||
{
|
||||
@ -625,10 +626,10 @@
|
||||
{
|
||||
$appname = 'phpgwapi';
|
||||
}
|
||||
|
||||
|
||||
$incdir = PHPGW_INCLUDE_ROOT . '/' . $appname . '/inc';
|
||||
$incdir_default = PHPGW_SERVER_ROOT . '/' . $appname . '/inc';
|
||||
|
||||
|
||||
if (@is_dir ($incdir))
|
||||
{
|
||||
return $incdir;
|
||||
@ -689,8 +690,8 @@
|
||||
$d = dir(PHPGW_SERVER_ROOT . '/phpgwapi/templates');
|
||||
while ($entry=$d->read())
|
||||
{
|
||||
if ($entry != 'CVS' && $entry != '.' && $entry != '..'
|
||||
&& $entry != 'phpgw_website'
|
||||
if ($entry != 'CVS' && $entry != '.' && $entry != '..'
|
||||
&& $entry != 'phpgw_website'
|
||||
&& is_dir(PHPGW_SERVER_ROOT . '/phpgwapi/templates/' . $entry))
|
||||
{
|
||||
$list[$entry]['name'] = $entry;
|
||||
@ -1047,7 +1048,7 @@
|
||||
unset($index);
|
||||
unset($value);
|
||||
unset($newarray);
|
||||
|
||||
|
||||
foreach($GLOBALS['phpgw_info']['user']['apps'] as $app => $data)
|
||||
{
|
||||
if (is_long($app))
|
||||
@ -1209,7 +1210,7 @@
|
||||
* Used by the template headers for including javascript in the header
|
||||
*
|
||||
* The method is included here to make it easier to change the js support
|
||||
* in phpgw. One change then all templates will support it (as long as they
|
||||
* in phpgw. One change then all templates will support it (as long as they
|
||||
* include a call to this method).
|
||||
*
|
||||
* @author Dave Hall (*vaguely based* on verdilak? css inclusion code)
|
||||
@ -1283,100 +1284,15 @@
|
||||
return $GLOBALS['phpgw']->crypto->decrypt($data);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function des_cryptpasswd
|
||||
@abstract des encrypt a password
|
||||
@param $userpass userpassword
|
||||
@param $random random seed
|
||||
*/
|
||||
function des_cryptpasswd($userpass, $random)
|
||||
{
|
||||
$lcrypt = '{crypt}';
|
||||
$password = crypt($userpass, $random);
|
||||
$ldappassword = sprintf('%s%s', $lcrypt, $password);
|
||||
return $ldappassword;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function md5_cryptpasswd
|
||||
@abstract md5 encrypt password
|
||||
@param $userpass user password
|
||||
@param $random random seed
|
||||
*/
|
||||
function old_md5_cryptpasswd($userpass, $random)
|
||||
{
|
||||
$bsalt = '$1$';
|
||||
$esalt = '$';
|
||||
$lcrypt = '{crypt}';
|
||||
$modsalt = sprintf('%s%s%s', $bsalt, $random, $esalt);
|
||||
$password = crypt($userpass, $modsalt);
|
||||
$ldappassword = sprintf('%s%s', $lcrypt, $password);
|
||||
|
||||
return $ldappassword;
|
||||
}
|
||||
|
||||
/* New method taken from the openldap-software list as recommended by
|
||||
* Kervin L. Pierre" <kervin@blueprint-tech.com>
|
||||
*/
|
||||
function md5_cryptpasswd($userpass, $random)
|
||||
{
|
||||
$ldappassword = '{md5}' . base64_encode(pack("H*",md5($userpass)));
|
||||
return $ldappassword;
|
||||
}
|
||||
|
||||
/* http://www.thomas-alfeld.de/frank/index.php?file=CodeSnippets%2FPHP%2Fldap_passwd.php */
|
||||
function sha_cryptpasswd($userpass, $random)
|
||||
{
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$ldappassword = '{SHA}' . base64_encode(mhash(MHASH_SHA1, $userpass));
|
||||
return $ldappassword;
|
||||
}
|
||||
|
||||
/* http://www.thomas-alfeld.de/frank/index.php?file=CodeSnippets%2FPHP%2Fldap_passwd.php */
|
||||
function ssha_cryptpasswd($userpass,$random)
|
||||
{
|
||||
if(!function_exists('mhash'))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$hash = mhash(MHASH_SHA1, $password . $random);
|
||||
$ldappassword = '{SSHA}' . base64_encode($hash . $random);
|
||||
return $ldappassword;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function encrypt_password
|
||||
@abstract encrypt password
|
||||
@abstract legacy wrapper for newer auth class function, encrypt_password
|
||||
@abstract uses the encryption type set in setup and calls the appropriate encryption functions
|
||||
@param $password password to encrypt
|
||||
*/
|
||||
function encrypt_password($password)
|
||||
{
|
||||
$type = strtolower($GLOBALS['phpgw_info']['server']['ldap_encryption_type']);
|
||||
$salt = '';
|
||||
switch($type)
|
||||
{
|
||||
case 'des':
|
||||
$salt = $this->randomstring(2);
|
||||
$e_password = $this->des_cryptpasswd($password, $salt);
|
||||
break;
|
||||
case 'md5':
|
||||
$e_password = $this->md5_cryptpasswd($password,$salt);
|
||||
break;
|
||||
case 'sha':
|
||||
$e_password = $this->sha_cryptpasswd($password,$salt);
|
||||
break;
|
||||
case 'ssha':
|
||||
$salt = $this->randomstring(8);
|
||||
$e_password = $this->ssha_cryptpasswd($password, $salt);
|
||||
break;
|
||||
default:
|
||||
return False;
|
||||
}
|
||||
return $e_password;
|
||||
return $GLOBALS['phpgw']->auth->encrypt_password($password);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1456,7 +1372,7 @@
|
||||
{
|
||||
$GLOBALS['phpgw']->datetime = createobject('phpgwapi.datetime');
|
||||
}
|
||||
|
||||
|
||||
if (!$t || (int)$t <= 0)
|
||||
{
|
||||
$t = $GLOBALS['phpgw']->datetime->gmtnow;
|
||||
@ -1464,7 +1380,7 @@
|
||||
|
||||
// + (date('I') == 1?3600:0)
|
||||
$t += $GLOBALS['phpgw']->datetime->tz_offset;
|
||||
|
||||
|
||||
if (! $format)
|
||||
{
|
||||
$format = $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'] . ' - ';
|
||||
@ -1477,12 +1393,16 @@
|
||||
$format .= 'H:i';
|
||||
}
|
||||
}
|
||||
if(PHP_OS == 'Windows' && (int)$t < 21600)
|
||||
{
|
||||
$t = 21600;
|
||||
}
|
||||
return date($format,$t);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function dateformatorder
|
||||
@abstract
|
||||
@abstract
|
||||
@param $yearstr year - string
|
||||
@param $monthstr month - string
|
||||
@param $day day - string
|
||||
@ -1506,7 +1426,7 @@
|
||||
{
|
||||
return (implode(' ',$dlarr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function formattime
|
||||
@ -1520,7 +1440,7 @@
|
||||
$h12 = $hour;
|
||||
if ($GLOBALS['phpgw_info']['user']['preferences']['common']['timeformat'] == '12')
|
||||
{
|
||||
if ($hour >= 12)
|
||||
if ($hour >= 12)
|
||||
{
|
||||
$ampm = ' pm';
|
||||
}
|
||||
@ -1540,7 +1460,7 @@
|
||||
$h12 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
$h12 = $hour;
|
||||
}
|
||||
@ -1627,10 +1547,10 @@
|
||||
function create_emailpreferences($prefs,$accountid='')
|
||||
{
|
||||
$account_id = get_account_id($accountid);
|
||||
|
||||
|
||||
// NEW EMAIL PASSWD METHOD (shared between SM and aeromail)
|
||||
$prefs['email']['passwd'] = $this->get_email_passwd_ex();
|
||||
|
||||
|
||||
// Add default preferences info
|
||||
if (!isset($prefs['email']['userid']))
|
||||
{
|
||||
@ -1649,7 +1569,7 @@
|
||||
{
|
||||
$GLOBALS['phpgw_info']['server']['mail_server_type'] = 'imap';
|
||||
}
|
||||
|
||||
|
||||
// OLD EMAIL PASSWD METHOD
|
||||
if (!isset($prefs['email']['passwd']))
|
||||
{
|
||||
@ -1660,7 +1580,7 @@
|
||||
$prefs['email']['passwd'] = $this->decrypt($prefs['email']['passwd']);
|
||||
}
|
||||
// NEW EMAIL PASSWD METHOD Located at the begining of this function
|
||||
|
||||
|
||||
if (!isset($prefs['email']['address']))
|
||||
{
|
||||
$prefs['email']['address'] = $GLOBALS['phpgw']->accounts->id2name($account_id)
|
||||
@ -1687,14 +1607,14 @@
|
||||
{
|
||||
$prefs['email']['mail_port'] = '110';
|
||||
}
|
||||
elseif ($prefs['email']['mail_server_type']=='imaps')
|
||||
{
|
||||
$prefs['email']['mail_port'] = '993';
|
||||
}
|
||||
elseif ($prefs['email']['mail_server_type']=='pop3s')
|
||||
{
|
||||
$prefs['email']['mail_port'] = '995';
|
||||
}
|
||||
elseif ($prefs['email']['mail_server_type']=='imaps')
|
||||
{
|
||||
$prefs['email']['mail_port'] = '993';
|
||||
}
|
||||
elseif ($prefs['email']['mail_server_type']=='pop3s')
|
||||
{
|
||||
$prefs['email']['mail_port'] = '995';
|
||||
}
|
||||
// This is going to be used to switch to the nntp class
|
||||
if (isset($phpgw_info['flags']['newsmode']) &&
|
||||
$GLOBALS['phpgw_info']['flags']['newsmode'])
|
||||
@ -1733,32 +1653,32 @@
|
||||
case 32: $s .= lang('Group has been deleted'); break;
|
||||
case 33: $s .= lang('Group has been updated'); break;
|
||||
case 34: $s .= lang('Account has been deleted') . '<p>'
|
||||
. lang('Error deleting %1 %2 directory',lang('users'),' '.lang('private').' ')
|
||||
. lang('Error deleting %1 %2 directory',lang('users'),' '.lang('private').' ')
|
||||
. ',<br>' . lang('Please %1 by hand',lang('delete')) . '<br><br>'
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
break;
|
||||
case 35: $s .= lang('Account has been updated') . '<p>'
|
||||
. lang('Error renaming %1 %2 directory',lang('users'),
|
||||
' '.lang('private').' ')
|
||||
' '.lang('private').' ')
|
||||
. ',<br>' . lang('Please %1 by hand',
|
||||
lang('rename')) . '<br><br>'
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
break;
|
||||
case 36: $s .= lang('Account has been created') . '<p>'
|
||||
. lang('Error creating %1 %2 directory',lang('users'),
|
||||
' '.lang('private').' ')
|
||||
' '.lang('private').' ')
|
||||
. ',<br>' . lang('Please %1 by hand',
|
||||
lang('create')) . '<br><br>'
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/users/');
|
||||
break;
|
||||
case 37: $s .= lang('Group has been added') . '<p>'
|
||||
. lang('Error creating %1 %2 directory',lang('groups'),' ')
|
||||
@ -1767,7 +1687,7 @@
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
break;
|
||||
case 38: $s .= lang('Group has been deleted') . '<p>'
|
||||
. lang('Error deleting %1 %2 directory',lang('groups'),' ')
|
||||
@ -1776,7 +1696,7 @@
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
break;
|
||||
case 39: $s .= lang('Group has been updated') . '<p>'
|
||||
. lang('Error renaming %1 %2 directory',lang('groups'),' ')
|
||||
@ -1785,7 +1705,7 @@
|
||||
. lang('To correct this error for the future you will need to properly set the')
|
||||
. '<br>' . lang('permissions to the files/users directory')
|
||||
. '<br>' . lang('On *nix systems please type: %1','chmod 770 '
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
. $GLOBALS['phpgw_info']['server']['files_dir'] . '/groups/');
|
||||
break;
|
||||
case 40: $s .= lang('You have not entered a title').'.';
|
||||
break;
|
||||
@ -1802,11 +1722,11 @@
|
||||
/*!
|
||||
@function phpgw_error
|
||||
@abstract process error message
|
||||
@param $error error
|
||||
@param $error error
|
||||
@param $line line
|
||||
@param $file file
|
||||
*/
|
||||
function phpgw_error($error,$line = '', $file = '')
|
||||
function phpgw_error($error,$line = '', $file = '')
|
||||
{
|
||||
echo '<p><b>phpGroupWare internal error:</b><p>'.$error;
|
||||
if ($line)
|
||||
|
Loading…
Reference in New Issue
Block a user