source: alternc/trunk/bureau/class/m_dom.php @ 2855

Revision 2855, 40.3 KB checked in by fufroma, 2 years ago (diff)

Vaguement :

  • correction de qques identation (et surement rajout d'erreur)
  • supression de apache 1 (c'est plus maintenu, on va pas s'étaler)
  • suppression du mass vhosting
  • corrections de bugs divers et varié
Line 
1<?php
2/*
3 $Id: m_dom.php,v 1.27 2006/02/17 18:34:30 olivier Exp $
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 Original Author of file: Benjamin Sonntag
20 Purpose of file: PHP Class that manage domain names installed on the server
21 ----------------------------------------------------------------------
22*/
23
24define('SLAVE_FLAG', "/var/run/alternc/refresh_slave");
25
26/**
27* Classe de gestion des domaines de l'hébergé.
28*
29* Cette classe permet de gérer les domaines / sous-domaines, redirections
30* dns et mx des domaines d'un membre hébergé.<br />
31* Copyleft {@link http://alternc.net/ AlternC Team}
32*
33* @copyright    AlternC-Team 2002-11-01 http://alternc.net/
34*
35*/
36class m_dom {
37
38  /** $domains : Cache des domaines du membre
39   * @access private
40   */
41  var $domains;
42
43  /** $dns : Liste des dns trouvés par la fonction whois
44   * @access private
45   */
46  var $dns;
47
48  /** Flag : a-t-on trouvé un sous-domaine Webmail pour ce domaine ?
49   * @access private
50   */
51  var $webmail;
52
53  /**
54   * Système de verrouillage du cron
55   * Ce fichier permet de verrouiller le cron en attendant la validation
56   * du domaine par update_domains.sh
57   * @access private
58   */
59  var $fic_lock_cron="/var/run/alternc/cron.lock";
60
61  /**
62   * Le cron a-t-il été bloqué ?
63   * Il faut appeler les fonctions privées lock et unlock entre les
64   * appels aux domaines.
65   * @access private
66   */
67  var $islocked=false;
68
69  var $type_local = "VHOST";
70  var $type_url = "URL";
71  var $type_ip = "IP";
72  var $type_webmail = "WEBMAIL";
73  var $type_ipv6 = "IPV6";
74  var $type_cname = "CNAME";
75  var $type_txt = "TXT";
76
77  var $action_insert = "0";
78  var $action_update= "1";
79  var $action_delete = "2";
80
81  /* ----------------------------------------------------------------- */
82  /**
83   * Constructeur
84   */
85  function m_dom() {
86  }
87
88  /* ----------------------------------------------------------------- */
89  /**
90   * Quota name
91   */
92  function alternc_quota_names() {
93    return "dom";
94  }
95  /* ----------------------------------------------------------------- */
96  /**
97   * Retourne un tableau contenant les types de domaines
98   *
99   * @return array retourne un tableau indexé contenant la liste types de domaines
100   *  authorisé. Retourne FALSE si une erreur s'est produite.
101   */
102  function domains_type_lst() {
103    global $db,$err,$cuid;
104    $err->log("dom","domains_type_lst");
105    $db->query("select * from domaines_type order by advanced, name;");
106    $this->domains_type_lst=false;
107    while ($db->next_record()) {
108      $this->domains_type_lst[] = $db->Record;
109    }
110    return $this->domains_type_lst;
111  }
112
113  function domains_type_enable_values() {
114    global $db,$err,$cuid;
115    $err->log("dom","domains_type_target_values");
116    $db->query("desc domaines_type;");
117    $r = array();
118    while ($db->next_record()) {
119      if ($db->f('Field') == 'enable') {
120        $tab = explode(",", substr($db->f('Type'), 5, -1));
121        foreach($tab as $t) { $r[]=substr($t,1,-1); }
122      }
123    }
124    return $r;
125  }
126
127  function domains_type_target_values($type=null) {
128    global $db,$err,$cuid;
129    $err->log("dom","domains_type_target_values");
130    if (is_null($type)) {
131      $db->query("desc domaines_type;");
132      $r = array();
133      while ($db->next_record()) {
134        if ($db->f('Field') == 'target') {
135          $tab = explode(",", substr($db->f('Type'), 5, -1));
136          foreach($tab as $t) { $r[]=substr($t,1,-1); }
137        }
138      }
139      return $r;
140    } else {
141      $db->query("select target from domaines_type where name='$type';");
142      if (! $db->next_record()) return false;
143      return $db->f('target');
144    }
145  }
146
147  function domains_type_regenerate($name) {
148    global $db,$err,$cuid; 
149    $name=mysql_real_escape_string($name);
150    $db->query("update sub_domaines set web_action='UPDATE' where lower(type) = lower('$name') ;");
151    $db->query("update domaines d, sub_domaines sd set d.dns_action = 'UPDATE' where lower(sd.type)=lower('$name');");
152    return true;
153  }
154
155  function domains_type_get($name) {
156    global $db,$err,$cuid; 
157    $name=mysql_real_escape_string($name);
158    $db->query("select * from domaines_type where name='$name' ;");
159    $db->next_record();
160    return $db->Record;
161  }
162
163  function domains_type_del($name) {
164    global $db,$err,$cuid;
165    $name=mysql_real_escape_string($name);
166    $db->query("delete domaines_type where name='$name';");
167    return true;
168  }
169
170  function domains_type_disable($id) {
171    global $db,$err,$cuid;
172    $id=intval($id);
173    $db->query("update domaines_type set enable=false where id=$id;");
174    return true;
175  }
176
177  function domains_type_enable($id) {
178    global $db,$err,$cuid;
179    $id=intval($id);
180    $db->query("update domaines_type set enable=true where id=$id;");
181    return true;
182  }
183
184  function domains_type_update($name, $description, $target, $entry, $compatibility, $enable, $only_dns, $need_dns,$advanced) {
185    global $err,$cuid,$db;
186    $id=intval($id);
187    $name=mysql_real_escape_string($name);
188    $description=mysql_real_escape_string($description);
189    $target=mysql_real_escape_string($target);
190    $entry=mysql_real_escape_string($entry);
191    $compatibility=mysql_real_escape_string($compatibility);
192    $enable=mysql_real_escape_string($enable);
193    $only_dns=intval($only_dns);
194    $need_dns=intval($need_dns);
195    $advanced=intval($advanced);
196    $db->query("UPDATE domaines_type SET description='$description', target='$target', entry='$entry', compatibility='$compatibility', enable='$enable', need_dns=$need_dns, only_dns=$only_dns, advanced='$advanced' where name='$name';");
197    return true;
198  }   
199
200  function sub_domain_change_status($domain,$sub,$type,$value,$status) {
201    global $db,$err,$cuid;
202    $err->log("dom","sub_domain_change_status");
203    $status=strtoupper($status);
204    if (! in_array($status,array('ENABLE', 'DISABLE'))) return false;
205
206    $db->query("update sub_domaines set enable='$status' where domaine='$domain' and sub='$sub' and lower(type)=lower('$type') and valeur='$value'");
207
208    return true;
209  } 
210
211  /* ----------------------------------------------------------------- */
212  /**
213   * Retourne un tableau contenant les domaines d'un membre.
214   *
215   * @return array retourne un tableau indexé contenant la liste des
216   *  domaines hébergés sur le compte courant. Retourne FALSE si une
217   *  erreur s'est produite.
218   */
219  function enum_domains() {
220    global $db,$err,$cuid;
221    $err->log("dom","enum_domains");
222    $db->query("select * from domaines where compte='$cuid' order by domaine asc;");
223    $this->domains=array();
224    if ($db->num_rows()>0) {
225      while ($db->next_record()) {
226      $this->domains[]=$db->f("domaine");
227      }
228    }
229    return $this->domains;
230  }
231
232  function del_domain_cancel($dom) {
233    global $db,$err,$classes,$cuid;
234    $err->log("dom","del_domaini_canl",$dom);
235    $dom=strtolower($dom);
236    $db->query("UPDATE sub_domaines SET web_action='UPDATE'  WHERE domaine='$dom';");
237    $db->query("UPDATE domaines SET dns_action='UPDATE'  WHERE domaine='$dom';");
238
239    # TODO : some work with domain sensitive classes
240
241    return true;
242  }
243
244  /* ----------------------------------------------------------------- */
245  /**
246   *  Efface un domaine du membre courant, et tous ses sous-domaines
247   *
248   * Cette fonction efface un domaine et tous ses sous-domaines, ainsi que
249   * les autres services attachés à celui-ci. Elle appelle donc les autres
250   * classe. Chaque classe peut déclarer une fonction del_dom qui sera
251   * appellée lors de la destruction d'un domaine.
252   *
253   * @param string $dom nom de domaine à effacer
254   * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
255   */
256  function del_domain($dom) {
257    global $db,$err,$classes,$cuid;
258    $err->log("dom","del_domain",$dom);
259    $dom=strtolower($dom);
260    $db->query("SELECT * FROM domaines WHERE domaine='$dom';");
261    if ($db->num_rows()==0) {
262      $err->raise("dom",1,$dom);
263      return false;
264    }
265    $db->next_record();
266    if ($db->f("compte")!=$cuid) {
267      $err->raise("dom",2,$dom);
268      return false;
269    }
270    $db->query("UPDATE sub_domaines SET web_action='DELETE'  WHERE domaine='$dom';");
271    $db->query("UPDATE domaines SET dns_action='DELETE'  WHERE domaine='$dom';");
272
273    // DEPENDANCE :
274    // Lancement de del_dom sur les classes domain_sensitive :
275    // Declenchons les autres classes.
276    foreach($classes as $c) {
277      if (method_exists($GLOBALS[$c],"alternc_del_domain")) {
278          $GLOBALS[$c]->alternc_del_domain($dom);
279      }
280    }
281    foreach($classes as $c) {
282      if (method_exists($GLOBALS[$c],"alternc_del_mx_domain")) {
283          $GLOBALS[$c]->alternc_del_mx_domain($dom);
284      }
285    }
286    return true;
287  }
288
289  /* ----------------------------------------------------------------- */
290  /**
291   *  Installe un domaine sur le compte courant.
292   *
293   * <p>Si le domaine existe déjà ou est interdit, ou est celui du serveur,
294   * l'installation est refusée. Si l'hébergement DNS est demandé, la fonction
295   * checkhostallow vérifiera que le domaine peut être installé conformément
296   * aux demandes des super-admin.
297   * Si le dns n'est pas demandé, le domaine peut être installé s'il est en
298   * seconde main d'un tld (exemple : test.eu.org ou test.com, mais pas
299   * toto.test.org ou test.test.asso.fr)</p>
300   * <p>Chaque classe peut définir une fonction add_dom($dom) qui sera
301   * appellée lors de l'installation d'un nouveau domaine.</p>
302   *
303   * @param string $dom nom fqdn du domaine à installer
304   * @param integer $dns 1 ou 0 pour héberger le DNS du domaine ou pas.
305   * @param integer $noerase 1 ou 0 pour rendre le domaine inamovible ou non
306   * @param integer $force 1 ou 0, si 1, n'effectue pas les tests de DNS.
307   *  force ne devrait être utilisé que par le super-admin.
308   $ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
309  */
310  function add_domain($domain,$dns,$noerase=0,$force=0,$isslave=0,$slavedom="") {
311    global $db,$err,$quota,$classes,$L_MX,$L_FQDN,$tld,$cuid,$bro;
312    $err->log("dom","add_domain",$domain);
313    $mx="1";
314    // Locked ?
315    if (!$this->islocked) {
316      $err->raise("dom",3);
317      return false;
318    }
319    // Verifie que le domaine est rfc-compliant
320    $domain=strtolower($domain);
321    $t=checkfqdn($domain);
322    if ($t) {
323      $err->raise("dom",3+$t);
324      return false;
325    }
326    // Interdit les domaines clés (table forbidden_domains) sauf en cas FORCE
327    $db->query("select domain from forbidden_domains where domain='$domain'");
328    if ($db->num_rows() && !$force) {
329      $err->raise("dom",22);
330      return false;
331    }
332    if ($domain==$L_FQDN || $domain=="www.$L_FQDN") {
333      $err->raise("dom",18);
334      return false;
335    }
336    $db->query("SELECT compte FROM domaines WHERE domaine='$domain';");
337    if ($db->num_rows()) {
338      $err->raise("dom",8);
339      return false;
340    }
341    $db->query("SELECT compte FROM `sub_domaines` WHERE sub != \"\" AND concat( sub, \".\", domaine )='$domain' OR domaine='$domain';");
342    if ($db->num_rows()) {
343      $err->raise("dom",8);
344      return false;
345    }
346    $this->dns=$this->whois($domain);
347    if (!$force) {
348      $v=checkhostallow($domain,$this->dns);
349      if ($v==-1) {
350  $err->raise("dom",7);   // TLD interdit
351  return false;
352      }
353      if ($dns && $v==-2) {
354  $err->raise("dom",12);   // Domaine non trouvé dans le whois
355  return false;
356      }
357      if ($dns && $v==-3) {
358  $err->raise("dom",23);   // Domaine non trouvé dans le whois
359  return false;
360      }
361
362      if ($dns) $dns="1"; else $dns="0";
363
364      // mode 5 : force DNS to NO.
365      if ($tld[$v]==5) $dns=0;
366      // It must be a real domain (no subdomain)
367      if (!$dns) {
368  $v=checkhostallow_nodns($domain);
369  if ($v) {
370    $err->raise("dom",22);
371    return false;
372  }
373      }
374    }
375    // Check the quota :
376    if (!$quota->cancreate("dom")) {
377      $err->raise("dom",10);
378      return false;
379    }
380    if ($noerase) $noerase="1"; else $noerase="0";
381    $db->query("insert into domaines (compte,domaine,mx,gesdns,gesmx,noerase,dns_action) values ('$cuid','$domain','$L_MX','$dns','$mx','$noerase','UPDATE');");
382
383    if ($isslave) {
384      $isslave=true;
385      $db->query("SELECT domaine FROM domaines WHERE compte='$cuid' AND domaine='$slavedom';");
386      $db->next_record();
387      if (!$db->Record["domaine"]) {
388  $err->raise("dom",1,$slavedom);
389  $isslave=false;
390      }
391      // Point to the master domain :
392      $this->set_sub_domain($domain, '',     $this->type_url, 'http://www.'.$slavedom);
393      $this->set_sub_domain($domain, 'www',  $this->type_url, 'http://www.'.$slavedom);
394      $this->set_sub_domain($domain, 'mail', $this->type_url, 'http://mail.'.$slavedom);     
395    }
396    if (!$isslave) {
397      // Creation du repertoire dans www
398      $dest_root = $bro->get_userid_root($cuid);
399      $domshort=str_replace("-","",str_replace(".","",$domain));
400     
401      if (! is_dir($dest_root . "/". $domshort)) {
402  mkdir($dest_root . "/". $domshort);
403      }
404     
405      // Creation des 3 sous-domaines par défaut : Vide, www et mail
406      $this->set_sub_domain($domain, '',     $this->type_url,     'http://www.'.$domain);
407      $this->set_sub_domain($domain, 'www',  $this->type_local,   '/'. $domshort);
408      $this->set_sub_domain($domain, 'mail', $this->type_webmail, '');
409    }
410    // DEPENDANCE :
411    // Lancement de add_dom sur les classes domain_sensitive :
412    // Declenchons les autres classes.   
413    foreach($classes as $c) {
414      if (method_exists($GLOBALS[$c],"alternc_add_domain")) {
415  $GLOBALS[$c]->alternc_add_domain($domain);
416      }
417    }
418    foreach($classes as $c) {
419      if (method_exists($GLOBALS[$c],"alternc_add_mx_domain")) {
420  $GLOBALS[$c]->alternc_add_mx_domain($domain);
421      }
422    }
423    if ($isslave) {
424      foreach($classes as $c) {
425  if (method_exists($GLOBALS[$c],"alternc_add_slave_domain")) {
426    $GLOBALS[$c]->alternc_add_slave_domain($domain,$slavedom);
427  }
428      } 
429    }
430    return true;
431  }
432
433  /* ----------------------------------------------------------------- */
434  /**
435   * Retourne les entrées DNS du domaine $domain issues du WHOIS.
436   *
437   * Cette fonction effectue un appel WHOIS($domain) sur Internet,
438   * et extrait du whois les serveurs DNS du domaine demandé. En fonction
439   * du TLD, on sait (ou pas) faire le whois correspondant.
440   * Actuellement, les tld suivants sont supportés :
441   * .com .net .org .be .info .ca .cx .fr .biz .name
442   *
443   * @param string $domain Domaine fqdn dont on souhaite les serveurs DNS
444   * @return array Retourne un tableau indexé avec les NOMS fqdn des dns
445   *   du domaine demandé. Retourne FALSE si une erreur s'est produite.
446   *
447   */
448  function whois($domain) {
449    global $db,$err;
450    $err->log("dom","whois",$domain);
451    // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
452    //  echo "whois : $domain<br />";
453    ereg(".*\.([^\.]*)",$domain,$out);
454    $ext=$out[1];
455    // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
456    //  echo "ext: $ext<br />";
457
458    if (($fp=@fsockopen("whois.iana.org", 43))>0) {
459      fputs($fp, "$domain\r\n");
460      $found = false;
461      $state=0;
462      while (!feof($fp)) {
463        $ligne = fgets($fp,128);
464        if (ereg('^whois:[[:space:]]+.*$', $ligne)) { $serveur=preg_replace('/whois:\ */','',$ligne,1); }
465      }
466    }
467
468    $egal="";
469    switch($ext) {
470    case "net":
471      $egal="=";
472      break;
473    case "name":
474      $egal="domain = ";
475      break;
476    }
477    // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
478    //  echo "serveur : $serveur <br />";
479    if (($fp=@fsockopen($serveur, 43))>0) {
480      fputs($fp, "$egal$domain\r\n");
481      $found = false;
482      $state=0;
483      while (!feof($fp)) {
484  $ligne = fgets($fp,128);
485  // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
486  //  echo "| $ligne<br />";
487  switch($ext) {
488  case "org":
489  case "com":
490  case "net":
491  case "info":
492  case "biz":
493  case "name":
494  case "cc":
495    if (ereg("Name Server:", $ligne)) {
496      $found = true;
497      $tmp=strtolower(ereg_replace(chr(10), "",ereg_replace(chr(13),"",ereg_replace(" ","", ereg_replace("Name Server:","", $ligne)))));
498      if ($tmp)
499        $server[]=$tmp;
500    }
501    break;
502  case "cx":
503    $ligne = ereg_replace(chr(10), "",ereg_replace(chr(13),"",ereg_replace(" ","", $ligne)));
504    if ($ligne=="" && $state==1)
505      $state=2;
506    if ($state==1)
507      $server[]=strtolower($ligne);
508    if ($ligne=="Nameservers:" && $state==0) {
509      $state=1;
510      $found = true;
511    }
512    break;
513        case "eu":
514  case "be":
515          $ligne=preg_replace("/^ *([^ ]*) \(.*\)$/","\\1",trim($ligne));
516          if($found)
517             $tmp = trim($ligne);
518          if ($tmp)
519             $server[]=$tmp;
520          if ($ligne=="Nameservers:") {
521            $state=1;
522            $found=true;
523          }
524          break;
525    case "im":
526          if (preg_match('/Name Server:/', $ligne)) {
527            $found = true;
528            // weird regexp (trailing garbage after name server), but I could not make it work otherwise
529            $tmp = strtolower(preg_replace('/Name Server: ([^ ]+)\..$/',"\\1", $ligne));
530            $tmp = preg_replace('/[^-_a-z0-9\.]/', '', $tmp);
531            if ($tmp)
532              $server[]=$tmp;
533          }
534          break;
535    case "it":
536          if (ereg("nserver:", $ligne)) {
537            $found=true;
538            $tmp=strtolower(preg_replace("/nserver:\s*[^ ]*\s*([^\s]*)$/","\\1", $ligne));
539            if ($tmp)
540              $server[]=$tmp;
541          }
542          break;
543  case "fr":
544  case "re":
545          if (ereg("nserver:", $ligne)) {
546            $found=true;
547            $tmp=strtolower(preg_replace("/nserver:\s*([^\s]*)\s*.*$/","\\1", $ligne));
548            if ($tmp)
549              $server[]=$tmp;
550          }
551          break;
552  case "ca":
553  case "ws";
554    if (ereg('^[[:space:]]*Name servers:[[:space:]]*$', $ligne)) {
555          // found the server
556      $state = 1;
557    } elseif ($state) {
558      if (ereg('^[^%]', $ligne) && $ligne = ereg_replace('[[:space:]]', "", $ligne)) {
559      // first non-whitespace line is considered to be the nameservers themselves
560      $found = true;
561      $server[] = $ligne;
562    }
563    }
564    break;
565        case "coop":
566          if (preg_match('/Host Name:\s*([^\s]+)/', $ligne, $matches)) {
567            $found = true;
568            $server[] = $matches[1];
569          }
570  } // switch
571      } // while
572      fclose($fp);
573    } else {
574      $err->raise("dom",11);
575      return false;
576    }
577
578    if ($found) {
579      return $server;
580    } else {
581      $err->raise("dom",12);
582      return false;
583    }
584  } // whois
585
586  /* ----------------------------------------------------------------- */
587  /**
588   *  vérifie la presence d'un champs mx valide sur un serveur DNS
589   *
590  */
591 
592  function checkmx($domaine,$mx) {
593    //initialise variables
594    $mxhosts = array();
595   
596    //récupére les champs mx
597    if (!getmxrr($domaine,$mxhosts)) {
598      //aucune hôte mx spécifié
599      return 1;
600    }
601    else {
602      //vérifie qu'un des hôtes est bien sur alternc
603      $bolmx = 0;
604      //décompose les différents champ MX coté alternc
605      $arrlocalmx = split(",",$mx);
606      //parcours les différents champ MX retournés
607      foreach($mxhosts as $mxhost) {
608        foreach($arrlocalmx as $localmx) {
609          if ($mxhost==$localmx) {
610            $bolmx = 1;
611          }
612        }
613      }
614      //définition de l'erreur selon reponse du parcours de mxhosts
615      if ($bolmx == 0) {
616        //aucun des champs MX ne correspond au serveur
617        return 2;         
618      }
619      else {
620        //un champ mx correct a été trouvé
621        return 0;
622      }
623    }
624  } //checkmx
625
626
627  /* ----------------------------------------------------------------- */
628  /**
629   *  retourne TOUTES les infos d'un domaine
630   *
631   * @param string $dom Domaine dont on souhaite les informations
632   * @return array Retourne toutes les infos du domaine sous la forme d'un
633   * tableau associatif comme suit :<br /><pre>
634   *  $r["name"] =  Nom fqdn
635   *  $r["dns"]  =  Gestion du dns ou pas ?
636   *  $r["mx"]   =  Valeur du champs MX si "dns"=true
637   *  $r["mail"] =  Heberge-t-on le mail ou pas ? (si "dns"=false)
638   *  $r["nsub"] =  Nombre de sous-domaines
639   *  $r["sub"]  =  tableau associatif des sous-domaines
640   *  $r["sub"][0-(nsub-1)]["name"] = nom du sous-domaine (NON-complet)
641   *  $r["sub"][0-(nsub-1)]["dest"] = Destination (url, ip, local ...)
642   *  $r["sub"][0-(nsub-1)]["type"] = Type (0-n) de la redirection.
643   *  </pre>
644   *  Retourne FALSE si une erreur s'est produite.
645   *
646   */
647  function get_domain_all($dom) {
648    global $db,$err,$cuid;
649    $err->log("dom","get_domain_all",$dom);
650    // Locked ?
651    if (!$this->islocked) {
652      $err->raise("dom",3);
653      return false;
654    }
655    $t=checkfqdn($dom);
656    if ($t) {
657      $err->raise("dom",3+$t);
658      return false;
659    }
660    $r["name"]=$dom;
661    $db->query("select * from domaines where compte='$cuid' and domaine='$dom'");
662    if ($db->num_rows()==0) {
663      $err->raise("dom",1,$dom);
664      return false;
665    }
666    $db->next_record();
667    $r["dns"]=$db->Record["gesdns"];
668    $r["dns_action"]=$db->Record["dns_action"];
669    $r["dns_result"]=$db->Record["dns_result"];
670    $r["mail"]=$db->Record["gesmx"];
671    $r["mx"]=$db->Record["mx"];
672    $r['noerase']=$db->Record['noerase'];
673    $db->free();
674    $db->query("select count(*) as cnt from sub_domaines where compte='$cuid' and domaine='$dom'");
675    $db->next_record();
676    $r["nsub"]=$db->Record["cnt"];
677    $db->free();
678    $db->query("select sd.*, dt.description as type_desc, dt.only_dns from sub_domaines sd, domaines_type dt where compte='$cuid' and domaine='$dom' and upper(dt.name)=upper(sd.type) order by sd.sub,sd.type");
679    // Pas de webmail, on le cochera si on le trouve.
680    $this->webmail=0;
681    for($i=0;$i<$r["nsub"];$i++) {
682      $db->next_record();
683      $r["sub"][$i]=array();
684      $r["sub"][$i]["name"]=$db->Record["sub"];
685      $r["sub"][$i]["dest"]=$db->Record["valeur"];
686      $r["sub"][$i]["type"]=$db->Record["type"];
687      $r["sub"][$i]["enable"]=$db->Record["enable"];
688      $r["sub"][$i]["type_desc"]=$db->Record["type_desc"];
689      $r["sub"][$i]["only_dns"]=$db->Record["only_dns"];
690      $r["sub"][$i]["web_action"]=$db->Record["web_action"];
691/*
692      if ($db->Record["type"]==3) { // Webmail
693  $this->webmail=1;
694  $r["sub"][$i]["dest"]=_("Webmail access");
695      }
696*/
697    }
698    $db->free();
699    return $r;
700  } // get_domain_all
701
702
703  /* ----------------------------------------------------------------- */
704  /**
705   * Retourne TOUTES les infos d'un sous domaine du compte courant.
706   *
707   * @param string $dom Domaine fqdn concerné
708   * @param string $sub Sous-domaine dont on souhaite les informations
709   * @return arrray Retourne un tableau associatif contenant les
710   *  informations du sous-domaine demandé.<pre>
711   *  $r["name"]= nom du sous-domaine (NON-complet)
712   *  $r["dest"]= Destination (url, ip, local ...)
713   *  </pre>
714   *  $r["type"]= Type (0-n) de la redirection.
715   *  Retourne FALSE si une erreur s'est produite.
716   */
717  function get_sub_domain_all($dom,$sub, $type="", $value='') {
718    global $db,$err,$cuid;
719    $err->log("dom","get_sub_domain_all",$dom."/".$sub);
720    // Locked ?
721    if (!$this->islocked) {
722      $err->raise("dom",3);
723      return false;
724    }
725    $t=checkfqdn($dom);
726    if ($t) {
727      $err->raise("dom",3+$t);
728      return false;
729    }
730/*
731    if ( ! empty($value)) {
732        $type = " and valeur=\"".mysql_real_escape_string($value)."\"";
733    }
734    if ( ! empty($type)) {
735        $type = " and type=\"".mysql_real_escape_string($type)."\"";
736    }
737*/
738    $db->query("select sd.*, dt.description as type_desc, dt.only_dns from sub_domaines sd, domaines_type dt where compte='$cuid' and domaine='$dom' and sub='$sub' and ( length('$type')=0 or type='$type') and (length('$value')=0 or '$value'=valeur) and upper(dt.name)=upper(sd.type);");
739    if ($db->num_rows()==0) {
740      $err->raise("dom",14);
741      return false;
742    }
743    $db->next_record();
744    $r=array();
745    $r["name"]=$db->Record["sub"];
746    $r["dest"]=$db->Record["valeur"];
747    $r["enable"]=$db->Record["enable"];
748    $r["type_desc"]=$db->Record["type_desc"];
749    $r["only_dns"]=$db->Record["only_dns"];
750    $r["web_action"]=$db->Record["web_action"];
751    $db->free();
752    return $r;
753  } // get_sub_domain_all
754
755
756  function check_type_value($type, $value) {
757    global $db,$err,$cuid;
758
759    // check the type we can have in domaines_type.target
760
761    switch ($this->domains_type_target_values($type)) {
762      case 'NONE':
763        if (empty($value) or is_null($value)) {return true;}
764        break;
765      case 'URL': 
766        if ( $value == strval($value)) {return true;}
767        break;
768      case 'DIRECTORY': 
769        if (substr($value,0,1)!="/") {
770          $value="/".$value;
771        }
772        if (!checkuserpath($value)) {
773          $err->raise("dom",21);
774        return false;
775        }
776        return true;
777        break;
778      case 'IP': 
779        if (checkip($value)) {return true;}
780        break;
781      case 'IPV6': 
782        if (checkipv6($value)) {return true;}
783        break;
784      case 'DOMAIN': 
785        if (checkcname($value)) {return true;}
786        break;
787      case 'TXT':
788        if ( $value == strval($value)) {return true;}
789        break;
790      default:
791        return false;
792        break;
793    }
794    return false;
795  } //check_type_value
796
797
798  function can_create_subdomain($dom,$sub,$type,$type_old='', $value_old='') {
799    global $db,$err,$cuid;
800    $err->log("dom","can_create_subdomain",$dom."/".$sub);
801
802    # Get the compatibility list for this domain type
803    $db->query("select upper(compatibility) as compatibility from domaines_type where upper(name)=upper('$type');");
804    if (!$db->next_record()) return false;
805    $compatibility_lst = explode(",",$db->f('compatibility'));
806
807    # Get the list of type of subdomains already here who have the same name
808    $db->query("select * from sub_domaines where sub='$sub' and domaine='$dom' and not (type='$type_old' and valeur='$value_old') and web_action != 'DELETE'");
809    #$db->query("select * from sub_domaines where sub='$sub' and domaine='$dom';");
810    while ($db->next_record()) {
811      # And if there is a domain with a incompatible type, return false
812      if (! in_array(strtoupper($db->f('type')),$compatibility_lst)) return false;
813    }
814   
815    # All is right, go ! Create ur domain !
816    return true;
817  }
818
819  //  /* ----------------------------------------------------------------- */
820  /**
821   * Modifier les information du sous-domaine demandé.
822   *
823   * <b>Note</b> : si le sous-domaine $sub.$dom n'existe pas, il est créé.<br />
824   * <b>Note : TODO</b> : vérification de concordance de $dest<br />
825   *
826   * @param string $dom Domaine dont on souhaite modifier/ajouter un sous domaine
827   * @param string $subk Sous domaine à modifier / créer
828   * @param integer $type Type de sous-domaine (local, ip, url ...)
829   * @param string $action Action : vaut "add" ou "edit" selon que l'on
830   *  Crée (add) ou Modifie (edit) le sous-domaine
831   * @param string $dest Destination du sous-domaine, dépend de la valeur
832   *  de $type (url, ip, dossier...)
833   * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
834   */
835   // TODO : j'ai viré le type action, valider que plus personne ne l'utilise (quatrieme argument)
836  function set_sub_domain($dom,$sub,$type,$dest, $type_old=null,$sub_old=null,$value_old=null) {
837    global $db,$err,$cuid;
838    $err->log("dom","set_sub_domain",$dom."/".$sub);
839    // Locked ?
840    if (!$this->islocked) {
841      $err->raise("dom",3);
842      return false;
843    }
844    $dest=trim($dest);
845    $sub=trim(trim($sub),".");
846    $dom=strtolower($dom);
847    $sub=strtolower($sub);
848
849    //    if (!(($sub == '*') || ($sub=="") || (preg_match('/([a-z0-9][\.\-a-z0-9]*)?[a-z0-9]/', $sub)))) {
850    $fqdn=checkfqdn($sub);
851    // Special cases : * (all subdomains at once) and '' empty subdomain are allowed.
852    if (($sub != '*' && $sub!='') && !($fqdn==0 || $fqdn==4)) {
853      $err->raise("dom",24);
854      return false;
855    }
856
857    if (! $this->check_type_value($type,$dest)) {
858      # TODO have a real err code
859      $err->raise("dom",667);
860      return false;
861    }
862
863    // On a épuré $dir des problèmes eventuels ... On est en DESSOUS du dossier de l'utilisateur.
864    if ($t=checkfqdn($dom)) {
865      $err->raise("dom",3+$t);
866      return false;
867    }
868
869    if (! $this->can_create_subdomain($dom,$sub,$type,$type_old,$value_old)) {
870      # TODO have a real error code
871      $err->raise("dom", 654);
872      return false;
873    }
874
875    if (! is_null($type_old )) { // It's not a creation, it's an edit. Delete the old one
876      $db->query("update sub_domaines set web_action='DELETE' where domaine='$dom' and sub='$sub' and upper(type)=upper('$type_old') and valeur='$value_old';");
877    }
878
879    // Re-create the one we want
880    if (! $db->query("insert into sub_domaines (compte,domaine,sub,valeur,type,web_action) values ('$cuid','$dom','$sub','$dest','$type','UPDATE');") ) {
881      echo "query failed: ".$db->Error;
882      return false;
883    }
884
885    // Tell to update the DNS file
886    $db->query("update domaines set dns_action='UPDATE' where domaine='$dom';");
887
888    return true;
889  } // set_sub_domain
890
891
892  /* ----------------------------------------------------------------- */
893  /**
894   *  Supprime le sous-domaine demandé
895   *
896   * @param string $dom Domaine dont on souhaite supprimer un sous-domaine
897   * @param string $sub Sous-domaine que l'on souhaite supprimer
898   * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
899   *
900   */
901  function del_sub_domain($dom,$sub,$type,$value='') {
902    global $db,$err,$cuid;
903    $err->log("dom","del_sub_domain",$dom."/".$sub);
904    // Locked ?
905    if (!$this->islocked) {
906      $err->raise("dom",3);
907      return false;
908    }
909    $t=checkfqdn($dom);
910    if ($t) {
911      $err->raise("dom",3+$t);
912      return false;
913    }
914    if (!$r=$this->get_sub_domain_all($dom,$sub,$type)) {
915      // Le sous-domaine n'existe pas, erreur
916      $err->raise("dom",14);
917      return false;
918    } else {
919      // OK, on valide :
920      $db->query("update sub_domaines set web_action='DELETE' where domaine='$dom' and sub='$sub' and type='$type' and ( length('$value')=0 or valeur='$value') ");
921      $db->query("update domaines set dns_action='UPDATE' where domaine='$dom';");
922    }
923    return true;
924  } // del_sub_domain
925
926  /* ----------------------------------------------------------------- */
927  /**
928   * Modifie les information du domaine précisé.
929   *
930   * @param string $dom Domaine du compte courant que l'on souhaite modifier
931   * @param integer $dns Vaut 1 ou 0 pour héberger ou pas le DNS du domaine
932   * @param integer $mx Nom fqdn du serveur mx, si le mx local est précisé,
933   *  on héberge alors les mails du domaine.
934   * @param boolean $force Faut-il passer les checks DNS ou MX ? (admin only)
935   * @return boolean appelle $mail->add_dom ou $ma->del_dom si besoin, en
936   *  fonction du champs MX. Retourne FALSE si une erreur s'est produite,
937   *  TRUE sinon.
938   *
939   */
940  function edit_domain($dom,$dns,$mx,$force=0) {
941    global $db,$err,$L_MX,$classes,$cuid;
942    $err->log("dom","edit_domain",$dom);
943    // Locked ?
944    if (!$this->islocked && !$force) {
945      $err->raise("dom",3);
946      return false;
947    }
948    if ($dns == 1 && !$force) {
949      $this->dns=$this->whois($dom);
950      $v=checkhostallow($dom,$this->dns);
951      if ($v==-1) {
952        $err->raise("dom",7);   // TLD interdit
953        return false;
954      }
955      if ($dns && $v==-2) {
956        $err->raise("dom",12);  // Domaine non trouvé dans le whois
957        return false;
958      }
959      if ($dns && $v==-3) {
960        $err->raise("dom",23);  // Domaine non trouvé dans le whois
961        return false;
962      }
963    }
964    $t=checkfqdn($dom);
965    if ($t) {
966      $err->raise("dom",3+$t);
967      return false;
968    }
969    if (!$r=$this->get_domain_all($dom)) {
970      // Le domaine n'existe pas, Failure
971      $err->raise("dom",4,$dom);
972      return false;
973    }
974    if ($dns!="1") $dns="0";
975    // On vérifie que des modifications ont bien eu lieu :)
976    if ($r["dns"]==$dns && $r["mx"]==$mx) {
977      $err->raise("dom",15);
978      return false;
979    }
980    // MX ?
981    if ($mx==$L_MX)
982      $gesmx="1";
983    else
984      $gesmx="0";
985     
986    //si gestion mx uniquement, vérification du dns externe
987    if ($dns=="0" && $gesmx=="1" && !$force) {
988      $vmx = $this->checkmx($dom,$mx);
989      if ($vmx == 1) {
990        // Aucun champ mx de spécifié sur le dns
991  $err->raise("dom",25);
992  return false;
993      }
994 
995      if ($vmx == 2) {
996        // Serveur non spécifié parmi les champx mx
997  $err->raise("dom",25);
998  return false;
999      }
1000    }
1001     
1002    // OK, des modifs ont été faites, on valide :
1003    // DEPENDANCE :
1004    if ($gesmx && !$r["mail"]) { // on a associé le MX : on cree donc l'entree dans LDAP
1005      // Lancement de add_dom sur les classes domain_sensitive :
1006      foreach($classes as $c) {
1007  if (method_exists($GLOBALS[$c],"alternc_add_mx_domain")) {
1008  $GLOBALS[$c]->alternc_add_mx_domain($dom);
1009  }
1010      }
1011    }
1012   
1013    if (!$gesmx && $r["mail"]) { // on a dissocié le MX : on détruit donc l'entree dans LDAP
1014      // Lancement de del_dom sur les classes domain_sensitive :
1015      foreach($classes as $c) {
1016  if (method_exists($GLOBALS[$c],"alternc_del_mx_domain")) {
1017    $GLOBALS[$c]->alternc_del_mx_domain($dom);
1018  }
1019      }
1020    }
1021   
1022    $db->query("UPDATE domaines SET gesdns='$dns', mx='$mx', gesmx='$gesmx' WHERE domaine='$dom'");
1023    $db->query("UPDATE domaines set dns_action='UPDATE' where domaine='$dom';");
1024
1025    return true;
1026  } // edit_domain
1027 
1028
1029
1030  /****************************/
1031  /*  Slave dns ip managment  */
1032  /****************************/
1033  /* ----------------------------------------------------------------- */
1034  /**
1035   * Return the list of ip addresses and classes that are allowed access to domain list
1036   * through AXFR Transfers from the bind server.
1037   */
1038  function enum_slave_ip() {
1039  global $db,$err;
1040  $db->query("SELECT * FROM slaveip;");
1041  if (!$db->next_record()) {
1042    return false;
1043  }
1044  do {
1045    $res[]=$db->Record;
1046  } while ($db->next_record());
1047  return $res;
1048  }
1049
1050  /* ----------------------------------------------------------------- */
1051  /**
1052   * Add an ip address (or a ip class) to the list of allowed slave ip access list.
1053   */
1054  function add_slave_ip($ip,$class="32") {
1055  global $db,$err;
1056  if (!checkip($ip)) {
1057    $err->raise("dom",19);
1058    return false;
1059  }
1060  $class=intval($class);
1061  if ($class<8 || $class>32) $class=32;
1062  $db->query("SELECT * FROM slaveip WHERE ip='$ip' AND class='$class';");
1063  if ($db->next_record()) {
1064    $err->raise("err",22);
1065    return false;
1066  }
1067  $db->query("INSERT INTO slaveip (ip,class) VALUES ('$ip','$class');");
1068  $f=fopen(SLAVE_FLAG,"w");
1069  fputs($f,"yopla");
1070  fclose($f); 
1071  return true;
1072  }
1073
1074  /* ----------------------------------------------------------------- */
1075  /**
1076   * Remove an ip address (or a ip class) from the list of allowed slave ip access list.
1077   */
1078  function del_slave_ip($ip) {
1079  global $db,$err;
1080  if (!checkip($ip)) {
1081    $err->raise("dom",19);
1082    return false;
1083  }
1084  $db->query("DELETE FROM slaveip WHERE ip='$ip'");
1085  $f=fopen(SLAVE_FLAG,"w");
1086  fputs($f,"yopla");
1087  fclose($f); 
1088  return true;
1089  }
1090
1091
1092
1093  /* ----------------------------------------------------------------- */
1094  /**
1095   * Check for a slave account
1096   */
1097  function check_slave_account($login,$pass) {
1098  global $db,$err;
1099  $db->query("SELECT * FROM slaveaccount WHERE login='$login' AND pass='$pass';");
1100  if ($db->next_record()) { 
1101    return true;
1102  }
1103  return false;
1104  }
1105
1106  /* ----------------------------------------------------------------- */
1107  /**
1108   * Out (echo) the complete hosted domain list :
1109   */
1110  function echo_domain_list() {
1111  global $db,$err;
1112  $db->query("SELECT domaine FROM domaines WHERE gesdns=1 ORDER BY domaine");
1113  while ($db->next_record()) {
1114    echo $db->f("domaine")."\n";
1115  }
1116  return true;
1117  }
1118
1119
1120  /* ----------------------------------------------------------------- */
1121  /**
1122   * Returns the complete hosted domain list :
1123   */
1124  function get_domain_list($uid=-1) {
1125  global $db,$err;
1126  $uid=intval($uid);
1127  $res=array();
1128  if ($uid!=-1) {
1129    $sql=" AND compte='$uid' ";
1130  }
1131  $db->query("SELECT domaine FROM domaines WHERE gesdns=1 $sql ORDER BY domaine");
1132  while ($db->next_record()) {
1133    $res[]=$db->f("domaine");
1134  }
1135  return $res;
1136  }
1137
1138
1139  /* ----------------------------------------------------------------- */
1140  /**
1141   * Return the list of allowed slave accounts
1142   */
1143  function enum_slave_account() {
1144  global $db,$err;
1145  $db->query("SELECT * FROM slaveaccount;");
1146  $res=array();
1147  while ($db->next_record()) {
1148    $res[]=$db->Record;
1149  }
1150  if (!count($res)) return false;
1151  return $res;
1152  }
1153
1154  /* ----------------------------------------------------------------- */
1155  /**
1156   * Add a slave account that will be allowed to access the domain list
1157   */
1158  function add_slave_account($login,$pass) {
1159  global $db,$err;
1160  $db->query("SELECT * FROM slaveaccount WHERE login='$login'");
1161  if ($db->next_record()) {
1162    $err->raise("err",23);
1163    return false;
1164  }
1165  $db->query("INSERT INTO slaveaccount (login,pass) VALUES ('$login','$pass')");
1166  return true;
1167  }
1168
1169  /* ----------------------------------------------------------------- */
1170  /**
1171   * Remove a slave account
1172   */
1173  function del_slave_account($login) {
1174  global $db,$err;
1175  $db->query("DELETE FROM slaveaccount WHERE login='$login'");
1176  return true;
1177  }
1178
1179  /*************/
1180  /*  Private  */
1181  /*************/
1182
1183
1184  /* ----------------------------------------------------------------- */
1185  /**
1186   * Lock tente de verrouiller le fichier lock du cron. Si tout va bien (toujours?)
1187   * retourne True, sinon retourne False
1188   * NOTE : le systeme de lock est asymétrique, si on a un fichier CRONLOCK, on
1189   * attends (que le cron ait fini son execution).
1190   * @access private
1191   */
1192  function lock() {
1193    global $db,$err;
1194    $err->log("dom","lock");
1195    if ($this->islocked) {
1196      $err->raise("dom",17);
1197    }
1198    while (file_exists($this->fic_lock_cron)) {
1199      sleep(2);
1200    }
1201    $this->islocked=true;
1202    return true;
1203  }
1204
1205  /* ----------------------------------------------------------------- */
1206  /**
1207   * unlock déverrouille le fichier lock du cron. Si tout va bien (toujours?)
1208   * retourne True, sinon retourne False
1209   * NOTE : actuellement, vu le système de lock asymetrique, on ne fait rien ;)
1210   * @access private
1211   */
1212  function unlock() {
1213    global $db,$err;
1214    $err->log("dom","unlock");
1215    if (!$this->islocked) {
1216      $err->raise("dom",3);
1217    }
1218    $this->islocked=false;
1219    return true;
1220  }
1221
1222  /* ----------------------------------------------------------------- */
1223  /**
1224   * Efface un compte (tous ses domaines)
1225   */
1226  function alternc_del_member() {
1227    global $err;
1228    $err->log("dom","alternc_del_member");
1229    $li=$this->enum_domains();
1230    foreach($li as $dom) {
1231      $this->del_domain($dom);
1232    }
1233    return true;
1234  }
1235
1236  /* ----------------------------------------------------------------- */
1237  /**
1238   * Returns the used quota for the $name service for the current user.
1239   * @param $name string name of the quota
1240   * @return integer the number of service used or false if an error occured
1241   * @access private
1242   */
1243  function alternc_get_quota($name) {
1244    global $db,$err,$cuid;
1245    if ($name=="dom") {
1246      $err->log("dom","get_quota");
1247      $db->query("SELECT COUNT(*) AS cnt FROM domaines WHERE compte='$cuid'");
1248      $db->next_record();
1249      return $db->f("cnt");
1250    } else return false;
1251  }
1252
1253
1254  /* ----------------------------------------------------------------- */
1255  /**
1256   * Exporte toutes les informations domaine du compte.
1257   * @access private
1258   * EXPERIMENTAL 'sid' function ;)
1259   */
1260  function alternc_export() {
1261    global $db,$err;
1262    $err->log("dom","export");
1263    $this->enum_domains();
1264    $str="<dom>\n";
1265    foreach ($this->domains as $d) {
1266      $str.="  <domain>\n    <name>".xml_entities($d)."</name>\n";
1267      $s=$this->get_domain_all($d);
1268      $str.="    <hasdns>".xml_entities($s[dns])."</hasdns>\n";
1269      $str.="    <hasmx>".xml_entities($s[mx])."</hasmx>\n";
1270      $str.="    <mx>".xml_entities($s[mail])."</mx>\n";
1271      if (is_array($s[sub])) {
1272        foreach ($s[sub] as $sub) {
1273          $str.="    <subdomain>";
1274          $str.="<name>".xml_entities($sub[name])."</name>";
1275          $str.="<dest>".xml_entities($sub[dest])."</dest>";
1276          $str.="<type>".xml_entities($sub[type])."</type>";
1277          $str.="</subdomain>\n";
1278        }
1279      }
1280      $str.="  </domain>\n";
1281    }
1282    $str.="</dom>\n";
1283    return $str;
1284  }
1285
1286
1287} /* Class m_domains */
1288
1289?>
Note: See TracBrowser for help on using the repository browser.