*/ class m_dom { /** $domains : Cache des domaines du membre * @access private */ var $domains; /** $dns : Liste des dns trouvés par la fonction whois * @access private */ var $dns; /** Flag : a-t-on trouvé un sous-domaine Webmail pour ce domaine ? * @access private */ var $webmail; /** * Système de verrouillage du cron * Ce fichier permet de verrouiller le cron en attendant la validation * du domaine par update_domains.sh * @access private */ var $fic_lock_cron="/var/run/alternc/cron.lock"; /** * Le cron a-t-il été bloqué ? * Il faut appeler les fonctions privées lock et unlock entre les * appels aux domaines. * @access private */ var $islocked=false; var $type_local = "VHOST"; var $type_url = "URL"; var $type_ip = "IP"; var $type_webmail = "WEBMAIL"; var $type_ipv6 = "IPV6"; var $type_cname = "CNAME"; var $type_txt = "TXT"; var $type_defmx = "DEFMX"; var $type_defmx2 = "DEFMX2"; var $action_insert = "0"; var $action_update= "1"; var $action_delete = "2"; /* ----------------------------------------------------------------- */ /** * Constructeur */ function m_dom() { } /* ----------------------------------------------------------------- */ /** * Quota name */ function hook_quota_names() { return array("dom"=>_("Domain name")); } /* ----------------------------------------------------------------- */ /** * Retourne un tableau contenant les types de domaines * * @return array retourne un tableau indexé contenant la liste types de domaines * authorisé. Retourne FALSE si une erreur s'est produite. */ function domains_type_lst() { global $db,$err,$cuid; $err->log("dom","domains_type_lst"); $db->query("select * from domaines_type order by advanced;"); $this->domains_type_lst=false; while ($db->next_record()) { $this->domains_type_lst[strtolower($db->Record["name"])] = $db->Record; } return $this->domains_type_lst; } function domains_type_enable_values() { global $db,$err,$cuid; $err->log("dom","domains_type_target_values"); $db->query("desc domaines_type;"); $r = array(); while ($db->next_record()) { if ($db->f('Field') == 'enable') { $tab = explode(",", substr($db->f('Type'), 5, -1)); foreach($tab as $t) { $r[]=substr($t,1,-1); } } } return $r; } function domains_type_target_values($type=null) { global $db,$err,$cuid; $err->log("dom","domains_type_target_values"); if (is_null($type)) { $db->query("desc domaines_type;"); $r = array(); while ($db->next_record()) { if ($db->f('Field') == 'target') { $tab = explode(",", substr($db->f('Type'), 5, -1)); foreach($tab as $t) { $r[]=substr($t,1,-1); } } } return $r; } else { $db->query("select target from domaines_type where name='$type';"); if (! $db->next_record()) return false; return $db->f('target'); } } function domains_type_regenerate($name) { global $db,$err,$cuid; $name=mysql_real_escape_string($name); $db->query("update sub_domaines set web_action='UPDATE' where lower(type) = lower('$name') ;"); $db->query("update domaines d, sub_domaines sd set d.dns_action = 'UPDATE' where lower(sd.type)=lower('$name');"); return true; } function domains_type_get($name) { global $db,$err,$cuid; $name=mysql_real_escape_string($name); $db->query("select * from domaines_type where name='$name' ;"); $db->next_record(); return $db->Record; } function domains_type_del($name) { global $db,$err,$cuid; $name=mysql_real_escape_string($name); $db->query("delete domaines_type where name='$name';"); return true; } function domains_type_update($name, $description, $target, $entry, $compatibility, $enable, $only_dns, $need_dns,$advanced) { global $err,$cuid,$db; $id=intval($id); // The name MUST contain only letter and digits, it's an identifier after all ... if (!preg_match("#^[a-z0-9]+$#",$name)) { $err->raise("dom", _("The name MUST contain only letter and digits.")); return false; } $name=mysql_real_escape_string($name); $description=mysql_real_escape_string($description); $target=mysql_real_escape_string($target); $entry=mysql_real_escape_string($entry); $compatibility=mysql_real_escape_string($compatibility); $enable=mysql_real_escape_string($enable); $only_dns=intval($only_dns); $need_dns=intval($need_dns); $advanced=intval($advanced); $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';"); return true; } function sub_domain_change_status($domain,$sub,$type,$value,$status) { global $db,$err,$cuid; $err->log("dom","sub_domain_change_status"); $status=strtoupper($status); if (! in_array($status,array('ENABLE', 'DISABLE'))) return false; $db->query("update sub_domaines set enable='$status' where domaine='$domain' and sub='$sub' and lower(type)=lower('$type') and valeur='$value'"); return true; } /* ----------------------------------------------------------------- */ /** * Retourne un tableau contenant les domaines d'un membre. * Par défaut le membre connecté * * @return array retourne un tableau indexé contenant la liste des * domaines hébergés sur le compte courant. Retourne FALSE si une * erreur s'est produite. */ function enum_domains($uid=-1) { global $db,$err,$cuid; $err->log("dom","enum_domains"); if ($uid == -1) { $uid = $cuid; } $db->query("SELECT * FROM domaines WHERE compte='{$uid}' ORDER BY domaine ASC;"); $this->domains=array(); if ($db->num_rows()>0) { while ($db->next_record()) { $this->domains[]=$db->f("domaine"); } } return $this->domains; } function del_domain_cancel($dom) { global $db,$err,$classes,$cuid; $err->log("dom","del_domaini_canl",$dom); $dom=strtolower($dom); $db->query("UPDATE sub_domaines SET web_action='UPDATE' WHERE domaine='$dom';"); $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine='$dom';"); # TODO : some work with domain sensitive classes return true; } /* ----------------------------------------------------------------- */ /** * Efface un domaine du membre courant, et tous ses sous-domaines * * Cette fonction efface un domaine et tous ses sous-domaines, ainsi que * les autres services attachés à celui-ci. Elle appelle donc les autres * classe. Chaque classe peut déclarer une fonction del_dom qui sera * appellée lors de la destruction d'un domaine. * * @param string $dom nom de domaine à effacer * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon. */ function del_domain($dom) { global $db,$err,$classes,$cuid,$hooks; $err->log("dom","del_domain",$dom); $dom=strtolower($dom); if (!$r=$this->get_domain_all($dom)) { return false; } // Call Hooks to delete the domain and the MX management: // TODO : the 2 calls below are using an OLD hook call, FIXME: remove them when unused $hooks->invoke("alternc_del_domain",array($dom)); $hooks->invoke("alternc_del_mx_domain",array($dom)); // New hook calls: $hooks->invoke("hook_dom_del_domain",array($r["id"])); $hooks->invoke("hook_dom_del_mx_domain",array($r["id"])); // Now mark the domain for deletion: $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine='$dom';"); $db->query("UPDATE domaines SET dns_action='DELETE' WHERE domaine='$dom';"); return true; } /* ----------------------------------------------------------------- */ /** * Installe un domaine sur le compte courant. * *
Si le domaine existe déjà ou est interdit, ou est celui du serveur, * l'installation est refusée. Si l'hébergement DNS est demandé, la fonction * checkhostallow vérifiera que le domaine peut être installé conformément * aux demandes des super-admin. * Si le dns n'est pas demandé, le domaine peut être installé s'il est en * seconde main d'un tld (exemple : test.eu.org ou test.com, mais pas * toto.test.org ou test.test.asso.fr)
*Chaque classe peut définir une fonction add_dom($dom) qui sera * appellée lors de l'installation d'un nouveau domaine.
* * @param string $dom nom fqdn du domaine à installer * @param integer $dns 1 ou 0 pour héberger le DNS du domaine ou pas. * @param integer $noerase 1 ou 0 pour rendre le domaine inamovible ou non * @param integer $force 1 ou 0, si 1, n'effectue pas les tests de DNS. * force ne devrait être utilisé que par le super-admin. $ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon. */ function add_domain($domain,$dns,$noerase=0,$force=0,$isslave=0,$slavedom="") { global $db,$err,$quota,$classes,$L_MX,$L_FQDN,$tld,$cuid,$bro,$hooks; $err->log("dom","add_domain",$domain); // Locked ? if (!$this->islocked) { $err->raise("dom",_("--- Program error --- No lock on the domains!")); return false; } // Verifie que le domaine est rfc-compliant $domain=strtolower($domain); $t=checkfqdn($domain); if ($t) { $err->raise("dom",_("The domain name is syntaxically incorrect")); return false; } // Interdit les domaines clés (table forbidden_domains) sauf en cas FORCE $db->query("SELECT domain FROM forbidden_domains WHERE domain='$domain'"); if ($db->num_rows() && !$force) { $err->raise("dom",_("The requested domain is forbidden in this server, please contact the administrator")); return false; } if ($domain==$L_FQDN || $domain=="www.$L_FQDN") { $err->raise("dom",_("This domain is the server's domain! You cannot host it on your account!")); return false; } $db->query("SELECT compte FROM domaines WHERE domaine='$domain';"); if ($db->num_rows()) { $err->raise("dom",_("The domain already exist.")); return false; } $db->query("SELECT compte FROM `sub_domaines` WHERE sub != \"\" AND concat( sub, \".\", domaine )='$domain' OR domaine='$domain';"); if ($db->num_rows()) { $err->raise("dom",_("The domain already exist.")); return false; } $this->dns=$this->whois($domain); if (!$force) { $v=checkhostallow($domain,$this->dns); if ($v==-1) { $err->raise("dom",_("The last member of the domain name is incorrect or cannot be hosted in that server.")); return false; } if ($dns && $v==-2) { $err->raise("dom",_("The domain cannot be found in the whois database.")); return false; } if ($dns && $v==-3) { $err->raise("dom",_("The domain cannot be found in the whois database.")); return false; } if ($dns) $dns="1"; else $dns="0"; // mode 5 : force DNS to NO. if ($tld[$v]==5) $dns=0; // It must be a real domain (no subdomain) if (!$dns) { $v=checkhostallow_nodns($domain); if ($v) { $err->raise("dom",_("The requested domain is forbidden in this server, please contact the administrator")); return false; } } } // Check the quota : if (!$quota->cancreate("dom")) { $err->raise("dom",_("Your domain quota is over, you cannot create more domain names.")); return false; } if ($noerase) $noerase="1"; else $noerase="0"; $db->query("INSERT INTO domaines (compte,domaine,gesdns,gesmx,noerase,dns_action) VALUES ('$cuid','$domain','$dns','1','$noerase','UPDATE');"); if (!($id=$db->lastid())) { $err->raise("dom",_("An unexpected error occured when creating the domain")); return false; } if ($isslave) { $isslave=true; $db->query("SELECT domaine FROM domaines WHERE compte='$cuid' AND domaine='$slavedom';"); $db->next_record(); if (!$db->Record["domaine"]) { $err->raise("dom",_("Domain '%s' not found."),$slavedom); $isslave=false; } // Point to the master domain : $this->set_sub_domain($domain, '', $this->type_url, 'http://www.'.$slavedom); $this->set_sub_domain($domain, 'www', $this->type_url, 'http://www.'.$slavedom); $this->set_sub_domain($domain, 'mail', $this->type_url, 'http://mail.'.$slavedom); } if (!$isslave) { // Creation du repertoire dans www $dest_root = $bro->get_userid_root($cuid); $domshort=str_replace("-","",str_replace(".","",$domain)); if (! is_dir($dest_root . "/". $domshort)) { if(!mkdir($dest_root . "/". $domshort)){ $err->raise("dom",_("I can't write to the destination folder")); return false; } } if (! is_dir($dest_root . "/tmp")) { if(!mkdir($dest_root . "/tmp")){ $err->raise("dom",_("I can't write to the destination folder")); return false; } } // Creation des 3 sous-domaines par défaut : Vide, www et mail $this->set_sub_domain($domain, '', $this->type_url, 'http://www.'.$domain); $this->set_sub_domain($domain, 'www', $this->type_local, '/'. $domshort); $this->set_sub_domain($domain, 'mail', $this->type_webmail, ''); } // TODO: Old hooks, FIXME: when unused remove them $hooks->invoke("alternc_add_domain",array($domain)); $hooks->invoke("alternc_add_mx_domain",array($domain)); if ($isslave) { $hooks->invoke("alternc_add_slave_domain",array($domain)); } // New Hooks: $hooks->invoke("hook_dom_add_domain",array($id)); $hooks->invoke("hook_dom_add_mx_domain",array($id)); if ($isslave) { $hooks->invoke("hook_dom_add_slave_domain",array($id)); } return true; } /* ----------------------------------------------------------------- */ /** * Retourne les entrées DNS du domaine $domain issues du WHOIS. * * Cette fonction effectue un appel WHOIS($domain) sur Internet, * et extrait du whois les serveurs DNS du domaine demandé. En fonction * du TLD, on sait (ou pas) faire le whois correspondant. * Actuellement, les tld suivants sont supportés : * .com .net .org .be .info .ca .cx .fr .biz .name * * @param string $domain Domaine fqdn dont on souhaite les serveurs DNS * @return array Retourne un tableau indexé avec les NOMS fqdn des dns * du domaine demandé. Retourne FALSE si une erreur s'est produite. * */ function whois($domain) { global $db,$err; $err->log("dom","whois",$domain); // pour ajouter un nouveau TLD, utiliser le code ci-dessous. // echo "whois : $domain* $r["name"] = Nom fqdn * $r["dns"] = Gestion du dns ou pas ? * $r["mx"] = Valeur du champs MX si "dns"=true * $r["mail"] = Heberge-t-on le mail ou pas ? (si "dns"=false) * $r["nsub"] = Nombre de sous-domaines * $r["sub"] = tableau associatif des sous-domaines * $r["sub"][0-(nsub-1)]["name"] = nom du sous-domaine (NON-complet) * $r["sub"][0-(nsub-1)]["dest"] = Destination (url, ip, local ...) * $r["sub"][0-(nsub-1)]["type"] = Type (0-n) de la redirection. ** Retourne FALSE si une erreur s'est produite. * */ function get_domain_all($dom) { global $db,$err,$cuid; $err->log("dom","get_domain_all",$dom); // Locked ? if (!$this->islocked) { $err->raise("dom",_("--- Program error --- No lock on the domains!")); return false; } $t=checkfqdn($dom); if ($t) { $err->raise("dom",_("The domain name is syntaxically incorrect")); return false; } $r["name"]=$dom; $db->query("SELECT * FROM domaines WHERE compte='$cuid' AND domaine='$dom'"); if ($db->num_rows()==0) { $err->raise("dom",1,_("Domain '%s' not found."),$dom); return false; } $db->next_record(); $r["id"]=$db->Record["id"]; $r["dns"]=$db->Record["gesdns"]; $r["dns_action"]=$db->Record["dns_action"]; $r["dns_result"]=$db->Record["dns_result"]; $r["mail"]=$db->Record["gesmx"]; $r['noerase']=$db->Record['noerase']; $db->free(); $db->query("SELECT COUNT(*) AS cnt FROM sub_domaines WHERE compte='$cuid' AND domaine='$dom'"); $db->next_record(); $r["nsub"]=$db->Record["cnt"]; $db->free(); $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"); // Pas de webmail, on le cochera si on le trouve. for($i=0;$i<$r["nsub"];$i++) { $db->next_record(); $r["sub"][$i]=array(); $r["sub"][$i]["name"]=$db->Record["sub"]; $r["sub"][$i]["dest"]=$db->Record["valeur"]; $r["sub"][$i]["type"]=$db->Record["type"]; $r["sub"][$i]["enable"]=$db->Record["enable"]; $r["sub"][$i]["type_desc"]=$db->Record["type_desc"]; $r["sub"][$i]["only_dns"]=$db->Record["only_dns"]; $r["sub"][$i]["web_action"]=$db->Record["web_action"]; } $db->free(); return $r; } // get_domain_all /* ----------------------------------------------------------------- */ /** * Retourne TOUTES les infos d'un sous domaine du compte courant. * * @param string $dom Domaine fqdn concerné * @param string $sub Sous-domaine dont on souhaite les informations * @return arrray Retourne un tableau associatif contenant les * informations du sous-domaine demandé.
* $r["name"]= nom du sous-domaine (NON-complet) * $r["dest"]= Destination (url, ip, local ...) ** $r["type"]= Type (0-n) de la redirection. * Retourne FALSE si une erreur s'est produite. */ function get_sub_domain_all($dom,$sub, $type="", $value='') { global $db,$err,$cuid; $err->log("dom","get_sub_domain_all",$dom."/".$sub); // Locked ? if (!$this->islocked) { $err->raise("dom",3); return false; } $t=checkfqdn($dom); if ($t) { $err->raise("dom",3+$t); return false; } $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);"); if ($db->num_rows()==0) { $err->raise("dom",14); return false; } $db->next_record(); $r=array(); $r["name"]=$db->Record["sub"]; $r["dest"]=$db->Record["valeur"]; $r["enable"]=$db->Record["enable"]; $r["type_desc"]=$db->Record["type_desc"]; $r["only_dns"]=$db->Record["only_dns"]; $r["web_action"]=$db->Record["web_action"]; $db->free(); return $r; } // get_sub_domain_all function check_type_value($type, $value) { global $db,$err,$cuid; // check the type we can have in domaines_type.target switch ($this->domains_type_target_values($type)) { case 'NONE': if (empty($value) or is_null($value)) {return true;} break; case 'URL': if ( $value == strval($value)) {return true;} break; case 'DIRECTORY': if (substr($value,0,1)!="/") { $value="/".$value; } if (!checkuserpath($value)) { $err->raise("dom",21); return false; } return true; break; case 'IP': if (checkip($value)) {return true;} break; case 'IPV6': if (checkipv6($value)) {return true;} break; case 'DOMAIN': if (checkcname($value)) {return true;} break; case 'TXT': if ( $value == strval($value)) {return true;} break; default: return false; break; } return false; } //check_type_value /* ----------------------------------------------------------------- */ /** * Check the compatibility of the POSTed parameters with the chosen * domain type * * @param string $dom FQDN of the domain name * @param string $sub SUBdomain * @return boolean tell you if the subdomain can be installed there */ function can_create_subdomain($dom,$sub,$type,$type_old='', $value_old='') { global $db,$err,$cuid; $err->log("dom","can_create_subdomain",$dom."/".$sub); // Get the compatibility list for this domain type $db->query("select upper(compatibility) as compatibility from domaines_type where upper(name)=upper('$type');"); if (!$db->next_record()) return false; $compatibility_lst = explode(",",$db->f('compatibility')); // Get the list of type of subdomains already here who have the same name $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'"); #$db->query("select * from sub_domaines where sub='$sub' and domaine='$dom';"); while ($db->next_record()) { // And if there is a domain with a incompatible type, return false if (! in_array(strtoupper($db->f('type')),$compatibility_lst)) return false; } // All is right, go ! Create ur domain ! return true; } /* ----------------------------------------------------------------- */ /** * Modifier les information du sous-domaine demandé. * * Note : si le sous-domaine $sub.$dom n'existe pas, il est créé.