GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

m_dom::whois()   F
last analyzed

Complexity

Conditions 50
Paths 870

Size

Total Lines 159
Code Lines 118

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 50
eloc 118
nc 870
nop 1
dl 0
loc 159
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
  ----------------------------------------------------------------------
5
  AlternC - Web Hosting System
6
  Copyright (C) 2000-2012 by the AlternC Development Team.
7
  https://alternc.org/
8
  ----------------------------------------------------------------------
9
  LICENSE
10
11
  This program is free software; you can redistribute it and/or
12
  modify it under the terms of the GNU General Public License (GPL)
13
  as published by the Free Software Foundation; either version 2
14
  of the License, or (at your option) any later version.
15
16
  This program is distributed in the hope that it will be useful,
17
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
  GNU General Public License for more details.
20
21
  To read the license please visit http://www.gnu.org/copyleft/gpl.html
22
  ----------------------------------------------------------------------
23
  Purpose of file: PHP Class that manage domain names installed on the server
24
  ----------------------------------------------------------------------
25
 */
26
27
define('SLAVE_FLAG', "/var/run/alternc/refresh_slave");
28
29
/**
30
 * Classe de gestion des domaines de l'hébergé.
31
 * 
32
 * Cette classe permet de gérer les domaines / sous-domaines, redirections
33
 * dns et mx des domaines d'un membre hébergé.<br />
34
 */
35
class m_dom {
36
37
    /** $domains : Cache des domaines du membre
38
     * @access private
39
     */
40
    var $domains;
41
42
    /** $dns : Liste des dns trouvés par la fonction whois
43
     * @access private
44
     */
45
    var $dns;
46
47
    /** Flag : a-t-on trouvé un sous-domaine Webmail pour ce domaine ?
48
     * @access private
49
     */
50
    var $webmail;
51
52
    /**
53
     * Systéme de verrouillage du cron
54
     * Ce fichier permet de verrouiller le cron en attendant la validation
55
     * du domaine par update_domains.sh
56
     * @access private
57
     */
58
    var $fic_lock_cron = "/var/run/alternc/cron.lock";
59
60
    /**
61
     * Le cron a-t-il été bloqué ?
62
     * Il faut appeler les fonctions privées lock et unlock entre les
63
     * appels aux domaines.
64
     * @access private
65
     */
66
    var $islocked = false;
67
    var $type_local = "VHOST";
68
    var $type_url = "URL";
69
    var $type_ip = "IP";
70
    var $type_webmail = "WEBMAIL";
71
    var $type_ipv6 = "IPV6";
72
    var $type_cname = "CNAME";
73
    var $type_txt = "TXT";
74
    var $type_defmx = "DEFMX";
75
    var $type_defmx2 = "DEFMX2";
76
    var $action_insert = "0";
77
    var $action_update = "1";
78
    var $action_delete = "2";
79
    var $tld_no_check_at_all = "1";
80
    var $cache_domains_type_lst = false;
81
82
    /* ----------------------------------------------------------------- */
83
84
    /**
85
     * Constructeur
86
     */
87
    function m_dom() {
88
        global $L_FQDN;
89
        $this->tld_no_check_at_all = variable_get('tld_no_check_at_all', 0, 'Disable ALL check on the TLD (users will be able to add any domain)', array('desc' => 'Disabled', 'type' => 'boolean'));
90
        variable_get('mailname_bounce', $L_FQDN, 'FQDN of the mail server, used to create vhost virtual mail_adress.', array('desc' => 'FQDN', 'type' => 'string'));
91
    }
92
93
    function get_panel_url_list() {
94
        global $db, $err;
95
        $err->log("dom", "get_panel_url_list");
96
        $db->query("SELECT sd.id as sub_id, if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) as fqdn from sub_domaines sd where type = 'PANEL';");
97
        $t = array();
98
        while ($db->next_record()) {
99
            $t[intval($db->f('sub_id'))] = $db->f('fqdn');
100
        }
101
        return $t;
102
    }
103
104
    /**
105
     * @param string $fqdn
106
     */
107
    public static function get_sub_domain_id_and_member_by_name($fqdn) {
108
        global $db, $err;
109
        $err->log("dom", "get_sub_domain_by_name");
110
        $db->query("select sd.* from sub_domaines sd where if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) = ?;", array($fqdn));
111
        if (!$db->next_record()) {
112
            return false;
113
        }
114
        return array('sub_id' => intval($db->f('id')), 'member_id' => intval($db->f('compte')));
115
    }
116
117
    function hook_menu() {
118
        global $quota;
119
        $obj = array(
120
            'title' => _("Domains"),
121
            'ico' => 'images/dom.png',
122
            'link' => 'toggle',
123
            'pos' => 20,
124
            'links' => array(),
125
        );
126
127
        if ($quota->cancreate("dom")) {
128
            $obj['links'][] = array(
129
                'ico' => 'images/new.png',
130
                'txt' => _("Add a domain"),
131
                'url' => "dom_add.php",
132
            );
133
        }
134
135
        foreach ($this->enum_domains() as $d) {
136
            $obj['links'][] = array(
137
                'txt' => htmlentities($d),
138
                'url' => "dom_edit.php?domain=" . urlencode($d),
139
            );
140
        }
141
142
        return $obj;
143
    }
144
145
    /* ----------------------------------------------------------------- */
146
147
    /**
148
     * Retourne un tableau contenant les types de domaines
149
     *
150
     * @return array retourne un tableau indexé contenant la liste types de domaines 
151
     *  authorisé. Retourne FALSE si une erreur s'est produite.
152
     */
153
    function domains_type_lst() {
154
        global $db, $err;
155
        $err->log("dom", "domains_type_lst");
156
        if (empty($this->cache_domains_type_lst)) {
157
            $db->query("select * from domaines_type order by advanced;");
158
            $this->cache_domains_type_lst = array();
159
            while ($db->next_record()) {
160
                $this->cache_domains_type_lst[strtolower($db->Record["name"])] = $db->Record;
161
            }
162
        }
163
        return $this->cache_domains_type_lst;
164
    }
165
166
    function domains_type_enable_values() {
167
        global $db, $err, $cuid;
168
        $err->log("dom", "domains_type_target_values");
169
        $db->query("desc domaines_type;");
170
        $r = array();
171
        while ($db->next_record()) {
172
            if ($db->f('Field') == 'enable') {
173
                $tab = explode(",", substr($db->f('Type'), 5, -1));
174
                foreach ($tab as $t) {
175
                    $r[] = substr($t, 1, -1);
176
                }
177
            }
178
        }
179
        return $r;
180
    }
181
182
    /**
183
     * @param integer $type
184
     */
185
    function domains_type_target_values($type = null) {
186
        global $db, $err;
187
        $err->log("dom", "domains_type_target_values");
188
        if (is_null($type)) {
189
            $db->query("desc domaines_type;");
190
            $r = array();
191
            while ($db->next_record()) {
192
                if ($db->f('Field') == 'target') {
193
                    $tab = explode(",", substr($db->f('Type'), 5, -1));
194
                    foreach ($tab as $t) {
195
                        $r[] = substr($t, 1, -1);
196
                    }
197
                }
198
            }
199
            return $r;
200
        } else {
201
            $db->query("select target from domaines_type where name= ? ;", array($type));
202
            if (!$db->next_record()) {
203
                return false;
204
            }
205
            return $db->f('target');
206
        }
207
    }
208
209
    function import_manual_dns_zone($zone, $domain, $detect_redirect = true, $save = false) {
210
        global $err;
211
        if ($save) {
212
            if (!$this->import_manual_dns_prep_zone($domain)) {
213
                $err->raise('dom', _("Err: failed to prepare the zone"));
214
                return false;
215
            }
216
        }
217
218
        $val = array();
219
        foreach (explode("\n", $zone) as $z) {
220
            $z = trim($z);
221
            if (empty($z)) {
222
                continue;
223
            }
224
            $val[] = $this->import_manual_dns_entry($z, $domain, $detect_redirect, $save);
225
        }
226
        return $val;
227
    }
228
229
    /**
230
     * @param string $zone
231
     */
232
    function import_manual_dns_entry($zone, $domain, $detect_redirect = true, $save = false) {
233
        global $err;
234
        $err->log("dom", "import_manual_dns_entry");
235
        $zone = trim($zone);
236
        if (empty($zone)) {
237
            return false;
238
        }
239
240
        $domain = trim($domain);
241
        if (empty($domain)) {
242
            $err->raise("dom", _("Missing domain name"));
243
            return false;
244
        }
245
246
        $val = array(
247
            'status' => 'err', // can be 'ok', 'err', 'warn'
248
            'comment' => 'no val',
249
            'entry_old' => $zone,
250
            'entry_new' => array('domain' => $domain),
251
        );
252
253
        // Examples:
254
        // ; hello comment
255
        if (preg_match('/^;/', $zone, $ret)) {
256
            $val['status'] = 'ok';
257
            $val['comment'] = 'Just a comment, do not import';
258
        } else
259
        // Examples:
260
        // $TTL 86400'
261
        if (preg_match('/^\$TTL\h+(?P<ttl>[\dMHDmhd]+)/', $zone, $ret)) {
262
            $val['status'] = 'ok';
263
            $val['comment'] = 'Set TTL to ' . $ret['ttl'];
264
            $val['entry_new']['type'] = 'set_ttl';
265
            $val['entry_new']['value'] = $ret['ttl'];
266
        } else
267
268
        // Examples:
269
        // @ IN AAAA 127.2.1.5
270
        // reseau IN AAAA 145.214.44.55
271
        if (preg_match('/^(?P<sub>[\w\.@\-]*)\h*(?P<ttl>\d*)\h*IN\h+AAAA\h+(?P<target>[0-9A-F:]{2,40})/i', $zone, $ret)) {
272
273
            // Check if it is just a redirect
274
            if (substr($ret['sub'], -1) == '.') { // if ending by a "." it is allready a FQDN
275
                $url = "http://" . $ret['sub'];
276
            } else {
277
                if ($ret['sub'] == '@' || empty($ret['sub'])) {
278
                    $url = "http://" . $domain;
279
                } else {
280
                    $url = "http://" . $ret['sub'] . "." . $domain;
281
                }
282
            }
283
            if ($detect_redirect && $dst_url = $this->is_it_a_redirect($url)) {
284
                $val['status'] = 'warn';
285
                $val['comment'] = "Became a redirect to $dst_url";
286
                $val['entry_new']['type'] = 'URL';
287
                $val['entry_new']['sub'] = $ret['sub'];
288
                $val['entry_new']['value'] = $dst_url;
289
            } else {
290
                $val['status'] = 'ok';
291
                $val['comment'] = "Create entry AAAA with " . $ret['sub'] . " go to " . $ret['target'] . " with ttl " . $ret['ttl'];
292
                $val['entry_new']['type'] = 'IPV6';
293
                $val['entry_new']['sub'] = $ret['sub'];
294
                $val['entry_new']['value'] = $ret['target'];
295
            }
296
        } else
297
298
299
        // Examples:
300
        // @ IN A 127.2.1.5
301
        // reseau IN A 145.214.44.55
302
        if (preg_match('/^(?P<sub>[\w\.@\-]*)\h*(?P<ttl>\d*)\h*IN\h+A\h+(?P<target>\d+\.\d+\.\d+\.\d+)/i', $zone, $ret)) {
303
            // Check if it is just a redirect
304
            if (substr($ret['sub'], -1) == '.') { // if ending by a "." it is allready a FQDN
305
                $url = "http://" . $ret['sub'];
306
            } else {
307
                if ($ret['sub'] == '@' || empty($ret['sub'])) {
308
                    $url = "http://" . $domain;
309
                } else {
310
                    $url = "http://" . $ret['sub'] . "." . $domain;
311
                }
312
            }
313
            if ($detect_redirect && $dst_url = $this->is_it_a_redirect($url)) {
314
                $val['status'] = 'warn';
315
                $val['comment'] = "Became a redirect to $dst_url";
316
                $val['entry_new']['type'] = 'URL';
317
                $val['entry_new']['sub'] = $ret['sub'];
318
                $val['entry_new']['value'] = $dst_url;
319
            } else {
320
                $val['status'] = 'ok';
321
                $val['comment'] = "Create entry A with " . $ret['sub'] . " go to " . $ret['target'] . " with ttl " . $ret['ttl'];
322
                $val['entry_new']['type'] = 'IP';
323
                $val['entry_new']['sub'] = $ret['sub'];
324
                $val['entry_new']['value'] = $ret['target'];
325
            }
326
        } else
327
328
        // Examples:
329
        // @ IN NS ns.example.tld.
330
        // ns 3600 IN NS 145.214.44.55
331
        if (preg_match('/^(?P<sub>[\-\w\.@]*)\h*(?P<ttl>\d*)\h*IN\h+NS\h+(?P<target>[\w\.\-]+)/i', $zone, $ret)) {
332
            if (empty($ret['sub']) || $ret['sub'] == '@') {
333
                $val['status'] = 'warn';
334
                $val['comment'] = "Won't migrate it, there will get a new value";
335
            } else {
336
                $val['status'] = 'ok';
337
                $val['comment'] = "Create entry NS with " . $ret['sub'] . " go to " . $ret['target'] . " with ttl " . $ret['ttl'];
338
                $val['entry_new']['type'] = 'FIXME-NS';
339
                $val['entry_new']['sub'] = $ret['sub'];
340
                $val['entry_new']['value'] = $ret['target'];
341
            }
342
        } else
343
344
        // Examples:
345
        // agenda IN CNAME ghs.google.com.
346
        // www 3600 IN CNAME @
347
        if (preg_match('/^(?P<sub>[\-\w\.@]*)\h*(?P<ttl>\d*)\h*IN\h+CNAME\h+(?P<target>[@\w+\.\-]+)/i', $zone, $ret)) {
348
            if (substr($ret['sub'], -1) == '.') { // if ending by a "." it is allready a FQDN
349
                $url = "http://" . $ret['sub'];
350
            } else {
351
                if ($ret['sub'] == '@' || empty($ret['sub'])) {
352
                    $url = "http://" . $domain;
353
                } else {
354
                    $url = "http://" . $ret['sub'] . "." . $domain;
355
                }
356
            }
357
            if ($detect_redirect && $dst_url = $this->is_it_a_redirect($url)) {
358
                $val['status'] = 'warn';
359
                $val['comment'] = "Became a redirect to $dst_url";
360
                $val['entry_new']['type'] = 'URL';
361
                $val['entry_new']['sub'] = $ret['sub'];
362
                $val['entry_new']['value'] = $dst_url;
363
            } else {
364
                $val['status'] = 'ok';
365
                $val['comment'] = "Create entry CNAME with " . $ret['sub'] . " go to " . $ret['target'] . " with ttl " . $ret['ttl'];
366
                $val['entry_new']['type'] = 'CNAME';
367
                $val['entry_new']['sub'] = $ret['sub'];
368
                $val['entry_new']['value'] = $ret['target'];
369
            }
370
        } else
371
372
        // Examples:
373
        // @ IN MX 10 aspmx.l.google.com.
374
        // arf 3600 IN MX 20 pouet.fr.
375
        if (preg_match('/^(?P<sub>[\-\w\.@]*)\h*(?P<ttl>\d*)\h*IN\h+MX\h+(?P<weight>\d+)\h+(?P<target>[@\w+\.\-]+)/i', $zone, $ret)) {
376
            $val['status'] = 'warn';
377
            $val['comment'] = "Create entry MX with " . $ret['sub'] . " go to " . $ret['target'] . " with ttl " . $ret['ttl'] . " and weight 5 (initial weight was " . $ret['weight'] . ")";
378
            $val['entry_new']['type'] = 'MX';
379
            $val['entry_new']['sub'] = $ret['sub'];
380
            $val['entry_new']['value'] = $ret['target'];
381
        } else
382
383
        // Examples:
384
        // _sip._tcp  IN      SRV             1 100 5061 sip.example.tld.
385
        if (preg_match('/^(?P<sub>[\_\w\.@\-]+)\h+(?P<ttl>\d*)\h*IN\h+SRV\h+/i', $zone, $ret)) {
386
            $val['status'] = 'err';
387
            $val['comment'] = "Please add yourself the entry $zone";
388
        } else
389
390
        // Examples:
391
        // @       IN      TXT             "google-site-verification=jjjjjjjjjjjjjjjjjjjjjjjjsdsdjlksjdljdslgNj5"
392
        if (preg_match('/^(?P<sub>[\_\w\.@\-]*)\h*(?P<ttl>\d*)\h*IN\h+TXT\h+\"(?P<target>.+)\"/i', $zone, $ret)) {
393
            $val['status'] = 'ok';
394
            $val['comment'] = "Create TXT entry with " . $ret['sub'] . " go to " . $ret['target'];
395
            $val['entry_new']['type'] = 'TXT';
396
            $val['entry_new']['sub'] = $ret['sub'];
397
            $val['entry_new']['value'] = $ret['target'];
398
        } else {
399
400
            // WTF can it be ?
401
            $val['comment'] = "Unknow: $zone";
402
        }
403
404
        if ($save) {
405
            return $this->import_manual_dns_entry_doit($val);
406
        }
407
408
        return $val;
409
    }
410
411
    private function import_manual_dns_entry_doit($entry) {
412
        $entry['did_it'] = 0;
413
        if ($entry['status'] == 'err') {
414
            return $entry;
415
        }
416
417
        $val = $entry['entry_new'];
418
419
        if (empty($val['type'])) {
420
            return false;
421
        }
422
423
        switch ($val['type']) {
424
            case "set_ttl":
425
                $entry['did_it'] = $this->set_ttl($this->get_domain_byname($val['domain']), $val['value']);
426
                return $entry;
427
        }
428
429
        // If it is an unknown domains type
430
        if (!array_key_exists(strtolower($val['type']), $this->domains_type_lst())) {
431
            echo "what is this shit ?\n";
432
            print_r($entry);
433
            return $entry;
434
        }
435
436
        // If the subdomain is @, we want an empty subdomain
437
        if ($val['sub'] == '@') {
438
            $val['sub'] = '';
439
        }
440
441
        $this->lock();
442
        $entry['did_it'] = $this->set_sub_domain($val['domain'], $val['sub'], $val['type'], $val['value']);
443
        $this->unlock();
444
445
        return $entry;
446
    }
447
448
    private function import_manual_dns_prep_zone($domain) {
449
        global $err;
450
        // Prepare a domain to be importer : 
451
        // * create the domain
452
        // * delete all automatic subdomain
453
        // * set no mx
454
        $this->lock();
455
456
        // function add_domain($domain,$dns,$noerase=0,$force=0,$isslave=0,$slavedom="") 
457
        if (!$this->add_domain($domain, true, false, true)) {
458
            $err->raise('dom', "Error adding domain");
459
            return false;
460
        }
461
462
        // Set no mx
463
        $this->edit_domain($domain, true, false);
464
465
        $d = $this->get_domain_all($domain);
466
        foreach ($d['sub'] as $sd) {
467
            $this->del_sub_domain($sd['id']);
468
        }
469
470
        $this->unlock();
471
472
        return true;
473
    }
474
475
    // Take an URL, and return FALSE is there is no redirection,
476
    // and the target URL if there is one (HTTP CODE 301 & 302)
477
    // CURL is needed
478
479
    /**
480
     * @param string $url
481
     */
482
    function is_it_a_redirect($url) {
483
        try {
484
            $params = array('http' => array(
485
                    'method' => 'HEAD',
486
                    'ignore_errors' => true
487
            ));
488
489
            $context = stream_context_create($params);
490
            $fp = @fopen($url, 'rb', false, $context);
491
            $result = @stream_get_contents($fp);
492
493
            if ($result === false) {
494
                throw new Exception("Could not read data from {$url}");
495
            }
496
            if (strstr($http_response_header[0], '301') || strstr($http_response_header[0], '302')) {
497
                // This is a redirection
498
                if (preg_match('/Location:\h+(?P<target>[\-\w:\/.\?\=.]+)/', implode("\n", $http_response_header), $ret)) {
499
                    // check if it is a redirection to himself
500
                    preg_match('/\/\/(?P<host>[\w\.\-]+)\//', ( substr($url, -1) == '/' ? $url : $url . '/'), $original_cname);
501
                    preg_match('/\/\/(?P<host>[\w\.\-]+)\//', $ret['target'], $target_url);
502
                    if (isset($target_url['host']) && ( $target_url['host'] == $original_cname['host'] )) { // if it's a redirection to himself (sub pages, http to https...)
503
                        return false; // do not do a redirection (we must point to the server)
504
                    }
505
506
                    // If it is a redirection to a sub directory
507
                    // (we know it is a redirection to a sub directory because it's not a complete URI)
508
                    if (substr($ret['target'], 0, 4) != 'http') {
509
                        return 'http://' . $original_cname['host'] . '/' . $ret['target'];
510
                    }
511
                    return $ret['target'];
512
                }
513
            } else { // it isn't a redirection 
514
                return false;
515
            }
516
        } catch (Exception $e) {
517
            return false;
518
        }
519
    }
520
521
    function domains_type_regenerate($name) {
522
        global $db, $err, $cuid;
523
        $db->query("update sub_domaines set web_action='UPDATE' where lower(type) = lower(?) ;", array($name));
524
        $db->query("update domaines d, sub_domaines sd set d.dns_action = 'UPDATE' where lower(sd.type)=lower(?);", array($name));
525
        return true;
526
    }
527
528
    function domains_type_get($name) {
529
        global $db;
530
        $db->query("select * from domaines_type where name= ?;", array($name));
531
        $db->next_record();
532
        return $db->Record;
533
    }
534
535
    function domains_type_del($name) {
536
        global $db;
537
        $db->query("delete domaines_type where name= ? ;", array($name));
538
        return true;
539
    }
540
541
    function domains_type_update($name, $description, $target, $entry, $compatibility, $enable, $only_dns, $need_dns, $advanced, $create_tmpdir, $create_targetdir) {
542
        global $err, $db;
543
        // The name MUST contain only letter and digits, it's an identifier after all ...
544
        if (!preg_match("#^[a-z0-9]+$#", $name)) {
545
            $err->raise("dom", _("The name MUST contain only letter and digits"));
546
            return false;
547
        }
548
        $only_dns = intval($only_dns);
549
        $need_dns = intval($need_dns);
550
        $advanced = intval($advanced);
551
        $create_tmpdir = intval($create_tmpdir);
552
        $create_targetdir = intval($create_targetdir);
553
        $db->query("UPDATE domaines_type SET description= ?, target= ?, entry= ?, compatibility= ?, enable= e, need_dns= ?, only_dns= ?, advanced= ?,create_tmpdir= ?,create_targetdir= ? where name= ?;", array($description, $target, $entry, $compatibility, $enable, $need_dns, $only_dns, $advanced, $create_tmpdir, $create_targetdir, $name));
554
        return true;
555
    }
556
557
    function sub_domain_change_status($sub_id, $status) {
558
        global $db, $err;
559
        $err->log("dom", "sub_domain_change_status");
560
        $sub_id = intval($sub_id);
561
        $status = strtoupper($status);
562
        if (!in_array($status, array('ENABLE', 'DISABLE'))) {
563
            return false;
564
        }
565
566
        $jh = $this->get_sub_domain_all($sub_id);
567
        if ($status == 'ENABLE') { // check compatibility with existing sub_domains
568
            if (!$this->can_create_subdomain($jh['domain'], $jh['name'], $jh['type'], $sub_id)) {
569
                $err->raise("dom", _("The parameters for this subdomain and domain type are invalid. Please check for subdomain entries incompatibility"));
570
                return false;
571
            }
572
        }
573
574
        $db->query("update sub_domaines set enable= ? where id = ? ;", array($status, intval($sub_id)));
575
        $this->set_dns_action($jh['domain'], 'UPDATE');
576
577
        return true;
578
    }
579
580
    /* ----------------------------------------------------------------- */
581
582
    /**
583
     * Retourne un tableau contenant les domaines d'un membre.
584
     * Par défaut le membre connecté
585
     *
586
     * @return array retourne un tableau indexé contenant la liste des
587
     *  domaines hébergés sur le compte courant. Retourne FALSE si une
588
     *  erreur s'est produite.
589
     */
590
    function enum_domains($uid = -1) {
591
        global $db, $err, $cuid;
592
        $err->log("dom", "enum_domains");
593
        if ($uid == -1) {
594
            $uid = $cuid;
595
        }
596
        $db->query("SELECT * FROM domaines WHERE compte= ? ORDER BY domaine ASC;", array($uid));
597
        $this->domains = array();
598
        if ($db->num_rows() > 0) {
599
            while ($db->next_record()) {
600
                $this->domains[] = $db->f("domaine");
601
            }
602
        }
603
        return $this->domains;
604
    }
605
606
    function del_domain_cancel($dom) {
607
        global $db, $err, $classes, $cuid;
608
        $err->log("dom", "del_domaini_canl", $dom);
609
        $dom = strtolower($dom);
610
        $db->query("UPDATE sub_domaines SET web_action='UPDATE'  WHERE domaine= ?;", array($dom));
611
        $this->set_dns_action($dom, 'UPDATE');
612
        # TODO : some work with domain sensitive classes
613
        return true;
614
    }
615
616
    /* ----------------------------------------------------------------- */
617
618
    /**
619
     *  Efface un domaine du membre courant, et tous ses sous-domaines
620
     *
621
     * Cette fonction efface un domaine et tous ses sous-domaines, ainsi que
622
     * les autres services attachés é celui-ci. Elle appelle donc les autres
623
     * classe. Chaque classe peut déclarer une fonction del_dom qui sera
624
     * appellée lors de la destruction d'un domaine.
625
     *
626
     * @param string $dom nom de domaine é effacer
627
     * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
628
     */
629
    function del_domain($dom) {
630
        global $db, $err, $hooks;
631
        $err->log("dom", "del_domain", $dom);
632
        $dom = strtolower($dom);
633
634
        $this->lock();
635
        if (!$r = $this->get_domain_all($dom)) {
636
            return false;
637
        }
638
        $this->unlock();
639
640
        // Call Hooks to delete the domain and the MX management:
641
        // TODO : the 2 calls below are using an OLD hook call, FIXME: remove them when unused
642
        $hooks->invoke("alternc_del_domain", array($dom));
643
        $hooks->invoke("alternc_del_mx_domain", array($dom));
644
        // New hook calls: 
645
        $hooks->invoke("hook_dom_del_domain", array($r["id"]));
646
        $hooks->invoke("hook_dom_del_mx_domain", array($r["id"]));
647
648
        // Now mark the domain for deletion:
649
        $db->query("UPDATE sub_domaines SET web_action='DELETE'  WHERE domaine= ?;", array($dom));
650
        $this->set_dns_action($dom, 'DELETE');
651
652
        return true;
653
    }
654
655
    function domshort($dom, $sub = "") {
656
        return str_replace("-", "", str_replace(".", "", empty($sub) ? "" : "$sub.") . $dom);
657
    }
658
659
    /* ----------------------------------------------------------------- */
660
661
    /**
662
     *  Installe un domaine sur le compte courant.
663
     *
664
     * <p>Si le domaine existe déjé ou est interdit, ou est celui du serveur,
665
     * l'installation est refusée. Si l'hébergement DNS est demandé, la fonction
666
     * checkhostallow vérifiera que le domaine peut étre installé conformément
667
     * aux demandes des super-admin.
668
     * Si le dns n'est pas demandé, le domaine peut étre installé s'il est en
669
     * seconde main d'un tld (exemple : test.eu.org ou test.com, mais pas
670
     * toto.test.org ou test.test.asso.fr)</p>
671
     * <p>Chaque classe peut définir une fonction add_dom($dom) qui sera
672
     * appellée lors de l'installation d'un nouveau domaine.</p>
673
     *
674
     * @param boolean $dns 1 ou 0 pour héberger le DNS du domaine ou pas.
675
     * @param boolean $noerase 1 ou 0 pour rendre le domaine inamovible ou non
676
     * @param boolean $force 1 ou 0, si 1, n'effectue pas les tests de DNS.
677
     *  force ne devrait étre utilisé que par le super-admin.
678
      $ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
679
     */
680
    function add_domain($domain, $dns, $noerase = false, $force = false, $isslave = false, $slavedom = "") {
681
        global $db, $err, $quota, $L_FQDN, $tld, $cuid, $hooks;
682
        $err->log("dom", "add_domain", $domain);
683
684
        // Locked ?
685
        if (!$this->islocked) {
686
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
687
            return false;
688
        }
689
        // Verifie que le domaine est rfc-compliant
690
        $domain = strtolower($domain);
691
        $t = checkfqdn($domain);
692
        if ($t) {
693
            $err->raise("dom", _("The domain name is syntaxically incorrect"));
694
            return false;
695
        }
696
        // Interdit les domaines clés (table forbidden_domains) sauf en cas FORCE
697
        $db->query("SELECT domain FROM forbidden_domains WHERE domain= ? ;", array($domain));
698
        if ($db->num_rows() && !$force) {
699
            $err->raise("dom", _("The requested domain is forbidden in this server, please contact the administrator"));
700
            return false;
701
        }
702
        if ($domain == $L_FQDN || $domain == "www.$L_FQDN") {
703
            $err->raise("dom", _("This domain is the server's domain! You cannot host it on your account!"));
704
            return false;
705
        }
706
        $db->query("SELECT compte FROM domaines WHERE domaine= ?;", array($domain));
707
        if ($db->num_rows()) {
708
            $err->raise("dom", _("The domain already exist"));
709
            return false;
710
        }
711
        $db->query("SELECT compte FROM `sub_domaines` WHERE sub != \"\" AND concat( sub, \".\", domaine )= ? OR domaine= ?;", array($domain, $domain));
712
        if ($db->num_rows()) {
713
            $err->raise("dom", _("The domain already exist"));
714
            return false;
715
        }
716
        $this->dns = $this->whois($domain);
717
        if (!$force) {
718
            $v = checkhostallow($domain, $this->dns);
719
            if ($v == -1) {
720
                $err->raise("dom", _("The last member of the domain name is incorrect or cannot be hosted in that server"));
721
                return false;
722
            }
723
            if ($dns && $v == -2) {
724
                $err->raise("dom", _("The domain cannot be found in the whois database"));
725
                return false;
726
            }
727
            if ($dns && $v == -3) {
728
                $err->raise("dom", _("The domain cannot be found in the whois database"));
729
                return false;
730
            }
731
732
            if ($dns) {
733
                $dns = "1";
734
            } else {
735
                $dns = "0";
736
            }
737
            // mode 5 : force DNS to NO.
738
            if ($tld[$v] == 5) {
739
                $dns = 0;
740
            }
741
            // It must be a real domain (no subdomain)
742
            if (!$dns) {
743
                $v = checkhostallow_nodns($domain);
744
                if ($v) {
745
                    $err->raise("dom", _("The requested domain is forbidden in this server, please contact the administrator"));
746
                    return false;
747
                }
748
            }
749
        }
750
        // Check the quota :
751
        if (!$quota->cancreate("dom")) {
752
            $err->raise("dom", _("Your domain quota is over, you cannot create more domain names"));
753
            return false;
754
        }
755
        if ($noerase) {
756
            $noerase = "1";
757
        } else {
758
            $noerase = "0";
759
        }
760
        if ($dns) {
761
            $gesmx = "1";
762
        } else {
763
            $gesmx = "0"; // do not host mx by default if not hosting the DNS
764
        }
765
        $db->query("INSERT INTO domaines (compte,domaine,gesdns,gesmx,noerase,dns_action) VALUES (?, ?, ?, ?, ?, 'UPDATE');", array($cuid,$domain,$dns,$gesmx,$noerase));
766
        if (!($id = $db->lastid())) {
767
            $err->raise("dom", _("An unexpected error occured when creating the domain"));
768
            return false;
769
        }
770
771
        if ($isslave) {
772
            $isslave = true;
773
            $db->query("SELECT domaine FROM domaines WHERE compte= ? AND domaine= ?;", array($cuid, $slavedom));
774
            $db->next_record();
775
            if (!$db->Record["domaine"]) {
776
                $err->raise("dom", _("Domain '%s' not found"), $slavedom);
777
                $isslave = false;
778
            }
779
            // Point to the master domain : 
780
            $this->create_default_subdomains($domain, $slavedom);
781
        }
782
        if (!$isslave) {
783
            $this->create_default_subdomains($domain);
784
        }
785
786
        // TODO: Old hooks, FIXME: when unused remove them
787
        $hooks->invoke("alternc_add_domain", array($domain));
788
        if ($isslave) {
789
            $hooks->invoke("alternc_add_slave_domain", array($domain));
790
        }
791
        // New Hooks: 
792
        $hooks->invoke("hook_dom_add_domain", array($id));
793
        if ($gesmx) {
794
            $hooks->invoke("hook_dom_add_mx_domain", array($id));
795
        }
796
        if ($isslave) {
797
            $hooks->invoke("hook_dom_add_slave_domain", array($id, $slavedom));
798
        }
799
        return true;
800
    }
801
802
    /**
803
     * @param string $domain
804
     */
805
    function create_default_subdomains($domain, $target_domain = "") {
806
        global $db, $err;
807
        $err->log("dom", "create_default_subdomains", $domain);
808
        $query = "SELECT sub, domain_type, domain_type_parameter FROM default_subdomains WHERE (concerned = 'SLAVE' or concerned = 'BOTH') and enabled=1;";
809
        if (empty($target_domain)) {
810
            $query = "SELECT sub, domain_type, domain_type_parameter FROM default_subdomains WHERE (concerned = 'MAIN' or concerned = 'BOTH') and enabled=1;";
811
        }
812
        $domaindir = $this->domdefaultdir($domain);
813
        $db->query($query);
814
        $jj = array();
815
        while ($db->next_record()) {
816
            $jj[] = Array("domain_type_parameter" => $db->f('domain_type_parameter'), "sub" => $db->f('sub'), "domain_type" => $db->f('domain_type'));
817
        }
818
        $src_var = array("%%SUB%%", "%%DOMAIN%%", "%%DOMAINDIR%%", "%%TARGETDOM%%");
819
        foreach ($jj as $j) {
820
            $trg_var = array($j['sub'], $domain, $domaindir, $target_domain);
821
            $domain_type_parameter = str_ireplace($src_var, $trg_var, $j['domain_type_parameter']);
822
            $this->set_sub_domain($domain, $j['sub'], strtolower($j['domain_type']), $domain_type_parameter);
823
        }
824
    }
825
826
    /**
827
     * @param string $domain
828
     */
829
    function domdefaultdir($domain) {
830
        return "/www/" . $this->domshort($domain);
831
    }
832
833
    function dump_axfr($domain, $ns = 'localhost') {
834
        $axfr = array();
835
        exec('/usr/bin/dig AXFR "' . escapeshellcmd($domain) . '" @"' . escapeshellcmd($ns) . '"', $axfr);
836
        return $axfr;
837
    }
838
839
    function lst_default_subdomains() {
840
        global $db, $err;
841
        $err->log("dom", "lst_default_subdomains");
842
        $c = array();
843
        $db->query("select * from default_subdomains;");
844
845
        while ($db->next_record()) {
846
            $c[] = array('id' => $db->f('id'),
847
                'sub' => $db->f('sub'),
848
                'domain_type' => $db->f('domain_type'),
849
                'domain_type_parameter' => $db->f('domain_type_parameter'),
850
                'concerned' => $db->f('concerned'),
851
                'enabled' => $db->f('enabled')
852
            );
853
        }
854
855
        return $c;
856
    }
857
858
    function update_default_subdomains($arr) {
859
        global $err;
860
        $err->log("dom", "update_default_subdomains");
861
        $ok = true;
862
        foreach ($arr as $a) {
863
            if (!isset($a['id'])) {
864
                $a['id'] = null;
865
            }
866
            if (!empty($a['sub']) || !empty($a['domain_type_parameter'])) {
867
868
                if (!isset($a['enabled'])) {
869
                    $a['enabled'] = 0;
870
                }
871
                if (!$this->update_one_default($a['domain_type'], $a['sub'], $a['domain_type_parameter'], $a['concerned'], $a['enabled'], $a['id'])) {
872
                    $ok = false;
873
                }
874
            }
875
        }
876
        return $ok;
877
    }
878
879
    function update_one_default($domain_type, $sub, $domain_type_parameter, $concerned, $enabled, $id = null) {
880
        global $db, $err;
881
        $err->log("dom", "update_one_default");
882
883
        if ($id == null) {
884
            $db->query("INSERT INTO default_subdomains values ('', ?, ?, ?, ?, ?);", array($sub, $domain_type, $domain_type_parameter, $concerned, $enabled));
885
        } else {
886
            $db->query("UPDATE default_subdomains set sub= ?, domain_type= ?, domain_type_parameter= ?, concerned= ?, enabled= ? where id= ?;", array($sub, $domain_type, $domain_type_parameter, $concerned, $enabled, $id));
887
        }
888
        return true;
889
        //update
890
    }
891
892
    function del_default_type($id) {
893
        global $err, $db;
894
        $err->log("dom", "del_default_type");
895
896
        if (!$db->query("delete from default_subdomains where id= ?;", array($id))) {
897
            $err->raise("dom", _("Could not delete default type"));
898
            return false;
899
        }
900
901
        return true;
902
    }
903
904
    /* ----------------------------------------------------------------- */
905
906
    /**
907
     * Retourne les entrées DNS du domaine $domain issues du WHOIS.
908
     *
909
     * Cette fonction effectue un appel WHOIS($domain) sur Internet,
910
     * et extrait du whois les serveurs DNS du domaine demandé. En fonction
911
     * du TLD, on sait (ou pas) faire le whois correspondant.
912
     * Actuellement, les tld suivants sont supportés :
913
     * .com .net .org .be .info .ca .cx .fr .biz .name
914
     *
915
     * @param string $domain Domaine fqdn dont on souhaite les serveurs DNS
916
     * @return array Retourne un tableau indexé avec les NOMS fqdn des dns
917
     *   du domaine demandé. Retourne FALSE si une erreur s'est produite.
918
     *
919
     */
920
    function whois($domain) {
921
        global $err;
922
        $err->log("dom", "whois", $domain);
923
        // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
924
        //  echo "whois : $domain<br />";
925
        preg_match("#.*\.([^\.]*)#", $domain, $out);
926
        $ext = $out[1];
927
        // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
928
        //  echo "ext: $ext<br />";
929
930
        $serveur = "";
931
        if (($fp = @fsockopen("whois.iana.org", 43)) > 0) {
932
            fputs($fp, "$domain\r\n");
933
            $found = false;
934
            $state = 0;
935
            while (!feof($fp)) {
936
                $ligne = fgets($fp, 128);
937
                if (preg_match('#^whois:#', $ligne)) {
938
                    $serveur = preg_replace('/whois:\ */', '', $ligne, 1);
939
                }
940
            }
941
        }
942
        $serveur = str_replace(array(" ", "\n"), "", $serveur);
943
944
        $egal = "";
945
        switch ($ext) {
946
            case "net":
947
                $egal = "=";
948
                break;
949
            case "name":
950
                $egal = "domain = ";
951
                break;
952
        }
953
        $serveurList = array();
954
        // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
955
        //  echo "serveur : $serveur <br />";
956
        if (($fp = @fsockopen($serveur, 43)) > 0) {
957
            fputs($fp, "$egal$domain\r\n");
958
            $found = false;
959
            $state = 0;
960
            while (!feof($fp)) {
961
                $ligne = fgets($fp, 128);
962
                // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
963
                //  echo "| $ligne<br />";
964
                switch ($ext) {
965
                    case "org":
966
                    case "com":
967
                    case "net":
968
                    case "info":
969
                    case "biz":
970
                    case "name":
971
                    case "cc":
972
                        if (preg_match("#Name Server:#", $ligne)) {
973
                            $found = true;
974
                            $tmp = strtolower(str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", str_replace("Name Server:", "", $ligne)))));
975
                            if ($tmp) {
976
                                $serveurList[] = $tmp;
977
                            }
978
                        }
979
                        break;
980
                    case "co":
981
                        if (preg_match("#Name Server:#", $ligne)) {
982
                            $found = true;
983
                            $tmp = strtolower(str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", str_replace("Name Server:", "", $ligne)))));
984
                            if ($tmp)
985
                                $serveurList[] = $tmp;
986
                        }
987
                        break;
988
                    case "cx":
989
                        $ligne = str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", $ligne)));
990
                        if ($ligne == "" && $state == 1) {
991
                            $state = 2;
992
                        }
993
                        if ($state == 1) {
994
                            $serveurList[] = strtolower($ligne);
995
                        }
996
                        if ($ligne == "Nameservers:" && $state == 0) {
997
                            $state = 1;
998
                            $found = true;
999
                        }
1000
                        break;
1001
                    case "eu":
1002
                    case "be":
1003
                        $ligne = preg_replace("/^ *([^ ]*) \(.*\)$/", "\\1", trim($ligne));
1004
                        $tmp="";
1005
                        if ($found) {
1006
                            $tmp = trim($ligne);
1007
                        }
1008
                        if ($tmp) {
1009
                            $serveurList[] = $tmp;
1010
                        }
1011
                        if ($ligne == "Nameservers:") {
1012
                            $state = 1;
1013
                            $found = true;
1014
                        }
1015
                        break;
1016
                    case "im":
1017
                        if (preg_match('/Name Server:/', $ligne)) {
1018
                            $found = true;
1019
                            // weird regexp (trailing garbage after name server), but I could not make it work otherwise
1020
                            $tmp = strtolower(preg_replace('/Name Server: ([^ ]+)\..$/', "\\1", $ligne));
1021
                            $tmp = preg_replace('/[^-_a-z0-9\.]/', '', $tmp);
1022
                            if ($tmp) {
1023
                                $serveurList[] = $tmp;
1024
                            }
1025
                        }
1026
                        break;
1027
                    case "it":
1028
                        if (preg_match("#nserver:#", $ligne)) {
1029
                            $found = true;
1030
                            $tmp = strtolower(preg_replace("/nserver:\s*[^ ]*\s*([^\s]*)$/", "\\1", $ligne));
1031
                            if ($tmp) {
1032
                                $serveurList[] = $tmp;
1033
                            }
1034
                        }
1035
                        break;
1036
                    case "fr":
1037
                    case "re":
1038
                        if (preg_match("#nserver:#", $ligne)) {
1039
                            $found = true;
1040
                            $tmp = strtolower(preg_replace("#nserver:\s*([^\s]*)\s*.*$#", "\\1", $ligne));
1041
                            if ($tmp) {
1042
                                $serveurList[] = $tmp;
1043
                            }
1044
                        }
1045
                        break;
1046
                    case "ca":
1047
                    case "ws";
1048
                        if (preg_match('#Name servers#', $ligne)) {
1049
                            // found the server
1050
                            $state = 1;
1051
                        } elseif ($state) {
1052
                            if (preg_match('#^[^%]#', $ligne) && $ligne = preg_replace('#[[:space:]]#', "", $ligne)) {
1053
                                // first non-whitespace line is considered to be the nameservers themselves
1054
                                $found = true;
1055
                                $serveurList[] = $ligne;
1056
                            }
1057
                        }
1058
                        break;
1059
                    case "coop":
1060
                        if (preg_match('#Host Name:\s*([^\s]+)#', $ligne, $matches)) {
1061
                            $found = true;
1062
                            $serveurList[] = $matches[1];
1063
                        }
1064
                } // switch
1065
            } // while
1066
            fclose($fp);
1067
        } else {
1068
            $err->raise("dom", _("The Whois database is unavailable, please try again later"));
1069
            return false;
1070
        }
1071
1072
        if ($found) {
1073
            return $serveurList;
1074
        } else {
1075
            $err->raise("dom", _("The domain cannot be found in the Whois database"));
1076
            return false;
1077
        }
1078
    }
1079
1080
// whois
1081
1082
1083
    /* ----------------------------------------------------------------- */
1084
1085
    /**
1086
     *  vérifie la presence d'un champs mx valide sur un serveur DNS
1087
     * $domaine est le domaine dont on veux véririfer les MX
1088
     * $ref_domaine est le domaine avec lequel on veux comparer les MX
1089
     *              si $ref_domaine == '', on prend les MX par default
1090
     *
1091
     * @param string $domaine
1092
     */
1093
    function checkmx($domaine, $ref_domain = '') {
1094
        global $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX;
1095
1096
        $ref_mx = array();
1097
        $mxhosts = array();
1098
        if (!empty($ref_domain)) {
1099
            getmxrr($ref_domain, $ref_mx);
1100
        } else {
1101
            $ref_mx = array($L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX);
1102
        }
1103
1104
        if (empty($ref_mx)) {
1105
            // No reference mx
1106
            return 3;
1107
        }
1108
1109
        //récupére les champs mx
1110
        if (!getmxrr($domaine, $mxhosts)) {
1111
            //aucun héte mx spécifié
1112
            return 1;
1113
        }
1114
1115
        if (empty($mxhosts)) {
1116
            // no mx on the target domaine
1117
            return 1;
1118
        }
1119
1120
        $intersect = array_intersect($mxhosts, $ref_mx);
1121
1122
        if (empty($intersect)) {
1123
            // no shared mx server
1124
            return 2;
1125
        }
1126
1127
        return 0;
1128
    }
1129
1130
    /* ----------------------------------------------------------------- */
1131
1132
    /**
1133
     *  retourne TOUTES les infos d'un domaine
1134
     *
1135
     * @param string $dom Domaine dont on souhaite les informations
1136
     * @return array Retourne toutes les infos du domaine sous la forme d'un
1137
     * tableau associatif comme suit :<br /><pre>
1138
     *  $r["name"] =  Nom fqdn
1139
     *  $r["dns"]  =  Gestion du dns ou pas ?
1140
     *  $r["mx"]   =  Valeur du champs MX si "dns"=true
1141
     *  $r["mail"] =  Heberge-t-on le mail ou pas ? (si "dns"=false)
1142
     *  $r["nsub"] =  Nombre de sous-domaines
1143
     *  $r["sub"]  =  tableau associatif des sous-domaines
1144
     *  $r["sub"][0-(nsub-1)]["name"] = nom du sous-domaine (NON-complet)
1145
     *  $r["sub"][0-(nsub-1)]["dest"] = Destination (url, ip, local ...)
1146
     *  $r["sub"][0-(nsub-1)]["type"] = Type (0-n) de la redirection.
1147
     *  </pre>
1148
     *  Retourne FALSE si une erreur s'est produite.
1149
     *
1150
     */
1151
    function get_domain_all($dom) {
1152
        global $db, $err, $cuid;
1153
        $err->log("dom", "get_domain_all", $dom);
1154
        // Locked ?
1155
        if (!$this->islocked) {
1156
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1157
            return false;
1158
        }
1159
        $t = checkfqdn($dom);
1160
        if ($t) {
1161
            $err->raise("dom", _("The domain name is syntaxically incorrect"));
1162
            return false;
1163
        }
1164
        $r = array();
1165
        $r["name"] = $dom;
1166
        $db->query("SELECT * FROM domaines WHERE compte= ? AND domaine= ?;", array($cuid, $dom));
1167
        if ($db->num_rows() == 0) {
1168
            $err->raise("dom", sprintf(_("Domain '%s' not found"), $dom));
1169
            return false;
1170
        }
1171
        $db->next_record();
1172
        $r["id"] = $db->Record["id"];
1173
        $r["dns"] = $db->Record["gesdns"];
1174
        $r["dns_action"] = $db->Record["dns_action"];
1175
        $r["dns_result"] = $db->Record["dns_result"];
1176
        $r["mail"] = $db->Record["gesmx"];
1177
        $r["zonettl"] = $db->Record["zonettl"];
1178
        $r['noerase'] = $db->Record['noerase'];
1179
        $db->free();
1180
        $db->query("SELECT COUNT(*) AS cnt FROM sub_domaines WHERE compte= ? AND domaine= ?;", array($cuid, $dom));
1181
        $db->next_record();
1182
        $r["nsub"] = $db->Record["cnt"];
1183
        $db->free();
1184
        #$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");
1185
        $db->query("SELECT sd.*, dt.description AS type_desc, dt.only_dns, dt.advanced FROM sub_domaines sd LEFT JOIN domaines_type dt on  UPPER(dt.name)=UPPER(sd.type) WHERE compte= ? AND domaine= ? ORDER BY dt.advanced,sd.sub,sd.type ;", array($cuid, $dom));
1186
        // Pas de webmail, on le cochera si on le trouve.
1187
        $r["sub"] = array();
1188
        for ($i = 0; $i < $r["nsub"]; $i++) {
1189
            $db->next_record();
1190
            $r["sub"][$i] = array();
1191
            $r["sub"][$i]["id"] = $db->Record["id"];
1192
            $r["sub"][$i]["name"] = $db->Record["sub"];
1193
            $r["sub"][$i]["dest"] = $db->Record["valeur"];
1194
            $r["sub"][$i]["type"] = $db->Record["type"];
1195
            $r["sub"][$i]["enable"] = $db->Record["enable"];
1196
            $r["sub"][$i]["type_desc"] = $db->Record["type_desc"];
1197
            $r["sub"][$i]["only_dns"] = $db->Record["only_dns"];
1198
            $r["sub"][$i]["web_action"] = $db->Record["web_action"];
1199
            $r["sub"][$i]["advanced"] = $db->Record["advanced"];
1200
            $r["sub"][$i]["fqdn"] = ((!empty($r["sub"][$i]["name"])) ? $r["sub"][$i]["name"] . "." : "") . $r["name"];
1201
        }
1202
        $db->free();
1203
        return $r;
1204
    }
1205
1206
// get_domain_all
1207
1208
1209
    /* ----------------------------------------------------------------- */
1210
1211
    /**
1212
     * Retourne TOUTES les infos d'un sous domaine du compte courant.
1213
     *
1214
     * @param integer sub_domain_id id du subdomain
1215
     * @return array Retourne un tableau associatif contenant les
1216
     *  informations du sous-domaine demandé.<pre>
1217
     *  $r["name"]= nom du sous-domaine (NON-complet)
1218
     *  $r["dest"]= Destination (url, ip, local ...)
1219
     *  </pre>
1220
     *  $r["type"]= Type (0-n) de la redirection.
1221
     *  Retourne FALSE si une erreur s'est produite.
1222
     */
1223
    function get_sub_domain_all($sub_domain_id) {
1224
        global $db, $err, $cuid;
1225
        $err->log("dom", "get_sub_domain_all", $sub_domain_id);
1226
        // Locked ?
1227
        if (!$this->islocked) {
1228
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1229
            return false;
1230
        }
1231
        $db->query("select sd.*, dt.description as type_desc, dt.only_dns, dt.advanced from sub_domaines sd, domaines_type dt where compte= ? and sd.id= ?  and upper(dt.name)=upper(sd.type) ORDER BY dt.advanced, sd.sub;", array($cuid, $sub_domain_id));
1232
        if ($db->num_rows() == 0) {
1233
            $err->raise("dom", _("The sub-domain does not exist"));
1234
            return false;
1235
        }
1236
        $db->next_record();
1237
        $r = array();
1238
        $r["id"] = $db->Record["id"];
1239
        $r["name"] = $db->Record["sub"];
1240
        $r["domain"] = $db->Record["domaine"];
1241
        $r["dest"] = $db->Record["valeur"];
1242
        $r["enable"] = $db->Record["enable"];
1243
        $r["type"] = $db->Record["type"];
1244
        $r["type_desc"] = $db->Record["type_desc"];
1245
        $r["only_dns"] = $db->Record["only_dns"];
1246
        $r["web_action"] = $db->Record["web_action"];
1247
        $db->free();
1248
        return $r;
1249
    }
1250
1251
// get_sub_domain_all
1252
1253
    /**
1254
     * @param integer $type
1255
     * @param string $value
1256
     */
1257
    function check_type_value($type, $value) {
1258
        global $err;
1259
1260
        // check the type we can have in domaines_type.target
1261
        switch ($this->domains_type_target_values($type)) {
1262
            case 'NONE':
1263
                if (empty($value) or is_null($value)) {
1264
                    return true;
1265
                }
1266
                break;
1267
            case 'URL':
1268
                if ($value == strval($value)) {
1269
                    if (filter_var($value, FILTER_VALIDATE_URL)) {
1270
                        return true;
1271
                    } else {
1272
                        $err->raise("dom", _("invalid url"));
1273
                        return false;
1274
                    }
1275
                }
1276
                break;
1277
            case 'DIRECTORY':
1278
                if (substr($value, 0, 1) != "/") {
1279
                    $value = "/" . $value;
1280
                }
1281
                if (!checkuserpath($value)) {
1282
                    $err->raise("dom", _("The folder you entered is incorrect or does not exist"));
1283
                    return false;
1284
                }
1285
                return true;
1286
            case 'IP':
1287
                if (checkip($value)) {
1288
                    return true;
1289
                } else {
1290
                    $err->raise("dom", _("The ip address is invalid"));
1291
                    return false;
1292
                }
1293
                break;
1294
            case 'IPV6':
1295
                if (checkipv6($value)) {
1296
                    return true;
1297
                } else {
1298
                    $err->raise("dom", _("The ip address is invalid"));
1299
                    return false;
1300
                }
1301
                break;
1302
            case 'DOMAIN':
1303
                if (checkcname($value)) {
1304
                    return true;
1305
                } else {
1306
                    $err->raise("dom", _("The name you entered is incorrect or not fully qualified (it must end with a DOT, like example.com<b>.</b>)"));
1307
                    return false;
1308
                }
1309
                break;
1310
            case 'TXT':
1311
                if ($value == strval($value)) {
1312
                    return true;
1313
                } else {
1314
                    $err->raise("dom", _("The TXT value you entered is incorrect"));
1315
                    return false;
1316
                }
1317
                break;
1318
            default:
1319
                $err->raise("dom", _("Invalid domain type selected, please check"));
1320
                return false;
1321
        }
1322
        return false;
1323
    }
1324
1325
    /* ----------------------------------------------------------------- */
1326
1327
    /**
1328
     * Check the compatibility of the POSTed parameters with the chosen
1329
     * domain type
1330
     *
1331
     * @param string $dom FQDN of the domain name
1332
     * @param string $sub SUBdomain 
1333
     * @return boolean tell you if the subdomain can be installed there 
1334
     */
1335
    function can_create_subdomain($dom, $sub, $type, $sub_domain_id = 'null') {
1336
        global $db, $err;
1337
        $err->log("dom", "can_create_subdomain", $dom . "/" . $sub);
1338
1339
        // Get the compatibility list for this domain type
1340
        $db->query("select upper(compatibility) as compatibility from domaines_type where upper(name)=upper(?);", array($type));
1341
        if (!$db->next_record()) {
1342
            return false;
1343
        }
1344
        $compatibility_lst = explode(",", $db->f('compatibility'));
1345
1346
        // Get the list of type of subdomains already here who have the same name
1347
        $db->query("select * from sub_domaines where sub= ? and domaine= ? and not id = ? and web_action != 'DELETE' and enabled not in ('DISABLED', 'DISABLE') ", array($sub, $dom, $sub_domain_id));
1348
        #$db->query("select * from sub_domaines where sub='$sub' and domaine='$dom';");
1349
        while ($db->next_record()) {
1350
            // And if there is a domain with a incompatible type, return false
1351
            if (!in_array(strtoupper($db->f('type')), $compatibility_lst)) {
1352
                return false;
1353
            }
1354
        }
1355
1356
        // Forbidden to create a CNAME RR on the domain APEX (RFC 1912)                                                                                                                               
1357
        if ($type == 'cname' && $sub == '')    
1358
            return false;  
1359
1360
        // All is right, go ! Create ur domain !
1361
        return true;
1362
    }
1363
1364
    /* ----------------------------------------------------------------- */
1365
1366
    /**
1367
     * Modifier les information du sous-domaine demandé.
1368
     *
1369
     * <b>Note</b> : si le sous-domaine $sub.$dom n'existe pas, il est créé.<br />
1370
     * <b>Note : TODO</b> : vérification de concordance de $dest<br />
1371
     *
1372
     * @param string $dom Domaine dont on souhaite modifier/ajouter un sous domaine
1373
     * @param string $sub Sous domaine é modifier / créer
1374
     * @param integer $type Type de sous-domaine (local, ip, url ...)
1375
     * @param string $dest Destination du sous-domaine, dépend de la valeur
1376
     *  de $type (url, ip, dossier...)
1377
     * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
1378
     */
1379
    function set_sub_domain($dom, $sub, $type, $dest, $sub_domain_id = null) {
1380
        global $db, $err, $cuid, $bro;
1381
        $err->log("dom", "set_sub_domain", $dom . "/" . $sub . "/" . $type . "/" . $dest);
1382
        // Locked ?
1383
        if (!$this->islocked) {
1384
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1385
            return false;
1386
        }
1387
        $dest = trim($dest);
1388
        $sub = trim(trim($sub), ".");
1389
        $dom = strtolower($dom);
1390
        $sub = strtolower($sub);
1391
1392
        //    if (!(($sub == '*') || ($sub=="") || (preg_match('/([a-z0-9][\.\-a-z0-9]*)?[a-z0-9]/', $sub)))) {
1393
        $fqdn = checkfqdn($sub);
1394
        // Special cases : * (all subdomains at once) and '' empty subdomain are allowed.
1395
        if (($sub != '*' && $sub != '') && !($fqdn == 0 || $fqdn == 4)) {
1396
            $err->raise("dom", _("There is some forbidden characters in the sub domain (only A-Z 0-9 and - are allowed)"));
1397
            return false;
1398
        }
1399
1400
        if (!$this->check_type_value($type, $dest)) {
1401
            //plutot verifier si la chaine d'erreur est vide avant de raise sinon sa veut dire que l(erruer est deja remonté
1402
	  // error raised by check_type_value
1403
            return false;
1404
        }
1405
1406
        // On a épuré $dir des problémes eventuels ... On est en DESSOUS du dossier de l'utilisateur.
1407
        if (($t = checkfqdn($dom))) {
1408
            $err->raise("dom", _("The domain name is syntaxically incorrect"));
1409
            return false;
1410
        }
1411
1412
        if (!$this->can_create_subdomain($dom, $sub, $type, $sub_domain_id)) {
1413
            $err->raise("dom", _("The parameters for this subdomain and domain type are invalid. Please check for subdomain entries incompatibility"));
1414
            return false;
1415
        }
1416
1417
        if (!is_null($sub_domain_id)) { // It's not a creation, it's an edit. Delete the old one
1418
            $this->del_sub_domain($sub_domain_id);
1419
        }
1420
1421
        // Re-create the one we want
1422
        if (!$db->query("replace into sub_domaines (compte,domaine,sub,valeur,type,web_action) values (?, ?, ?, ?, ?, 'UPDATE');", array( $cuid , $dom , $sub , $dest , $type ))) {
1423
            echo "query failed: " . $db->Error;
1424
            return false;
1425
        }
1426
1427
        // Create TMP dir and TARGET dir if needed by the domains_type
1428
        $dest_root = $bro->get_userid_root($cuid);
1429
        //$domshort = $this->domshort($dom, $sub);
1430
        $db->query("select create_tmpdir, create_targetdir from domaines_type where name = ?;", array($type));
1431
        $db->next_record();
1432
        if ($db->f('create_tmpdir')) {
1433
            if (!is_dir($dest_root . "/tmp")) {
1434
                if (!@mkdir($dest_root . "/tmp", 0777, true)) {
1435
                    $err->raise("dom", _("Cannot write to the destination folder"));
1436
                }
1437
            }
1438
        }
1439
        if ($db->f('create_targetdir')) {
1440
            $dirr = $dest_root . $dest;
1441
            $dirr = str_replace('//', '/', $dirr);
1442
1443
            if (!is_dir($dirr)) {
1444
                $old = umask(0);
1445
                if (!@mkdir($dirr, 0770, true)) {
1446
                    $err->raise("dom", _("Cannot write to the destination folder"));
1447
                }
1448
                umask($old);
1449
            }
1450
        }
1451
1452
        // Tell to update the DNS file
1453
        $db->query("update domaines set dns_action='UPDATE' where domaine= ?;", array($dom));
1454
1455
        return true;
1456
    }
1457
1458
    /* ----------------------------------------------------------------- */
1459
1460
    /**
1461
     *  Supprime le sous-domaine demandé
1462
     *
1463
     * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
1464
     *
1465
     */
1466
    function del_sub_domain($sub_domain_id) {
1467
        global $db, $err;
1468
        $err->log("dom", "del_sub_domain", $sub_domain_id);
1469
        // Locked ?
1470
        if (!$this->islocked) {
1471
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1472
            return false;
1473
        }
1474
        if (!$r = $this->get_sub_domain_all($sub_domain_id)) {
1475
            $err->raise("dom", _("The sub-domain does not exist"));
1476
            return false;
1477
        } else {
1478
            $db->query("update sub_domaines set web_action='DELETE' where id= ?; ", array($sub_domain_id));
1479
            $db->query("update domaines set dns_action='UPDATE' where domaine= ?;", array($r['domain']));
1480
        }
1481
        return true;
1482
    }
1483
1484
    /**
1485
     * @param integer $dom_id
1486
     */
1487
    function set_ttl($dom_id, $ttl) {
1488
        global $err;
1489
        $err->log("dom", "set_ttl", "$dom_id / $ttl");
1490
        $this->lock();
1491
        $domaine = $this->get_domain_byid($dom_id);
1492
        $d = $this->get_domain_all($domaine);
1493
1494
        $j = $this->edit_domain($domaine, $d['dns'], $d['mail'], false, $ttl);
1495
        $this->unlock();
1496
        return $j;
1497
    }
1498
1499
    /* ----------------------------------------------------------------- */
1500
1501
    /**
1502
     * Modifie les information du domaine précisé.
1503
     *
1504
     * @param string $dom Domaine du compte courant que l'on souhaite modifier
1505
     * @param boolean $dns Vaut 1 ou 0 pour héberger ou pas le DNS du domaine
1506
     * @param boolean $gesmx Héberge-t-on le emails du domaines sur ce serveur ?
1507
     * @param boolean $force Faut-il passer les checks DNS ou MX ? (admin only)
1508
     * @return boolean appelle $mail->add_dom ou $ma->del_dom si besoin, en
1509
     *  fonction du champs MX. Retourne FALSE si une erreur s'est produite,
1510
     *  TRUE sinon.
1511
     *
1512
     */
1513
    function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400) {
1514
        global $db, $err, $hooks;
1515
        $err->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx);
1516
        // Locked ?
1517
        if (!$this->islocked && !$force) {
1518
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1519
            return false;
1520
        }
1521
        if ($dns == true && !$force) {
1522
            $this->dns = $this->whois($dom);
1523
            $v = checkhostallow($dom, $this->dns);
1524
            if ($v == -1) {
1525
                $err->raise("dom", _("The last member of the domain name is incorrect or cannot be hosted in that server"));
1526
                return false;
1527
            }
1528
            if ($dns && $v == -2) {
1529
                $err->raise("dom", _("The domain cannot be found in the Whois database"));
1530
                return false;
1531
            }
1532
            if ($dns && $v == -3) {
1533
                $err->raise("dom", _("The DNS of this domain do not match the server's DNS. Please change your domain's DNS before you install it again"));
1534
                return false;
1535
            }
1536
        }
1537
1538
        # Can't have ttl == 0. There is also a check in function_dns
1539
        if ($ttl == 0) {
1540
            $ttl = 86400;
1541
        }
1542
1543
        $t = checkfqdn($dom);
1544
        if ($t) {
1545
            $err->raise("dom", _("The domain name is syntaxically incorrect"));
1546
            return false;
1547
        }
1548
        if (!$r = $this->get_domain_all($dom)) {
1549
            // Le domaine n'existe pas, Failure
1550
            $err->raise("dom", _("The domain name %s does not exist"), $dom);
1551
            return false;
1552
        }
1553
        if ($dns != "1") {
1554
            $dns = "0";
1555
        }
1556
        // On vérifie que des modifications ont bien eu lieu :)
1557
        if ($r["dns"] == $dns && $r["mail"] == $gesmx && $r["zonettl"] == $ttl) {
1558
            $err->raise("dom", _("No change has been requested..."));
1559
            return true;
1560
        }
1561
1562
        //si gestion mx uniquement, vérification du dns externe
1563
        if ($dns == "0" && $gesmx == "1" && !$force) {
1564
            $vmx = $this->checkmx($dom);
1565
            if ($vmx == 1) {
1566
                $err->raise("dom", _("There is no MX record pointing to this server, and you are asking us to host the mail here. Make sure to update your MX entries or no mail will be received"));
1567
            }
1568
1569
            if ($vmx == 2) {
1570
                // Serveur non spécifié parmi les champx mx
1571
                $err->raise("dom", _("There is no MX record pointing to this server, and you are asking us to host the mail here. Make sure to update your MX entries or no mail will be received"));
1572
            }
1573
        }
1574
1575
        if ($gesmx && !$r["mail"]) {
1576
            $hooks->invoke("hook_dom_add_mx_domain", array($r["id"]));
1577
        }
1578
1579
        if (!$gesmx && $r["mail"]) { // on a dissocié le MX : on détruit donc l'entree dans LDAP
1580
            $hooks->invoke("hook_dom_del_mx_domain", array($r["id"]));
1581
        }
1582
1583
        $db->query("UPDATE domaines SET gesdns= ?, gesmx= ?, zonettl= ? WHERE domaine= ?", array($dns, $gesmx, $ttl, $dom));
1584
        $this->set_dns_action($dom, 'UPDATE');
1585
1586
        return true;
1587
    }
1588
1589
    /*     * ************************* */
1590
    /*  Slave dns ip managment  */
1591
    /*     * ************************* */
1592
1593
    /* ----------------------------------------------------------------- */
1594
1595
    /** Return the list of ip addresses and classes that are allowed access to domain list
1596
     * through AXFR Transfers from the bind server.
1597
     */
1598
    function enum_slave_ip() {
1599
        global $db, $err;
1600
        $db->query("SELECT * FROM slaveip;");
1601
        if (!$db->next_record()) {
1602
            return false;
1603
        }
1604
        $res = array();
1605
        do {
1606
            $res[] = $db->Record;
1607
        } while ($db->next_record());
1608
        return $res;
1609
    }
1610
1611
    /* ----------------------------------------------------------------- */
1612
1613
    /** Add an ip address (or a ip class) to the list of allowed slave ip access list.
1614
     */
1615
    function add_slave_ip($ip, $class = "32") {
1616
        global $db, $err;
1617
        if (!checkip($ip)) {
1618
            $err->raise("dom", _("The IP address you entered is incorrect"));
1619
            return false;
1620
        }
1621
        $class = intval($class);
1622
        if ($class < 8 || $class > 32) {
1623
            $class = 32;
1624
        }
1625
        $db->query("SELECT * FROM slaveip WHERE ip= ? AND class= ?;", array($ip, $class));
1626
        if ($db->next_record()) {
1627
            $err->raise("err", _("The requested domain is forbidden in this server, please contact the administrator"));
1628
            return false;
1629
        }
1630
        $db->query("INSERT INTO slaveip (ip,class) VALUES (?, ?);", array($ip, $class));
1631
        $f = fopen(SLAVE_FLAG, "w");
1632
        fputs($f, "yopla");
1633
        fclose($f);
1634
        return true;
1635
    }
1636
1637
    /* ----------------------------------------------------------------- */
1638
1639
    /** Remove an ip address (or a ip class) from the list of allowed slave ip access list.
1640
     */
1641
    function del_slave_ip($ip) {
1642
        global $db, $err;
1643
        if (!checkip($ip)) {
1644
            $err->raise("dom", _("The IP address you entered is incorrect"));
1645
            return false;
1646
        }
1647
        $db->query("DELETE FROM slaveip WHERE ip= ?;", array($ip));
1648
        $f = fopen(SLAVE_FLAG, "w");
1649
        fputs($f, "yopla");
1650
        fclose($f);
1651
        return true;
1652
    }
1653
1654
    /* ----------------------------------------------------------------- */
1655
1656
    /** Check for a slave account
1657
     */
1658
    function check_slave_account($login, $pass) {
1659
        global $db;
1660
        $db->query("SELECT * FROM slaveaccount WHERE login= ? AND pass= ?;", array($login, $pass));
1661
        if ($db->next_record()) {
1662
            return true;
1663
        }
1664
        return false;
1665
    }
1666
1667
    /* ----------------------------------------------------------------- */
1668
1669
    /** Out (echo) the complete hosted domain list : 
1670
     */
1671
    function echo_domain_list($integrity = false) {
1672
        global $db;
1673
        $db->query("SELECT domaine FROM domaines WHERE gesdns=1 ORDER BY domaine");
1674
        $tt = "";
1675
        while ($db->next_record()) {
1676
            #echo $db->f("domaine")."\n";
1677
            $tt.=$db->f("domaine") . "\n";
1678
        }
1679
        echo $tt;
1680
        if ($integrity) {
1681
            echo md5($tt) . "\n";
1682
        }
1683
        return true;
1684
    }
1685
1686
    /* ----------------------------------------------------------------- */
1687
1688
    /** Returns the complete hosted domain list : 
1689
     */
1690
    function get_domain_list($uid = -1) {
1691
        global $db;
1692
        $uid = intval($uid);
1693
        $res = array();
1694
        $sql = "";
0 ignored issues
show
Unused Code introduced by
$sql is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1695
1696
        $query  =   "SELECT domaine FROM domaines WHERE gesdns=1 ";
1697
        $query_args = array();
1698
        if ($uid != -1) {
1699
            $query .= " AND compte= ? ";
1700
            array_push($query_args, $uid);
1701
        }
1702
        $query  .= " ORDER BY domaine;";
1703
        $db->query($query, $query_args);
1704
        while ($db->next_record()) {
1705
            $res[] = $db->f("domaine");
1706
        }
1707
        return $res;
1708
    }
1709
1710
    /**
1711
     * 
1712
     * @return array
1713
     */
1714
    function get_domain_all_summary() {
1715
        global $db;
1716
        $res = array();
1717
        $db->query("SELECT domaine, gesdns, gesmx, dns_action, zonettl FROM domaines ORDER BY domaine");
1718
        while ($db->next_record()) {
1719
            $res[$db->f("domaine")] = array(
1720
                "gesdns" => $db->f("gesdns"),
1721
                "gesmx" => $db->f("gesmx"),
1722
                "dns_action" => $db->f("dns_action"),
1723
                "zonettl" => $db->f("zonettl"),
1724
            );
1725
        }
1726
        return $res;
1727
    }
1728
1729
    /* ----------------------------------------------------------------- */
1730
1731
    /** Returns the name of a domain for the current user, from it's domain_id
1732
     * @param $dom_id integer the domain_id to search for
1733
     * @return string the domain name, or false with an error raised.
1734
     */
1735
    function get_domain_byid($dom_id) {
1736
        global $db, $err, $cuid;
1737
        $dom_id = intval($dom_id);
1738
        $db->query("SELECT domaine FROM domaines WHERE id= ? AND compte= ?;", array($dom_id, $cuid));
1739
        if ($db->next_record()) {
1740
            $domain = $db->f("domaine");
1741
            if (!$domain) {
1742
                $err->raise("dom", _("This domain is not installed in your account"));
1743
                return false;
1744
            } else {
1745
                return $domain;
1746
            }
1747
        } else {
1748
            $err->raise("dom", _("This domain is not installed in your account"));
1749
            return false;
1750
        }
1751
    }
1752
1753
    /* ----------------------------------------------------------------- */
1754
1755
    /** Returns the id of a domain for the current user, from it's domain name
1756
     * @param $domain string the domain name to search for
1757
     * @return integer the domain id, or false with an error raised.
1758
     */
1759
    function get_domain_byname($domain) {
1760
        global $db, $err, $cuid;
1761
        $domain = trim($domain);
1762
        $db->query("SELECT id FROM domaines WHERE domaine= ? AND compte= ?;", array($domain, $cuid));
1763
        if ($db->next_record()) {
1764
            $id = $db->f("id");
1765
            if (!$id) {
1766
                $err->raise("dom", _("This domain is not installed in your account"));
1767
                return false;
1768
            } else {
1769
                return $id;
1770
            }
1771
        } else {
1772
            $err->raise("dom", _("This domain is not installed in your account"));
1773
            return false;
1774
        }
1775
    }
1776
1777
    /* ----------------------------------------------------------------- */
1778
1779
    /** Count all domains, for all users
1780
     */
1781
    function count_domains_all() {
1782
        global $db;
1783
        $db->query("SELECT COUNT(*) AS count FROM domaines;");
1784
        if ($db->next_record()) {
1785
            return $db->f('count');
1786
        } else {
1787
            return 0;
1788
        }
1789
    }
1790
1791
    /* ----------------------------------------------------------------- */
1792
1793
    /** Return the list of allowed slave accounts 
1794
     */
1795
    function enum_slave_account() {
1796
        global $db;
1797
        $db->query("SELECT * FROM slaveaccount;");
1798
        $res = array();
1799
        while ($db->next_record()) {
1800
            $res[] = $db->Record;
1801
        }
1802
        if (!count($res)) {
1803
            return false;
1804
        }
1805
        return $res;
1806
    }
1807
1808
    /* ----------------------------------------------------------------- */
1809
1810
    /** Add a slave account that will be allowed to access the domain list
1811
     */
1812
    function add_slave_account($login, $pass) {
1813
        global $db, $err;
1814
        $db->query("SELECT * FROM slaveaccount WHERE login= ?", array($login));
1815
        if ($db->next_record()) {
1816
            $err->raise("dom", _("The specified slave account already exists"));
1817
            return false;
1818
        }
1819
        $db->query("INSERT INTO slaveaccount (login,pass) VALUES (?, ?)", array($login, $pass));
1820
        return true;
1821
    }
1822
1823
    /* ----------------------------------------------------------------- */
1824
1825
    /** Remove a slave account
1826
     */
1827
    function del_slave_account($login) {
1828
        global $db, $err;
1829
        $db->query("DELETE FROM slaveaccount WHERE login= ?", array($login));
1830
        return true;
1831
    }
1832
1833
    /*     * ********** */
1834
    /*  Private  */
1835
    /*     * ********** */
1836
1837
1838
    /* ----------------------------------------------------------------- */
1839
1840
    /** Try to lock a domain
1841
     * @access private
1842
     */
1843
    function lock() {
1844
        global $err;
1845
        $err->log("dom", "lock");
1846
        if ($this->islocked) {
1847
            $err->raise("dom", _("--- Program error --- Lock already obtained!"));
1848
        }
1849
        while (file_exists($this->fic_lock_cron)) {
1850
            sleep(2);
1851
        }
1852
        $this->islocked = true;
1853
        return true;
1854
    }
1855
1856
    /* ----------------------------------------------------------------- */
1857
1858
    /** Unlock the cron for domain management
1859
     * return true
1860
     * @access private
1861
     */
1862
    function unlock() {
1863
        global $err;
1864
        $err->log("dom", "unlock");
1865
        if (!$this->islocked) {
1866
            $err->raise("dom", _("--- Program error --- No lock on the domains!"));
1867
        }
1868
        $this->islocked = false;
1869
        return true;
1870
    }
1871
1872
    /* ----------------------------------------------------------------- */
1873
1874
    /** Declare that a domain's emails are hosted in this server : 
1875
     * This adds 2 MX entries in this domain (if required)
1876
     */
1877
    function hook_dom_add_mx_domain($dom_id) {
1878
        global $err;
1879
        $domain = $this->get_domain_byid($dom_id);
1880
        $err->log("dom", "hook_dom_add_mx_domain");
1881
        $this->set_sub_domain($domain, '', $this->type_defmx, '');
1882
        if (!empty($GLOBALS['L_DEFAULT_SECONDARY_MX'])) {
1883
            $this->set_sub_domain($domain, '', $this->type_defmx2, '');
1884
        }
1885
        return true;
1886
    }
1887
1888
    /* ----------------------------------------------------------------- */
1889
1890
    /**
1891
     * Delete an account (all his domains)
1892
     */
1893
    function hook_admin_del_member() {
1894
        global $err;
1895
        $err->log("dom", "alternc_del_member");
1896
        $li = $this->enum_domains();
1897
        foreach ($li as $dom) {
1898
            $this->del_domain($dom);
1899
        }
1900
        return true;
1901
    }
1902
1903
    /* ----------------------------------------------------------------- */
1904
1905
    /** Returns the used quota for the $name service for the current user.
1906
     * @param $name string name of the quota
1907
     * @return integer the number of service used or false if an error occured
1908
     * @access private
1909
     */
1910
    function hook_quota_get() {
1911
        global $db, $err, $cuid;
1912
        $err->log("dom", "get_quota");
1913
        $q = Array("name" => "dom", "description" => _("Domain name"), "used" => 0);
1914
        $db->query("SELECT COUNT(*) AS cnt FROM domaines WHERE compte= ?", array($cuid));
1915
        if ($db->next_record()) {
1916
            $q['used'] = $db->f("cnt");
1917
        }
1918
        return $q;
1919
    }
1920
1921
    /* --------------------------------------------------------------------- */
1922
1923
    /** Returns the global domain(s) configuration(s) of a particular user
1924
     * No parameters needed 
1925
     * */
1926
    function alternc_export_conf() {
1927
        global $err;
1928
        $err->log("dom", "export");
1929
        $this->enum_domains();
1930
        $str = "";
1931
        foreach ($this->domains as $d) {
1932
            $str.= "  <domaines>\n";
1933
            $str.="   <nom>" . $d . "</nom>\n";
1934
            $this->lock();
1935
            $s = $this->get_domain_all($d);
1936
            $this->unlock();
1937
            if (empty($s["dns"])) {
1938
                $s["dns"] = "non";
1939
            } else {
1940
                $s["dns"] = "oui";
1941
            }
1942
            $str.="   <dns>" . $s["dns"] . "</dns>\n";
1943
1944
            if (empty($s["mx"])) {
1945
                $s["mx"] = "non";
1946
            } else {
1947
                $s["mx"] = "oui";
1948
            }
1949
1950
            $str.="   <mx>" . $s["mx"] . "</mx>\n";
1951
1952
            if (empty($s["mail"])) {
1953
                $s["mail"] = "non";
1954
            }
1955
            $str.="   <mail>" . $s["mail"] . "</mail>\n";
1956
            if (is_array($s["sub"])) {
1957
                foreach ($s["sub"] as $sub) {
1958
                    $str.="     <subdomain>\n";
1959
                    $str.="       <enabled>" . $sub["enable"] . " </enabled>\n";
1960
                    $str.="       <destination>" . $sub["dest"] . " </destination>\n";
1961
                    $str.="       <type>" . $sub["type"] . " </type>\n";
1962
                    $str.="     </subdomain>\n";
1963
                }
1964
            }
1965
            $str.=" </domaines>\n";
1966
        }
1967
        return $str;
1968
    }
1969
1970
    /**
1971
     * Return an array with all the needed parameters to generate conf 
1972
     * of a vhost.
1973
     * If no parameters, return the parameters for ALL the vhost.
1974
     * Optionnal parameters: id of the sub_domaines
1975
     * */
1976
    function generation_parameters($id = null, $only_apache = true) {
1977
        global $db, $err;
1978
        $err->log("dom", "generation_parameters");
1979
        $params = "";
0 ignored issues
show
Unused Code introduced by
$params is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1980
        /** 2016_05_18 : this comments was here before escaping the request... is there still something to do here ?
1981
         *   // BUG BUG BUG FIXME
1982
         *   // Suppression de comptes -> membres existe pas -> domaines a supprimer ne sont pas lister
1983
         */
1984
        $query  = "
1985
                select 
1986
                  sd.id as sub_id, 
1987
                  lower(sd.type) as type, 
1988
                  m.login, 
1989
                  m.uid as uid, 
1990
                  if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) as fqdn, 
1991
                  concat_ws('@',m.login,v.value) as mail, 
1992
                  sd.valeur  
1993
                from 
1994
                  sub_domaines sd left join membres m on sd.compte=m.uid,
1995
                  variable v, 
1996
                  domaines_type dt 
1997
                where 
1998
                  v.name='mailname_bounce' 
1999
                  and lower(dt.name) = lower(sd.type)"; 
2000
        $query_args =   array();
2001
2002
        if (!is_null($id) && intval($id) == $id) {
2003
            $query .= " AND sd.id = ? ";
2004
            array_push($query_args, intval($id));
2005
        }
2006
        if ($only_apache) {
2007
            $query .=" and dt.only_dns is false ";
2008
        }
2009
2010
        $query  .=  "
2011
                order by 
2012
                  m.login, 
2013
                  sd.domaine, 
2014
                  sd.sub;";
2015
2016
        
2017
        $db->query($query, $query_args);
2018
2019
        $r = array();
2020
        while ($db->next_record()) {
2021
            $r[$db->Record['sub_id']] = $db->Record;
2022
        }
2023
        return $r;
2024
    }
2025
2026
    /**
2027
     * Return an array with all informations of the domains_type
2028
     * used to generate Apache conf.
2029
     * Die if templates missing.
2030
     * Warning: an Apache domains_type must have 'only_dns' == TRUE
2031
     *
2032
     * */
2033
    function generation_domains_type() {
2034
        global $dom;
2035
        $d = array();
2036
        foreach ($dom->domains_type_lst() as $k => $v) {
2037
            if ($v['only_dns'] == true) {
2038
                continue;
2039
            }
2040
            if (!$j = file_get_contents(ALTERNC_APACHE2_GEN_TMPL_DIR . '/' . strtolower($k) . '.conf')) {
2041
                die("Error: missing file for $k");
2042
            }
2043
            $d[$k] = $v;
2044
            $d[$k]['tpl'] = $j;
2045
        }
2046
        return $d;
2047
    }
2048
2049
// Launch old fashionned hooks as there was in AlternC 1.0
2050
    function generate_conf_oldhook($action, $lst_sub, $sub_obj = null) {
2051
        if (is_null($sub_obj)) {
2052
            $sub_obj = $this->generation_parameters(null, false);
2053
        }
2054
        if (!isset($lst_sub[strtoupper($action)]) || empty($lst_sub[strtoupper($action)])) {
2055
            return false;
2056
        }
2057
2058
        $lst_by_type = $lst_sub[strtoupper($action)];
2059
2060
        foreach ($lst_by_type as $type => $lid_arr) {
2061
            $script = "/etc/alternc/functions_hosting/hosting_" . strtolower($type) . ".sh";
2062
            if (!@is_executable($script)) {
2063
                continue;
2064
            }
2065
            foreach ($lid_arr as $lid) {
2066
                $o = $sub_obj[$lid];
2067
                $cmd = $script . " " . escapeshellcmd(strtolower($action)) . " ";
2068
                $cmd .= escapeshellcmd($o['fqdn']) . " " . escapeshellcmd($o['valeur']);
2069
2070
                system($cmd);
2071
            }
2072
        } // foreach $lst_by_type
2073
    }
2074
2075
    /**
2076
     * Generate apache configuration.
2077
     * Die if a specific FQDN have 2 vhost conf.
2078
     *
2079
     * */
2080
    function generate_apacheconf($p = null) {
2081
        // Get the parameters
2082
        $lst = $this->generation_parameters($p);
2083
2084
        $gdt = $this->generation_domains_type();
2085
2086
        // Initialize duplicate check
2087
        $check_dup = array();
2088
2089
        $ret = '';
2090
        foreach ($lst as $p) {
2091
            // Check if duplicate
2092
            if (in_array($p['fqdn'], $check_dup)) {
2093
                die("Error: duplicate fqdn : " . $p['fqdn']);
2094
            } else {
2095
                $check_dup[] = $p['fqdn'];
2096
            }
2097
2098
            // Get the needed template
2099
            $tpl = $gdt[$p['type']] ['tpl'];
2100
2101
            // Replace needed vars
2102
            $tpl = strtr($tpl, array(
2103
                "%%LOGIN%%" => $p['login'],
2104
                "%%fqdn%%" => $p['fqdn'],
2105
                "%%document_root%%" => getuserpath($p['login']) . $p['valeur'],
2106
                "%%account_root%%" => getuserpath($p['login']),
2107
                "%%redirect%%" => $p['valeur'],
2108
                "%%UID%%" => $p['uid'],
2109
                "%%GID%%" => $p['uid'],
2110
                "%%mail_account%%" => $p['mail'],
2111
                "%%user%%" => "FIXME",
2112
            ));
2113
2114
            // Security check
2115
            if ($p['uid'] < 1999) { // if UID is not an AlternC uid
2116
                $ret.= "# ERROR: Sub_id: " . $p['sub_id'] . "- The uid seem to be dangerous\n";
2117
                continue;
2118
            }
2119
2120
            // Return the conf
2121
            $ret.= "# Sub_id: " . $p['sub_id'] . "\n" . $tpl;
2122
        }
2123
2124
        return $ret;
2125
    }
2126
2127
    // Return an array with the list of id of sub_domains waiting for an action
2128
    function generation_todo() {
2129
        global $db, $err;
2130
        $err->log("dom", "generation_todo");
2131
        $db->query("select id as sub_id, web_action, type from sub_domaines where web_action !='ok';");
2132
        $r = array();
2133
        while ($db->next_record()) {
2134
            $r[strtoupper($db->Record['web_action'])][strtoupper($db->Record['type'])][] = $db->f('sub_id');
2135
        }
2136
        return $r;
2137
    }
2138
2139
    function subdomain_modif_are_done($sub_domain_id, $action) {
2140
        global $db;
2141
        $sub_domain_id = intval($sub_domain_id);
2142
        switch (strtolower($action)) {
2143
            case "delete":
2144
                $sql = "DELETE FROM sub_domaines WHERE id =$sub_domain_id;";
2145
                break;
2146
            default:
2147
                $sql = "UPDATE sub_domaines SET web_action='OK' WHERE id='$sub_domain_id'; ";
2148
        }
2149
        $db->query($sql);
2150
        return true;
2151
    }
2152
2153
    /**
2154
     * @param string $dns_action
2155
     */
2156
    function set_dns_action($domain, $dns_action) {
2157
        global $db;
2158
        $db->query("UPDATE domaines SET dns_action= ? WHERE domaine= ?; ", array($dns_action, $domain));
2159
        return true;
2160
    }
2161
2162
    function set_dns_result($domain, $dns_result) {
2163
        global $db;
2164
        $db->query("UPDATE domaines SET dns_result= ? WHERE domaine= ?; ", array($dns_result, $domain));
2165
        return true;
2166
    }
2167
2168
    /* ----------------------------------------------------------------- */
2169
2170
    /** hook function called by AlternC-upnp to know which open 
2171
     * tcp or udp ports this class requires or suggests
2172
     * @return array a key => value list of port protocol name mandatory values
2173
     * @access private
2174
     */
2175
    function hook_upnp_list() {
2176
        return array(
2177
            "dns-tcp" => array("port" => 53, "protocol" => "tcp", "mandatory" => 1),
2178
            "dns-udp" => array("port" => 53, "protocol" => "udp", "mandatory" => 1),
2179
        );
2180
    }
2181
2182
    // List if there is problems in the domains.
2183
    // Problems can appear when editing domains type properties
2184
    function get_problems($domain) {
2185
        $this->lock();
2186
        $da = $this->get_domain_all($domain);
2187
        $this->unlock();
2188
2189
        $errors = array();
2190
        // Check if there is more than 1 apache conf
2191
        // by subdomain
2192
        $tmp = array();
2193
        foreach ($da['sub'] as $sub) {
2194
            if ($sub['web_action'] != 'OK') {
2195
                continue;
2196
            }
2197
            if (!$sub['only_dns']) {
2198
                if (!isset($tmp[$sub['fqdn']])) {
2199
                    $tmp[$sub['fqdn']] = 0;
2200
                }
2201
                $tmp[$sub['fqdn']] ++;
2202
                if ($tmp[$sub['fqdn']] >= 2) {
2203
                    $errors[$sub['fqdn']] = sprintf(_("Problem on %s: there is more than 1 web configuration going to be generated for this sub-domain."), $sub['fqdn']);
2204
                }
2205
            }
2206
        }
2207
2208
        // Check if we know each type of subdomain
2209
        // Example: we may not know WEBMAIL if we upgrade from a previous setup
2210
        foreach ($da['sub'] as $sub) {
2211
            if (is_null($sub['type_desc'])) {
2212
                $errors[$sub['fqdn']] = sprintf(_("Problem on %s: we do not know domain's type <b>%s</b>."), $sub['fqdn'], $sub['type']);
2213
            }
2214
        }
2215
2216
        // TODO: add a full compatibility check.
2217
2218
        return $errors;
2219
    }
2220
2221
    function default_domain_type() {
2222
        // This function is only used to allow translation of default domain types:
2223
        _("Locally hosted");
2224
        _("URL redirection");
2225
        _("IPv4 redirect");
2226
        _("Webmail access");
2227
        _("Squirrelmail Webmail access");
2228
        _("Roundcube Webmail access");
2229
        _("IPv6 redirect");
2230
        _("CNAME DNS entry");
2231
        _("TXT DNS entry");
2232
        _("MX DNS entry");
2233
        _("secondary MX DNS entry");
2234
        _("Default mail server");
2235
        _("Default backup mail server");
2236
        _("AlternC panel access");
2237
    }
2238
2239
}
2240
2241
/* Class m_domains */
2242