1+ <?php
2+
3+ /*
4+ Copyright (c) 2009, Falko Timme, Till Brehm, projektfarm Gmbh
5+ All rights reserved.
6+
7+ Redistribution and use in source and binary forms, with or without modification,
8+ are permitted provided that the following conditions are met:
9+
10+ * Redistributions of source code must retain the above copyright notice,
11+ this list of conditions and the following disclaimer.
12+ * Redistributions in binary form must reproduce the above copyright notice,
13+ this list of conditions and the following disclaimer in the documentation
14+ and/or other materials provided with the distribution.
15+ * Neither the name of ISPConfig nor the names of its contributors
16+ may be used to endorse or promote products derived from this software without
17+ specific prior written permission.
18+
19+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+ */
30+
31+ /*
32+ TABLE STRUCTURE of the "named" database:
33+
34+ CREATE TABLE IF NOT EXISTS `records` (
35+ `id` int(10) unsigned NOT NULL auto_increment,
36+ `zone` varchar(255) NOT NULL,
37+ `ttl` int(11) NOT NULL default '86400',
38+ `type` varchar(255) NOT NULL,
39+ `host` varchar(255) NOT NULL default '@',
40+ `mx_priority` int(11) default NULL,
41+ `data` text,
42+ `primary_ns` varchar(255) default NULL,
43+ `resp_contact` varchar(255) default NULL,
44+ `serial` bigint(20) default NULL,
45+ `refresh` int(11) default NULL,
46+ `retry` int(11) default NULL,
47+ `expire` int(11) default NULL,
48+ `minimum` int(11) default NULL,
49+ `ispconfig_id` int(11) NOT NULL,
50+ PRIMARY KEY (`id`),
51+ KEY `type` (`type`),
52+ KEY `host` (`host`),
53+ KEY `zone` (`zone`)
54+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
55+
56+ CREATE TABLE IF NOT EXISTS `xfr` (
57+ `id` int(11) NOT NULL auto_increment,
58+ `zone` varchar(255) NOT NULL,
59+ `client` varchar(255) NOT NULL,
60+ `ispconfig_id` int(11) NOT NULL,
61+ PRIMARY KEY (`id`),
62+ KEY `zone` (`zone`),
63+ KEY `client` (`client`)
64+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
65+
66+ */
67+
68+ class bind_dlz_plugin {
69+
70+ var $ plugin_name = 'bind_dlz_plugin ' ;
71+ var $ class_name = 'bind_dlz_plugin ' ;
72+
73+ //* This function is called during ispconfig installation to determine
74+ // if a symlink shall be created for this plugin.
75+ function onInstall ()
76+ {
77+ global $ conf ;
78+
79+ if (isset ($ conf ['bind ' ]['installed ' ]) && $ conf ['bind ' ]['installed ' ] == true ) {
80+ return true ;
81+ } else {
82+ return false ;
83+ }
84+
85+ }
86+
87+ /*
88+ This function is called when the plugin is loaded
89+ */
90+
91+ function onLoad ()
92+ {
93+ global $ app ;
94+
95+ /*
96+ Register for the events
97+ */
98+
99+ //* SOA
100+ $ app ->plugins ->registerEvent ('dns_soa_insert ' ,$ this ->plugin_name ,'soa_insert ' );
101+ $ app ->plugins ->registerEvent ('dns_soa_update ' ,$ this ->plugin_name ,'soa_update ' );
102+ $ app ->plugins ->registerEvent ('dns_soa_delete ' ,$ this ->plugin_name ,'soa_delete ' );
103+
104+ //* RR
105+ $ app ->plugins ->registerEvent ('dns_rr_insert ' ,$ this ->plugin_name ,'rr_insert ' );
106+ $ app ->plugins ->registerEvent ('dns_rr_update ' ,$ this ->plugin_name ,'rr_update ' );
107+ $ app ->plugins ->registerEvent ('dns_rr_delete ' ,$ this ->plugin_name ,'rr_delete ' );
108+ }
109+
110+
111+ function soa_insert ($ event_name ,$ data )
112+ {
113+ global $ app , $ conf ;
114+
115+ if ($ data ["new " ]["active " ] != 'Y ' ) return ;
116+
117+ $ origin = substr ($ data ["new " ]["origin " ], 0 , -1 );
118+ $ ispconfig_id = $ data ["new " ]["id " ];
119+ $ serial = $ app ->db ->queryOneRecord ("SELECT * FROM dns_soa WHERE id = " .$ ispconfig_id );
120+
121+ $ ttl = $ data ["new " ]["ttl " ];
122+
123+ $ _db = clone $ app ->db ;
124+ $ _db ->dbName = 'named ' ;
125+
126+ $ _db ->query ("INSERT INTO records (zone, ttl, type, primary_ns, resp_contact, serial, refresh, retry, expire, minimum, ispconfig_id) VALUES " .
127+ "(' $ origin', $ ttl, 'SOA', ' {$ data ["new " ]["ns " ]}', ' {$ data ["new " ]["mbox " ]}', ' {$ serial ["serial " ]}', ' {$ serial ["refresh " ]}', " .
128+ "' {$ serial ["retry " ]}', ' {$ serial ["expire " ]}', ' {$ serial ["minimum " ]}', $ ispconfig_id) " );
129+ unset($ _db );
130+ }
131+
132+ function soa_update ($ event_name ,$ data )
133+ {
134+ global $ app , $ conf ;
135+
136+ if ($ data ["new " ]["active " ] != 'Y ' )
137+ {
138+ if ($ data ["old " ]["active " ] != 'Y ' ) return ;
139+ $ this ->soa_delete ($ event_name ,$ data );
140+ }
141+ else
142+ {
143+ if ($ data ["old " ]["active " ] == 'Y ' )
144+ {
145+ $ origin = substr ($ data ["new " ]["origin " ], 0 , -1 );
146+ $ ispconfig_id = $ data ["new " ]["id " ];
147+ $ serial = $ app ->db ->queryOneRecord ("SELECT * FROM dns_soa WHERE id = " .$ ispconfig_id );
148+
149+ $ ttl = $ data ["new " ]["ttl " ];
150+
151+ $ _db = clone $ app ->db ;
152+ $ _db ->dbName = 'named ' ;
153+
154+ $ _db ->query ("UPDATE records SET zone = ' $ origin', ttl = $ ttl, primary_ns = ' {$ data ["new " ]["ns " ]}', resp_contact = ' {$ data ["new " ]["mbox " ]}', " .
155+ "serial = ' {$ serial ["serial " ]}', refresh = ' {$ serial ["refresh " ]}', retry = ' {$ serial ["retry " ]}', expire = ' {$ serial ["expire " ]}', " .
156+ "minimum = ' {$ serial ["minimum " ]}' WHERE ispconfig_id = " .$ data ["new " ]["id " ]." AND type = 'SOA' " );
157+ unset($ _db );
158+ }
159+ else
160+ {
161+ $ this ->soa_insert ($ event_name ,$ data );
162+ $ ispconfig_id = $ data ["new " ]["id " ];
163+
164+ if ($ records = $ app ->db ->queryAllRecords ("SELECT * FROM dns_rr WHERE zone = $ ispconfig_id AND active = 'Y' " ))
165+ {
166+ foreach ($ records as $ record )
167+ {
168+ foreach ($ record as $ key => $ val ) {
169+ $ data ["new " ][$ key ] = $ val ;
170+ }
171+ $ this ->rr_insert ("dns_rr_insert " , $ data );
172+ }
173+ }
174+ }
175+ }
176+
177+ }
178+
179+ function soa_delete ($ event_name ,$ data )
180+ {
181+ global $ app , $ conf ;
182+
183+ $ _db = clone $ app ->db ;
184+ $ _db ->dbName = 'named ' ;
185+
186+ $ _db ->query ("DELETE FROM records WHERE ispconfig_id = {$ data ["old " ]["id " ]}" );
187+ unset($ _db );
188+ }
189+
190+ function rr_insert ($ event_name ,$ data )
191+ {
192+ global $ app , $ conf ;
193+ if ($ data ["new " ]["active " ] != 'Y ' ) return ;
194+
195+ $ zone = $ app ->db ->queryOneRecord ("SELECT * FROM dns_soa WHERE id = " .$ data ["new " ]["zone " ]);
196+ $ origin = substr ($ zone ["origin " ], 0 , -1 );
197+ $ ispconfig_id = $ data ["new " ]["id " ];
198+
199+ $ type = $ data ["new " ]["type " ];
200+
201+ if (substr ($ data ["new " ]["name " ], -1 ) == '. ' ) {
202+ $ name = substr ($ data ["new " ]["name " ], 0 , -1 );
203+ } else {
204+ $ name = ($ data ["new " ]["name " ] == "" ) ? $ name = '@ ' : $ data ["new " ]["name " ];
205+ }
206+
207+ if ($ name == $ origin || $ name == '' ) {
208+ $ name = '@ ' ;
209+ }
210+
211+ switch ($ type )
212+ {
213+ case "CNAME " :
214+ case "MX " :
215+ case "NS " :
216+ case "ALIAS " :
217+ case "PTR " :
218+ case "SRV " :
219+ if (substr ($ data ["new " ]["data " ], -1 ) != '. ' ){
220+ $ content = $ data ["new " ]["data " ] . '. ' ;
221+ } else {
222+ $ content = $ data ["new " ]["data " ];
223+ }
224+ break ;
225+ case "HINFO " :
226+ $ content = $ data ["new " ]["data " ];
227+ $ quote1 = strpos ($ content , '" ' );
228+
229+ if ($ quote1 !== FALSE ) {
230+ $ quote2 = strpos (substr ($ content , ($ quote1 + 1 )), '" ' );
231+ }
232+
233+ if ($ quote1 !== FALSE && $ quote2 !== FALSE ) {
234+ $ text_between_quotes = str_replace (' ' , '_ ' , substr ($ content , ($ quote1 + 1 ), (($ quote2 - $ quote1 ))));
235+ $ content = $ text_between_quotes .substr ($ content , ($ quote2 + 2 ));
236+ }
237+ break ;
238+ default :
239+ $ content = $ data ["new " ]["data " ];
240+ }
241+
242+ $ ttl = $ data ["new " ]["ttl " ];
243+
244+ $ _db = clone $ app ->db ;
245+ $ _db ->dbName = 'named ' ;
246+
247+ if ($ type == 'MX ' ) {
248+ $ _db ->query ("INSERT INTO records (zone, ttl, type, host, mx_priority, data, ispconfig_id) " .
249+ " VALUES (' $ origin', $ ttl, ' $ type', ' $ name', {$ data ["new " ]["aux " ]}, ' $ content', $ ispconfig_id) " );
250+ } else {
251+ $ _db ->query ("INSERT INTO records (zone, ttl, type, host, data, ispconfig_id) " .
252+ " VALUES (' $ origin', $ ttl, ' $ type', ' $ name', ' $ content', $ ispconfig_id) " );
253+ }
254+
255+ unset($ _db );
256+ }
257+
258+ function rr_update ($ event_name ,$ data )
259+ {
260+ global $ app , $ conf ;
261+
262+ if ($ data ["new " ]["active " ] != 'Y ' )
263+ {
264+ if ($ data ["old " ]["active " ] != 'Y ' ) return ;
265+ $ this ->rr_delete ($ event_name ,$ data );
266+ }
267+ else
268+ {
269+ if ($ data ["old " ]["active " ] == 'Y ' )
270+ {
271+ $ zone = $ app ->db ->queryOneRecord ("SELECT * FROM dns_soa WHERE id = " .$ data ["new " ]["zone " ]);
272+ $ origin = substr ($ zone ["origin " ], 0 , -1 );
273+ $ ispconfig_id = $ data ["new " ]["id " ];
274+
275+ $ type = $ data ["new " ]["type " ];
276+
277+ if (substr ($ data ["new " ]["name " ], -1 ) == '. ' ) {
278+ $ name = substr ($ data ["new " ]["name " ], 0 , -1 );
279+ } else {
280+ $ name = ($ data ["new " ]["name " ] == "" ) ? $ name = '@ ' : $ data ["new " ]["name " ];
281+ }
282+
283+ if ($ name == $ origin || $ name == '' ) {
284+ $ name = '@ ' ;
285+ }
286+
287+ switch ($ type )
288+ {
289+ case "CNAME " :
290+ case "MX " :
291+ case "NS " :
292+ case "ALIAS " :
293+ case "PTR " :
294+ case "SRV " :
295+ if (substr ($ data ["new " ]["data " ], -1 ) != '. ' ){
296+ $ content = $ data ["new " ]["data " ] . '. ' ;
297+ } else {
298+ $ content = $ data ["new " ]["data " ];
299+ }
300+ break ;
301+ case "HINFO " :
302+ $ content = $ data ["new " ]["data " ];
303+ $ quote1 = strpos ($ content , '" ' );
304+ if ($ quote1 !== FALSE ){
305+ $ quote2 = strpos (substr ($ content , ($ quote1 + 1 )), '" ' );
306+ }
307+ if ($ quote1 !== FALSE && $ quote2 !== FALSE ){
308+ $ text_between_quotes = str_replace (' ' , '_ ' , substr ($ content , ($ quote1 + 1 ), (($ quote2 - $ quote1 ))));
309+ $ content = $ text_between_quotes .substr ($ content , ($ quote2 + 2 ));
310+ }
311+ break ;
312+ default :
313+ $ content = $ data ["new " ]["data " ];
314+ }
315+
316+ $ ttl = $ data ["new " ]["ttl " ];
317+ $ prio = (int )$ data ["new " ]["aux " ];
318+
319+ $ _db = clone $ app ->db ;
320+ $ _db ->dbName = 'named ' ;
321+
322+ if ($ type == 'MX ' ) {
323+ $ _db ->query ("UPDATE records SET zone = ' $ origin', ttl = $ ttl, type = ' $ type', host = ' $ name', mx_priority = $ prio, " .
324+ "data = ' $ content' WHERE ispconfig_id = $ ispconfig_id AND type != 'SOA' " );
325+ } else {
326+ $ _db ->query ("UPDATE records SET zone = ' $ origin', ttl = $ ttl, type = ' $ type', host = ' $ name', " .
327+ "data = ' $ content' WHERE ispconfig_id = $ ispconfig_id AND type != 'SOA' " );
328+ }
329+
330+ unset($ _db );
331+ } else {
332+ $ this ->rr_insert ($ event_name ,$ data );
333+ }
334+ }
335+ }
336+
337+ function rr_delete ($ event_name ,$ data ) {
338+ global $ app , $ conf ;
339+
340+ $ _db = clone $ app ->db ;
341+ $ _db ->dbName = 'named ' ;
342+
343+ $ _db ->query ("DELETE FROM named.records WHERE ispconfig_id = {$ data ["old " ]["id " ]} AND type != 'SOA' " );
344+ unset($ _db );
345+ }
346+ } // end class
347+ ?>
0 commit comments