root/alternc/trunk/bureau/class/m_dom.php

Revision 2250, 32.4 kB (checked in by anarcat, 2 months ago)

.ca WHOIS replies change and are now like .ws. Thanks CIRA!

Reported by: Claude Girard

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
24 define('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 */
36 class 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 = "0";
70   var $type_url = "1";
71   var $type_ip = "2";
72   var $type_webmail = "3";
73
74   var $action_insert = "0";
75   var $action_update= "1";
76   var $action_delete = "2";
77
78   /* ----------------------------------------------------------------- */
79   /**
80    * Constructeur
81    */
82   function m_dom() {
83   }
84
85   /* ----------------------------------------------------------------- */
86   /**
87    * Quota name
88    */
89   function alternc_quota_names() {
90     return "dom";
91   }
92
93   /* ----------------------------------------------------------------- */
94   /**
95    * Retourne un tableau contenant les domaines d'un membre.
96    *
97    * @return array retourne un tableau indexé contenant la liste des
98    *  domaines hébergés sur le compte courant. Retourne FALSE si une
99    *  erreur s'est produite.
100    */
101   function enum_domains() {
102     global $db,$err,$cuid;
103     $err->log("dom","enum_domains");
104     $db->query("select * from domaines where compte='$cuid';");
105     $this->domains=array();
106     if ($db->num_rows()>0) {
107       while ($db->next_record()) {
108     $this->domains[]=$db->f("domaine");
109       }
110     }
111     return $this->domains;
112   }
113
114   /* ----------------------------------------------------------------- */
115   /**
116    *  Efface un domaine du membre courant, et tous ses sous-domaines
117    *
118    * Cette fonction efface un domaine et tous ses sous-domaines, ainsi que
119    * les autres services attachés à celui-ci. Elle appelle donc les autres
120    * classe. Chaque classe peut déclarer une fonction del_dom qui sera
121    * appellée lors de la destruction d'un domaine.
122    *
123    * @param string $dom nom de domaine à effacer
124    * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
125    */
126   function del_domain($dom) {
127     global $db,$err,$classes,$cuid;
128     $err->log("dom","del_domain",$dom);
129     $dom=strtolower($dom);
130     $db->query("SELECT * FROM domaines WHERE domaine='$dom';");
131     if ($db->num_rows()==0) {
132       $err->raise("dom",1,$dom);
133       return false;
134     }
135     $db->next_record();
136     if ($db->f("compte")!=$cuid) {
137       $err->raise("dom",2,$dom);
138       return false;
139     }
140     $db->query("INSERT INTO domaines_standby (compte,domaine,mx,gesdns,gesmx,action) SELECT compte,domaine,mx,gesdns,gesmx,2 FROM domaines WHERE domaine='$dom'"); // DELETE
141     $db->query("DELETE FROM domaines WHERE domaine='$dom';");
142     $db->query("DELETE FROM sub_domaines WHERE domaine='$dom';");
143
144     // DEPENDANCE :
145     // Lancement de del_dom sur les classes domain_sensitive :
146     // Declenchons les autres classes.
147     foreach($classes as $c) {
148       if (method_exists($GLOBALS[$c],"alternc_del_domain")) {
149     $GLOBALS[$c]->alternc_del_domain($dom);
150       }
151     }
152     foreach($classes as $c) {
153       if (method_exists($GLOBALS[$c],"alternc_del_mx_domain")) {
154     $GLOBALS[$c]->alternc_del_mx_domain($dom);
155       }
156     }
157     return true;
158   }
159
160   /* ----------------------------------------------------------------- */
161   /**
162    *  Installe un domaine sur le compte courant.
163    *
164    * <p>Si le domaine existe déjà ou est interdit, ou est celui du serveur,
165    * l'installation est refusée. Si l'hébergement DNS est demandé, la fonction
166    * checkhostallow vérifiera que le domaine peut être installé conformément
167    * aux demandes des super-admin.
168    * Si le dns n'est pas demandé, le domaine peut être installé s'il est en
169    * seconde main d'un tld (exemple : test.eu.org ou test.com, mais pas
170    * toto.test.org ou test.test.asso.fr)</p>
171    * <p>Chaque classe peut définir une fonction add_dom($dom) qui sera
172    * appellée lors de l'installation d'un nouveau domaine.</p>
173    *
174    * @param string $dom nom fqdn du domaine à installer
175    * @param integer $dns 1 ou 0 pour héberger le DNS du domaine ou pas.
176    * @param integer $noerase 1 ou 0 pour rendre le domaine inamovible ou non
177    * @param integer $force 1 ou 0, si 1, n'effectue pas les tests de DNS.
178    *  force ne devrait être utilisé que par le super-admin.
179    $ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
180   */
181   function add_domain($domain,$dns,$noerase=0,$force=0) {
182     global $db,$err,$quota,$classes,$L_MX,$L_FQDN,$tld,$cuid;
183     $err->log("dom","add_domain",$domain);
184     $mx="1";
185     // Locked ?
186     if (!$this->islocked) {
187       $err->raise("dom",3);
188       return false;
189     }
190     // Verifie que le domaine est rfc-compliant
191     $domain=strtolower($domain);
192     $t=checkfqdn($domain);
193     if ($t) {
194       $err->raise("dom",3+$t);
195       return false;
196     }
197     // Interdit les domaines clés (table forbidden_domains) sauf en cas FORCE
198     $db->query("select domain from forbidden_domains where domain='$domain'");
199     if ($db->num_rows() && !$force) {
200       $err->raise("dom",22);
201       return false;
202     }
203     if ($domain==$L_FQDN || $domain=="www.$L_FQDN") {
204       $err->raise("dom",18);
205       return false;
206     }
207     $db->query("SELECT compte FROM domaines WHERE domaine='$domain';");
208     if ($db->num_rows()) {
209       $err->raise("dom",8);
210       return false;
211     }
212     $db->query("SELECT compte FROM `sub_domaines` WHERE sub != \"\" AND concat( sub, \".\", domaine )='$domain' OR domaine='$domain';");
213     if ($db->num_rows()) {
214       $err->raise("dom",8);
215       return false;
216     }
217     $db->query("select compte from domaines_standby where domaine='$domain';");
218     if ($db->num_rows()!=0) {
219       $err->raise("dom",9);
220       return false;
221     }
222     $this->dns=$this->whois($domain);
223     if (!$force) {
224       $v=checkhostallow($domain,$this->dns);
225       if ($v==-1) {
226     $err->raise("dom",7);     // TLD interdit
227     return false;
228       }
229       if ($dns && $v==-2) {
230     $err->raise("dom",12);     // Domaine non trouvé dans le whois
231     return false;
232       }
233       if ($dns && $v==-3) {
234     $err->raise("dom",23);     // Domaine non trouvé dans le whois
235     return false;
236       }
237
238       if ($dns) $dns="1"; else $dns="0";
239
240       // mode 5 : force DNS to NO.
241       if ($tld[$v]==5) $dns=0;
242       // It must be a real domain (no subdomain)
243       if (!$dns) {
244     $v=checkhostallow_nodns($domain);
245     if ($v) {
246       $err->raise("dom",22);
247       return false;
248     }
249       }
250     }
251     // Check the quota :
252     if (!$quota->cancreate("dom")) {
253       $err->raise("dom",10);
254       return false;
255     }
256     if ($noerase) $noerase="1"; else $noerase="0";
257     $db->query("insert into domaines (compte,domaine,mx,gesdns,gesmx,noerase) values ('$cuid','$domain','$L_MX','$dns','$mx','$noerase');");
258     $db->query("insert into domaines_standby (compte,domaine,mx,gesdns,gesmx,action) values ('$cuid','$domain','$L_MX','$dns','$mx',0);"); // INSERT
259     // Creation des 3 sous-domaines par défaut : Vide, www et mail
260     $this->set_sub_domain($domain, '',     $this->type_url,     'add', 'http://www.'.$domain);
261     $this->set_sub_domain($domain, 'www'$this->type_local,   'add', '/');
262     $this->set_sub_domain($domain, 'mail', $this->type_webmail, 'add', '');
263     // DEPENDANCE :
264     // Lancement de add_dom sur les classes domain_sensitive :
265      // Declenchons les autres classes.   
266     foreach($classes as $c) {
267       if (method_exists($GLOBALS[$c],"alternc_add_domain")) {
268     $GLOBALS[$c]->alternc_add_domain($domain);
269       }
270     }
271     foreach($classes as $c) {
272       if (method_exists($GLOBALS[$c],"alternc_add_mx_domain")) {
273     $GLOBALS[$c]->alternc_add_mx_domain($domain);
274       }
275     }
276    return true;
277   }
278
279   /* ----------------------------------------------------------------- */
280   /**
281    * Retourne les entrées DNS du domaine $domain issues du WHOIS.
282    *
283    * Cette fonction effectue un appel WHOIS($domain) sur Internet,
284    * et extrait du whois les serveurs DNS du domaine demandé. En fonction
285    * du TLD, on sait (ou pas) faire le whois correspondant.
286    * Actuellement, les tld suivants sont supportés :
287    * .com .net .org .be .info .ca .cx .fr .biz .name
288    *
289    * @param string $domain Domaine fqdn dont on souhaite les serveurs DNS
290    * @return array Retourne un tableau indexé avec les NOMS fqdn des dns
291    *   du domaine demandé. Retourne FALSE si une erreur s'est produite.
292    *
293    */
294   function whois($domain) {
295     global $db,$err;
296     $err->log("dom","whois",$domain);
297     // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
298     //    echo "whois : $domain<br />";
299     ereg(".*\.([^\.]*)",$domain,$out);
300     $ext=$out[1];
301     // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
302     //    echo "ext: $ext<br />";
303     $egal="";
304     switch($ext) {
305     case "com":
306     case "net":
307       $serveur="rs.internic.net";
308       $egal="=";
309       break;
310     case "org":
311       $serveur="whois.pir.org";
312       break;
313     case "be":
314       $serveur="whois.dns.be";
315       break;
316     case "eu":
317       $serveur="195.234.53.193";
318       break;
319     case "info":
320       $serveur="whois.afilias.net";
321       break;
322     case "ca":
323       $serveur="whois.cira.ca";
324       break;
325     case "cx":
326       $serveur="whois.nic.cx";
327       break;
328     case "it":
329       $serveur="whois.nic.it";
330       break;
331     case "fr":
332       $serveur="whois.nic.fr";
333       break;
334     case "biz":
335       $serveur="whois.nic.biz";
336       break;
337     case "name":
338       $serveur="whois.nic.name";
339       $egal="domain = ";
340       break;
341     case "ws":
342       $serveur="whois.samoanic.ws";
343       break;
344     default:
345       $err->raise("dom",7);
346       return false;
347       break;
348     }
349     // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
350     //    echo "serveur : $serveur <br />";
351     if (($fp=fsockopen($serveur, 43))>0) {
352       fputs($fp, "$egal$domain\r\n");
353       $found = false;
354       $state=0;
355       while (!feof($fp)) {
356     $ligne = fgets($fp,128);
357     // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
358     //    echo "| $ligne<br />";
359     switch($ext) {
360     case "org":
361     case "com":
362     case "net":
363     case "info":
364     case "biz":
365     case "name":
366       if (ereg("Name Server:", $ligne)) {
367         $found = true;
368         $tmp=strtolower(ereg_replace(chr(10), "",ereg_replace(chr(13),"",ereg_replace(" ","", ereg_replace("Name Server:","", $ligne)))));
369         if ($tmp)
370           $server[]=$tmp;
371       }
372       break;
373     case "cx":
374       $ligne = ereg_replace(chr(10), "",ereg_replace(chr(13),"",ereg_replace(" ","", $ligne)));
375       if ($ligne=="" && $state==1)
376         $state=2;
377       if ($state==1)
378         $server[]=strtolower($ligne);
379       if ($ligne=="Nameservers:" && $state==0) {
380         $state=1;
381         $found = true;
382       }
383       break;
384         case "eu":
385     case "be":
386           $ligne=preg_replace("/^ *([^ ]*) \(.*\)$/","\\1",trim($ligne));
387           if($found)
388              $tmp = trim($ligne);
389           if ($tmp)
390              $server[]=$tmp;
391           if ($ligne=="Nameservers:") {
392             $state=1;
393             $found=true;
394           }
395           break;
396         case "it":
397           if (ereg("nserver:", $ligne)) {
398             $found=true;
399             $tmp=strtolower(preg_replace("/nserver:\s*[^ ]*\s*([^\s]*)$/","\\1", $ligne));
400             if ($tmp)
401               $server[]=$tmp;
402           }
403           break;
404     case "fr":
405           if (ereg("nserver:", $ligne)) {
406             $found=true;
407             $tmp=strtolower(preg_replace("/nserver:\s*([^\s]*)\s*.*$/","\\1", $ligne));
408             if ($tmp)
409               $server[]=$tmp;
410           }
411           break;
412     case "ca":
413     case "ws";
414       if (ereg('^[[:space:]]*Name servers:[[:space:]]*$', $ligne)) {
415             // found the server
416           $state = 1;
417       } elseif ($state) {
418           if (ereg('^[^%]', $ligne) && $ligne = ereg_replace('[[:space:]]', "", $ligne)) {
419           // first non-whitespace line is considered to be the nameservers themselves
420           $found = true;
421           $server[] = $ligne;
422         }
423       }
424       break;
425     } // switch
426       } // while
427       fclose($fp);
428     } else {
429       $err->raise("dom",11);
430       return false;
431     }
432
433     if ($found) {
434       return $server;
435     } else {
436       $err->raise("dom",12);
437       return false;
438     }
439   } // whois
440
441   /* ----------------------------------------------------------------- */
442   /**
443    *  vérifie la presence d'un champs mx valide sur un serveur DNS
444    *
445   */
446  
447   function checkmx($domaine,$mx) {
448     //initialise variables
449     $mxhosts = array();
450     
451     //récupére les champs mx
452     if (!getmxrr($domaine,$mxhosts)) {
453       //aucune hôte mx spécifié
454       return 1;
455     }
456     else {
457       //vérifie qu'un des hôtes est bien sur alternc
458       $bolmx = 0;
459       //décompose les différents champ MX coté alternc
460       $arrlocalmx = split(",",$mx);
461       //parcours les différents champ MX retournés
462       foreach($mxhosts as $mxhost) {
463         foreach($arrlocalmx as $localmx) {
464           if ($mxhost==$localmx) {
465             $bolmx = 1;
466           }
467         }
468       }
469       //définition de l'erreur selon reponse du parcours de mxhosts
470       if ($bolmx == 0) {
471         //aucun des champs MX ne correspond au serveur
472         return 2;         
473       }
474       else {
475         //un champ mx correct a été trouvé
476         return 0;
477       }
478     }
479   } //checkmx
480
481
482   /* ----------------------------------------------------------------- */
483   /**
484    *  retourne TOUTES les infos d'un domaine
485    *
486    * <b>Note</b> : si le domaine est en attente (présent dans
487    *  domaines_standby), une erreur est retournée
488    *
489    * @param string $dom Domaine dont on souhaite les informations
490    * @return array Retourne toutes les infos du domaine sous la forme d'un
491    * tableau associatif comme suit :<br /><pre>
492    *  $r["name"] =  Nom fqdn
493    *  $r["dns"]  =  Gestion du dns ou pas ?
494    *  $r["mx"]   =  Valeur du champs MX si "dns"=true
495    *  $r["mail"] =  Heberge-t-on le mail ou pas ? (si "dns"=false)
496    *  $r["nsub"] =  Nombre de sous-domaines
497    *  $r["sub"]  =  tableau associatif des sous-domaines
498    *  $r["sub"][0-(nsub-1)]["name"] = nom du sous-domaine (NON-complet)
499    *  $r["sub"][0-(nsub-1)]["dest"] = Destination (url, ip, local ...)
500    *  $r["sub"][0-(nsub-1)]["type"] = Type (0-n) de la redirection.
501    *  </pre>
502    *  Retourne FALSE si une erreur s'est produite.
503    *
504    */
505   function get_domain_all($dom) {
506     global $db,$err,$cuid;
507     $err->log("dom","get_domain_all",$dom);
508     // Locked ?
509     if (!$this->islocked) {
510       $err->raise("dom",3);
511       return false;
512     }
513     $t=checkfqdn($dom);
514     if ($t) {
515       $err->raise("dom",3+$t);
516       return false;
517     }
518     $r["name"]=$dom;
519     $db->query("select * from domaines_standby where compte='$cuid' and domaine='$dom'");
520     if ($db->num_rows()>0) {
521       $err->raise("dom",13);
522       return false;
523     }
524     $db->query("select * from domaines where compte='$cuid' and domaine='$dom'");
525     if ($db->num_rows()==0) {
526       $err->raise("dom",1,$dom);
527       return false;
528     }
529     $db->next_record();
530     $r["dns"]=$db->Record["gesdns"];
531     $r["mail"]=$db->Record["gesmx"];
532     $r["mx"]=$db->Record["mx"];
533     $r[noerase]=$db->Record[noerase];
534     $db->free();
535     $db->query("select count(*) as cnt from sub_domaines where compte='$cuid' and domaine='$dom'");
536     $db->next_record();
537     $r["nsub"]=$db->Record["cnt"];
538     $db->free();
539     $db->query("select * from sub_domaines where compte='$cuid' and domaine='$dom'");
540     // Pas de webmail, on le cochera si on le trouve.
541     $this->webmail=0;
542     for($i=0;$i<$r["nsub"];$i++) {
543       $db->next_record();
544       $r["sub"][$i]=array();
545       $r["sub"][$i]["name"]=$db->Record["sub"];
546       $r["sub"