m_hta.php 12.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
/*
 $Id: m_hta.php,v 1.5 2004/11/29 17:15:37 anonymous Exp $
 ----------------------------------------------------------------------
 AlternC - Web Hosting System
 Copyright (C) 2002 by the AlternC Development Team.
 http://alternc.org/
 ----------------------------------------------------------------------
 Based on:
 Valentin Lacambre's web hosting softwares: http://altern.org/
 ----------------------------------------------------------------------
 LICENSE

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License (GPL)
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program 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.

 To read the license please visit http://www.gnu.org/copyleft/gpl.html
 ----------------------------------------------------------------------
 Original Author of file:
 Purpose of file:
 ----------------------------------------------------------------------
*/
30

31
/**
32
33
* This class handle folder web restricted access through .htaccess/.htpassword
* files.
34
35
36
* 
* Copyleft {@link http://alternc.net/ AlternC Team}
* 
37
* @copyright    AlternC-Team 2002-11-01 http://alternc.org/
38
39
40
41
* 
*/
class m_hta {

42

43
44
  /*---------------------------------------------------------------------------*/
  /**
45
   * Constructor
46
47
48
49
   */
  function m_webaccess() {
  }

50

51
52
53
54
55
56
57
  /**
   * Password kind used in this class (hook for admin class)
   */
  function alternc_password_policy() {
    return array("hta"=>"Protected folders passwords");
  }

58
59
60
61
62
63
64
65
66
67
68
  function hook_menu() {
    $obj = array(
      'title'       => _("Protected folders"),
      'ico'         => 'images/password.png',
      'link'        => 'hta_list.php',
      'pos'         => 50,
     ) ;

     return $obj;
  }

69

70
71
  /*---------------------------------------------------------------------------*/
  /**
72
73
74
   * Create a protected folder (.htaccess et .htpasswd)
   * @param string $dir Folder to protect (relative to user root)
   * @return boolean TRUE if the folder has been protected, or FALSE if an error occurred
75
76
   */
  function CreateDir($dir) {
77
    global $mem,$bro,$err;
78
79
80
    $err->log("hta","createdir",$dir);
    $absolute=$bro->convertabsolute($dir,0);
    if (!$absolute) {
Alan Garcia's avatar
Alan Garcia committed
81
      $err->raise("hta",printf(_("The folder '%s' does not exist"),$dir));
82
83
84
      return false;
    }
    if (!file_exists($absolute)) {
85
      @mkdir($absolute,00777);
86
87
    }
    if (!file_exists("$absolute/.htaccess")) {
88
      if (!@touch("$absolute/.htaccess")) {
Alan Garcia's avatar
Alan Garcia committed
89
	$err->raise("hta",_("File already exist"));
90
91
92
93
	return false;
      }
      $file = @fopen("$absolute/.htaccess","r+");
      if (!$file) {
Alan Garcia's avatar
Alan Garcia committed
94
	$err->raise("hta",_("File already exist"));
95
96
        return false;
      }
97
      fseek($file,0);
Alan Garcia's avatar
Alan Garcia committed
98
      $param="AuthUserFile \"$absolute/.htpasswd\"\nAuthName \""._("Restricted area")."\"\nAuthType Basic\nrequire valid-user\n";
99
100
101
102
      fwrite($file, $param);
      fclose($file);
    }
    if (!file_exists("$absolute/.htpasswd")) {
103
      if (!touch("$absolute/.htpasswd")) {
Alan Garcia's avatar
Alan Garcia committed
104
	$err->raise("hta",_("File already exist"));
105
106
        return false;
      }
107
108
109
110
111
      return true;
    }
    return true;
  }

112

113
114
  /*---------------------------------------------------------------------------*/
  /**
115
116
   * Returns the list of all user folder currently protected by a .htpasswd file
   * @return array Array containing user folder list
117
118
   */

119
  function ListDir(){
120
    global$err,$mem;
Alan Garcia's avatar
Alan Garcia committed
121
122
    $err->log("hta","listdir");
    $sortie=array();
123
    $absolute=ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"];
Alan Garcia's avatar
Alan Garcia committed
124
125
126
127
128
    exec("find $absolute -name .htpasswd|sort",$sortie);
    if(!count($sortie)){
      $err->raise("hta",_("No protected folder"));
      return false;
    }
129
    $pattern="/^".preg_quote(ALTERNC_HTML,"/")."\/.\/[^\/]*\/(.*)\/\.htpasswd/";
Alan Garcia's avatar
Alan Garcia committed
130
131
132
    
    $r=array();
    for($i=0;$i<count($sortie);$i++){
Alan Garcia's avatar
Alan Garcia committed
133
      preg_match($pattern,$sortie[$i],$matches);
134
      $tmpm=isset($matches[1])?'/'.$matches[1]:'';
Alan Garcia's avatar
Alan Garcia committed
135
136
137
      $r[$i]=$tmpm."/";
    }
    return $r;
138
  }
139

140
141
  /*---------------------------------------------------------------------------*/
  /**
142
143
144
   * Tells if a folder is protected.
   * @param string $dir Folder to check
   * @return TRUE if the folder is protected, or FALSE if it is not
145
146
   */
  function is_protected($dir){
147
    global $mem,$err;
148
    $err->log("hta","is_protected",$dir);
149
    $absolute=ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"]."/$dir";
150
151
152
153
154
155
156
157
158
    $sortie=array();
    if (file_exists("$absolute/.htpasswd")){
      return true;
    }
    else {
      return false;
    }
  }

159

160
161
  /*---------------------------------------------------------------------------*/
  /**
162
163
164
   * Returns the list of login for a protected folder.
   * @param string $dir The folder to lookup (relative to user root)
   * @return array An array containing the list of logins from the .htpasswd file, or FALSE
165
166
   */
  function get_hta_detail($dir) {
167
    global $mem,$err;
168
    $err->log("hta","get_hta_detail");
169
    $absolute=ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"]."/$dir";
170
171
172
173
174
    if (file_exists("$absolute/.htaccess")) {
      /*		if (!_reading_htaccess($absolute)) {
			return false;
			}
      */	}
175
    $file = @fopen("$absolute/.htpasswd","r");
176
177
    $i=0;
    $res=array();
178
179
180
    if (!$file) {
      return false;
    }
181
    // TODO: Tester la validit� du .htpasswd
182
183
184
185
186
187
188
189
190
191
192
193
    while (!feof($file)) {
      $s=fgets($file,1024);
      $t=explode(":",$s);
      if ($t[0]!=$s) {
	$res[$i]=$t[0];
	$i=$i+1;
      }
    }
    fclose($file);
    return $res;
  }

194

195
196
  /*---------------------------------------------------------------------------*/
  /**
197
198
199
   * Unprotect a folder
   * @param string $dir Folder to unprotect, relative to user root
   * @return boolean TRUE if the folder has been unprotected, or FALSE if an error occurred
200
201
202
203
204
205
   */
  function DelDir($dir) {
    global $mem,$bro,$err;
    $err->log("hta","deldir",$dir);
    $dir=$bro->convertabsolute($dir,0);
    if (!$dir) {
Alan Garcia's avatar
Alan Garcia committed
206
      $err->raise("hta",printf(("The folder '%s' does not exist"),$dir));
207
208
      return false;
    }
209
    if (!@unlink("$dir/.htaccess")) {
210
      $err->raise("hta",printf(_("I cannot delete the file '%s/.htaccess'"),$dir));
211
212
      return false;
    }
213
    if (!@unlink("$dir/.htpasswd")) {
214
      $err->raise("hta",printf(_("I cannot delete the file '%s/.htpasswd'"),$dir));
215
216
217
218
219
      return false;
    }
    return true;
  }

220

221
222
  /*---------------------------------------------------------------------------*/
  /**
223
224
225
226
227
   * Add a user to a protected folder
   * @param string $login The user login to add
   * @param string $password The password to add (cleartext)
   * @param string $dir The folder we add it to (relative to user root).
   * @return boolean TRUE if the user has been added, or FALSE if an error occurred
228
229
   */
  function add_user($user,$password,$dir) {
230
    global $err, $bro, $admin;
231
    $err->log("hta","add_user",$user."/".$dir);
232
233
234
235
236
237
238
239
    if (empty($user)) {	
      $err->raise('hta',_("Please enter a user"));
      return false;
    }
    if (empty($password)) {	
      $err->raise('hta',_("Please enter a password"));
      return false;
    }
240
241
    $absolute=$bro->convertabsolute($dir,0);
    if (!file_exists($absolute)) {
Alan Garcia's avatar
Alan Garcia committed
242
      $err->raise("hta",printf(("The folder '%s' does not exist"),$dir));
243
244
      return false;
    }
245
    // @todo delete cf!. functions.php checkloginemail definition
246
    if (checkloginmail($user)){
247
248
249
250
251
252
253
      // Check this password against the password policy using common API : 
      if (is_callable(array($admin,"checkPolicy"))) {
	if (!$admin->checkPolicy("hta",$user,$password)) {
	  return false; // The error has been raised by checkPolicy()
	}
      }

254
255
      $file = @fopen("$absolute/.htpasswd","a+");
      if (!$file) {
Alan Garcia's avatar
Alan Garcia committed
256
	$err->raise("hta",_("File already exist"));
257
258
	return false;
      }
259
260
261
262
263
      fseek($file,0);
      while (!feof($file)) {
	$s=fgets($file,1024);
	$t=explode(":",$s);
	if ($t[0]==$user) {
Axel ROGER's avatar
Axel ROGER committed
264
	  $err->raise("hta",_("The user '%s' already exist for this folder"),$user);
265
266
267
268
	  return false;
	}
      }
      fseek($file,SEEK_END);
269
      if ( empty($t[1]) || substr($t[1],-1)!="\n") {
270
271
272
273
274
275
	fwrite($file,"\n");
      }
      fwrite($file, "$user:"._md5cr($password)."\n");
      fclose($file);
      return true;
    } else {
Alan Garcia's avatar
Alan Garcia committed
276
      $err->raise("hta",_("Please enter a valid username"));
277
278
279
280
      return false;
    }
  }

281

282
283
  /*---------------------------------------------------------------------------*/
  /**
284
285
286
287
   * Delete a user from a protected folder.
   * @param array $lst An array with login to delete.
   * @param string $dir The folder, relative to user root, where we want to delete users.
   * @return boolean TRUE if users has been deleted, or FALSE if an error occurred.
288
289
290
291
292
293
   */
  function del_user($lst,$dir) {
    global $bro,$err;
    $err->log("hta","del_user",$lst."/".$dir);
    $absolute=$bro->convertabsolute($dir,0);
    if (!file_exists($absolute)) {
Alan Garcia's avatar
Alan Garcia committed
294
      $err->raise("hta",printf(_("The folder '%s' does not exist"),$dir));
295
296
297
298
299
      return false;
    }
    touch("$absolute/.htpasswd.new");
    $file = fopen("$absolute/.htpasswd","r");
    $newf = fopen("$absolute/.htpasswd.new","a");
300
    if (!$file || !$newf) {
Alan Garcia's avatar
Alan Garcia committed
301
      $err->raise("hta",_("File already exist"));
302
303
      return false;
    }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
    reset($lst);
    fseek($file,0);
    while (!feof($file)) {
      $s=fgets($file,1024);
      $t=explode(":",$s);
      if (!in_array($t[0],$lst) && ($t[0]!="\n")) {
	fseek($newf,0);
	fwrite($newf, "$s");
      }
    }
    fclose($file);
    fclose($newf);
    unlink("$absolute/.htpasswd");
    rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
    return true;
  }

321

322
323
  /*---------------------------------------------------------------------------*/
  /**
324
325
326
327
328
   * Change the password of a user in a protected folder
   * @param string $user The users whose password should be changed
   * @param string $newpass The new password of this user
   * @param string $dir The folder, relative to user root, in which we will change a password
   * @return boolean TRUE if the password has been changed, or FALSE if an error occurred
329
330
   */
  function change_pass($user,$newpass,$dir) {
331
    global $bro,$err,$admin;
332
333
334
    $err->log("hta","change_pass",$user."/".$dir);
    $absolute=$bro->convertabsolute($dir,0);
    if (!file_exists($absolute)) {
Alan Garcia's avatar
Alan Garcia committed
335
      $err->raise("hta",printf(_("The folder '%s' does not exist"),$dir));
336
337
      return false;
    }
338
339
340

    // Check this password against the password policy using common API : 
    if (is_callable(array($admin,"checkPolicy"))) {
341
      if (!$admin->checkPolicy("hta",$user,$newpass)) {
342
343
344
345
	return false; // The error has been raised by checkPolicy()
      }
    }

346
347
348
    touch("$absolute/.htpasswd.new");
    $file = fopen("$absolute/.htpasswd","r");
    $newf = fopen("$absolute/.htpasswd.new","a");
349
    if (!$file || !$newf) {
Alan Garcia's avatar
Alan Garcia committed
350
      $err->raise("hta",_("File already exist"));
351
352
      return false;
    }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    while (!feof($file)) {
      $s=fgets($file,1024);
      $t=explode(":",$s);
      if ($t[0]!=$user) {
	fwrite($newf, "$s");
      }
    }
    fwrite($newf, "$user:"._md5cr($newpass)."\n");
    fclose($file);
    fclose($newf);
    unlink("$absolute/.htpasswd");
    rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
    return true;
  }

368

369
370
  /*---------------------------------------------------------------------------*/
  /**
371
372
373
   * Check that a .htaccess file is valid (for authentication)
   * @param string $absolute Folder we want to check (relative to user root)
   * @return boolean TRUE is the .htaccess is protecting this folder, or FALSE else
374
375
376
377
378
379
380
381
   * @access private
   */
  function _reading_htaccess($absolute) {
    global $err;
    $err->log("hta","_reading_htaccess",$absolute);
    $file = fopen("$absolute/.htaccess","r+");
    $lignes=array(1,1,1);
    $errr=0;
382
383
384
    if (!$file) {
      return false;
    }
385
386
    while (!feof($file) && !$errr) {
      $s=fgets($file,1024);
387
      if (substr($s,0,12)!="RewriteCond " && substr($s,0,14)!="ErrorDocument " && substr($s,0,12)!="RewriteRule " && substr($s,0,14)!="RewriteEngine " && trim($s)!="") {
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	$errr=1;
      }
      if (strtolower(trim($s))==strtolower("authuserfile $absolute/.htpasswd")) {
	$lignes[0]=0;
	$errr=0;
      } // authuserfile
      if (strtolower(trim($s))=="require valid-user") {
	$lignes[1]=0;
	$errr=0;
      } //require
      if (strtolower(trim($s))=="authtype basic") {
	$lignes[2]=0;
	$errr=0;
      } //authtype
    } // Reading config file
    fclose($file);
404
405
    if ($errr || in_array(0,$lignes)) {
      $err->raise("hta",_("An incompatible .htaccess file exists in this folder"));
406
407
408
409
410
      return false;
    }
    return true;
  } 

411
412
413
} /* CLASS m_hta */