]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/scripts/setddns.pl
Updated setddns.pl to support regfish.de and some new ddns services.
[people/pmueller/ipfire-2.x.git] / src / scripts / setddns.pl
1 #!/usr/bin/perl
2 #
3 # SmoothWall CGIs
4 #
5 # This code is distributed under the terms of the GPL
6 #
7 # (c) The SmoothWall Team
8 #
9 # $Id: setddns.pl,v 1.4.2.55 2009/05/29 21:49:37 owes Exp $
10 #
11
12 #close(STDIN);
13 #close(STDOUT);
14 #close(STDERR);
15
16 use strict;
17 use IO::Socket;
18 use Net::SSLeay;
19
20 require '/var/ipfire/general-functions.pl';
21
22 #Prototypes functions
23 sub encode_base64 ($;$);
24
25 my %settings;
26 my $filename = "${General::swroot}/ddns/config";
27 my $logDirName = "/var/log/dyndns";
28 my @current = ();
29
30 if (open(FILE, "$filename")) {
31 @current = <FILE>;
32 close(FILE);
33 unless(@current) {
34 exit 0;
35 }
36 } else {
37 &General::log('Dynamic DNS failure : unable to open config file.');
38 exit 0;
39 }
40
41 &General::readhash("${General::swroot}/ddns/settings", \%settings);
42
43 # ignore monthly update if not in minimize update mode
44 exit 0 if (($settings{'MINIMIZEUPDATES'} ne 'on') && ($ARGV[1] eq '-m'));
45
46 my $ip;
47 if (open(IP, "${General::swroot}/red/local-ipaddress")) {
48 $ip = <IP>;
49 close(IP);
50 chomp $ip;
51 } else {
52 &General::log('Dynamic DNS failure : unable to open local-ipaddress file.');
53 exit 0;
54 }
55
56 # Do delete the the logdir before fetching IP (and write fetch IP state into logdir)
57 # On delete the fetch IP state is deleted too, but it gets rewritten on -force anyway
58 if ($ARGV[0] eq '-f') {
59 # delete all cache files.
60 # next regular calls will try again if this force update fails.
61 system("/bin/rm -f $logDirName/*");
62 }
63
64 #If IP is reserved network, we are behind a router. May we ask for our real public IP ?
65 if ( &General::IpInSubnet ($ip,'10.0.0.0','255.0.0.0') ||
66 &General::IpInSubnet ($ip,'172.16.0.0','255.240.0.0') ||
67 &General::IpInSubnet ($ip,'192.168.0.0','255.255.0.0')) {
68 # We can, but are we authorized by GUI ?
69 if ($settings{'BEHINDROUTER'} eq 'FETCH_IP') {
70
71 my %fetchIpState = ();
72 $fetchIpState{'FETCHED_IP'} = "";
73 $fetchIpState{'BEHINDROUTERWAITLOOP'} = -1;
74 &General::readhash("$logDirName/fetchIpState", \%fetchIpState) if(-e "$logDirName/fetchIpState");
75
76 if ($ARGV[0] eq '-f'){
77 $fetchIpState{'BEHINDROUTERWAITLOOP'} = -1; # When forced option, fectch PublicIP now
78 }
79
80 # Increment counter modulo 4. When it is zero, fetch ip else exit
81 # This divides by 4 the requests to the dyndns server.
82 $fetchIpState{'BEHINDROUTERWAITLOOP'} = ($fetchIpState{'BEHINDROUTERWAITLOOP'}+1) %4;
83 &General::writehash("$logDirName/fetchIpState", \%fetchIpState);
84
85 exit 0 if ( $fetchIpState{'BEHINDROUTERWAITLOOP'} ne 0 );
86 my $RealIP = &General::FetchPublicIp;
87 $ip = (&General::validip ($RealIP) ? $RealIP : 'unavailable');
88 $fetchIpState{'FETCHED_IP'} = $ip;
89 &General::writehash("$logDirName/fetchIpState", \%fetchIpState);
90 &General::log ("Dynamic DNS public router IP is: $ip");
91 }
92 }
93
94
95 foreach my $line (@current) {
96 chomp($line);
97 my @temp = split(/\,/,$line);
98 next if ($temp[7] ne "on");
99
100 $settings{'SERVICE'} = $temp[0];
101 $settings{'HOSTNAME'} = $temp[1];
102 $settings{'DOMAIN'} = $temp[2];
103 $settings{'PROXY'} = $temp[3];
104 $settings{'WILDCARDS'} = $temp[4];
105 $settings{'LOGIN'} = $temp[5];
106 $settings{'PASSWORD'} = $temp[6];
107 $settings{'ENABLED'} = $temp[7];
108
109 my $ipcache = 0;
110 my $success = 0;
111 my $ipCacheFile = "$logDirName/$settings{'SERVICE'}.$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
112 if(-e $ipCacheFile) {
113 open(IPCACHE, $ipCacheFile);
114 $ipcache = <IPCACHE>;
115 close(IPCACHE);
116 chomp $ipcache;
117 }
118
119 next if ($ip eq $ipcache);
120
121 #Some connection are very stable (more than 40 days). Finally force
122 #one update / month to avoid account lost
123 #cron call once/week with -f & once/month with -f -m options
124 #minimize update ?
125 if ( ($settings{'MINIMIZEUPDATES'} eq 'on') && ($ARGV[1] ne '-m')) {
126 if (General::DyndnsServiceSync($ip, $settings{'HOSTNAME'},$settings{'DOMAIN'})) {
127 &General::log ("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} is uptodate [$ip]");
128
129 # write cachefile (in case of -force the file is missing) otherwise the log
130 # is filled up with "... is uptodate ..." messages every 5 minutes.
131 open(IPCACHE, ">$ipCacheFile");
132 flock IPCACHE, 2;
133 print IPCACHE $ip;
134 close(IPCACHE);
135
136 next; # do not update, go to test next service
137 }
138 }
139 my @service = split(/\./, "$settings{'SERVICE'}");
140 $settings{'SERVICE'} = "$service[0]";
141 if ($settings{'SERVICE'} eq 'cjb') {
142 # use proxy ?
143 my %proxysettings;
144 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
145 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
146 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
147 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
148 }
149
150 my ($out, $response) = Net::SSLeay::get_http( 'www.cjb.net',
151 80,
152 "/cgi-bin/dynip.cgi?username=$settings{'LOGIN'}&password=$settings{'PASSWORD'}&ip=$ip",
153 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
154 );
155 #Valid responses from service are:
156 # has been updated to point to
157 if ($response =~ m%HTTP/1\.. 200 OK%) {
158 if ( $out !~ m/has been updated to point to/ ) {
159 &General::log("Dynamic DNS ip-update for cjb.net ($settings{'LOGIN'}) : failure (bad password or login)");
160 } else {
161 &General::log("Dynamic DNS ip-update for cjb.net ($settings{'LOGIN'}) : success");
162 $success++;
163 }
164 } else {
165 &General::log("Dynamic DNS ip-update for cjb.net ($settings{'LOGIN'}) : failure (could not connect to server)");
166 }
167 }
168 # dhs.org=>ez-ipupdate
169 elsif ($settings{'SERVICE'} eq 'dnsmadeeasy') {
170 # use proxy ?
171 my %proxysettings;
172 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
173 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
174 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
175 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
176 }
177
178 # replace the ';' with ',' because comma is the separator in the config file.
179 $settings{'HOSTNAME'} =~ tr /;/,/;
180 my ($out, $response) = Net::SSLeay::get_https( 'www.dnsmadeeasy.com',
181 443,
182 "/servlet/updateip?username=$settings{'LOGIN'}&password=$settings{'PASSWORD'}&id=$settings{'HOSTNAME'}&ip=$ip",
183 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
184 );
185 #Valid responses from service are:
186 # success
187 if ($response =~ m%HTTP/1\.. 200 OK%) {
188 if ( $out !~ m/success/ ) {
189 $out =~ s/\cM//g;
190 &General::log("Dynamic DNS ip-update for dnsmadeeasy ID $settings{'HOSTNAME'} : failure ($out)");
191 } else {
192 &General::log("Dynamic DNS ip-update for dnsmadeeasy ID $settings{'HOSTNAME'} : success");
193 $success++;
194 }
195 } else {
196 &General::log("Dynamic DNS ip-update for dnsmadeeasy ID $settings{'HOSTNAME'} : failure (could not connect to server)");
197 }
198 }
199 elsif ($settings{'SERVICE'} eq 'dnspark') {
200 # use proxy ?
201 my %proxysettings;
202 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
203 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
204 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
205 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
206 }
207
208 if ($settings{'HOSTNAME'} eq '') {
209 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
210 } else {
211 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
212 }
213
214 my ($out, $response) = Net::SSLeay::get_https( "www.dnspark.net",
215 443,
216 "/api/dynamic/update.php?hostname=$settings{'HOSTDOMAIN'}&ip=$ip",
217 Net::SSLeay::make_headers('User-Agent' => 'Ipcop',
218 'Authorization' => 'Basic ' . encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}")
219 )
220 );
221 # Valid response are
222 # 'ok' 'nochange'
223 if ($response =~ m%HTTP/1\.. 200 OK%) {
224 if ( $out !~ m/^(ok|nochange)/ ) {
225 $out =~ s/\n/ /g;
226 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
227 } else {
228 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
229 $success++;
230 }
231 } else {
232 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server, check your credentials)");
233 }
234 }
235 elsif ($settings{'SERVICE'} eq 'dtdns') {
236 # use proxy ?
237 my %proxysettings;
238 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
239 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
240 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
241 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
242 }
243
244 if ($settings{'HOSTNAME'} eq '') {
245 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
246 } else {
247 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
248 }
249
250 my ($out, $response) = Net::SSLeay::get_http( 'www.dtdns.com',
251 80,
252 "/api/autodns.cfm?id=$settings{'HOSTDOMAIN'}&pw=$settings{'PASSWORD'}",
253 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
254 );
255 #Valid responses from service are:
256 # now points to
257 if ($response =~ m%HTTP/1\.. 200 OK%) {
258 if ( $out !~ m/Host .* now points to/ig ) {
259 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
260 } else {
261 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
262 $success++;
263 }
264 } else {
265 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
266 }
267 }
268 # dyndns-custom,dyndns-static,dyndns.org,dyns.cx => ez-ipupdate
269 elsif ($settings{'SERVICE'} eq 'dynu') {
270 # use proxy ?
271 my %proxysettings;
272 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
273 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
274 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
275 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
276 }
277
278 if ($settings{'HOSTNAME'} eq '') {
279 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
280 } else {
281 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
282 }
283
284 my ($out, $response) = Net::SSLeay::get_http( 'dynserv.ca',
285 80,
286 "/dyn/dynengine.cgi?func=set&name=$settings{'LOGIN'}&pass=$settings{'PASSWORD'}&ip=$ip&domain=$settings{'HOSTDOMAIN'}",
287 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
288 );
289 #Valid responses from service are:
290 # 02 == Domain already exists, refreshing data for ... => xxx.xxx.xxx.xxx
291 if ($response =~ m%HTTP/1\.. 200 OK%) {
292 if ( $out !~ m/Domain already exists, refreshing data for/ig ) {
293 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
294 } else {
295 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
296 $success++;
297 }
298 } else {
299 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
300 }
301 }
302 # easydns => see 'ez-ipupdate'
303 elsif ($settings{'SERVICE'} eq 'editdns') {
304 # use proxy ?
305 my %proxysettings;
306 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
307 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
308 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
309 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
310 }
311 if ($settings{'HOSTNAME'} eq '') {
312 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
313 } else {
314 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
315 }
316
317 my ($out, $response) = Net::SSLeay::get_http( 'dyndns.editdns.net',
318 80,
319 "/api/dynLinux.php?r=$settings{'HOSTDOMAIN'}&p=$settings{'PASSWORD'}",
320 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
321 );
322 #Valid responses from service are:
323 # Record has been updated
324 # Record already exists with the same IP
325 if ($response =~ m%HTTP/1\.. 200 OK%) {
326 if ( $out !~ m/Record (has been updated|already exists with the same IP)/ ) {
327 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
328 } else {
329 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
330 $success++;
331 }
332 } else {
333 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
334 }
335 }
336 elsif ($settings{'SERVICE'} eq 'enom') {
337 # use proxy ?
338 my %proxysettings;
339 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
340 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
341 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
342 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
343 }
344 if ($settings{'HOSTNAME'} eq '') {
345 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
346 } else {
347 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
348 }
349
350 my ($out, $response) = Net::SSLeay::get_http( 'dynamic.name-services.com',
351 80,
352 "/interface.asp?Command=SetDNSHost&Zone=$settings{'HOSTDOMAIN'}&DomainPassword=$settings{'PASSWORD'}&Address=$ip",
353 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
354 );
355 #Valid responses from service are:
356 # ErrCount=0
357 if ($response =~ m%HTTP/1\.. 200 OK%) {
358 if ( $out !~ m/ErrCount=0/ ) {
359 $out =~ s/(\n|\x0D)/ /g;
360 $out =~ /Err1=([\w ]+) /;
361 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($1)");
362 } else {
363 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
364 $success++;
365 }
366 } else {
367 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
368 }
369 }
370 elsif ($settings{'SERVICE'} eq 'everydns') {
371 # use proxy ?
372 my %proxysettings;
373 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
374 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
375 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
376 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
377 }
378
379 if ($settings{'HOSTNAME'} eq '') {
380 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
381 } else {
382 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
383 }
384 my $code64 = encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}");
385 my $version = "0.1"; # developped for this version of dyn server.
386
387 my ($out, $response) = Net::SSLeay::get_http( 'dyn.everydns.net',
388 80,
389 "/index.php?ver=$version&ip=$ip&domain=$settings{'HOSTDOMAIN'}",
390 Net::SSLeay::make_headers('User-Agent' => 'Ipcop',
391 'Authorization' => "Basic $code64")
392 );
393 #Valid responses from service are:
394 # "... Exit code: 0" 0:ok else error
395 if ($response =~ m%HTTP/1\.. 200 OK%) {
396 if ( $out !~ m/Exit code: 0/ig ) {
397 &General::log("Dynamic DNS everydns for $settings{'HOSTDOMAIN'} : failure ($out)");
398 } else {
399 &General::log("Dynamic DNS everydns for $settings{'HOSTDOMAIN'} : success");
400 $success++;
401 }
402 } else {
403 &General::log("Dynamic DNS everydns for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
404 }
405 }
406 elsif ($settings{'SERVICE'} eq 'freedns') {
407 # use proxy ?
408 my %proxysettings;
409 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
410 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
411 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
412 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
413 }
414
415 my ($out, $response) = Net::SSLeay::get_https( 'freedns.afraid.org',
416 443,
417 "/dynamic/update.php?$settings{'LOGIN'}",
418 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
419 );
420 #Valid responses from service are:
421 # Updated n host(s) <domain>
422 # ERROR: <ip> has not changed.
423 if ($response =~ m%HTTP/1\.. 200 OK%) {
424 if ( $out !~ m/(^Updated|Address .* has not changed)/ig ) {
425 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure ($out)");
426 } else {
427 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : success");
428 $success++;
429 }
430 } else {
431 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure (could not connect to server)");
432 }
433 }
434 elsif ($settings{'SERVICE'} eq 'namecheap') {
435 # use proxy ?
436 my %proxysettings;
437 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
438 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
439 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
440 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
441 }
442
443 my ($out, $response) = Net::SSLeay::get_https( 'dynamicdns.park-your-domain.com',
444 443,
445 "/update?host=$settings{'HOSTNAME'}&domain=$settings{'DOMAIN'}&password=$settings{'PASSWORD'}&ip=$ip",
446 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
447 );
448 #Valid responses from service are:
449 # wait confirmation!!
450 if ($response =~ m%HTTP/1\.. 200 OK%) {
451 if ( $out !~ m/<ErrCount>0<\/ErrCount>/ ) {
452 $out =~ m/<Err1>(.*)<\/Err1>/;
453 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure ($1)");
454 } else {
455 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : success");
456 $success++;
457 }
458 } else {
459 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure (could not connect to server)");
460 }
461 }
462 elsif ($settings{'SERVICE'} eq 'no-ip') {
463 # use proxy ?
464 my %proxysettings;
465 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
466 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
467 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
468 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
469 }
470 my $request = "username=$settings{'LOGIN'}&pass=$settings{'PASSWORD'}&ip=$ip";
471 my $display;
472 if ($settings{'HOSTNAME'} !~ s/$General::noipprefix//) {
473 if ($settings{'HOSTNAME'} eq "") {
474 $request .= "&h[]=$settings{'DOMAIN'}";
475 $display = "$settings{'DOMAIN'}";
476 } else {
477 $request .= "&h[]=$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
478 $display = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
479 }
480 } else {
481 $request .= "&groupname=$settings{'HOSTNAME'}";
482 $display = "group:$settings{'HOSTNAME'}";
483 }
484 $request = encode_base64($request,"");
485
486 my ($out, $response) = Net::SSLeay::get_http( 'dynupdate.no-ip.com',
487 80,
488 "/ducupdate.php?requestL=$request",
489 Net::SSLeay::make_headers('User-Agent' => 'IPCop/'.${General::version} )
490 );
491
492 if ($response =~ m%HTTP/1\.. 200 OK%) {
493 # expected response format: [host].[domain]:[return_code]
494 # example: myhost.example.com:0
495 if ($out =~ m/:(.*)/) {
496 if (($1 == 0) || ($1 == 11) || ($1 == 12)) {
497 # 0 is success, 11 is success group, 12 is already set group
498 &General::log("Dynamic DNS ip-update for $display : success");
499 $success++;
500 } else {
501 &General::log("Dynamic DNS ip-update for $display : failure ($1)");
502 }
503 } else {
504 &General::log("Dynamic DNS ip-update for $display : failure ($out)");
505 }
506 } else {
507 &General::log("Dynamic DNS ip-update for $display : failure (could not connect to server)");
508 }
509 }
510 elsif ($settings{'SERVICE'} eq 'nsupdate') {
511 # Fetch UI configurable values and assemble the host name.
512
513 my $hostName="$settings{'DOMAIN'}";
514 if ($settings{'HOSTNAME'} ne "") {
515 $hostName="$settings{'HOSTNAME'}.$hostName";
516 }
517 my $keyName=$settings{'LOGIN'};
518 my $keySecret=$settings{'PASSWORD'};
519
520 # Use a relatively long TTL value to reduce load on DNS.
521 # Some public Dynamic DNS servers use values around 4 hours,
522 # some use values as low as 60 seconds.
523 # XXX Maybe we could fetch the master value from the server
524 # (not the timed-down version supplied by DNS cache)
525
526 my $timeToLive="3600";
527
528 # Internal setting that can be used to override the DNS server
529 # where the update is applied. It can be of use when testing
530 # against a private DNS server.
531
532 my $masterServer="";
533
534 # Prepare the nsupdate command script to remove and re-add the
535 # updated A record for the domain.
536
537 my $cmdFile="/tmp/nsupdate-$hostName-commands";
538 my $logFile="/tmp/nsupdate-$hostName-result";
539 open(TF, ">$cmdFile");
540 if ($masterServer ne "") {
541 print TF "server $masterServer\n";
542 }
543 if ($keyName ne "" && $keySecret ne "") {
544 print TF "key $keyName $keySecret\n";
545 }
546 print TF "update delete $hostName A\n";
547 print TF "update add $hostName $timeToLive A $ip\n";
548 print TF "send\n";
549 close(TF);
550
551 # Run nsupdate with -v to use TCP instead of UDP because we're
552 # issuing multiple cmds and potentially long keys, and -d to
553 # get diagnostic result output.
554
555 my $result = system("/usr/bin/nsupdate -v -d $cmdFile 2>$logFile");
556 if ($result != 0) {
557 &General::log("Dynamic DNS ip-update for $hostName : failure");
558 open(NSLOG, "$logFile");
559 my @nsLog = <NSLOG>;
560 close(NSLOG);
561 my $logLine;
562 foreach $logLine (@nsLog) {
563 chomp($logLine);
564 if ($logLine ne "") {
565 &General::log("... $logLine");
566 }
567 }
568 } else {
569 &General::log("Dynamic DNS ip-update for $hostName : success");
570 $success++;
571 }
572 unlink $cmdFile, $logFile;
573 }
574 # ods => ez-ipupdate
575 elsif ($settings{'SERVICE'} eq 'opendns') {
576 # use proxy ?
577 my %proxysettings;
578 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
579 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
580 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
581 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
582 }
583
584 if ($settings{'HOSTNAME'} eq '') {
585 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
586 } else {
587 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
588 }
589
590 my ($out, $response) = Net::SSLeay::get_https( "updates.opendns.com",
591 443,
592 "/account/ddns.php?hostname=$settings{'HOSTDOMAIN'}&myip=$ip",
593 Net::SSLeay::make_headers('User-Agent' => 'Ipcop',
594 'Authorization' => 'Basic ' . encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}")
595 )
596 );
597 #Valid responses from service are:
598 # 'good ip-address' , 'nochg ip-address' (ez-ipupdate like)
599 if ($response =~ m%HTTP/1\.. 200 OK%) {
600 if ($out =~ m/good |nochg /ig) {
601 &General::log("Dynamic DNS ip-update for opendns $settings{'HOSTDOMAIN'} : success");
602 $success++;
603 } else {
604 &General::log("Dynamic DNS ip-update for opendns $settings{'HOSTDOMAIN'} : failure ($out)");
605 }
606 } elsif ( $out =~ m/<title>(.*)<\/title>/ig ) {
607 &General::log("Dynamic DNS ip-update for opendns $settings{'HOSTDOMAIN'} : failure ($1)");
608 } else {
609 &General::log("Dynamic DNS ip-update for opendns $settings{'HOSTDOMAIN'} : failure ($response)");
610 }
611 }
612 elsif ($settings{'SERVICE'} eq 'ovh') {
613 # use proxy ?
614 my %proxysettings;
615 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
616 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
617 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
618 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
619 }
620 if ($settings{'DOMAIN'} eq '') {
621 $settings{'HOSTDOMAIN'} = $settings{'HOSTNAME'};
622 } else {
623 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
624 }
625
626 my $code64 = encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}");
627 chomp($code64);
628 my ($out, $response) = Net::SSLeay::get_https( 'www.ovh.com',
629 443,
630 "/nic/update?system=dyndns&hostname=$settings{'HOSTDOMAIN'}&myip=$ip",
631 Net::SSLeay::make_headers('User-Agent' => 'Ipcop',
632 'Authorization' => "Basic $code64" )
633 );
634 #Valid responses from service are:
635 # 'good ip-address' , 'nochg ip-address' (ez-ipupdate like)
636 if ($response =~ m%HTTP/1\.. 200 OK%) {
637 if ($out =~ m/good |nochg /ig) {
638 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
639 $success++;
640 } else {
641 &General::log("Dynamic DNS ovh.com for $settings{'HOSTDOMAIN'} : failure ($out)");
642 }
643 } elsif ( $out =~ m/<title>(.*)<\/title>/ig ) {
644 &General::log("Dynamic DNS ovh.com for $settings{'HOSTDOMAIN'} : failure ($1)");
645 } else {
646 &General::log("Dynamic DNS ovh.com for $settings{'HOSTDOMAIN'} : failure ($response)");
647 }
648 }
649 elsif ($settings{'SERVICE'} eq 'regfish') {
650 # use proxy ?
651 my %proxysettings;
652 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
653 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
654 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
655 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
656 }
657 my ($out, $response) = Net::SSLeay::get_https( 'dyndns.regfish.de',
658 443,
659 "/?fqdn=$settings{'DOMAIN'}&ipv4=$ip&forcehost=1&authtype=secure&token=$settings{'LOGIN'}",
660 Net::SSLeay::make_headers('User-Agent' => 'Ipfire' )
661 );
662 #Valid responses from service are:
663 # success|100|update succeeded!
664 # success|101|no update needed at this time..
665 if ($response =~ m%HTTP/1\.. 200 OK%) {
666 if ( $out !~ m/(success\|(100|101)\|)/ig ) {
667 &General::log("Dynamic DNS ip-update for $settings{'DOMAIN'} : failure ($out)");
668 } else {
669 &General::log("Dynamic DNS ip-update for $settings{'DOMAIN'} : success");
670 $success++;
671 }
672 } else {
673 &General::log("Dynamic DNS ip-update for $settings{'DOMAIN'} : failure (could not connect to server)");
674 }
675 }
676 elsif ($settings{'SERVICE'} eq 'registerfly') {
677 # use proxy ?
678 my %proxysettings;
679 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
680 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
681 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
682 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
683 }
684
685 my ($out, $response) = Net::SSLeay::get_https( 'dynamic.registerfly.com',
686 443,
687 "?domain=$settings{'DOMAIN'}&password=$settings{'PASSWORD'}&host=$settings{'HOSTNAME'}&ipaddress=$ip",
688 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
689 );
690 #Valid responses from service are:
691 # <strong><b>Your Dynamic DNS change was accepted by our system</b></strong>
692 if ($response =~ m%HTTP/1\.. 200 OK%) {
693 if ( $out !~ m/DNS change was accepted/ig ) {
694 $out =~ /<strong>(.*)<\/strong>/;
695 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure ($1)");
696 } else {
697 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : success");
698 $success++;
699 }
700 } else {
701 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'}.$settings{'DOMAIN'} : failure (could not connect to server)");
702 }
703 }
704 elsif ($settings{'SERVICE'} eq 'sitelutions') {
705 # use proxy ?
706 my %proxysettings;
707 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
708 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
709 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
710 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
711 }
712
713 my ($out, $response) = Net::SSLeay::get_https( 'www.sitelutions.com',
714 443,
715 "/dnsup?ttl=60&id=$settings{'HOSTNAME'}&user=$settings{'LOGIN'}&pass=$settings{'PASSWORD'}&ip=$ip",
716 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
717 );
718 #Valid responses from service are:
719 # success
720 if ($response =~ m%HTTP/1\.. 200 OK%) {
721 if ( $out !~ m/(success)/ ) {
722 $out =~ s/\n/ /g;
723 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'} : failure ($out)");
724 } else {
725 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'} : success");
726 $success++;
727 }
728 } else {
729 &General::log("Dynamic DNS ip-update for $settings{'HOSTNAME'} : failure (could not connect to server)");
730 }
731 }
732 elsif ($settings{'SERVICE'} eq 'selfhost') {
733 # use proxy ?
734 my %proxysettings;
735 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
736 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
737 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
738 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
739 }
740 if ($settings{'DOMAIN'} eq '') {
741 $settings{'HOSTDOMAIN'} = "selfhost.de ($settings{'LOGIN'})";
742 } else {
743 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
744 }
745
746 my ($out, $response) = Net::SSLeay::get_https( 'carol.selfhost.de',
747 443,
748 "/update?username=$settings{'LOGIN'}&password=$settings{'PASSWORD'}&textmodi=1",
749 Net::SSLeay::make_headers('User-Agent' => 'Ipcop' )
750 );
751 #Valid responses from service are:
752 # status=200 status=204
753 if ($response =~ m%HTTP/1\.. 200 OK%) {
754 if ( $out !~ m/status=(200|204)/ ) {
755 $out =~ s/\n/ /g;
756 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
757 } else {
758 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
759 $success++;
760 }
761 } else {
762 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure (could not connect to server)");
763 }
764 }
765 # strato
766 elsif ($settings{'SERVICE'} eq 'strato') {
767 # use proxy ?
768 my %proxysettings;
769 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
770 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
771 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
772 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
773 }
774
775 if ($settings{'HOSTNAME'} eq '') {
776 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
777 } else {
778 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
779 }
780
781 my ($out, $response) = Net::SSLeay::get_https( "dyndns.strato.com",
782 443,
783 "/nic/update?hostname=$settings{'HOSTDOMAIN'}&myip=$ip",
784 Net::SSLeay::make_headers('User-Agent' => 'Ipcop',
785 'Authorization' => 'Basic ' . encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}")
786 )
787 );
788 # Valid response are 'ok' 'nochange'
789 if ($response =~ m%HTTP/1\.. 200 OK%) {
790 if ($out =~ m/good |nochg /ig) {
791 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : success");
792 $success++;
793 } else {
794 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($out)");
795 }
796 } elsif ( $out =~ m/<title>(.*)<\/title>/ig ) {
797 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($1)");
798 } else {
799 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'} : failure ($response)");
800 }
801 }
802 elsif ($settings{'SERVICE'} eq 'tiggerswelt') {
803 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
804
805 my ($out, $response) = Net::SSLeay::get_https( "ssl.tiggerswelt.net",
806 443,
807 "/nic/update?hostname=$settings{'HOSTDOMAIN'}&myip=$ip",
808 Net::SSLeay::make_headers('User-Agent' => 'IPCop',
809 'Authorization' => 'Basic ' . encode_base64("$settings{'LOGIN'}:$settings{'PASSWORD'}")
810 )
811 );
812
813 if ($response =~ m%HTTP/1\.. 200 OK%) {
814 if ($out =~ m/good |nochg /ig) {
815 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'}: success");
816 $success++;
817 } else {
818 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'}: failure ($out)");
819 }
820 } else {
821 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'}: failure ($response)");
822 }
823 }
824 # zonedit => see 'ez-ipupdate'
825 else {
826 if ($settings{'WILDCARDS'} eq 'on') {
827 $settings{'WILDCARDS'} = '-w';
828 } else {
829 $settings{'WILDCARDS'} = '';
830 }
831 if (($settings{'SERVICE'} eq 'dyndns-custom' ||
832 $settings{'SERVICE'} eq 'easydns' ||
833 $settings{'SERVICE'} eq 'zoneedit') && $settings{'HOSTNAME'} eq '') {
834 $settings{'HOSTDOMAIN'} = $settings{'DOMAIN'};
835 } else {
836 $settings{'HOSTDOMAIN'} = "$settings{'HOSTNAME'}.$settings{'DOMAIN'}";
837 }
838 my @ddnscommand = ('/usr/bin/ez-ipupdate', '-a', "$ip", '-S', "$settings{'SERVICE'}", '-u', "$settings{'LOGIN'}:$settings{'PASSWORD'}", '-h', "$settings{'HOSTDOMAIN'}", "$settings{'WILDCARDS'}", '-q');
839 my $result = system(@ddnscommand);
840 if ( $result != 0) {
841 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'}: failure");
842 } else {
843 &General::log("Dynamic DNS ip-update for $settings{'HOSTDOMAIN'}: success");
844 $success++;
845 }
846 }
847 # DEBUG:
848 #print "Success: $success, file: $ipCacheFile\n";
849 # write current IP to specific cache file
850 if ($success == 1) {
851 open(IPCACHE, ">$ipCacheFile");
852 flock IPCACHE, 2;
853 print IPCACHE $ip;
854 close(IPCACHE);
855 }
856 }
857 exit 0;
858
859 # Extracted from Base64.pm
860 sub encode_base64 ($;$) {
861 my $res = "";
862 my $eol = $_[1];
863 $eol = "\n" unless defined $eol;
864 pos($_[0]) = 0; # ensure start at the beginning
865 while ($_[0] =~ /(.{1,45})/gs) {
866 $res .= substr(pack('u', $1), 1);
867 chop($res);
868 }
869 $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs
870 # fix padding at the end
871 my $padding = (3 - length($_[0]) % 3) % 3;
872 $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
873 # break encoded string into lines of no more than 76 characters each
874 if (length $eol) {
875 $res =~ s/(.{1,76})/$1$eol/g;
876 }
877 $res;
878 }