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

Revision 2817, 38.3 KB checked in by fufroma, 2 years ago (diff)

Structure d'annulation de suppression de domaine.
Fonction commentée parce que pas complete en ce qui concerne les classes "domaine sensitives"

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