function execute() { /* * Validate a POST (page navigation move will prompt this) */ if (isset($_POST['record_custom_page'])) { // fetch data from POST and validate - we then return values $data = stripslashes_deep($this->obj_domain->validate_custom_records()); // validate the record_custom_page for returning the user to their page, default to page 1 if any errors in validating... $data['record_custom_page'] = @security_form_input_predefined("int", "record_custom_page", 1, ""); /* echo '<tr><td colspan="100%">post-validation POST data<pre>'; echo '<pre>'; print_R($data); echo '</pre>'; echo '</td></tr>'; die("debug"); */ if (error_check()) { log_write("debug", "records-ajax", "POST records provided but error encountered, failing"); $_SESSION["error"]["form"]["domain_records"] = "failed"; $this->page = $data['record_custom_page']; } else { // no errors... set the records to the session $_SESSION['form']['domain_records'][$this->obj_domain->id][$data['record_custom_page']] = $data['records']; } } /* Load domain data & records */ $this->num_records_custom_total = $this->obj_domain->data_record_custom_count(); $this->obj_domain->load_data(); // if the data is present in the session then it has either changed and is awaiting submission // or the user has visited that page before during this edit session if (isset($_SESSION['form']['domain_records'][$this->obj_domain->id][$this->page]) && count($_SESSION['form']['domain_records'][$this->obj_domain->id][$this->page])) { log_debug("execute", 'Loading records from session as previous load or edit detected'); $this->obj_domain->data['records'] = $_SESSION['form']['domain_records'][$this->obj_domain->id][$this->page]; /* echo '<tr><td colspan="100%">from sesssion<pre>'; print_R($this->obj_domain->data['records']); echo '</td></tr>'; */ } else { log_debug("execute", 'Loading records from db for page: ' . $this->page); $this->obj_domain->load_data_record_custom($this->offset, $GLOBALS["config"]['PAGINATION_DOMAIN_RECORDS']); /* echo '<tr><td colspan="100%">from db<pre>'; print_R($this->obj_domain->data['records']); echo '</td></tr>'; */ } // work out the IP for reverse domains if (strpos($this->obj_domain->data["domain_name"], "in-addr.arpa")) { // IPv4 $ip = explode(".", $this->obj_domain->data["domain_name"]); $this->obj_domain->data["domain_ip_prefix"] = $ip[2] . "." . $ip[1] . "." . $ip[0]; } elseif (strpos($this->obj_domain->data["domain_name"], "ip6.arpa")) { // IPv6 $ip_reverse = substr($this->obj_domain->data["domain_name"], 0, strlen($this->obj_domain->data["domain_name"]) - 9); $ip_array = array(); $i = 0; foreach (array_reverse(explode(".", $ip_reverse)) as $ip) { $i++; $ip_array[] = $ip; if ($i == 4) { $i = 0; $ip_array[] = ":"; } } $this->obj_domain->data["domain_ip_prefix"] = implode("", $ip_array); } /* Define form structure */ $this->obj_form = new form_input(); $this->obj_form->formname = "domain_records"; $this->obj_form->language = $_SESSION["user"]["lang"]; $this->obj_form->action = "domains/records-process.php"; $this->obj_form->method = "post"; /* General Domain Info */ $structure = NULL; $structure["fieldname"] = "domain_name"; $structure["type"] = "message"; $structure["options"]["css_row_class"] = "table_highlight"; $structure["defaultvalue"] = "<p><b>Domain " . $this->obj_domain->data["domain_name"] . " selected for adjustment</b></p>"; $this->obj_form->add_input($structure); /* Define stucture for all other record types This includes A, AAAA, PTR and other record types. */ // fetch all the known record types from the database $dns_record_types = sql_get_singlecol("SELECT type as value FROM `dns_record_types` WHERE user_selectable='1'"); // unless there has been error data returned, fetch all the records // and work out the number of rows if (!isset($_SESSION["error"]["form"][$this->obj_form->formname])) { $this->num_records_custom = 1; foreach ($this->obj_domain->data["records"] as $record) { if (in_array($record["type"], $dns_record_types)) { $this->num_records_custom++; } } } else { $this->num_records_custom = @security_script_input('/^[0-9]*$/', $_SESSION["error"]["num_records_custom"]); } // ensure there are at least two rows, if more are needed when entering information, // then the javascript functions will provide. if ($this->num_records_custom < 2) { $this->num_records_custom = 2; } // custom domain records for ($i = 0; $i < $this->num_records_custom; $i++) { // values $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_id"; $structure["type"] = "hidden"; $this->obj_form->add_input($structure); if (strpos($this->obj_domain->data["domain_name"], "arpa")) { $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_type"; $structure["type"] = "text"; $structure["defaultvalue"] = "PTR"; $this->obj_form->add_input($structure); } else { $structure = form_helper_prepare_dropdownfromdb("record_custom_" . $i . "_type", "SELECT type as label, type as id FROM `dns_record_types` WHERE user_selectable='1' AND is_standard='1'"); $structure["defaultvalue"] = "A"; $structure["options"]["width"] = "100"; $this->obj_form->add_input($structure); } $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_name"; $structure["type"] = "input"; if (strpos($this->obj_domain->data["domain_name"], "in-addr.arpa")) { $structure["options"]["width"] = "50"; $structure["options"]["max_length"] = "3"; $structure["options"]["prelabel"] = $this->obj_domain->data["domain_ip_prefix"] . ". "; $structure["options"]["help"] = "?"; } elseif (strpos($this->obj_domain->data["domain_name"], "ip6.arpa")) { $structure["options"]["width"] = "300"; $structure["options"]["prelabel"] = " "; $structure["options"]["help"] = $this->obj_domain->data["domain_ip_prefix"] . "...."; $structure["options"]["autofill"] = $this->obj_domain->data["domain_ip_prefix"]; } else { $structure["options"]["width"] = "300"; $structure["options"]["help"] = "Record name, eg www"; } $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_content"; $structure["type"] = "input"; $structure["options"]["width"] = "300"; if (strpos($this->obj_domain->data["domain_name"], "arpa")) { // both IPv4 and IPv6 $structure["options"]["help"] = "Reverse record name, eg www.example.com"; } else { $structure["options"]["help"] = "Target IP, eg 192.168.0.1"; } $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_ttl"; $structure["type"] = "input"; $structure["options"]["width"] = "80"; $structure["defaultvalue"] = $this->obj_domain->data["soa_default_ttl"]; $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_delete_undo"; $structure["type"] = "hidden"; $structure["defaultvalue"] = "false"; $this->obj_form->add_input($structure); if (!strpos($this->obj_domain->data["domain_name"], "arpa")) { $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_reverse_ptr"; $structure["type"] = "checkbox"; $structure["options"]["label"] = ""; $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "record_custom_" . $i . "_reverse_ptr_orig"; $structure["type"] = "hidden"; $this->obj_form->add_input($structure); } } // load in what data we have //disable invalid fields $i = 0; foreach ($this->obj_domain->data["records"] as $record) { if (in_array($record["type"], $dns_record_types)) { // special ID rules if ($record["id"]) { $this->obj_form->structure["record_custom_" . $i . "_id"]["defaultvalue"] = $record["id"]; } else { $this->obj_form->structure["record_custom_" . $i . "_id"]["defaultvalue"] = $record["id_record"]; } // fetch data $this->obj_form->structure["record_custom_" . $i . "_type"]["defaultvalue"] = $record["type"]; $this->obj_form->structure["record_custom_" . $i . "_prio"]["defaultvalue"] = $record["prio"]; $this->obj_form->structure["record_custom_" . $i . "_name"]["defaultvalue"] = $record["name"]; $this->obj_form->structure["record_custom_" . $i . "_content"]["defaultvalue"] = $record["content"]; $this->obj_form->structure["record_custom_" . $i . "_ttl"]["defaultvalue"] = $record["ttl"]; if ($record["type"] == "CNAME") { // disable inappropate values for CNAME fields $this->obj_form->structure["record_custom_" . $i . "_reverse_ptr"]["options"]["disabled"] = "yes"; $this->obj_form->structure["record_custom_" . $i . "_reverse_ptr_orig"]["options"]["disabled"] = "yes"; } elseif ($record["type"] == "PTR") { if (strpos($this->obj_domain->data["domain_name"], "ip6.arpa")) { // IPv6 PTR records are in ARPA format, we should convert it to something human readable $this->obj_form->structure["record_custom_" . $i . "_name"]["defaultvalue"] = ipv6_convert_fromarpa($record["name"]); } } elseif ($record["type"] != "PTR") { if ($record["type"] == "A" || $record["type"] == "AAAA") { // check if this record has a reverse PTR value $obj_ptr = new domain_records(); $obj_ptr->find_reverse_domain($record["content"]); if ($obj_ptr->id_record) { $obj_ptr->load_data_record(); if ($record["name"] == "@" || $record["name"] == "*" || preg_match("/^\\*\\.[A-Za-z0-9:._-]+\$/", $record["name"])) { $record["name"] = $this->obj_domain->data["domain_name"]; } if ($obj_ptr->data_record["content"] == $record["name"] || $obj_ptr->data_record["content"] == $record["name"] . "." . $this->obj_domain->data["domain_name"]) { $this->obj_form->structure["record_custom_" . $i . "_reverse_ptr"]["defaultvalue"] = "on"; $this->obj_form->structure["record_custom_" . $i . "_reverse_ptr_orig"]["defaultvalue"] = "on"; } } unset($obj_ptr); } else { // reverse PTR not valid for this record type $this->obj_form->structure["record_custom_" . $i . "_reverse_ptr"]["options"]["disabled"] = "yes"; } } $i++; } } // hidden $structure = NULL; $structure["fieldname"] = "id_domain"; $structure["type"] = "hidden"; $structure["defaultvalue"] = $this->obj_domain->id; $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "record_custom_page"; $structure["type"] = "hidden"; $structure["defaultvalue"] = "{$this->page}"; $this->obj_form->add_input($structure); $structure = NULL; $structure["fieldname"] = "num_records_custom"; $structure["type"] = "hidden"; $structure["defaultvalue"] = "{$this->num_records_custom}"; $this->obj_form->add_input($structure); // a record that can be set to determine the form status for final submit $structure = NULL; $structure["fieldname"] = "record_custom_status"; $structure["type"] = "hidden"; // fetch data in event of an error if (error_check()) { $this->obj_form->load_data_error(); $structure["defaultvalue"] = "0"; } else { $structure["defaultvalue"] = "1"; } $this->obj_form->add_input($structure); }
function validate_custom_records($data_orig = array()) { log_debug("domain", "Executing validate_custom_records(array_data)"); if (!isset($this->data)) { // we need the domain details if we don't already have them $this->load_data(); } $data = array(); $data_tmp = array(); if (!empty($data_orig)) { /* Supplied Array Data - this data has some amount of pre-processing done, having already run through the javascript validation. */ log_debug("domain", "Using supplied array data in \$data_orig"); /* Fetch Data */ $data["custom"]["num_records"] = count(array_keys($data_orig)); for ($i = 0; $i < $data["custom"]["num_records"]; $i++) { $data_tmp[$i]["id"] = @security_script_input_predefined("int", $data_orig[$i]["id"], 1); $data_tmp[$i]["type"] = @security_script_input_predefined("any", $data_orig[$i]["type"], 1); $data_tmp[$i]["ttl"] = @security_script_input_predefined("int", $data_orig[$i]["ttl"], 1); $data_tmp[$i]["name"] = @security_script_input_predefined("any", $data_orig[$i]["name"], 1); $data_tmp[$i]["prio"] = @security_script_input_predefined("int", $data_orig[$i]["prio"], 0); $data_tmp[$i]["content"] = @security_script_input_predefined("any", $data_orig[$i]["content"], 1); $data_tmp[$i]["reverse_ptr"] = @security_script_input_predefined("checkbox", $data_orig[$i]["reverse_ptr"], 1); $data_tmp[$i]["reverse_ptr_orig"] = @security_script_input_predefined("checkbox", $data_orig[$i]["reverse_ptr_orig"], 1); $data_tmp[$i]["delete_undo"] = @security_script_input_predefined("any", $data_orig[$i]["delete_undo"], 1); if (empty($data_tmp[$i]["mode"]) || $data_tmp[$i]["mode"] != "delete" && $data_tmp[$i]["mode"] != "update") { // mode undetermined, run check if ($data_tmp[$i]["id"] && $data_tmp[$i]["delete_undo"] == "true") { $data_tmp[$i]["mode"] = "delete"; } else { if (!empty($data_tmp[$i]["content"]) && $data_tmp[$i]["delete_undo"] == "false") { $data_tmp[$i]["mode"] = "update"; } } } } } elseif (isset($_POST['record_custom_page'])) { /* Fetch data from POST - easiest way, since we can take advantage of smart error handling functions built in. */ // fetch number of records $data["custom"]["num_records"] = @security_form_input_predefined("int", "num_records_custom", 0, ""); for ($i = 0; $i < $data["custom"]["num_records"]; $i++) { /* Fetch Data */ $data_tmp[$i]["id"] = @security_form_input_predefined("int", "record_custom_" . $i . "_id", 0, ""); $data_tmp[$i]["type"] = @security_form_input_predefined("any", "record_custom_" . $i . "_type", 0, ""); $data_tmp[$i]["ttl"] = @security_form_input_predefined("int", "record_custom_" . $i . "_ttl", 0, ""); $data_tmp[$i]["name"] = @security_form_input_predefined("any", "record_custom_" . $i . "_name", 0, ""); $data_tmp[$i]["content"] = @security_form_input_predefined("any", "record_custom_" . $i . "_content", 0, ""); $data_tmp[$i]["reverse_ptr"] = @security_form_input_predefined("checkbox", "record_custom_" . $i . "_reverse_ptr", 0, ""); $data_tmp[$i]["reverse_ptr_orig"] = @security_form_input_predefined("checkbox", "record_custom_" . $i . "_reverse_ptr_orig", 0, ""); $data_tmp[$i]["delete_undo"] = @security_form_input_predefined("any", "record_custom_" . $i . "_delete_undo", 0, ""); /* Process Raw Data */ if ($data_tmp[$i]["id"] && $data_tmp[$i]["delete_undo"] == "true") { $data_tmp[$i]["mode"] = "delete"; } else { if (!empty($data_tmp[$i]["content"]) && $data_tmp[$i]["delete_undo"] == "false") { $data_tmp[$i]["mode"] = "update"; } } } } /* Process Validated Inputs */ if (!empty($data_tmp)) { log_write("debug", "domains", "Record values obtained, running detailed check"); for ($i = 0; $i < $data["custom"]["num_records"]; $i++) { /* Error Handling */ // verify name syntax if ($data_tmp[$i]["name"] == "*" || preg_match("/^\\*\\.[A-Za-z0-9\\p{L}:._-]+\$/", $data_tmp[$i]["name"])) { // wildcard records are annoying - wildcards must be standalone, and can't be part of a sring // OK -> * // OK -> *.example.com // BAD -> abc*.example.com // BAD -> std*abc.example.com // nothing todo } elseif ($data_tmp[$i]["name"] != "@" && !preg_match("/^[A-Za-z0-9\\p{L}:._-]*\$/", $data_tmp[$i]["name"])) { // all other record types log_write("error", "process", "Sorry, the value you have entered for record " . $data_tmp[$i]["name"] . " contains invalid charactors"); error_flag_field("record_custom_" . $i . ""); } // validate content and name formatting per domain type if ($data_tmp[$i]["name"] != "") { switch ($data_tmp[$i]["type"]) { case "A": // validate IPv4 if (!preg_match("/^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:[.](?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}\$/", $data_tmp[$i]["content"])) { // invalid IP address log_write("error", "process", "A record for " . $data_tmp[$i]["name"] . " did not validate as an IPv4 address"); error_flag_field("record_custom_" . $i . ""); } break; case "AAAA": // validate IPv6 if (filter_var($data_tmp[$i]["content"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) == FALSE) { // invalid IP address log_write("error", "process", "AAAA record for " . $data_tmp[$i]["name"] . " did not validate as an IPv6 address"); error_flag_field("record_custom_" . $i . ""); } break; case "CNAME": // validate CNAME if ($data_tmp[$i]["content"] != "@" && !preg_match("/^[A-Za-z0-9\\p{L}._-]*\$/", $data_tmp[$i]["content"])) { // invalid CNAME log_write("error", "process", "CNAME record for " . $data_tmp[$i]["name"] . " contains invalid characters."); error_flag_field("record_custom_" . $i . ""); } // make sure it's not an IP if (filter_var($data_tmp[$i]["content"], FILTER_VALIDATE_IP) == $data_tmp[$i]["content"]) { // CNAME is pointing at an IP log_write("error", "process", "CNAME record for " . $data_tmp[$i]["name"] . " is incorrectly referencing an IP address."); error_flag_field("record_custom_" . $i . ""); } break; case "SRV": // validate SRV name (_service._proto.name OR _service._proto)) if (!preg_match("/^_[A-Za-z0-9\\p{L}.-]*\\._[A-Za-z\\p{L}]*\\.[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["name"]) && !preg_match("/^_[A-Za-z0-9\\p{L}.-]*\\._[A-Za-z\\p{L}]*\$/", $data_tmp[$i]["name"])) { log_write("error", "process", "SRV record for " . $data_tmp[$i]["name"] . " is not correctly formatted - name must be: _service._proto.name"); error_flag_field("record_custom_" . $i . ""); } // validate SRV content (priority, weight, port, target/host) if (!preg_match("/^[0-9]*\\s[0-9]*\\s[0-9]*\\s[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) { log_write("error", "process", "SRV record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must be: priority weight port target/hostname"); error_flag_field("record_custom_" . $i . ""); } break; case "SPF": case "TXT": // TXT string could be almost anything, just make sure it's quoted. $data_tmp[$i]["content"] = str_replace("'", "", $data_tmp[$i]["content"]); $data_tmp[$i]["content"] = str_replace('"', "", $data_tmp[$i]["content"]); $data_tmp[$i]["content"] = '"' . $data_tmp[$i]["content"] . '"'; break; case "PTR": if (strpos($this->data["domain_name"], "in-addr.arpa")) { // IPv4 PTR Record // We only pass through the 4th octet to the end user. if (!preg_match("/^[0-9]*\$/", $data_tmp[$i]["name"])) { log_write("error", "process", "PTR reverse record for " . $data_tmp[$i]["content"] . " should be a single octet."); error_flag_field("record_custom_" . $i . ""); } if (!preg_match("/^[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) { log_write("error", "process", "PTR reverse record for " . $data_tmp[$i]["name"] . " is not correctly formatted."); error_flag_field("record_custom_" . $i . ""); } } elseif (strpos($this->data["domain_name"], "ip6.arpa")) { // IPv6 PTR Record // If the record is already in reverse ARPA format, we should convert it first if (strpos($data_tmp[$i]["name"], "ip6.arpa")) { $data_tmp[$i]["name"] = ipv6_convert_fromarpa($data_tmp[$i]["name"]); } // We pass through a full IPv6 address and maybe a CIDR value - if provided, // we should strip off the CIDR and then validate the address and process. $data_tmp[$i]["name"] = preg_replace("/\\/[0-9]*\$/", '', $data_tmp[$i]["name"]); if (!filter_var($data_tmp[$i]["name"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { log_write("error", "process", "Provided PTR IPv6 address for " . $data_tmp[$i]["name"] . " is not a valid IPv6 address."); error_flag_field("record_custom_" . $i . ""); } if (!preg_match("/^[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) { log_write("error", "process", "Provided PTR IPv6 reverse record for " . $data_tmp[$i]["name"] . " is not correctly formatted."); error_flag_field("record_custom_" . $i . ""); } // convert the record into PTR formatted value $data_tmp[$i]["name"] = ipv6_convert_arpa($data_tmp[$i]["name"]); } break; case "SSHFP": // validate SSHFP content (algorithm, type, key/fingerprint) if (!preg_match("/^[1-4] [1-2] [a-fA-F0-9]+\$/", $data_tmp[$i]["content"])) { log_write("error", "process", "SSHFP record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must be: algorithm(1-4) type(1-2) <key/fingerprint>"); error_flag_field("record_custom_" . $i . ""); } break; case "LOC": // validate SSHFP content (algorithm, type, key/fingerprint) if (!preg_match("/^[0-9]+( [0-9]+( [0-9]+\\.[0-9]+)?)? N|S [0-9]+( [0-9]+( [0-9]+\\.[0-9]+)?)? E|W \\-?[0-9]+\\.[0-9]+m?( [0-9]+\\.[0-9]+m?)?( [0-9]+\\.[0-9]+m?)?/", $data_tmp[$i]["content"])) { log_write("error", "process", "LOC record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must follow RFC 1876"); error_flag_field("record_custom_" . $i . ""); } break; case "NS": case "MX": case "HINFO": // nothing todo. break; default: log_write("error", "process", "Unknown record type " . $data_tmp[$i]["type"] . ""); break; } // remove excess "." which might have been added $data_tmp[$i]["name"] = rtrim($data_tmp[$i]["name"], "."); $data_tmp[$i]["content"] = rtrim($data_tmp[$i]["content"], "."); // verify reverse PTR options if ($data_tmp[$i]["reverse_ptr"]) { if ($data_tmp[$i]["type"] == "A" || $data_tmp[$i]["type"] == "AAAA") { // check if the appropiate reverse DNS domain exists $obj_record = new domain_records(); if (!$obj_record->find_reverse_domain($data_tmp[$i]["content"])) { // no match log_write("error", "process", "Sorry, we can't set a reverse PTR for " . $data_tmp[$i]["content"] . " --> " . $data_tmp[$i]["name"] . ", since there is no reverse domain record for that IP address"); error_flag_field("record_custom_" . $i . ""); } else { // match, record the domain ID and record ID to save a lookup $data_tmp[$i]["reverse_ptr_id_domain"] = $obj_record->id; $data_tmp[$i]["reverse_ptr_id_record"] = $obj_record->id_record; } // add to the reverse domain list - we use this list to avoid reloading for every record if (@(!in_array($obj_record->id, $data["reverse"]))) { $data["reverse"][] = $obj_record->id; } unset($obj_record); } else { log_write("error", "process", "A reverse PTR record is only valid for an A or AAAA record"); error_flag_field("record_custom_" . $i . ""); } } // add to processing array $data["records"][] = $data_tmp[$i]; } else { /* No record name exists - this is only valid if no content is also supplied */ if (!empty($data_tmp[$i]['content'])) { log_write("error", "process", "Name cannot be empty for IP address: " . $data_tmp[$i]['content']); error_flag_field("record_custom_" . $i . ""); } } } // end of loop through records } else { log_write("debug", "domains", "No records provided, no validation performed"); } // return structured array return $data; }
/* Transaction Start */ $sql_obj = new sql_query(); $sql_obj->trans_begin(); /* Update Domain */ log_write("debug", "process", "Updating main domain"); // fetch all DNS records $obj_domain->load_data(); $obj_domain->load_data_record_all(); // update records foreach ($data["records"] as $record) { if (!empty($record["mode"])) { $obj_record = new domain_records(); $obj_record->id = $obj_domain->id; $obj_record->data = $obj_domain->data; // copy domain data from existing object to save time & SQL queries $obj_record->id_record = $record["id"]; $obj_record->load_data_record(); // load record data if ($record["mode"] == "update") { // data sent through, we should update an existing record. But first, let's check if we actually need to // make a change or not. if ($obj_record->data_record["name"] != $record["name"] || $obj_record->data_record["type"] != $record["type"] || $obj_record->data_record["content"] != $record["content"] || $obj_record->data_record["ttl"] != (int) $record["ttl"] || $obj_record->data_record["prio"] != (int) $record["prio"] || $record["reverse_ptr"] != $record["reverse_ptr_orig"]) { /* Update record */ log_write("debug", "process", "Updating record " . $record["id"] . " due to changed details"); $obj_record->data_record["name"] = $record["name"];
function update_record($id_domain, $id_record, $record_name, $record_type, $record_content, $record_ttl, $record_prio) { log_write("debug", "api_namedmanager", "Executing update_record( {$id_domain}, {$id_record}, {$record_name}, {$record_type}, {$record_content}, {$record_ttl}, {$record_prio} )"); if ($this->auth_admin) { $obj_record = new domain_records(); // validate record inpit $data = array(); $data["id_domain"] = @security_script_input_predefined("int", $id_domain); $data["id_record"] = @security_script_input_predefined("int", $id_record); $data["record_name"] = @security_script_input_predefined("any", $record_name); $data["record_type"] = @security_script_input_predefined("any", $record_type); $data["record_content"] = @security_script_input_predefined("any", $record_content); $data["record_ttl"] = @security_script_input_predefined("int", $record_ttl); $data["record_prio"] = @security_script_input_predefined("int", $record_prio); foreach ($data as $value) { if ($value == "error" && $value != 0) { throw new SoapFault("Sender", "INVALID_INPUT"); } } if (!$data["id_domain"] || !$data["record_name"] || !$data["record_type"] || !$data["record_content"]) { throw new SoapFault("Sender", "INVALID_INPUT"); } // verify domain ID $obj_record->id = $data["id_domain"]; if (!$obj_record->verify_id()) { throw new SoapFault("Sender", "INVALID_ID"); } // load domain and record data $obj_record->load_data(); if ($data["id_record"]) { $obj_record->id_record = $data["id_record"]; if (!$obj_record->verify_id_record()) { // ID is invalid // // blank the ID and create a new record - we do this for apps like // phpfreeradius, but it might not be the best approach long-term $data["id_record"] = 0; } else { $obj_record->load_data_record(); } } else { // check if there is a record with the same values already - if so, we should // take it's ID. // // TODO: turn this into a proper function // $sql_obj = new sql_query(); $sql_obj->string = "SELECT id FROM `dns_records` WHERE id_domain='" . $data["id_domain"] . "' AND name='" . $data["record_name"] . "' LIMIT 1"; $sql_obj->execute(); if ($sql_obj->num_rows()) { $sql_obj->fetch_array(); $obj_record->id_record = $sql_obj->data[0]["id"]; $obj_record->load_data_record(); } } // apply changes $obj_record->data_record["name"] = $data["record_name"]; $obj_record->data_record["type"] = $data["record_type"]; $obj_record->data_record["content"] = $data["record_content"]; $obj_record->data_record["ttl"] = $data["record_ttl"]; $obj_record->data_record["prio"] = $data["record_prio"]; if (!$data["record_ttl"]) { $obj_record->data_record["ttl"] = $obj_record->data["soa_default_ttl"]; } if ($obj_record->action_update_record()) { return $obj_record->id_record; } else { throw new SoapFault("Sender", "UNKNOWN_ERROR"); } } else { throw new SoapFault("Sender", "ACCESS_DENIED"); } }
/* Update/Create Domain */ // update domain details $obj_domain->action_update(); // update nameserver $obj_domain->action_update_ns(); /* Update/Create Domain Records */ // fetch all DNS records $obj_domain->load_data(); $obj_domain->load_data_record_all(); // update records foreach ($data["records"] as $record) { $obj_record = new domain_records(); $obj_record->id = $obj_domain->id; $obj_record->data = $obj_domain->data; // copy domain data from existing object to save time & SQL queries /* Update record */ log_write("debug", "process", "Updating record " . $record["id"] . " due to changed details"); $obj_record->data_record["name"] = $record["name"]; $obj_record->data_record["type"] = $record["type"]; $obj_record->data_record["content"] = $record["content"]; $obj_record->data_record["ttl"] = $record["ttl"]; $obj_record->data_record["prio"] = $record["prio"]; $obj_record->action_update_record(); } // end for records