]> git.mxchange.org Git - friendica.git/blobdiff - include/notifier.php
improvied group highlighting, move new group link down
[friendica.git] / include / notifier.php
index 0beb72cd0e76e0725cb718a452262cabcbd712b1..9c194d962cfbbc5e419d94a354a7f391612244c0 100644 (file)
 <?php
+require_once("boot.php");
 
+function notifier_run($argv, $argc){
+       global $a, $db;
 
+       if(is_null($a)){
+               $a = new App;
+       }
+  
+       if(is_null($db)) {
+               @include(".htconfig.php");
+               require_once("dba.php");
+               $db = new dba($db_host, $db_user, $db_pass, $db_data);
+                       unset($db_host, $db_user, $db_pass, $db_data);
+       }
 
+       require_once("session.php");
+       require_once("datetime.php");
+       require_once('include/items.php');
+       require_once('include/bbcode.php');
 
-/*
-The reason for the MySQL "Lost Connection during query" issue when forking is the fact that the child process inherits the parent's database connection. When the child exits, the connection is closed. If the parent is performing a query at this very moment, it is doing it on an already closed connection, hence the error.
+       load_config('config');
+       load_config('system');
 
-An easy way to avoid this is to create a new database connection in parent immediately after forking. Don't forget to force a new connection by passing true in the 4th argument of mysql_connect():
+       load_hooks();
 
+       if($argc < 3)
+               return;
 
+       $a->set_baseurl(get_config('system','url'));
 
+       logger('notifier: invoked: ' . print_r($argv,true));
 
-$pid = pcntl_fork();
-            
-if ( $pid == -1 ) {       
-    // Fork failed           
-    exit(1);
-} else if ( $pid ) {
-       // parent process - regenerate our connections in case the kid kills them
-       @include(".htconfig.php");
-       $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
-       unset($db_host, $db_user, $db_pass, $db_data);
-       session_write_close();
-       session_start();
+       $cmd = $argv[1];
 
-       return;
-} else {
-    // We are the child
-    // Do something with the inherited connection here
-    // It will get closed upon exit
-    exit(0);
-?>
+       switch($cmd) {
 
+               case 'mail':
+               default:
+                       $item_id = intval($argv[2]);
+                       if(! $item_id){
+                               return;
+                       }
+                       break;
+       }
 
-If you want to execute some code after your php page has been returned to the user. Try something like this -
+       $expire = false;
+       $top_level = false;
+       $recipients = array();
+       $url_recipients = array();
 
-<?php
-function index()
-{
-        function shutdown() {
-            posix_kill(posix_getpid(), SIGHUP);
-        }
+       if($cmd === 'mail') {
 
-        // Do some initial processing
+               $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
+                               intval($item_id)
+               );
+               if(! count($message)){
+                       return;
+               }
+               $uid = $message[0]['uid'];
+               $recipients[] = $message[0]['contact-id'];
+               $item = $message[0];
 
-        echo("Hello World");
+       }
+       elseif($cmd === 'expire') {
+               $expire = true;
+               $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1 
+                       AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP - INTERVAL 10 MINUTE",
+                       intval($item_id)
+               );
+               $uid = $item_id;
+               $item_id = 0;
+               if(! count($items))
+                       return;
+       }
+       elseif($cmd === 'suggest') {
+               $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
+                       intval($item_id)
+               );
+               if(! count($suggest))
+                       return;
+               $uid = $suggest[0]['uid'];
+               $recipients[] = $suggest[0]['cid'];
+               $item = $suggest[0];
+       }
+       else {
 
-        // Switch over to daemon mode.
+               // find ancestors
+               $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
+                       intval($item_id)
+               );
 
-        if ($pid = pcntl_fork())
-            return;     // Parent
+               if((! count($r)) || (! intval($r[0]['parent']))) {
+                       return;
+               }
 
-        ob_end_clean(); // Discard the output buffer and close
+               $parent_item = $r[0];
+               $parent_id = intval($r[0]['parent']);
+               $uid = $r[0]['uid'];
+               $updated = $r[0]['edited'];
 
-        fclose(STDIN);  // Close all of the standard
-        fclose(STDOUT); // file descriptors as we
-        fclose(STDERR); // are running as a daemon.
+               $items = q("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id` ASC",
+                       intval($parent_id)
+               );
 
-        register_shutdown_function('shutdown');
+               if(! count($items)) {
+                       return;
+               }
 
-        if (posix_setsid() < 0)
-            return;
+               // avoid race condition with deleting entries
 
-        if ($pid = pcntl_fork())
-            return;     // Parent
+               if($items[0]['deleted']) {
+                       foreach($items as $item)
+                               $item['deleted'] = 1;
+               }
 
-        // Now running as a daemon. This process will even survive
-        // an apachectl stop.
+               if(count($items) == 1 && $items[0]['uri'] === $items[0]['parent-uri'])
+                       $top_level = true;
+       }
 
-        sleep(10);
+       $r = q("SELECT `contact`.*, `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, 
+               `user`.`page-flags`, `user`.`prvnets`
+               FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid` 
+               WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
+               intval($uid)
+       );
 
-        $fp = fopen("/tmp/sdf123", "w");
-        fprintf($fp, "PID = %s\n", posix_getpid());
-        fclose($fp);
+       if(! count($r))
+               return;
 
-        return;
-}
-?>
+       $owner = $r[0];
 
-while(count($this->currentJobs) >= $this->maxProcesses){
-    echo "Maximum children allowed, waiting...\n";
-    sleep(1);
-}
-duerra at yahoo dot com
-02-Jul-2010 02:06
-Using pcntl_fork() can be a little tricky in some situations.  For fast jobs, a child can finish processing before the parent process has executed some code related to the launching of the process.  The parent can receive a signal before it's ready to handle the child process' status.  To handle this scenario, I add an id to a "queue" of processes in the signal handler that need to be cleaned up if the parent process is not yet ready to handle them. 
+       $hub = get_config('system','huburl');
 
-I am including a stripped down version of a job daemon that should get a person on the right track.
+       // If this is a public conversation, notify the feed hub
+       $notify_hub = true;
 
-<?php
-declare(ticks=1);
-//A very basic job daemon that you can extend to your needs.
-class JobDaemon{
-
-    public $maxProcesses = 25;
-    protected $jobsStarted = 0;
-    protected $currentJobs = array();
-    protected $signalQueue=array();  
-    protected $parentPID;
-  
-    public function __construct(){
-        echo "constructed \n";
-        $this->parentPID = getmypid();
-        pcntl_signal(SIGCHLD, array($this, "childSignalHandler"));
-    }
-  
-    /**
-    * Run the Daemon
-    */
-    public function run(){
-        echo "Running \n";
-        for($i=0; $i<10000; $i++){
-            $jobID = rand(0,10000000000000);
-            $launched = $this->launchJob($jobID);
-        }
-      
-        //Wait for child processes to finish before exiting here
-        while(count($this->currentJobs)){
-            echo "Waiting for current jobs to finish... \n";
-            sleep(1);
-        }
-    }
-  
-    /**
-    * Launch a job from the job queue
-    */
-    protected function launchJob($jobID){
-        $pid = pcntl_fork();
-        if($pid == -1){
-            //Problem launching the job
-            error_log('Could not launch new job, exiting');
-            return false;
-        }
-        else if ($pid){
-            // Parent process
-            // Sometimes you can receive a signal to the childSignalHandler function before this code executes if
-            // the child script executes quickly enough!
-            //
-            $this->currentJobs[$pid] = $jobID;
-          
-            // In the event that a signal for this pid was caught before we get here, it will be in our signalQueue array
-            // So let's go ahead and process it now as if we'd just received the signal
-            if(isset($this->signalQueue[$pid])){
-                echo "found $pid in the signal queue, processing it now \n";
-                $this->childSignalHandler(SIGCHLD, $pid, $this->signalQueue[$pid]);
-                unset($this->signalQueue[$pid]);
-            }
-        }
-        else{
-            //Forked child, do your deeds....
-            $exitStatus = 0; //Error code if you need to or whatever
-            echo "Doing something fun in pid ".getmypid()."\n";
-            exit($exitStatus);
-        }
-        return true;
-    }
-  
-    public function childSignalHandler($signo, $pid=null, $status=null){
-      
-        //If no pid is provided, that means we're getting the signal from the system.  Let's figure out
-        //which child process ended
-        if(!$pid){
-            $pid = pcntl_waitpid(-1, $status, WNOHANG);
-        }
-      
-        //Make sure we get all of the exited children
-        while($pid > 0){
-            if($pid && isset($this->currentJobs[$pid])){
-                $exitCode = pcntl_wexitstatus($status);
-                if($exitCode != 0){
-                    echo "$pid exited with status ".$exitCode."\n";
-                }
-                unset($this->currentJobs[$pid]);
-            }
-            else if($pid){
-                //Oh no, our job has finished before this parent process could even note that it had been launched!
-                //Let's make note of it and handle it when the parent process is ready for it
-                echo "..... Adding $pid to the signal queue ..... \n";
-                $this->signalQueue[$pid] = $status;
-            }
-            $pid = pcntl_waitpid(-1, $status, WNOHANG);
-        }
-        return true;
-    }
-}
+       // fill this in with a single salmon slap if applicable
+       $slap = '';
 
+       if($cmd != 'mail' && $cmd != 'suggest') {
 
+               require_once('include/group.php');
 
-*/
+               $parent = $items[0];
 
+               if($parent['type'] === 'remote' && (! $expire)) {
+                       // local followup to remote post
+                       $followup = true;
+                       $notify_hub = false; // not public
+                       $conversant_str = dbesc($parent['contact-id']);
+               }
+               else {
+                       $followup = false;
 
+                       if((strlen($parent['allow_cid'])) 
+                               || (strlen($parent['allow_gid'])) 
+                               || (strlen($parent['deny_cid'])) 
+                               || (strlen($parent['deny_gid']))) {
+                               $notify_hub = false; // private recipients, not public
+                       }
 
-function notifier(&$a,$item_id,$parent_id) {
+                       $allow_people = expand_acl($parent['allow_cid']);
+                       $allow_groups = expand_groups(expand_acl($parent['allow_gid']));
+                       $deny_people  = expand_acl($parent['deny_cid']);
+                       $deny_groups  = expand_groups(expand_acl($parent['deny_gid']));
 
-       $pid = pcntl_fork();
-            
-       if ($pid == (-1)) {
-               notice("Failed to launch background notifier." . EOL );
-               return;
-       }       
+                       $conversants = array();
 
-       if ($pid > 0) {
-               // parent process - regenerate our connections in case the kid kills them
-       
-               @include(".htconfig.php");
-               $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
-               unset($db_host, $db_user, $db_pass, $db_data);
-               session_write_close();
-               session_start();
+                       foreach($items as $item) {
+                               $recipients[] = $item['contact-id'];
+                               $conversants[] = $item['contact-id'];
+                               // pull out additional tagged people to notify (if public message)
+                               if($notify_hub && strlen($item['inform'])) {
+                                       $people = explode(',',$item['inform']);
+                                       foreach($people as $person) {
+                                               if(substr($person,0,4) === 'cid:') {
+                                                       $recipients[] = intval(substr($person,4));
+                                                       $conversants[] = intval(substr($person,4));
+                                               }
+                                               else {
+                                                       $url_recipients[] = substr($person,4);
+                                               }
+                                       }
+                               }
+                       }
 
-               // go back and finish the page
-               return;
-       } 
+                       logger('notifier: url_recipients' . print_r($url_recipients,true));
+
+                       $conversants = array_unique($conversants);
+
+
+                       $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups));
+                       $deny = array_unique(array_merge($deny_people,$deny_groups));
+                       $recipients = array_diff($recipients,$deny);
+
+                       $conversant_str = dbesc(implode(', ',$conversants));
+               }
+
+               $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0");
+
+
+               if(count($r))
+                       $contacts = $r;
+       }
+
+       $feed_template = get_markup_template('atom_feed.tpl');
+       $mail_template = get_markup_template('atom_mail.tpl');
+
+       $atom = '';
+       $slaps = array();
+
+       $hubxml = feed_hublinks();
+
+       $birthday = feed_birthday($owner['uid'],$owner['timezone']);
+
+       if(strlen($birthday))
+               $birthday = '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>';
+
+       $atom .= replace_macros($feed_template, array(
+                       '$version'      => xmlify(FRIENDIKA_VERSION),
+                       '$feed_id'      => xmlify($a->get_baseurl() . '/profile/' . $owner['nickname'] ),
+                       '$feed_title'   => xmlify($owner['name']),
+                       '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00' , ATOM_TIME)) ,
+                       '$hub'          => $hubxml,
+                       '$salmon'       => '',  // private feed, we don't use salmon here
+                       '$name'         => xmlify($owner['name']),
+                       '$profile_page' => xmlify($owner['url']),
+                       '$photo'        => xmlify($owner['photo']),
+                       '$thumb'        => xmlify($owner['thumb']),
+                       '$picdate'      => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) ,
+                       '$uridate'      => xmlify(datetime_convert('UTC','UTC',$owner['uri-date']    . '+00:00' , ATOM_TIME)) ,
+                       '$namdate'      => xmlify(datetime_convert('UTC','UTC',$owner['name-date']   . '+00:00' , ATOM_TIME)) ,
+                       '$birthday'     => $birthday
+       ));
+
+       if($cmd === 'mail') {
+               $notify_hub = false;  // mail is  not public
+
+               $body = fix_private_photos($item['body'],$owner['uid']);
+
+               $atom .= replace_macros($mail_template, array(
+                       '$name'         => xmlify($owner['name']),
+                       '$profile_page' => xmlify($owner['url']),
+                       '$thumb'        => xmlify($owner['thumb']),
+                       '$item_id'      => xmlify($item['uri']),
+                       '$subject'      => xmlify($item['title']),
+                       '$created'      => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
+                       '$content'      => xmlify($body),
+                       '$parent_id'    => xmlify($item['parent-uri'])
+               ));
+       }
+       elseif($cmd === 'suggest') {
+               $notify_hub = false;  // suggestions are not public
+
+               $sugg_template = get_markup_template('atom_suggest.tpl');
+
+               $atom .= replace_macros($sugg_template, array(
+                       '$name'         => xmlify($item['name']),
+                       '$url'          => xmlify($item['url']),
+                       '$photo'        => xmlify($item['photo']),
+                       '$request'      => xmlify($item['request']),
+                       '$note'         => xmlify($item['note'])
+               ));
+
+               // We don't need this any more
+
+               q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1",
+                       intval($item['id'])
+               );
+
+       }
        else {
-               // We are the child
+               if($followup) {
+                       foreach($items as $item) {  // there is only one item
+                               if(! $item['parent'])
+                                       continue;
+                               if($item['id'] == $item_id) {
+                                       logger('notifier: followup: item: ' . print_r($item,true), LOGGER_DATA);
+                                       $slap  = atom_entry($item,'html',$owner,$owner,false);
+                                       $atom .= atom_entry($item,'text',$owner,$owner,false);
+                               }
+                       }
+               }
+               else {
+                       foreach($items as $item) {
+
+                               if(! $item['parent'])
+                                       continue;
+
+                               $contact = get_item_contact($item,$contacts);
+                               if(! $contact)
+                                       continue;
+
+                               $atom .= atom_entry($item,'text',$contact,$owner,true);
+
+                               if(($top_level) && ($notify_hub) && ($item['author-link'] === $item['owner-link']) && (! $expire)) 
+                                       $slaps[] = atom_entry($item,'html',$contact,$owner,true);
+                       }
+               }
+       }
+       $atom .= '</feed>' . "\r\n";
 
-       // fetch item
+       logger('notifier: ' . $atom, LOGGER_DATA);
 
-       // if not parent, fetch it
+       logger('notifier: slaps: ' . print_r($slaps,true), LOGGER_DATA);
 
-       // atomify
+       // If this is a public message and pubmail is set on the parent, include all your email contacts
 
-       // expand list of recipients
+       $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
 
-       // grab the contact records
+       if(! $mail_disabled) {
+               if((! strlen($parent_item['allow_cid'])) && (! strlen($parent_item['allow_gid'])) 
+                       && (! strlen($parent_item['deny_cid'])) && (! strlen($parent_item['deny_gid'])) 
+                       && (intval($parent_item['pubmail']))) {
+                       $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
+                               intval($uid),
+                               dbesc(NETWORK_MAIL)
+                       );
+                       if(count($r)) {
+                               foreach($r as $rr)
+                                       $recipients[] = $rr['id'];
+                       }
+               }
+       }
 
-       // foreach recipient
+       if($followup)
+               $recip_str = $parent['contact-id'];
+       else
+               $recip_str = implode(', ', $recipients);
 
-       // if no dfrn-id continue
+       $r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) AND `blocked` = 0 AND `pending` = 0 ",
+               dbesc($recip_str)
+       );
 
-       // fetch_url dfrn-notify
+       // delivery loop
 
-       // decrypt challenge
+       require_once('include/salmon.php');
 
-       // post result
+       if(count($r)) {
+               foreach($r as $contact) {
+                       if($contact['self'])
+                               continue;
 
-       // continue
+                       $deliver_status = 0;
 
-               killme();
+                       switch($contact['network']) {
+                               case 'dfrn':
+                                       logger('notifier: dfrndelivery: ' . $contact['name']);
+                                       $deliver_status = dfrn_deliver($owner,$contact,$atom);
+
+                                       logger('notifier: dfrn_delivery returns ' . $deliver_status);
+       
+                                       if($deliver_status == (-1)) {
+                                               logger('notifier: delivery failed: queuing message');
+                                               // queue message for redelivery
+                                               q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
+                                                       VALUES ( %d, '%s', '%s', '%s') ",
+                                                       intval($contact['id']),
+                                                       dbesc(datetime_convert()),
+                                                       dbesc(datetime_convert()),
+                                                       dbesc($atom)
+                                               );
+                                       }
+                                       break;
+                               case 'stat':
+                                       if($owner['prvnets'])
+                                               break;
+                                       if($followup && $contact['notify']) {
+                                               logger('notifier: slapdelivery: ' . $contact['name']);
+                                               $deliver_status = slapper($owner,$contact['notify'],$slap);
+
+                                               if($deliver_status == (-1)) {
+                                                       // queue message for redelivery
+                                                       q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
+                                                               VALUES ( %d, '%s', '%s', '%s') ",
+                                                               intval($contact['id']),
+                                                               dbesc(datetime_convert()),
+                                                               dbesc(datetime_convert()),
+                                                               dbesc($slap)
+                                                       );
+
+                                               }
+       
+
+                                       }
+                                       else {
+
+                                               // only send salmon if public - e.g. if it's ok to notify
+                                               // a public hub, it's ok to send a salmon
+
+                                               if((count($slaps)) && ($notify_hub) && (! $expire)) {
+                                                       logger('notifier: slapdelivery: ' . $contact['name']);
+                                                       foreach($slaps as $slappy) {
+                                                               if($contact['notify']) {
+                                                                       $deliver_status = slapper($owner,$contact['notify'],$slappy);
+                                                                       if($deliver_status == (-1)) {
+                                                                               // queue message for redelivery
+                                                                               q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
+                                                                                       VALUES ( %d, '%s', '%s', '%s') ",
+                                                                                       intval($contact['id']),
+                                                                                       dbesc(datetime_convert()),
+                                                                                       dbesc(datetime_convert()),
+                                                                                       dbesc($slappy)
+                                                                               );                                                              
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       break;
+
+                               case 'mail':
+                                               
+                                       // WARNING: does not currently convert to RFC2047 header encodings, etc.
+
+                                       $addr = $contact['addr'];
+                                       if(! strlen($addr))
+                                               break;
+
+                                       if($cmd === 'wall-new' || $cmd === 'comment-new') {
+
+                                               $it = null;
+                                               if($cmd === 'wall-new') 
+                                                       $it = $items[0];
+                                               else {
+                                                       $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", 
+                                                               intval($argv[2]),
+                                                               intval($uid)
+                                                       );
+                                                       if(count($r))
+                                                               $it = $r[0];
+                                               }
+                                               if(! $it)
+                                                       break;
+                                               
+
+
+                                               $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
+                                                       intval($uid)
+                                               );
+                                               if(! count($local_user))
+                                                       break;
+                                               
+                                               $reply_to = '';
+                                               $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
+                                                       intval($uid)
+                                               );
+                                               if($r1 && $r1[0]['reply_to'])
+                                                       $reply_to = $r1[0]['reply_to'];
+       
+                                               $subject  = (($it['title']) ? $it['title'] : t("\x28no subject\x29")) ;
+                                               $headers  = 'From: ' . $local_user[0]['username'] . ' <' . $local_user[0]['email'] . '>' . "\n";
+
+                                               if($reply_to)
+                                                       $headers .= 'Reply-to: ' . $reply_to . "\n";
+
+                                               $headers .= 'Message-id: <' . $it['uri'] . '>' . "\n";
+
+                                               if($it['uri'] !== $it['parent-uri']) {
+                                                       $header .= 'References: <' . $it['parent-uri'] . '>' . "\n";
+                                                       if(! strlen($it['title'])) {
+                                                               $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' LIMIT 1",
+                                                                       dbesc($it['parent-uri'])
+                                                               );
+                                                               if(count($r)) {
+                                                                       $subtitle = $r[0]['title'];
+                                                                       if($subtitle) {
+                                                                               if(strncasecmp($subtitle,'RE:',3))
+                                                                                       $subject = $subtitle;
+                                                                               else
+                                                                                       $subject = 'Re: ' . $subtitle;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+
+                                               $headers .= 'MIME-Version: 1.0' . "\n";
+                                               $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n";
+                                               $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n";
+                                               $html    = prepare_body($it);
+                                               $message = '<html><body>' . $html . '</body></html>';
+                                               logger('notifier: email delivery to ' . $addr);
+                                               mail($addr, $subject, $message, $headers);
+                                       }
+                                       break;
+                               case 'feed':
+                               case 'face':
+                               case 'dspr':
+                               default:
+                                       break;
+                       }
+               }
+       }
+               
+       // send additional slaps to mentioned remote tags (@foo@example.com)
+
+       if($slap && count($url_recipients) && $followup && $notify_hub && (! $expire)) {
+               foreach($url_recipients as $url) {
+                       if($url) {
+                               logger('notifier: urldelivery: ' . $url);
+                               $deliver_status = slapper($owner,$url,$slap);
+                               // TODO: redeliver/queue these items on failure, though there is no contact record
+                       }
+               }
+       }
+
+       if((strlen($hub)) && ($notify_hub)) {
+               $hubs = explode(',', $hub);
+               if(count($hubs)) {
+                       foreach($hubs as $h) {
+                               $h = trim($h);
+                               if(! strlen($h))
+                                       continue;
+                               $params = 'hub.mode=publish&hub.url=' . urlencode($a->get_baseurl() . '/dfrn_poll/' . $owner['nickname'] );
+                               post_url($h,$params);
+                               logger('pubsub: publish: ' . $h . ' ' . $params . ' returned ' . $a->get_curl_code());
+                               if(count($hubs) > 1)
+                                       sleep(7);                               // try and avoid multiple hubs responding at precisely the same time
+                       }
+               }
+       }
+
+       if($notify_hub) {
+
+               /**
+                *
+                * If you have less than 150 dfrn friends and it's a public message,
+                * we'll just go ahead and push them out securely with dfrn/rino.
+                * If you've got more than that, you'll have to rely on PuSH delivery.
+                *
+                */
+
+               $max_allowed = ((get_config('system','maxpubdeliver') === false) ? 150 : intval(get_config('system','maxpubdeliver')));
+                               
+               /**
+                *
+                * Only get the bare essentials and go back for the full record. 
+                * If you've got a lot of friends and we grab all the details at once it could exhaust memory. 
+                *
+                */
+
+               $r = q("SELECT `id`, `name` FROM `contact` 
+                       WHERE `network` = 'dfrn' AND `uid` = %d AND `blocked` = 0 AND `pending` = 0
+                       AND `rel` != %d ",
+                       intval($owner['uid']),
+                       intval(REL_FAN)
+               );
+
+               if((count($r)) && (($max_allowed == 0) || (count($r) < $max_allowed))) {
+
+                       logger('pubdeliver: ' . print_r($r,true));
+
+                       foreach($r as $rr) {
+
+                               /* Don't deliver to folks who have already been delivered to */
+
+                               if(! in_array($rr['id'], $conversants)) {
+                                       $n = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
+                                                       intval($rr['id'])
+                                       );
+
+                                       if(count($n)) {
+                                       
+                                               logger('notifier: dfrnpubdelivery: ' . $n[0]['name']);
+                                               $deliver_status = dfrn_deliver($owner,$n[0],$atom);
+                                       }
+                               }
+                               else
+                                       logger('notifier: dfrnpubdelivery: ignoring ' . $rr['name']);
+                       }
+               }
        }
+
+       return;
+}
+
+if (array_search(__file__,get_included_files())===0){
+  echo "run!";
+  notifier_run($argv,$argc);
+  killme();
 }