Beispiel #1
0
    /**
     * Imports records from a zone file and presents a confirmation
     */
    function zoneImportWizard()
    {
        global $__FM_CONFIG, $fm_name;
        if (!currentUserCan('manage_records', $_SESSION['module'])) {
            return $this->unAuth('zone');
        }
        if (!zoneAccessIsAllowed(array($_POST['domain_id']))) {
            return $this->unAuth('zone');
        }
        $raw_contents = file_get_contents($_FILES['import-file']['tmp_name']);
        /** Strip commented lines */
        $clean_contents = preg_replace('/^;.*\\n?/m', '', $raw_contents);
        /** Strip blank lines */
        $clean_contents = preg_replace('/^\\n?/m', '', $clean_contents);
        /** Strip $GENERATE lines */
        $clean_contents = preg_replace('/^\\$GENERATE.*\\n?/m', '', $clean_contents, -1, $generate_count);
        /** Strip $ORIGIN lines */
        $clean_contents = preg_replace('/^\\$ORIGIN.*\\n?/m', '', $clean_contents, -1, $origin_count);
        /** Handle unsupported message */
        if ($generate_count || $origin_count) {
            $unsupported[] = sprintf('<h4>%s:</h4>', __('Unsupported Entries'));
            $unsupported[] = '<p class="soa_import">' . sprintf(__('%s currently does not support importing $GENERATE and $ORIGIN entries which were found in your zone file.'), $fm_name) . '</p>';
            $unsupported = implode("\n", $unsupported);
        } else {
            $unsupported = null;
        }
        $domain_name = getNameFromID($_POST['domain_id'], 'fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'domains', 'domain_', 'domain_id', 'domain_name');
        $domain_map = getNameFromID($_POST['domain_id'], 'fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'domains', 'domain_', 'domain_id', 'domain_mapping');
        $count = 1;
        /** Detect SOA */
        if (!getSOACount($_POST['domain_id']) && strpos($clean_contents, ' SOA ') !== false && (in_array('SOA', $__FM_CONFIG['records']['require_zone_rights']) && currentUserCan('manage_zones', $_SESSION['module']))) {
            $raw_soa = preg_replace("/SOA(.+?)\\)/esim", "str_replace(PHP_EOL, ' ', '\\1')", $clean_contents);
            preg_match("/SOA(.+?)\\)/esim", $clean_contents, $raw_soa);
            preg_match("/TTL(.+?)\$/esim", $clean_contents, $raw_ttl);
            if (is_array($raw_ttl)) {
                $soa_array['soa_ttl'] = trim(preg_replace('/;(.+?)+/', '', $raw_ttl[1]));
            }
            if (is_array($raw_soa)) {
                $raw_soa = preg_replace('/;(.+?)+/', '', $raw_soa[1]);
                $soa = str_replace(array("\n", "\t", '(', ')', '  '), ' ', preg_replace('/\\s\\s+/', ' ', $raw_soa));
                $soa = str_replace(' ', '|', trim($soa));
                $soa_fields = explode('|', str_replace('||', '|', $soa));
                list($soa_array['soa_master_server'], $soa_array['soa_email_address'], $tmp_serial, $soa_array['soa_refresh'], $soa_array['soa_retry'], $soa_array['soa_expire'], $tmp_neg_cache) = $soa_fields;
                if (strpos($soa_array['soa_master_server'], $domain_name) !== false) {
                    $soa_array['soa_master_server'] = str_replace('.' . trimFullStop($domain_name) . '.', '', $soa_array['soa_master_server']);
                    $soa_array['soa_email_address'] = str_replace('.' . trimFullStop($domain_name) . '.', '', $soa_array['soa_email_address']);
                    $soa_array['soa_append'] = 'yes';
                } else {
                    $soa_array['soa_append'] = 'no';
                }
            }
            $soa_row = '<h4>SOA:</h4><p class="soa_import">' . trimFullStop($domain_name) . '. IN SOA ' . $soa_array['soa_master_server'];
            if ($soa_array['soa_append'] == 'yes') {
                $soa_row .= '.' . trimFullStop($domain_name) . '.';
            }
            $soa_row .= ' ' . $soa_array['soa_email_address'];
            if ($soa_array['soa_append'] == 'yes') {
                $soa_row .= '.' . trimFullStop($domain_name) . '.';
            }
            $soa_row .= ' ( &lt;autogen_serial&gt; ' . $soa_array['soa_refresh'] . ' ' . $soa_array['soa_retry'] . ' ' . $soa_array['soa_expire'] . ' ' . $soa_array['soa_ttl'] . ' )';
            $soa_row = <<<HTML
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_master_server]" value="{$soa_array['soa_master_server']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_email_address]" value="{$soa_array['soa_email_address']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_refresh]" value="{$soa_array['soa_refresh']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_retry]" value="{$soa_array['soa_retry']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_expire]" value="{$soa_array['soa_expire']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_ttl]" value="{$soa_array['soa_ttl']}" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][record_type]" value="SOA" />
\t\t\t\t\t\t<input type="hidden" name="create[{$count}][soa_append]" value="{$soa_array['soa_append']}" />
\t\t\t\t\t\t{$soa_row}
\t\t\t\t\t\t<span><label><input type="checkbox" name="create[{$count}][record_skip]" />Skip Import</label></span>
\t\t\t\t\t\t</p>
\t\t\t\t\t\t
\t\t\t\t\t\t<h4>Records:</h4>

HTML;
            $count++;
        } else {
            $soa_row = null;
        }
        $clean_contents = str_replace('.' . trimFullStop($domain_name) . '.', '', $clean_contents);
        $clean_contents = str_replace(trimFullStop($domain_name) . '.', '', $clean_contents);
        $available_record_types = array_filter(enumMYSQLSelect('fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'records', 'record_type'), 'removeRestrictedRR');
        sort($available_record_types);
        /** Loop through the lines */
        $lines = explode(PHP_EOL, $clean_contents);
        $failed = 0;
        $rows = null;
        $valid_hashes = array(';', '//', '#');
        foreach ($lines as $line) {
            $null_keys = array('record_ttl', 'record_priority', 'record_weight', 'record_port');
            foreach ($null_keys as $key) {
                $array[$key] = null;
            }
            if (!strlen(trim($line))) {
                continue;
            }
            foreach ($valid_hashes as $tmp_hash) {
                if (strpos($line, $tmp_hash)) {
                    $hash = $tmp_hash;
                    break;
                } else {
                    $hash = null;
                }
            }
            if ($hash == '//') {
                $hash = '\\/\\/';
            }
            /** Break up the line for comments */
            if ($hash) {
                $comment_parts = preg_split("/{$hash}+/", $line);
                $array['record_comment'] = trim($comment_parts[1]) ? trim($comment_parts[1]) : 'none';
            } else {
                $comment_parts[0] = $line;
                $array['record_comment'] = 'none';
            }
            /** Break up the line for parts */
            $parts = preg_split('/\\s+/', trim($comment_parts[0]));
            if ($domain_map == 'forward') {
                if (in_array('MX', $parts)) {
                    switch (array_search('MX', $parts)) {
                        case 3:
                            list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_value']) = $parts;
                            break;
                        case 2:
                            if (is_numeric($parts[0])) {
                                $array['record_name'] = isset($current_name) ? $current_name : '@';
                                list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_value']) = $parts;
                            } else {
                                list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_value']) = $parts;
                            }
                            break;
                        case 1:
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_class'], $array['record_type'], $array['record_priority'], $array['record_value']) = $parts;
                    }
                } elseif (in_array('SRV', $parts)) {
                    switch (array_search('SRV', $parts)) {
                        case 3:
                            list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_weight'], $array['record_port'], $array['record_value']) = $parts;
                            break;
                        case 2:
                            if (is_numeric($parts[0])) {
                                $array['record_name'] = isset($current_name) ? $current_name : '@';
                                list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_weight'], $array['record_port'], $array['record_value']) = $parts;
                            } else {
                                list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_priority'], $array['record_weight'], $array['record_port'], $array['record_value']) = $parts;
                            }
                            break;
                        case 1:
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_class'], $array['record_type'], $array['record_priority'], $array['record_weight'], $array['record_port'], $array['record_value']) = $parts;
                    }
                } elseif (in_array('TXT', $parts)) {
                    $key = array_search('TXT', $parts);
                    $txt_record = null;
                    for ($i = $key + 1; $i < count($parts); $i++) {
                        $txt_record .= $parts[$i] . ' ';
                    }
                    $parts[$key + 1] = rtrim($txt_record);
                    switch ($key) {
                        case 3:
                            list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            break;
                        case 2:
                            if (is_numeric($parts[0])) {
                                $array['record_name'] = isset($current_name) ? $current_name : '@';
                                list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            } else {
                                list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            }
                            break;
                        case 1:
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                    }
                    $array['record_value'] = str_replace('"', '', $array['record_value']);
                } elseif (in_array('A', $parts) || in_array('CNAME', $parts) || in_array('AAAA', $parts)) {
                    if (in_array('AAAA', $parts)) {
                        $key = array_search('AAAA', $parts);
                    } else {
                        $key = in_array('A', $parts) ? array_search('A', $parts) : array_search('CNAME', $parts);
                    }
                    switch ($key) {
                        case 3:
                            list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            break;
                        case 2:
                            if (is_numeric($parts[0])) {
                                $array['record_name'] = isset($current_name) ? $current_name : '@';
                                list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            } else {
                                list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            }
                            break;
                        case 1:
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                    }
                }
            } else {
                if (in_array('PTR', $parts)) {
                    switch (array_search('PTR', $parts)) {
                        case 3:
                            list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            break;
                        case 2:
                            if ($parts[0] > 255) {
                                $array['record_name'] = isset($current_name) ? $current_name : '@';
                                list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            } else {
                                list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                            }
                            break;
                        case 1:
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                    }
                }
            }
            if (in_array('NS', $parts) && in_array('NS', $__FM_CONFIG['records']['require_zone_rights']) && currentUserCan('manage_zones', $_SESSION['module'])) {
                switch (array_search('NS', $parts)) {
                    case 3:
                        list($array['record_name'], $array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                        break;
                    case 2:
                        if (is_numeric($parts[0])) {
                            $array['record_name'] = isset($current_name) ? $current_name : '@';
                            list($array['record_ttl'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                        } else {
                            list($array['record_name'], $array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                        }
                        break;
                    case 1:
                        $array['record_name'] = isset($current_name) ? $current_name : '@';
                        list($array['record_class'], $array['record_type'], $array['record_value']) = $parts;
                }
            }
            if (empty($array['record_name']) && !empty($array['record_comment'])) {
                continue;
            }
            $array['record_append'] = substr($array['record_value'], -1) == '.' ? 'no' : 'yes';
            /** Set current_name to check for blanks on next run */
            $current_name = $array['record_name'];
            /** Automatically skip duplicates */
            $checked = $this->checkDuplicates($array, $_POST['domain_id']);
            $rows .= <<<ROW
\t\t\t\t\t<tr class="import_swap">
\t\t\t\t\t\t<td><span id="name{$count}" onclick="exchange(this);">{$array['record_name']}</span><input onblur="exchange(this);" type="text" id="name{$count}b" name="create[{$count}][record_name]" value="{$array['record_name']}" /></td>
\t\t\t\t\t\t<td><span id="ttl{$count}" onclick="exchange(this);">{$array['record_ttl']}</span><input onblur="exchange(this);" type="number" id="ttl{$count}b" name="create[{$count}][record_ttl]" value="{$array['record_ttl']}" /></td>
\t\t\t\t\t\t<td><input type="hidden" name="create[{$count}][record_class]" value="{$array['record_class']}" />{$array['record_class']}</td>
\t\t\t\t\t\t<td><input type="hidden" name="create[{$count}][record_type]" value="{$array['record_type']}" />{$array['record_type']}</td>
\t\t\t\t\t\t<td><span id="priority{$count}" onclick="exchange(this);">{$array['record_priority']}</span><input onblur="exchange(this);" type="number" id="priority{$count}b" name="create[{$count}][record_priority]" value="{$array['record_priority']}" /></td>
\t\t\t\t\t\t<td><span id="value{$count}" onclick="exchange(this);">{$array['record_value']}</span><input onblur="exchange(this);" type="text" id="value{$count}b" name="create[{$count}][record_value]" value="{$array['record_value']}" /></td>
\t\t\t\t\t\t<td><span id="weight{$count}" onclick="exchange(this);">{$array['record_weight']}</span><input onblur="exchange(this);" type="number" id="weight{$count}b" name="create[{$count}][record_weight]" value="{$array['record_weight']}" /></td>
\t\t\t\t\t\t<td><span id="port{$count}" onclick="exchange(this);">{$array['record_port']}</span><input onblur="exchange(this);" type="number" id="port{$count}b" name="create[{$count}][record_port]" value="{$array['record_port']}" /></td>
\t\t\t\t\t\t<td><span id="comment{$count}" onclick="exchange(this);">{$array['record_comment']}</span><input onblur="exchange(this);" type="text" id="comment{$count}b" name="create[{$count}][record_comment]" value="{$array['record_comment']}" /></td>
\t\t\t\t\t\t<td style="text-align: center;" nowrap><input type="hidden" name="create[{$count}][record_append]" value="{$array['record_append']}" />{$array['record_append']}</td>
\t\t\t\t\t\t<td style="text-align: center;"><label><input type="checkbox" name="create[{$count}][record_skip]" {$checked} />Skip Import</label></td>
\t\t\t\t\t</tr>

ROW;
            $count++;
        }
        $table_info = array('class' => 'display_results', 'id' => 'table_edits', 'name' => 'views');
        $title_array = array(__('Record'), __('TTL'), __('Class'), __('Type'), __('Priority'), __('Value'), __('Weight'), __('Port'), __('Comment'));
        $title_array[] = array('title' => __('Append Domain'), 'style' => 'text-align: center;', 'nowrap' => null);
        $title_array[] = array('title' => __('Actions'), 'class' => 'header-actions');
        $table_header = displayTableHeader($table_info, $title_array);
        $popup_header = buildPopup('header', __('Import Verification'));
        $popup_footer = buildPopup('footer', __('Import'), array('import' => 'submit', 'cancel_button' => 'cancel'));
        $body = <<<BODY
\t\t<form method="post" action="zone-records-write.php">
\t\t{$popup_header}
\t\t\t<p>Domain: {$domain_name}</p>
\t\t\t<input type="hidden" name="domain_id" value="{$_POST['domain_id']}">
\t\t\t<input type="hidden" name="map" value="{$domain_map}">
\t\t\t<input type="hidden" name="import_records" value="true">
\t\t\t<input type="hidden" name="import_file" value="{$_FILES['import-file']['name']}">
\t\t\t{$unsupported}
\t\t\t{$soa_row}
\t\t\t{$table_header}
\t\t\t\t{$rows}
\t\t\t\t</tbody>
\t\t\t</table>
\t\t\t<br />
\t\t{$popup_footer}
\t\t</form>
BODY;
        return $body;
    }
 /**
  * Builds the records for $domain->domain_id
  *
  * @since 1.0
  * @package fmDNS
  */
 function buildRecords($domain, $server_serial_no)
 {
     global $fmdb, $__FM_CONFIG;
     $zone_file = $skipped_records = null;
     $domain_name_trim = trimFullStop($domain->domain_name);
     list($server_version) = explode('-', getNameFromID($server_serial_no, 'fm_' . $__FM_CONFIG[$_SESSION['module']]['prefix'] . 'servers', 'server_', 'server_serial_no', 'server_version'));
     /** Is this a cloned zone */
     if (isset($domain->parent_domain_id)) {
         $full_zone_clone = getOption('clones_use_dnames', $_SESSION['user']['account_id'], $_SESSION['module']) == 'yes' ? true : false;
         if ($domain->domain_clone_dname) {
             $full_zone_clone = $domain->domain_clone_dname == 'yes' ? true : false;
         }
         /** Are there any additional records? */
         basicGet('fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'records', $domain->parent_domain_id, 'record_', 'domain_id', "AND `record_status`='active'");
         if ($fmdb->num_rows) {
             $full_zone_clone = false;
         }
         /** Are there any skipped records? */
         global $fm_dns_records;
         if (!class_exists('fm_dns_records')) {
             include ABSPATH . 'fm-modules/fmDNS/classes/class_records.php';
         }
         if ($skipped_records = $fm_dns_records->getSkippedRecordIDs($domain->parent_domain_id)) {
             $full_zone_clone = false;
         }
         $valid_domain_ids = $full_zone_clone == false ? "IN (" . join(',', getZoneParentID($domain->parent_domain_id)) . ')' : "='{$domain->domain_id}' AND record_type='NS'";
     } else {
         $valid_domain_ids = "='{$domain->domain_id}'";
     }
     $order_sql = $domain->domain_mapping == 'reverse' ? array('record_type', 'INET_ATON(record_name)', 'record_value') : array('record_type', 'record_name', 'INET_ATON(record_value)');
     $record_sql = "AND domain_id {$valid_domain_ids} AND record_status='active'";
     $record_sql .= $skipped_records ? ' AND record_id NOT IN (' . implode(',', $skipped_records) . ')' : null;
     $result = basicGetList('fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'records', $order_sql, 'record_', $record_sql);
     if ($fmdb->num_rows) {
         $count = $fmdb->num_rows;
         $record_result = $fmdb->last_result;
         $separator = '   ';
         /** Add full zone clone dname record */
         if (isset($domain->parent_domain_id) && $full_zone_clone == true) {
             $record_result[$count]->record_name = '@';
             $record_result[$count]->record_value = trimFullStop(getNameFromID($domain->domain_id, 'fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'domains', 'domain_', 'domain_id', 'domain_name')) . '.';
             $record_result[$count]->record_ttl = null;
             $record_result[$count]->record_class = 'IN';
             $record_result[$count]->record_type = 'DNAME';
             $record_result[$count]->record_append = 'no';
             $record_result[$count]->record_comment = null;
             $count++;
         }
         for ($i = 0; $i < $count; $i++) {
             $domain_name = $this->getDomainName($domain->domain_mapping, $domain_name_trim);
             $record_comment = $record_result[$i]->record_comment ? ' ; ' . $record_result[$i]->record_comment : null;
             $record_name = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_name . '.' . $domain_name_trim . '.' : $record_result[$i]->record_name;
             if ($record_result[$i]->record_name[0] == '@') {
                 $record_name = $domain_name;
             }
             $record_start = str_pad($record_name, 25) . $separator . $record_result[$i]->record_ttl . $separator . $record_result[$i]->record_class . $separator . $record_result[$i]->record_type;
             switch ($record_result[$i]->record_type) {
                 case 'A':
                 case 'AAAA':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Host addresses';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_value . $record_comment . "\n";
                     break;
                 case 'CERT':
                     $record_array[$record_result[$i]->record_type]['Version'] = '9.7.0';
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Certificates';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_cert_type . ' ' . $record_result[$i]->record_key_tag . ' ' . $record_result[$i]->record_algorithm . "\t(\n\t\t\t" . str_replace("\n", "\n\t\t\t", $record_result[$i]->record_value) . ' )' . $record_comment . "\n";
                     break;
                 case 'CNAME':
                 case 'DNAME':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Aliases';
                     $record_value = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_value . '.' . $domain_name_trim . '.' : $record_result[$i]->record_value;
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_value . $record_comment . "\n";
                     break;
                 case 'DHCID':
                     $record_array[$record_result[$i]->record_type]['Version'] = '9.5.0';
                     $record_array[$record_result[$i]->record_type]['Description'] = 'DHCP ID records';
                     //						$record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_flags . ' 3 ' . $record_result[$i]->record_algorithm . "\t(\n\t\t\t" . str_replace("\n", "\n\t\t\t", $record_result[$i]->record_value) . ' )' . $record_comment . "\n";
                     break;
                 case 'DLV':
                 case 'DS':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'DNSSEC Lookaside Validation';
                     //						$record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_cert_type . ' ' . $record_result[$i]->record_key_tag . ' ' . $record_result[$i]->record_algorithm . "\t(\n\t\t\t" . str_replace("\n", "\n\t\t\t", $record_result[$i]->record_value) . ' )' . $record_comment . "\n";
                     break;
                 case 'DNSKEY':
                 case 'KEY':
                     $record_array[$record_result[$i]->record_type]['Version'] = '9.5.0';
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Key records';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_flags . ' 3 ' . $record_result[$i]->record_algorithm . "\t(\n\t\t\t" . str_replace("\n", "\n\t\t\t", $record_result[$i]->record_value) . ' )' . $record_comment . "\n";
                     break;
                 case 'HINFO':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Hardware information records';
                     $hardware = strpos($record_result[$i]->record_value, ' ') === false ? $record_result[$i]->record_value : '"' . $record_result[$i]->record_value . '"';
                     $os = strpos($record_result[$i]->record_os, ' ') === false ? $record_result[$i]->record_os : '"' . $record_result[$i]->record_os . '"';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $hardware . ' ' . $os . $record_comment . "\n";
                     break;
                 case 'KX':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Key Exchange records';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_priority . $separator . $record_result[$i]->record_value . $record_comment . "\n";
                     break;
                 case 'MX':
                     $record_array[2 . $record_result[$i]->record_type]['Description'] = 'Mail Exchange records';
                     $record_array[2 . $record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_priority . $separator . $record_result[$i]->record_value . $record_comment . "\n";
                     break;
                 case 'NAPTR':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Name Authority Pointer records';
                     $record_value = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_value . '.' . $domain_name_trim . '.' : $record_result[$i]->record_value;
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_weight . $separator . $record_result[$i]->record_priority . $separator . '"' . $record_result[$i]->record_flags . '"' . $separator . '"' . $record_result[$i]->record_params . '"' . $separator . '"' . $record_result[$i]->record_regex . '"' . $separator . $record_value . $record_comment . "\n";
                     break;
                 case 'NS':
                     $record_array[1 . $record_result[$i]->record_type]['Description'] = 'Name servers';
                     $record_value = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_value . '.' . $domain_name_trim . '.' : $record_result[$i]->record_value;
                     $record_array[1 . $record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_value . $record_comment . "\n";
                     break;
                 case 'PTR':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Addresses point to hosts';
                     $record_name = $record_result[$i]->record_append == 'yes' && $domain->domain_mapping == 'reverse' ? $record_result[$i]->record_name . '.' . $domain_name : $record_result[$i]->record_name;
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_value . $record_comment . "\n";
                     break;
                 case 'RP':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Responsible Persons';
                     $record_value = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_value . '.' . $domain_name_trim . '.' : $record_result[$i]->record_value;
                     $record_text = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_text . '.' . $domain_name_trim . '.' : $record_result[$i]->record_text;
                     if (!strlen($record_result[$i]->record_text)) {
                         $record_text = '.';
                     }
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_value . $separator . $record_text . $record_comment . "\n";
                     break;
                 case 'SSHFP':
                     $record_array[$record_result[$i]->record_type]['Version'] = '9.3.0';
                     $record_array[$record_result[$i]->record_type]['Description'] = 'SSH Key Fingerprint records';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_algorithm . ' 1 ' . $record_result[$i]->record_value . $record_comment . "\n";
                     break;
                 case 'SRV':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'Service records';
                     $record_value = $record_result[$i]->record_append == 'yes' ? $record_result[$i]->record_value . '.' . $domain_name_trim . '.' : $record_result[$i]->record_value;
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . $separator . $record_result[$i]->record_priority . $separator . $record_result[$i]->record_weight . $separator . $record_result[$i]->record_port . $separator . $record_value . $record_comment . "\n";
                     break;
                 case 'TXT':
                     $record_array[$record_result[$i]->record_type]['Description'] = 'TXT records';
                     $record_array[$record_result[$i]->record_type]['Data'][] = $record_start . "\t(\"" . join("\";\n\t\t\"", $this->characterSplit($record_result[$i]->record_value)) . "\")" . $record_comment . "\n";
                     break;
             }
         }
         ksort($record_array);
         /** Zone file output */
         foreach ($record_array as $rr => $rr_array) {
             /** Check if rr is supported by server_version */
             if (array_key_exists('Version', $rr_array) && version_compare($server_version, $rr_array['Version'], '<')) {
                 $zone_file .= ";\n; BIND " . $rr_array['Version'] . ' or greater is required for ' . $rr . ' types.' . "\n;\n\n";
                 continue;
             }
             $zone_file .= '; ' . $rr_array['Description'] . "\n";
             $zone_file .= implode('', $rr_array['Data']);
             $zone_file .= "\n";
         }
     }
     return $zone_file;
 }
function autoCreatePTR($domain_id, $record_type, $data)
{
    if ($record_type == 'A' && isset($data['PTR']) && zoneAccessIsAllowed(array($data['PTR']))) {
        global $__FM_CONFIG;
        $domain = '.' . trimFullStop(getNameFromID($domain_id, 'fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'domains', 'domain_', 'domain_id', 'domain_name')) . '.';
        if ($data['record_name'][0] == '@') {
            $data['record_name'] = null;
            $domain = substr($domain, 1);
        }
        /** Get reverse zone */
        if (!strrpos($data['record_value'], ':')) {
            $rev_domain = trimFullStop(getNameFromID($data['PTR'], 'fm_' . $__FM_CONFIG['fmDNS']['prefix'] . 'domains', 'domain_', 'domain_id', 'domain_name'));
            $domain_pieces = array_reverse(explode('.', $rev_domain));
            $domain_parts = count($domain_pieces);
            $subnet_ips = null;
            for ($i = 2; $i < $domain_parts; $i++) {
                $subnet_ips .= $domain_pieces[$i] . '.';
            }
            $record_octets = array_reverse(explode('.', str_replace($subnet_ips, '', $data['record_value'])));
            $temp_record_value = null;
            for ($j = 0; $j < count($record_octets); $j++) {
                $temp_record_value .= $record_octets[$j] . '.';
            }
            $data['record_value'] = rtrim($temp_record_value, '.');
        } else {
            /** IPv6 not yet supported */
            break;
        }
        $array = array('record_name' => $data['record_value'], 'record_value' => $data['record_name'] . $domain, 'record_comment' => $data['record_comment'], 'record_status' => $data['record_status']);
        global $fm_dns_records;
        $fm_dns_records->add($data['PTR'], 'PTR', $array, 'replace');
    }
}