<pre style='margin:0'>
Ryan Schmidt (ryandesign) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/e864fde4e5a2a1b0ef040cc297b64ca10d7f6abb">https://github.com/macports/macports-ports/commit/e864fde4e5a2a1b0ef040cc297b64ca10d7f6abb</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit e864fde4e5a2a1b0ef040cc297b64ca10d7f6abb
</span>Author: Steven Thomas Smith <s.t.smith@ieee.org>
AuthorDate: Sat Oct 10 10:25:12 2020 -0400

<span style='display:block; white-space:pre;color:#404040;'>    dovecot: Update APNS Service to use Apple's new HTTP/2-based APNs
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    * Legacy binary protocol deprecated as of November 2020
</span><span style='display:block; white-space:pre;color:#404040;'>    * https://developer.apple.com/news/?id=11042019a&1572897862
</span>---
 mail/dovecot/Portfile                     |  22 ++-
 mail/dovecot/files/Net/APNS/SimpleCert.pm | 245 ++++++++++++++++++++++++++++++
 mail/dovecot/files/pushnotify.pl          | 184 +++++++---------------
 3 files changed, 318 insertions(+), 133 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/mail/dovecot/Portfile b/mail/dovecot/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index fae4923163e..c46d9f42b08 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/mail/dovecot/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/mail/dovecot/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -5,7 +5,7 @@ PortGroup           github 1.0
</span> 
 github.setup        dovecot core 2.3.11.3
 name                dovecot
<span style='display:block; white-space:pre;background:#ffe0e0;'>-revision            1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+revision            2
</span> epoch               20060722
 set core_version    ${version}
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -16,10 +16,12 @@ license             LGPL-2.1
</span> homepage            https://www.dovecot.org
 
 description         Secure, fast imap and pop3 server
<span style='display:block; white-space:pre;background:#ffe0e0;'>-long_description    Dovecot is an IMAP and POP3 server for Linux/UNIX-like\
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    systems, written with security primarily in mind. Although\
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    it is written in C, it uses several coding techniques to\
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    avoid most of the common pitfalls.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+long_description    Dovecot is an IMAP and POP3 server for \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    Linux/UNIX-like systems, written with security \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    primarily in mind. Although it is written in C, it \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    uses several coding techniques to avoid most of \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    the common pitfalls.
</span> 
 checksums           rmd160  78920585b85a6ff582711f4d3b1ea9be9254197f \
                     sha256  242ecbf563b07ce9c5201464f1d0c42ec0df8511de0eda46129b6c42d5b97fe2 \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -185,13 +187,17 @@ if {${name} eq ${subport}} {
</span>         }
         depends_run-append \
                         port:perl${perl5_major_version} \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        port:p${perl5_major_version}-net-apns-persistent \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        port:p${perl5_major_version}-privileges-drop
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        port:p${perl5_major_version}-json \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        port:p${perl5_major_version}-moo \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        port:p${perl5_major_version}-privileges-drop \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        port:p${perl5_major_version}-protocol-http2
</span>         pre-destroot {
             xinstall -m 0750 -d \
                 -o ${default_internal_user} -g ${default_login_user} \
                 ${destroot}${prefix}/etc/${name}-apns \
                 ${destroot}${prefix}/var/db/${name}-apns
<span style='display:block; white-space:pre;background:#e0ffe0;'>+            xinstall -m 0755 -d \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ${destroot}${prefix}/lib/pushnotify/Net/APNS
</span>             close [open ${destroot}${prefix}/var/db/${name}-apns/devices a]
             file attributes \
                 ${destroot}${prefix}/var/db/${name}-apns/devices \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -202,6 +208,8 @@ if {${name} eq ${subport}} {
</span>                 ${destroot}${prefix}/var/db/${name}-apns
             xinstall -m 0755 ${filespath}/pushnotify.pl \
                 ${destroot}${prefix}/sbin
<span style='display:block; white-space:pre;background:#e0ffe0;'>+            xinstall -m 0755 ${filespath}/Net/APNS/SimpleCert.pm \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ${destroot}${prefix}/lib/pushnotify/Net/APNS
</span>             foreach cmd [list \
                 "s|@PREFIX@|${prefix}|g" \
                 "s|@PERL5_MAJOR_VERSION@|${perl5_major_version}|g" \
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/mail/dovecot/files/Net/APNS/SimpleCert.pm b/mail/dovecot/files/Net/APNS/SimpleCert.pm
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..b83d59495ac
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/mail/dovecot/files/Net/APNS/SimpleCert.pm
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,245 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+package Net::APNS::SimpleCert;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use 5.008001;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use strict;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use warnings;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use Carp ();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use JSON;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use Moo;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use Protocol::HTTP2::Client;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use IO::Select;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use IO::Socket::SSL qw();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+our $VERSION = "0.04";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+has [qw/cert key development/] => (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    is => 'rw',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+has apns_expiration => (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    is => 'rw',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    default => 0,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+has apns_priority => (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    is => 'rw',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    default => 10,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub algorithm {'ES256'}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub _host {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return 'api.' . ($self->development ? 'development.' : '') . 'push.apple.com'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub _port {443}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub _socket {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!$self->{_socket} || !$self->{_socket}->opened){
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # TLS transport socket
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $self->{_socket} = IO::Socket::SSL->new(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            PeerHost => $self->_host,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            PeerPort => $self->_port,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # openssl 1.0.1 support only NPN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SSL_npn_protocols => ['h2'],
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # openssl 1.0.2 also have ALPN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SSL_alpn_protocols => ['h2'],
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SSL_version => 'TLSv1_2',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # for certificate authentication
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SSL_cert_file => $self->cert,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SSL_key_file => $self->key,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ) or die $! || $IO::Socket::SSL::SSL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # non blocking
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $self->{_socket}->blocking(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return $self->{_socket};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub _client {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $self->{_client} ||= Protocol::HTTP2::Client->new(keepalive => 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return $self->{_client};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub prepare {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self, $device_token, $payload, $cb) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   my $path = sprintf '/3/device/%s', $device_token;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    push @{$self->{_request}}, {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ':scheme' => 'https',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ':authority' => join(":", $self->_host, $self->_port),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ':path' => $path,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ':method' => 'POST',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        headers => [
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            'apns-expiration' => $self->apns_expiration,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            'apns-priority' => $self->apns_priority,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ],
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        data => JSON::encode_json($payload),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        on_done => $cb,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return $self;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub _make_client_request_single {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (my $req = shift @{$self->{_request}}){
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        my $done_cb = delete $req->{on_done};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $self->_client->request(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            %$req,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            on_done => sub {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ref $done_cb eq 'CODE'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    and $done_cb->(@_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                $self->_make_client_request_single();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            },
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $self->_client->close;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sub notify {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my ($self) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # request one by one as APNS server returns SETTINGS_MAX_CONCURRENT_STREAMS = 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $self->_make_client_request_single();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my $io = IO::Select->new($self->_socket);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # send/recv frames until request is done
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    while ( !$self->_client->shutdown ) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $io->can_write;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        while ( my $frame = $self->_client->next_frame ) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            syswrite $self->_socket, $frame;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        $io->can_read;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        while ( sysread $self->_socket, my $data, 4096 ) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            $self->_client->feed($data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    undef $self->{_client};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $self->_socket->close(SSL_ctx_free => 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__END__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=encoding utf-8
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 NAME
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Net::APNS::SimpleCert - APNS Perl implementation
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 DESCRIPTION
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+A Perl implementation for sending notifications via APNS using Apple's new HTTP/2 API.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This library uses Protocol::HTTP2::Client as http2 backend.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+And it also supports multiple stream at one connection.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+(It does not correspond to parallel stream because APNS server returns SETTINGS_MAX_CONCURRENT_STREAMS = 1.)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 SYNOPSIS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    use Net::APNS::SimpleCert;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    my $apns = Net::APNS::SimpleCert->new(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # enable if development
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # development => 1,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        cert => '/path/to/certificate.pem',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        key => '/path/to/key.pem',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        apns_expiration => 0,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        apns_priority => 10,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # 1st request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $apns->prepare('DEVICE_ID',{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            aps => {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                alert => 'APNS message: HELLO!',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                badge => 1,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                sound => "default",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                # SEE: https://developer.apple.com/jp/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            },
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }, sub {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            my ($header, $content) = @_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            require Data::Dumper;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            print Dumper $header;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # $VAR1 = [
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #           ':status',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #           '200',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #           'apns-id',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #           '791DE8BA-7CAA-B820-BD2D-5B12653A8DF3'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #         ];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            print Dumper $content;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # $VAR1 = undef;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # 2nd request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $apns->prepare(...);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # also supports method chain
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # $apns->prepare(1st request)->prepare(2nd request)....
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # send notification
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $apns->notify();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 METHODS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head2 my $apns = Net::APNS::SimpleCert->new(%arg)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=over
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=item development : bool
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Switch API's URL to 'api.development.push.apple.com' if enabled.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=item cert : string
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Path to Apple push notification certificate.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=item key : string
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Path to Apple push notification certificate's private key.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=item apns_expiration : number
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Default 0.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=item apns_priority : number
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Default 10.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=back
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    All properties can be accessed as Getter/Setter like `$apns->development`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head2 $apns->prepare($DEVICE_ID, $PAYLOAD);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Prepare notification.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It is possible to specify more than one. Please do before invoking notify method.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    $apns->prepare(1st request)->prepare(2nd request)....
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Payload please refer: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head2 $apns->notify();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Execute notification.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Multiple notifications can be executed with one SSL connection.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 LICENSE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Based on Net::APNS::Simple, Copyright (C) Tooru Tsurukawa.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This library is free software; you can redistribute it and/or modify
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+it under the same terms as Perl itself.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=head1 AUTHOR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Tooru Tsurukawa E<lt>rockbone.g at gmail.comE<gt>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Modifications by Matthew Powell E<lt>matthew at atom.netE<gt>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+https://github.com/rockbone/p5-Net-APNS-Simple
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+=cut
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/mail/dovecot/files/pushnotify.pl b/mail/dovecot/files/pushnotify.pl
</span><span style='display:block; white-space:pre;color:#808080;'>index 4b72b4de5b5..862e329fa23 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/mail/dovecot/files/pushnotify.pl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/mail/dovecot/files/pushnotify.pl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,14 +1,15 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#!@PREFIX@/bin/perl@PERL5_MAJOR_VERSION@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#!@PREFIX@/bin/perl@PERL5_MAJOR_VERSION@ -w -T
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# Based on https://github.com/matthewpowell/pushnotify
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# LGPLv2.1
</span> 
 use strict;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-use warnings;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use lib '@PREFIX@/lib/pushnotify';
</span> 
 use Privileges::Drop;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-use Getopt::Long;
</span> use IO::Socket::UNIX qw( SOCK_DGRAM SOMAXCONN );
 use Sys::Syslog qw( openlog syslog LOG_INFO );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-use Net::APNS::Persistent;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-use Net::APNS::Feedback;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use Net::APNS::SimpleCert;
</span> 
 sub save_devices;
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -17,170 +18,101 @@ my $sockpath = '@PREFIX@/var/run/dovecot/push_notify';
</span> 
 # user to drop privileges to
 my $user = '@DEFAULT_INTERNAL_USER@';
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # A file containing registration information
 my $devicepath = '@PREFIX@/var/db/dovecot-apns/devices';
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # APNS certificate
 my $apns_cert = '@PREFIX@/etc/dovecot-apns/com.apple.mail.cert.pem';
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # APNS key (might be the same as $apns_cert)
 my $apns_key = '@PREFIX@/etc/dovecot-apns/com.apple.mail.key.pem';
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-my $help;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-sub usage {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-<<"EOF";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-$0 [arguments]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-Arguments:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  --user <unprivileged_user>     (default $user)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  --tokendb <devices_file>       (default $devicepath)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  --certfile <apns_certificate>  (default $apns_cert)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  --keyfile <apns_privkey>       (default $apns_key)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  --help
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-EOF
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-GetOptions('user=s'     => \$user,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           'tokendb=s'  => \$devicepath,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           'certfile=s' => \$apns_cert,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           'keyfile=s'  => \$apns_key,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           'help'       => \$help)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-or die usage;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-if ($help) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  print usage;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  exit 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> # Read in the list of registered devices.
 my %devices;
 if (open DEVICES, $devicepath) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-while (<DEVICES>) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   chomp;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   my ($username, $devicedata) = split /:/;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   push @{$devices{$username}}, $devicedata;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-close DEVICES;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   while (<DEVICES>) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           chomp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           my ($username, $devicedata) = split /:/;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           push @{$devices{$username}}, $devicedata;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   close DEVICES;
</span> }
 
 # Open the socket to Dovecot
 unlink $sockpath;
 umask (0111);
 my $socket = IO::Socket::UNIX->new(
<span style='display:block; white-space:pre;background:#ffe0e0;'>-Type   => SOCK_DGRAM,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-Local  => $sockpath,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-Listen => SOMAXCONN,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-or die("Can't create server socket: $!\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   Type  => SOCK_DGRAM,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   Local => $sockpath,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   Listen => SOMAXCONN,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+) or die("Can't create server socket: $!\n");
</span> 
 drop_privileges($user);
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-openlog ('apns', 'ndelay', 'mail');
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# When we last checked the feedback service (right now, never).
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-my $last_feedback = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-# When we last reconnected to APNS
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-my $last_connect = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+openlog ('pushnotify', 'ndelay', 'mail');
</span> 
 # We'll defer connecting to APNS until our first notification, but define $apns here
 my $apns;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-syslog (LOG_INFO, 'Dovecot APNS service running');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+syslog (LOG_INFO, 'Atomnet push notify service running');
</span> 
 while(1)
 {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-my $data;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-$socket->recv($data, 2048);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-my $pretty = join('|', split(/\0+/, $data));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-my ($junk, $username, $aps_acct_id, $aps_dev_token, $aps_sub_topic) = split /\0+/, $data;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-if ($aps_acct_id) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   $aps_dev_token = lc($aps_dev_token);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   my $devicedata = join ',', $aps_acct_id, $aps_dev_token, $aps_sub_topic, time;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   syslog (LOG_INFO, "Register device $aps_dev_token for $username");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   # Cancel any duplicate registration
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   @{$devices{$username}} = grep {!/$aps_dev_token/} @{$devices{$username}};
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   # Register new device
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   push @{$devices{$username}}, $devicedata;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   save_devices;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-} else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   if (defined $devices{$username}) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           # User has at least one device registered
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           # Do the push notification
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           foreach (@{$devices{$username}}) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   my ($aps_acct_id, $aps_dev_token, $aps_sub_topic, $time) = split /,/;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   syslog(LOG_INFO, "Send notification to $aps_dev_token for $username");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   eval {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           die if (time - $last_connect > 600);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           $apns->queue_notification (
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   $aps_dev_token,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           aps => {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   'account-id' => $aps_acct_id
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           },
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   });
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           $apns->send_queue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   my $data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   $socket->recv($data, 2048);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   my ($junk, $username, $aps_acct_id, $aps_dev_token, $aps_sub_topic) = split /\0+/, $data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if ($aps_acct_id) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           $aps_dev_token = lc($aps_dev_token);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           my $devicedata = join ',', $aps_acct_id, $aps_dev_token, $aps_sub_topic, time;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           syslog (LOG_INFO, "Register device $aps_dev_token for $username");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           # Cancel any duplicate registration
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           @{$devices{$username}} = grep {!/$aps_dev_token/} @{$devices{$username}};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           # Register new device
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           push @{$devices{$username}}, $devicedata;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           save_devices;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           if (defined $devices{$username}) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   # User has at least one device registered
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   # Do the push notification
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   foreach (@{$devices{$username}}) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           my ($aps_acct_id, $aps_dev_token, $aps_sub_topic, $time) = split /,/;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           syslog(LOG_INFO, "Send notification to $aps_dev_token for $username");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           eval {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                   $apns->prepare (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                           $aps_dev_token,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                           {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                                   aps => {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                                           'account-id' => $aps_acct_id
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                                   },
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                           });
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                   $apns->notify;
</span>                                   1;
                                } or do {
                                        # Failed; connect to APNS and try again
                                        syslog(LOG_INFO, 'Connect to APNS push gateway');
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                        $last_connect = time;
</span>                                   eval { $apns->disconnect };
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                        $apns = Net::APNS::Persistent->new({
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           sandbox => 0,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                   $apns = Net::APNS::SimpleCert->new({
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                           development => 0,
</span>                                           cert => $apns_cert,
                                                key => $apns_key 
                                        });
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                        $apns->queue_notification (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                   $apns->prepare (
</span>                                           $aps_dev_token,
                                                {
                                                        aps => {
                                                                'account-id' => $aps_acct_id
                                                        },
                                                });
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                        $apns->send_queue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                   $apns->notify;
</span>                           }       
                        }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   # Check for devices that don't want notifications any more
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   if (time - $last_feedback > 3600) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           syslog(LOG_INFO, 'Check APNS feedback service');
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           $last_feedback = time;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           my $apns_feedback = Net::APNS::Feedback->new({
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   sandbox => 0,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   cert => $apns_cert,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   key => $apns_key
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           });
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           my $feedback =  $apns_feedback->retrieve_feedback;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           $apns_feedback->disconnect;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           if (defined $feedback) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   # Got at least one value
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   foreach (@$feedback) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           my $feedback_token = lc($$_{token});
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           my $feedback_time = $$_{time_t};
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           foreach my $username (keys %devices) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   my @unregister; 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   foreach (@{$devices{$username}}) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                           my ($aps_acct_id, $aps_dev_token, $aps_sub_topic, $time) = split /,/;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                           if ($aps_dev_token eq $feedback_token && $time < $feedback_time) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                                   # Hasn't registered since the rejection; unregister
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                                   push @unregister, $feedback_token
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                           }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   foreach my $token (@unregister) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                           syslog(LOG_INFO, "Unregister device $token");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                           @{$devices{$username}} = grep {!/$token/} @{$devices{$username}};
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                                   }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                           }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                   save_devices;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                           }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   }
</span>           }
        }
 }
</pre><pre style='margin:0'>

</pre>