Alternc  latest
Alternc logiel libre pour l'hébergement
m_ftp.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  ----------------------------------------------------------------------
5  LICENSE
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License (GPL)
9  as published by the Free Software Foundation; either version 2
10  of the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  To read the license please visit http://www.gnu.org/copyleft/gpl.html
18  ----------------------------------------------------------------------
19 */
20 
21 /**
22  * FTP account management class
23  *
24  * @copyright AlternC-Team 2000-2017 https://alternc.com/
25  */
26 class m_ftp {
27 
29 
30 
31  /**
32  * Constructor
33  */
34  function m_ftp() {
35  global $L_FQDN;
36  $this->srv_proftpd = variable_get('fqdn_proftpd', $L_FQDN, 'Human name for FTP server. If you change it, launch reload-certs', array('desc' => 'Name', 'type' => 'string'));
37  }
38 
39 
40  /**
41  * Password kind used in this class (hook for admin class)
42  */
44  return array("ftp" => "FTP accounts");
45  }
46 
47 
48  /**
49  * hook function called by menu class
50  * to add menu to the left panel
51  */
52  function hook_menu() {
53  global $quota;
54  $q = $quota->getquota("ftp");
55 
56  $obj = array(
57  'title' => _("FTP accounts"),
58  'link' => 'toggle',
59  'pos' => 100,
60  'links' => array(),
61  );
62 
63  if ($quota->cancreate("ftp")) {
64  $obj['links'][] = array(
65  'txt' => _("Create a new ftp account"),
66  'url' => "ftp_edit.php?create=1",
67  'class' => '',
68  );
69  }
70 
71  if ($q['u'] > 0) { // if there are some FTP accounts
72  $obj['links'][] = array(
73  'txt' => _("FTP accounts list"),
74  'url' => "ftp_list.php"
75  );
76  }
77 
78  return $obj;
79  }
80 
81 
82  /**
83  * Return the values needed to activate security access. See get_auth_class()
84  * in authip for more informations
85  */
86  function authip_class() {
87  $c = Array();
88  $c['name'] = "FTP";
89  $c['protocol'] = "ftp";
90  $c['values'] = Array();
91 
92  $tt = $this->get_list();
93  if (empty($tt) || !is_array($tt)) {
94  return $c;
95  }
96  foreach ($this->get_list() as $v) {
97  $c['values'][$v['id']] = $v['login'];
98  }
99 
100  return $c;
101  }
102 
103 
104  /**
105  * Switch enabled status of an account
106  */
107  function switch_enabled($id, $status = null) {
108  global $cuid, $db, $msg;
109  if (!$jj = $this->get_ftp_details($id)) {
110  $msg->raise("ERROR", 'ftp', _("This account do not exist or is not of this account"));
111  return false;
112  }
113  if ($status == null) {
114  if ($jj[0]['enabled'] == true) {
115  $status = 0;
116  } else {
117  $status = 1;
118  }
119  }
120  // Be sure what is in $status, in case of it was a parameter
121  $status = ($status ? 1 : 0);
122 
123  if (!$db->query("UPDATE ftpusers SET enabled = ? WHERE uid = ? AND id = ? ;", array($status, $cuid, $id))) {
124  $msg->raise("ERROR", 'ftp', _("Error during update"));
125  return false;
126  } else {
127  return true;
128  }
129  }
130 
131 
132  /**
133  * Retourne la liste des comptes FTP du compte h�berg�
134  * Retourne la liste des comptes FTP sous forme de tableau index� de
135  * tableaus associatifs comme suit :
136  * $a["id"]= ID du compte ftp
137  * $a["login"]= Nom de login du compte
138  * $a["dir"]= Dossier relatif � la racine du compte de l'utilisateur
139  * @return array Retourne le tableau des comptes
140  */
141  function get_list() {
142  global $db, $msg, $cuid;
143  $msg->debug("ftp", "get_list");
144  $r = array();
145  $db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid= ? ORDER BY name;", array($cuid));
146  if ($db->num_rows()) {
147  while ($db->next_record()) {
148  $r[] = array(
149  "id" => $db->f("id"),
150  "login" => $db->f("name"),
151  "enabled" => $db->f("enabled"),
152  //"dir"=>$match[1]
153  "dir" => $db->f("homedir")
154  );
155  }
156  return $r;
157  } else {
158  $msg->raise("INFO", "ftp", _("No FTP account found"));
159  return array();
160  }
161  }
162 
163 
164  /**
165  * Retourne les details d'un compte FTP (voir get_list)
166  * Le tableau est celui du compte d'id specifie
167  * @param integer $id Numero du compte dont on souhaite obtenir les d�tails
168  * @return array Tableau associatif contenant les infos du comptes ftp
169  */
170  function get_ftp_details($id) {
171  global $db, $msg, $cuid;
172  $msg->debug("ftp", "get_ftp_details", $id);
173  $r = array();
174  $db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid= ? AND id= ?;", array($cuid, $id));
175  if ($db->num_rows()) {
176  $db->next_record();
177 
178  $regexp = "/^" . preg_quote(getuserpath(), "/") . "\/(.*)$/";
179  $match = array();
180  preg_match($regexp, $db->f("homedir"), $match);
181 
182  $lg = explode("_", $db->f("name"));
183  if ((!is_array($lg)) || (count($lg) != 2)) {
184  $lg[0] = $db->f("name");
185  $lg[1] = "";
186  }
187  $r[] = array(
188  "id" => $db->f("id"),
189  "prefixe" => $lg[0],
190  "login" => $lg[1],
191  "dir" => $match[1],
192  "enabled" => $db->f("enabled")
193  );
194  return $r;
195  } else {
196  $msg->raise("ERROR", "ftp", _("This FTP account does not exist"));
197  return false;
198  }
199  }
200 
201 
202  /**
203  * Retourne la liste des prefixes utilisables par le compte courant
204  * @return array tableau contenant la liste des prefixes (domaines + login)
205  * du compte actuel.
206  */
207  function prefix_list() {
208  global $db, $mem, $cuid;
209  $r = array();
210  $r[] = $mem->user["login"];
211  $db->query("SELECT domaine FROM domaines WHERE compte= ? ORDER BY domaine;", array($cuid));
212  while ($db->next_record()) {
213  $r[] = $db->f("domaine");
214  }
215  return $r;
216  }
217 
218 
219  /**
220  * Check if the login is fine (syntax)
221  * @param string $l
222  */
223  function check_login($l) {
224  global $msg;
225  // special chars and the max numbers of them allowed
226  // to be able to give a specific error
227  $vv = array('_' => '1', ' ' => 0);
228  foreach ($vv as $k => $n) {
229  if (substr_count($l, $k) > $n) { // if there is more than $n $k
230  $msg->raise("ERROR", 'ftp', sprintf(_("FTP login is incorrect: too many '%s'"), $k));
231  return false;
232  }
233  }
234  // Explicitly look for only allowed chars
235  if (!preg_match("/^[A-Za-z0-9]+[A-Za-z0-9_\.\-]*$/", $l)) {
236  $msg->raise("ERROR", 'ftp', _("FTP login is incorrect"));
237  return false;
238  }
239  return true;
240  }
241 
242 
243  /**
244  * Affiche (ECHO) la liste des prefixes disponibles sous forme de champs d'option
245  * Les champs sont affich�s sous la forme <option>prefixe</option>...
246  * La valeur $current se voit affubl�e de la balise SELECTED.
247  * @param string $current Prefixe s�lectionn� par d�faut
248  * @return boolean TRUE.
249  */
250  function select_prefix_list($current) {
251  $r = $this->prefix_list();
252  reset($r);
253  while (list($key, $val) = each($r)) {
254  if ($current == $val) {
255  $c = " selected=\"selected\"";
256  } else {
257  $c = "";
258  }
259  echo "<option$c>$val</option>";
260  }
261  return true;
262  }
263 
264 
265  /**
266  * Modifie les param�tres du comptes FTP $id.
267  * @param integer $id Num�ro du compte dont on veut modifier les param�tres
268  * @param string $prefixe Prefixe du compte FTP
269  * @param string $login login ajout� au pr�fixe ($prefixe_$login)
270  * @param string $pass mot de passe
271  * @param string $dir R�pertoire racine du compte
272  * @return boolean TRUE si le compte a �t� modifi�, FALSE si une erreur est survenue.
273  */
274  function put_ftp_details($id, $prefixe, $login, $pass, $dir) {
275  global $db, $msg, $bro, $cuid, $admin;
276  $msg->log("ftp", "put_ftp_details", $id);
277  $db->query("SELECT count(*) AS cnt FROM ftpusers WHERE id= ? and uid= ?;", array($id, $cuid));
278  $db->next_record();
279  if (!$db->f("cnt")) {
280  $msg->raise("ERROR", "ftp", _("This FTP account does not exist"));
281  return false;
282  }
283  $dir = $bro->convertabsolute($dir);
284  if (substr($dir, 0, 1) == "/") {
285  $dir = substr($dir, 1);
286  }
287  $r = $this->prefix_list();
288  if (!in_array($prefixe, $r)) {
289  $msg->raise("ERROR", "ftp", _("The chosen prefix is not allowed"));
290  return false;
291  }
292 
293  $full_login = $prefixe;
294  if ($login) {
295  $full_login.="_" . $login;
296  }
297  if (!$this->check_login($full_login)) {
298  return false;
299  }
300  $db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE id!= ? AND name= ?;", array($id, $full_login));
301  $db->next_record();
302  if ($db->f("cnt")) {
303  $msg->raise("ERROR", "ftp", _("This FTP account already exists"));
304  return false;
305  }
306  $absolute = getuserpath() . "/$dir";
307  if (!file_exists($absolute)) {
308  system("/bin/mkdir -p $absolute");
309  }
310  if (!is_dir($absolute)) {
311  $msg->raise("ERROR", "ftp", _("The directory cannot be created"));
312  return false;
313  }
314  if (trim($pass)) {
315 
316  // Check this password against the password policy using common API :
317  if (is_callable(array($admin, "checkPolicy"))) {
318  if (!$admin->checkPolicy("ftp", $full_login, $pass)) {
319  return false; // The error has been raised by checkPolicy()
320  }
321  }
322  $encrypted_password = _sha512cr($pass);
323  $db->query("UPDATE ftpusers SET name= ? , password='', encrypted_password= ?, homedir= ?, uid= ? WHERE id= ?;", array($full_login, $encrypted_password, $absolute, $cuid, $id));
324  } else {
325  $db->query("UPDATE ftpusers SET name= ? , homedir= ? , uid= ? WHERE id= ? ;", array($full_login, $absolute, $cuid, $id));
326  }
327  return true;
328  }
329 
330 
331  /**
332  * Efface le compte ftp specifie
333  * @param integer $id Numero du compte FTP a supprimer.
334  * @return boolean TRUE si le compte a ete efface, FALSE sinon.
335  */
336  function delete_ftp($id) {
337  global $db, $msg, $cuid;
338  $msg->log("ftp", "delete_ftp", $id);
339  $db->query("SELECT name FROM ftpusers WHERE id= ? and uid= ? ;", array($id, $cuid));
340  $db->next_record();
341  $name = $db->f("name");
342  if (!$name) {
343  $msg->raise("ERROR", "ftp", _("This FTP account does not exist"));
344  return false;
345  }
346  $db->query("DELETE FROM ftpusers WHERE id= ? ;", array($id));
347  return $name;
348  }
349 
350 
351  /**
352  * Cree un nouveau compte FTP.
353  * @param string $prefixe Prefixe au login
354  * @param string $login Login ftp (login=prefixe_login)
355  * @param string $pass Mot de passe FTP
356  * @param string $dir Repertoire racine du compte relatif à la racine du membre
357  * @return boolean TRUE si le compte a ete cree, FALSE sinon.
358  */
359  function add_ftp($prefixe, $login, $pass, $dir) {
360  global $db, $msg, $quota, $bro, $cuid, $admin;
361  $msg->log("ftp", "add_ftp", $prefixe . "_" . $login);
362  $dir = $bro->convertabsolute($dir);
363  if (substr($dir, 0, 1) == "/") {
364  $dir = substr($dir, 1);
365  }
366  $r = $this->prefix_list();
367  if (empty($pass)) {
368  $msg->raise("ERROR", "ftp", _("Password can't be empty"));
369  return false;
370  }
371  if (!in_array($prefixe, $r) || $prefixe == "") {
372  $msg->raise("ERROR", "ftp", _("The chosen prefix is not allowed"));
373  return false;
374  }
375  $full_login = $prefixe;
376  if ($login) {
377  $full_login.="_" . $login;
378  }
379  if (!$this->check_login($full_login)) {
380  return false;
381  }
382  $db->query("SELECT count(*) AS cnt FROM ftpusers WHERE name= ? ;", array($full_login));
383  $db->next_record();
384  if ($db->f("cnt")) {
385  $msg->raise("ERROR", "ftp", _("This FTP account already exists"));
386  return false;
387  }
388  $db->query("SELECT login FROM membres WHERE uid= ? ;", array($cuid));
389  $db->next_record();
390  $absolute = getuserpath() . "/$dir";
391  if (!file_exists($absolute)) {
392  system("/bin/mkdir -p $absolute"); // FIXME replace with action
393  }
394  if (!is_dir($absolute)) {
395  $msg->raise("ERROR", "ftp", _("The directory cannot be created"));
396  return false;
397  }
398 
399  // Check this password against the password policy using common API :
400  if (is_callable(array($admin, "checkPolicy"))) {
401  if (!$admin->checkPolicy("ftp", $full_login, $pass)) {
402  return false; // The error has been raised by checkPolicy()
403  }
404  }
405 
406  if ($quota->cancreate("ftp")) {
407  $encrypted_password = _sha512cr($pass);
408  $db->query("INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES ( ?, '', ?, ?, ?)", array($full_login, $encrypted_password, $absolute, $cuid));
409  return true;
410  } else {
411  $msg->raise("ERROR", "ftp", _("Your FTP account quota is over. You cannot create more FTP accounts"));
412  return false;
413  }
414  }
415 
416 
417  /**
418  * Retourne TRUE si $dir possee un compte FTP
419  * @param string $dir Dossier a tester, relatif a la racine du compte courant
420  * @return boolean retourne TRUE si $dir a un compte FTP, FALSE sinon.
421  */
422  function is_ftp($dir) {
423  global $db, $msg;
424  $msg->debug("ftp", "is_ftp", $dir);
425  if (substr($dir, 0, 1) == "/") {
426  $dir = substr($dir, 1);
427  }
428  $db->query("SELECT id FROM ftpusers WHERE homedir= ? ;", array( getuserpath() . "/" .$dir ));
429  if ($db->num_rows()) {
430  $db->next_record();
431  return $db->f("id");
432  } else {
433  return false;
434  }
435  }
436 
437 
438  /**
439  * Fonction appellee par domains quand un domaine est supprime pour le membre
440  * @param string $dom Domaine à detruire.
441  * @access private
442  */
444  global $db, $msg, $cuid;
445  $msg->log("ftp", "alternc_del_domain", $dom);
446  $db->query("DELETE FROM ftpusers WHERE uid= ? AND ( name LIKE ? OR name LIKE ?) ", array($cuid, $dom."\_%", $dom));
447  return true;
448  }
449 
450 
451  /**
452  * Fonction appellee par membres quand un membre est efface
453  * @access private
454  */
455  function alternc_del_member() {
456  global $db, $msg, $cuid;
457  $msg->log("ftp", "alternc_del_member");
458  $db->query("DELETE FROM ftpusers WHERE uid= ?", array($cuid));
459  return true;
460  }
461 
462 
463  /**
464  * Returns the used quota for the $name service for the current user.
465  * @param $name string name of the quota
466  * @return integer the number of service used or false if an error occured
467  * @access private
468  */
469  function hook_quota_get() {
470  global $db, $msg, $cuid;
471  $msg->debug("ftp", "getquota");
472  $q = Array("name" => "ftp", "description" => _("FTP accounts"), "used" => 0);
473  $db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE uid= ? ", array($cuid));
474  if ($db->next_record()) {
475  $q['used'] = $db->f("cnt");
476  }
477  return $q;
478  }
479 
480 
481  /**
482  * Exporte toutes les informations ftp du compte AlternC
483  * @access private
484  * EXPERIMENTAL 'sid' function ;)
485  */
486  function alternc_export_conf() {
487  global $db, $msg;
488  $msg->log("ftp", "export");
489  $f = $this->get_list();
490  $str = " <ftp>";
491  foreach ($f as $d => $v) {
492  $str.=" <login>" . ($v["login"]) . "</login>\n";
493  $str.=" <password>" . ($v["encrypted_password"]) . "</password>\n";
494  $str.=" <directory>" . ($v["dir"]) . "<directory>\n";
495  }
496  $str.=" </ftp>\n";
497  return $str;
498  }
499 
500 
501 } /* Class m_ftp */
502 
global $db
Definition: bootstrap.php:26
$mem
Definition: bootstrap.php:71
$msg
Definition: bootstrap.php:75
$c
Definition: bootstrap.php:47
$cuid
Definition: bootstrap.php:43
$r
Definition: aws_add.php:75
$d
variable_get($name, $default=null, $createit_comment=null)
Return a persistent variable.
Definition: variables.php:85
FTP account management class.
Definition: m_ftp.php:26
hook_menu()
hook function called by menu class to add menu to the left panel
Definition: m_ftp.php:52
get_ftp_details($id)
Retourne les details d'un compte FTP (voir get_list) Le tableau est celui du compte d'id specifie.
Definition: m_ftp.php:170
alternc_export_conf()
Exporte toutes les informations ftp du compte AlternC @access private EXPERIMENTAL 'sid' function ;)
Definition: m_ftp.php:486
put_ftp_details($id, $prefixe, $login, $pass, $dir)
Modifie les param�tres du comptes FTP $id.
Definition: m_ftp.php:274
is_ftp($dir)
Retourne TRUE si $dir possee un compte FTP.
Definition: m_ftp.php:422
select_prefix_list($current)
Affiche (ECHO) la liste des prefixes disponibles sous forme de champs d'option Les champs sont affich...
Definition: m_ftp.php:250
hook_quota_get()
Returns the used quota for the $name service for the current user.
Definition: m_ftp.php:469
get_list()
Retourne la liste des comptes FTP du compte h�berg� Retourne la liste des comptes FTP sous forme de t...
Definition: m_ftp.php:141
prefix_list()
Retourne la liste des prefixes utilisables par le compte courant.
Definition: m_ftp.php:207
alternc_del_domain($dom)
Fonction appellee par domains quand un domaine est supprime pour le membre.
Definition: m_ftp.php:443
authip_class()
Return the values needed to activate security access.
Definition: m_ftp.php:86
check_login($l)
Check if the login is fine (syntax)
Definition: m_ftp.php:223
alternc_del_member()
Fonction appellee par membres quand un membre est efface @access private.
Definition: m_ftp.php:455
$srv_proftpd
Definition: m_ftp.php:28
delete_ftp($id)
Efface le compte ftp specifie.
Definition: m_ftp.php:336
m_ftp()
Constructor.
Definition: m_ftp.php:34
alternc_password_policy()
Password kind used in this class (hook for admin class)
Definition: m_ftp.php:43
switch_enabled($id, $status=null)
Switch enabled status of an account.
Definition: m_ftp.php:107
add_ftp($prefixe, $login, $pass, $dir)
Cree un nouveau compte FTP.
Definition: m_ftp.php:359
getuserpath($user=null)
get the home of the user
Definition: functions.php:329
_sha512cr($password, $salt=NULL)
Create a SHA512-CRYPT hash of a string.
Definition: functions.php:1213
$q
Definition: menu_aws.php:32
$bro
Definition: bootstrap.php:151
$login
if(!isset($is_include)) if(! $key &&! $crt) $id
$val
Definition: tempovars.php:15
if(empty($_POST['key'])||empty($_POST['val'])) $key
Definition: tempovars.php:14
$dom
Definition: whois_test.php:10