You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

templates.inc.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. <?php
  2. /* Poweradmin, a friendly web-based admin tool for PowerDNS.
  3. * See <http://www.poweradmin.org> for more details.
  4. *
  5. * Copyright 2007-2009 Rejo Zenger <rejo@zenger.nl>
  6. * Copyright 2010-2017 Poweradmin Development Team
  7. * <http://www.poweradmin.org/credits.html>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. /**
  23. * Template functions
  24. *
  25. * @package Poweradmin
  26. * @copyright 2007-2010 Rejo Zenger <rejo@zenger.nl>
  27. * @copyright 2010-2017 Poweradmin Development Team
  28. * @license http://opensource.org/licenses/GPL-3.0 GPL
  29. */
  30. /** Get a list of all available zone templates
  31. *
  32. * @param int $userid User ID
  33. *
  34. * @return mixed[] array of zone templates [id,name,descr]
  35. */
  36. function get_list_zone_templ($userid) {
  37. global $db;
  38. $query = "SELECT * FROM zone_templ "
  39. . "WHERE owner = '" . $userid . "' "
  40. . "ORDER BY name";
  41. $result = $db->query($query);
  42. if (PEAR::isError($result)) {
  43. error("Not all tables available in database, please make sure all upgrade/install proceedures were followed");
  44. return false;
  45. }
  46. $zone_templ_list = array();
  47. while ($zone_templ = $result->fetchRow()) {
  48. $zone_templ_list[] = array(
  49. "id" => $zone_templ['id'],
  50. "name" => $zone_templ['name'],
  51. "descr" => $zone_templ['descr']
  52. );
  53. }
  54. return $zone_templ_list;
  55. }
  56. /** Add a zone template
  57. *
  58. * @param mixed[] $details zone template details
  59. * @param $userid User ID that owns template
  60. *
  61. * @return boolean true on success, false otherwise
  62. */
  63. function add_zone_templ($details, $userid) {
  64. global $db;
  65. $zone_name_exists = zone_templ_name_exists($details['templ_name']);
  66. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  67. error(ERR_PERM_ADD_ZONE_TEMPL);
  68. return false;
  69. } elseif ($zone_name_exists != '0') {
  70. error(ERR_ZONE_TEMPL_EXIST);
  71. } else {
  72. $query = "INSERT INTO zone_templ (name, descr, owner)
  73. VALUES ("
  74. . $db->quote($details['templ_name'], 'text') . ", "
  75. . $db->quote($details['templ_descr'], 'text') . ", "
  76. . $db->quote($userid, 'integer') . ")";
  77. $result = $db->query($query);
  78. if (PEAR::isError($result)) {
  79. error($result->getMessage());
  80. return false;
  81. }
  82. return true;
  83. }
  84. }
  85. /** Get name and description of template based on template ID
  86. *
  87. * @param int $zone_templ_id Zone template ID
  88. *
  89. * @return mixed[] zone template details
  90. */
  91. function get_zone_templ_details($zone_templ_id) {
  92. global $db;
  93. $query = "SELECT *"
  94. . " FROM zone_templ"
  95. . " WHERE id = " . $db->quote($zone_templ_id, 'integer');
  96. $result = $db->query($query);
  97. if (PEAR::isError($result)) {
  98. error($result->getMessage());
  99. return false;
  100. }
  101. $details = $result->fetchRow();
  102. return $details;
  103. }
  104. /** Delete a zone template
  105. *
  106. * @param int $zone_templ_id Zone template ID
  107. *
  108. * @return boolean true on success, false otherwise
  109. */
  110. function delete_zone_templ($zone_templ_id) {
  111. global $db;
  112. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  113. error(ERR_PERM_DEL_ZONE_TEMPL);
  114. return false;
  115. } else {
  116. // Delete the zone template
  117. $query = "DELETE FROM zone_templ"
  118. . " WHERE id = " . $db->quote($zone_templ_id, 'integer');
  119. $result = $db->query($query);
  120. if (PEAR::isError($result)) {
  121. error($result->getMessage());
  122. return false;
  123. }
  124. // Delete the zone template records
  125. $query = "DELETE FROM zone_templ_records"
  126. . " WHERE zone_templ_id = " . $db->quote($zone_templ_id, 'integer');
  127. $result = $db->query($query);
  128. if (PEAR::isError($result)) {
  129. error($result->getMessage());
  130. return false;
  131. }
  132. // Delete references to zone template
  133. $query = "DELETE FROM records_zone_templ"
  134. . " WHERE zone_templ_id = " . $db->quote($zone_templ_id, 'integer');
  135. $result = $db->query($query);
  136. if (PEAR::isError($result)) {
  137. error($result->getMessage());
  138. return false;
  139. }
  140. return true;
  141. }
  142. }
  143. /** Delete all zone templates for specific user
  144. *
  145. * @param $userid User ID
  146. *
  147. * @return boolean true on success, false otherwise
  148. */
  149. function delete_zone_templ_userid($userid) {
  150. global $db;
  151. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  152. error(ERR_PERM_DEL_ZONE_TEMPL);
  153. return false;
  154. } else {
  155. $query = "DELETE FROM zone_templ"
  156. . " WHERE owner = " . $db->quote($userid, 'integer');
  157. $result = $db->query($query);
  158. if (PEAR::isError($result)) {
  159. error($result->getMessage());
  160. return false;
  161. }
  162. return true;
  163. }
  164. }
  165. /** Count zone template records
  166. *
  167. * @param int $zone_templ_id Zone template ID
  168. *
  169. * @return boolean true on success, false otherwise
  170. */
  171. function count_zone_templ_records($zone_templ_id) {
  172. global $db;
  173. $query = "SELECT COUNT(id) FROM zone_templ_records WHERE zone_templ_id = " . $db->quote($zone_templ_id, 'integer');
  174. $record_count = $db->queryOne($query);
  175. if (PEAR::isError($record_count)) {
  176. error($record_count->getMessage());
  177. return false;
  178. }
  179. return $record_count;
  180. }
  181. /** Check if zone template exist
  182. *
  183. * @param int $zone_templ_id Zone template ID
  184. *
  185. * @return boolean true on success, false otherwise
  186. */
  187. function zone_templ_id_exists($zone_templ_id) {
  188. global $db;
  189. $query = "SELECT COUNT(id) FROM zone_templ WHERE id = " . $db->quote($zone_templ_id, 'integer');
  190. $count = $db->queryOne($query);
  191. if (PEAR::isError($count)) {
  192. error($count->getMessage());
  193. return false;
  194. }
  195. return $count;
  196. }
  197. /** Get a zone template record from an id
  198. *
  199. * Retrieve all fields of the record and send it back to the function caller.
  200. *
  201. * @param int $id zone template record id
  202. *
  203. * @return mixed[] zone template record
  204. * [id,zone_templ_id,name,type,content,ttl,prio] or -1 if nothing is found
  205. */
  206. function get_zone_templ_record_from_id($id) {
  207. global $db;
  208. if (is_numeric($id)) {
  209. $result = $db->queryRow("SELECT id, zone_templ_id, name, type, content, ttl, prio FROM zone_templ_records WHERE id=" . $db->quote($id, 'integer'));
  210. if ($result) {
  211. $ret = array(
  212. "id" => $result["id"],
  213. "zone_templ_id" => $result["zone_templ_id"],
  214. "name" => $result["name"],
  215. "type" => $result["type"],
  216. "content" => $result["content"],
  217. "ttl" => $result["ttl"],
  218. "prio" => $result["prio"],
  219. );
  220. return $ret;
  221. } else {
  222. return -1;
  223. }
  224. } else {
  225. error(sprintf(ERR_INV_ARG, "get_zone_templ_record_from_id"));
  226. }
  227. }
  228. /** Get all zone template records from a zone template id
  229. *
  230. * Retrieve all fields of the records and send it back to the function caller.
  231. *
  232. * @param int $id zone template ID
  233. * @param int $rowstart Starting row (default=0)
  234. * @param int $rowamount Number of rows per query (default=999999)
  235. * @param string $sortby Column to sort by (default='name')
  236. *
  237. * @return mixed[] zone template records numerically indexed
  238. * [id,zone_templd_id,name,type,content,ttl,pro] or -1 if nothing is found
  239. */
  240. function get_zone_templ_records($id, $rowstart = 0, $rowamount = 999999, $sortby = 'name') {
  241. global $db;
  242. if (is_numeric($id)) {
  243. $db->setLimit($rowamount, $rowstart);
  244. $result = $db->query("SELECT id FROM zone_templ_records WHERE zone_templ_id=" . $db->quote($id, 'integer') . " ORDER BY " . $sortby);
  245. $ret[] = array();
  246. $retcount = 0;
  247. while ($r = $result->fetchRow()) {
  248. // Call get_record_from_id for each row.
  249. $ret[$retcount] = get_zone_templ_record_from_id($r["id"]);
  250. $retcount++;
  251. }
  252. return ($retcount > 0 ? $ret : -1);
  253. } else {
  254. error(sprintf(ERR_INV_ARG, "get_zone_templ_records"));
  255. }
  256. }
  257. /** Add a record for a zone template
  258. *
  259. * This function validates and if correct it inserts it into the database.
  260. * TODO: actual validation?
  261. *
  262. * @param int $zone_templ_id zone template ID
  263. * @param string $name name part of record
  264. * @param string $type record type
  265. * @param string $content record content
  266. * @param int $ttl TTL
  267. * @param int $prio Priority
  268. *
  269. * @return boolean true if succesful, false otherwise
  270. */
  271. function add_zone_templ_record($zone_templ_id, $name, $type, $content, $ttl, $prio) {
  272. global $db;
  273. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  274. error(ERR_PERM_ADD_RECORD);
  275. return false;
  276. } else {
  277. if ($content == '') {
  278. error(ERR_DNS_CONTENT);
  279. return false;
  280. }
  281. if ($name != '') {
  282. $query = "INSERT INTO zone_templ_records (zone_templ_id, name, type, content, ttl, prio) VALUES ("
  283. . $db->quote($zone_templ_id, 'integer') . ","
  284. . $db->quote($name, 'text') . ","
  285. . $db->quote($type, 'text') . ","
  286. . $db->quote($content, 'text') . ","
  287. . $db->quote($ttl, 'integer') . ","
  288. . $db->quote($prio, 'integer') . ")";
  289. $result = $db->query($query);
  290. if (PEAR::isError($result)) {
  291. error($result->getMessage());
  292. return false;
  293. }
  294. return true;
  295. } else {
  296. error(ERR_DNS_HOSTNAME);
  297. return false;
  298. }
  299. }
  300. }
  301. /** Modify zone template reocrd
  302. *
  303. * Edit a record for a zone template.
  304. * This function validates it if correct it inserts it into the database.
  305. *
  306. * @param mixed[] $record zone record array
  307. *
  308. * @return boolean true on success, false otherwise
  309. */
  310. function edit_zone_templ_record($record) {
  311. global $db;
  312. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  313. error(ERR_PERM_EDIT_RECORD);
  314. return false;
  315. } else {
  316. if ("" != $record['name']) {
  317. $query = "UPDATE zone_templ_records
  318. SET name=" . $db->quote($record['name'], 'text') . ",
  319. type=" . $db->quote($record['type'], 'text') . ",
  320. content=" . $db->quote($record['content'], 'text') . ",
  321. ttl=" . $db->quote($record['ttl'], 'integer') . ",
  322. prio=" . $db->quote(isset($record['prio']) ? $record['prio'] : 0, 'integer') . "
  323. WHERE id=" . $db->quote($record['rid'], 'integer');
  324. $result = $db->query($query);
  325. if (PEAR::isError($result)) {
  326. error($result->getMessage());
  327. return false;
  328. }
  329. return true;
  330. } else {
  331. error(ERR_DNS_HOSTNAME);
  332. return false;
  333. }
  334. }
  335. }
  336. /** Delete a record for a zone template by a given id
  337. *
  338. * @param int $rid template record id
  339. *
  340. * @return boolean true on success, false otherwise
  341. */
  342. function delete_zone_templ_record($rid) {
  343. global $db;
  344. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  345. error(ERR_PERM_DEL_RECORD);
  346. return false;
  347. } else {
  348. $query = "DELETE FROM zone_templ_records WHERE id = " . $db->quote($rid, 'integer');
  349. $result = $db->query($query);
  350. if (PEAR::isError($result)) {
  351. error($result->getMessage());
  352. return false;
  353. }
  354. return true;
  355. }
  356. }
  357. /** Check if the session user is the owner for the zone template
  358. *
  359. * @param int $zone_templ_id zone template id
  360. * @param int $userid user id
  361. *
  362. * @return boolean true on success, false otherwise
  363. */
  364. function get_zone_templ_is_owner($zone_templ_id, $userid) {
  365. global $db;
  366. $query = "SELECT owner FROM zone_templ WHERE id = " . $db->quote($zone_templ_id, 'integer');
  367. $result = $db->queryOne($query);
  368. if (PEAR::isError($result)) {
  369. error($result->getMessage());
  370. return false;
  371. }
  372. if ($result == $userid) {
  373. return true;
  374. } else {
  375. return false;
  376. }
  377. }
  378. /** Add a zone template from zone / another template
  379. *
  380. * @param string $template_name template name
  381. * @param string $description description
  382. * @param int $userid user id
  383. * @param mixed[] $records array of zone records
  384. * @param string $domain domain to substitute with '[ZONE]' (optional) [default=null]
  385. *
  386. * @return boolean true on success, false otherwise
  387. */
  388. function add_zone_templ_save_as($template_name, $description, $userid, $records, $domain = null) {
  389. global $db;
  390. global $db_type;
  391. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  392. error(ERR_PERM_ADD_ZONE_TEMPL);
  393. return false;
  394. } else {
  395. $result = $db->beginTransaction();
  396. $query = "INSERT INTO zone_templ (name, descr, owner)
  397. VALUES ("
  398. . $db->quote($template_name, 'text') . ", "
  399. . $db->quote($description, 'text') . ", "
  400. . $db->quote($userid, 'integer') . ")";
  401. $result = $db->exec($query);
  402. if ($db_type == 'pgsql') {
  403. $zone_templ_id = $db->lastInsertId('zone_templ_id_seq');
  404. } else {
  405. $zone_templ_id = $db->lastInsertId();
  406. }
  407. $owner = get_zone_templ_is_owner($zone_templ_id, $_SESSION['userid']);
  408. foreach ($records as $record) {
  409. $name = $domain ? preg_replace('/' . $domain . '/', '[ZONE]', $record['name']) : $record['name'];
  410. $content = $domain ? preg_replace('/' . $domain . '/', '[ZONE]', $content) : $content;
  411. $query2 = "INSERT INTO zone_templ_records (zone_templ_id, name, type, content, ttl, prio) VALUES ("
  412. . $db->quote($zone_templ_id, 'integer') . ","
  413. . $db->quote($name, 'text') . ","
  414. . $db->quote($record['type'], 'text') . ","
  415. . $db->quote($record['content'], 'text') . ","
  416. . $db->quote($record['ttl'], 'integer') . ","
  417. . $db->quote(isset($record['prio']) ? $record['prio'] : 0, 'integer') . ")";
  418. $result = $db->exec($query2);
  419. }
  420. if (PEAR::isError($result)) {
  421. $result = $db->rollback();
  422. } else {
  423. $result = $db->commit();
  424. }
  425. }
  426. return true;
  427. }
  428. /** Get list of all zones using template
  429. *
  430. * @param int $zone_templ_id zone template id
  431. * @param int $userid user id
  432. *
  433. * @return mixed[] array of zones [id,name,type,count_records]
  434. */
  435. function get_list_zone_use_templ($zone_templ_id, $userid) {
  436. global $db;
  437. if (do_hook('verify_permission' , 'zone_content_edit_others' )) {
  438. $perm_edit = "all";
  439. } elseif (do_hook('verify_permission' , 'zone_content_edit_own' )) {
  440. $perm_edit = "own";
  441. } else {
  442. $perm_edit = "none";
  443. }
  444. $sql_add = '';
  445. if ($perm_edit != "all") {
  446. $sql_add = " AND zones.domain_id = domains.id
  447. AND zones.owner = " . $db->quote($userid, 'integer');
  448. }
  449. $query = "SELECT domains.id,
  450. domains.name,
  451. domains.type,
  452. Record_Count.count_records
  453. FROM domains
  454. LEFT JOIN zones ON domains.id=zones.domain_id
  455. LEFT JOIN (
  456. SELECT COUNT(domain_id) AS count_records, domain_id FROM records GROUP BY domain_id
  457. ) Record_Count ON Record_Count.domain_id=domains.id
  458. WHERE 1=1" . $sql_add . "
  459. AND zone_templ_id = " . $db->quote($zone_templ_id, 'integer') . "
  460. GROUP BY domains.name, domains.id, domains.type, Record_Count.count_records";
  461. $result = $db->query($query);
  462. if (PEAR::isError($result)) {
  463. error("Not all tables available in database, please make sure all upgrade/install proceedures were followed");
  464. return false;
  465. }
  466. $zone_list = array();
  467. while ($zone = $result->fetchRow()) {
  468. $zone_list[] = array(
  469. "id" => $zone['id'],
  470. "name" => $zone['name'],
  471. "type" => $zone['type'],
  472. "count_records" => $zone['count_records']
  473. );
  474. }
  475. return $zone_list;
  476. }
  477. /** Modify zone template
  478. *
  479. * @param mixed[] $details array of new zone template details
  480. * @param int $zone_templ_id zone template id
  481. *
  482. * @return boolean true on success, false otherwise
  483. */
  484. function edit_zone_templ($details, $zone_templ_id) {
  485. global $db;
  486. $zone_name_exists = zone_templ_name_exists($details['templ_name'], $zone_templ_id);
  487. if (!(do_hook('verify_permission' , 'zone_master_add' ))) {
  488. error(ERR_PERM_ADD_ZONE_TEMPL);
  489. return false;
  490. } elseif ($zone_name_exists != '0') {
  491. error(ERR_ZONE_TEMPL_EXIST);
  492. return false;
  493. } else {
  494. $query = "UPDATE zone_templ
  495. SET name=" . $db->quote($details['templ_name'], 'text') . ",
  496. descr=" . $db->quote($details['templ_descr'], 'text') . "
  497. WHERE id=" . $db->quote($zone_templ_id, 'integer');
  498. $result = $db->query($query);
  499. if (PEAR::isError($result)) {
  500. error($result->getMessage());
  501. return false;
  502. }
  503. return true;
  504. }
  505. }
  506. /** Check if zone template name exists
  507. *
  508. * @param string $zone_templ_name zone template name
  509. * @param int $zone_templ_id zone template id (optional) [default=null]
  510. *
  511. * @return int number of matching templates
  512. */
  513. function zone_templ_name_exists($zone_templ_name, $zone_templ_id = null) {
  514. global $db;
  515. $sql_add = '';
  516. if ($zone_templ_id) {
  517. $sql_add = " AND id != " . $db->quote($zone_templ_id, 'integer');
  518. }
  519. $query = "SELECT COUNT(id) FROM zone_templ WHERE name = " . $db->quote($zone_templ_name, 'text') . "" . $sql_add;
  520. $count = $db->queryOne($query);
  521. if (PEAR::isError($count)) {
  522. error($count->getMessage());
  523. return false;
  524. }
  525. return $count;
  526. }
  527. /** Parse string and substitute domain and serial
  528. *
  529. * @param string $val string to parse containing tokens '[ZONE]' and '[SERIAL]'
  530. * @param string $domain domain to subsitute for '[ZONE]'
  531. *
  532. * @return string interpolated/parsed string
  533. */
  534. function parse_template_value($val, $domain) {
  535. $serial = date("Ymd");
  536. $serial .= "00";
  537. $val = str_replace('[ZONE]', $domain, $val);
  538. $val = str_replace('[SERIAL]', $serial, $val);
  539. return $val;
  540. }
  541. /** Add relation between zone record and template
  542. *
  543. * @param type $db DB link
  544. * @param type $domain_id Domain id
  545. * @param type $record_id Record id
  546. * @param type $zone_templ_id Zone template id
  547. */
  548. function add_record_relation_to_templ($db, $domain_id, $record_id, $zone_templ_id) {
  549. $query = "INSERT INTO records_zone_templ (domain_id, record_id, zone_templ_id) VALUES ("
  550. . $db->quote($domain_id, 'integer') . ","
  551. . $db->quote($record_id, 'integer') . ","
  552. . $db->quote($zone_templ_id, 'integer') . ")";
  553. $db->query($query);
  554. }
  555. /** Check if given relation exists
  556. *
  557. * @param type $db
  558. * @param type $domain_id
  559. * @param type $record_id
  560. * @param type $zone_templ_id
  561. * @return boolean true on success, false on failure
  562. */
  563. function record_relation_to_templ_exists($db, $domain_id, $record_id, $zone_templ_id) {
  564. $query = "SELECT COUNT(*) FROM records_zone_templ WHERE domain_id = " . $db->quote($domain_id, 'integer') .
  565. " AND record_id = " . $db->quote($record_id, 'integer') . " AND zone_templ_id = " . $db->quote($zone_templ_id, 'integer');
  566. $count = $db->queryOne($query);
  567. if ($count == 0) {
  568. return false;
  569. }
  570. return true;
  571. }