| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | <?php | 
					
						
							|  |  |  | /* | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |  * StatusNet - the distributed open-source microblogging tool | 
					
						
							|  |  |  |  * Copyright (C) 2009-2010, StatusNet, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @package FeedSubPlugin | 
					
						
							|  |  |  |  * @maintainer Brion Vibber <brion@status.net> | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  | /* | 
					
						
							|  |  |  | PuSH subscription flow: | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     $profile->subscribe() | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         generate random verification token | 
					
						
							|  |  |  |             save to verify_token | 
					
						
							|  |  |  |         sends a sub request to the hub... | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     main/push/callback | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         hub sends confirmation back to us via GET | 
					
						
							|  |  |  |         We verify the request, then echo back the challenge. | 
					
						
							|  |  |  |         On our end, we save the time we subscribed and the lease expiration | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     main/push/callback | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         hub sends us updates via POST | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FeedDBException extends FeedSubException | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public $obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function __construct($obj) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         parent::__construct('Database insert failure'); | 
					
						
							|  |  |  |         $this->obj = $obj; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  | class Ostatus_profile extends Memcached_DataObject | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     public $__table = 'ostatus_profile'; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public $id; | 
					
						
							|  |  |  |     public $profile_id; | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     public $group_id; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public $feeduri; | 
					
						
							|  |  |  |     public $homeuri; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // PuSH subscription data
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     public $huburi; | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |     public $secret; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     public $verify_token; | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     public $sub_state; // subscribe, active, unsubscribe
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     public $sub_start; | 
					
						
							|  |  |  |     public $sub_end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |     public $salmonuri; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     public $created; | 
					
						
							|  |  |  |     public $lastupdate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public /*static*/ function staticGet($k, $v=null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return parent::staticGet(__CLASS__, $k, $v); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * return table definition for DB_DataObject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * DB_DataObject needs to know something about the table to manipulate | 
					
						
							|  |  |  |      * instances. This method provides all the DB_DataObject needs to know. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array array of column definitions | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function table() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array('id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |                      'profile_id' => DB_DATAOBJECT_INT, | 
					
						
							|  |  |  |                      'group_id' => DB_DATAOBJECT_INT, | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      'feeduri' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL, | 
					
						
							|  |  |  |                      'homeuri' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL, | 
					
						
							| 
									
										
										
										
											2010-02-11 20:12:48 +00:00
										 |  |  |                      'huburi' =>  DB_DATAOBJECT_STR, | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |                      'secret' => DB_DATAOBJECT_STR, | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      'verify_token' => DB_DATAOBJECT_STR, | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |                      'sub_state' => DB_DATAOBJECT_STR, | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      'sub_start' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, | 
					
						
							|  |  |  |                      'sub_end' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME, | 
					
						
							| 
									
										
										
										
											2010-02-11 20:12:48 +00:00
										 |  |  |                      'salmonuri' =>  DB_DATAOBJECT_STR, | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL, | 
					
						
							|  |  |  |                      'lastupdate' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     static function schemaDef() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array(new ColumnDef('id', 'integer', | 
					
						
							|  |  |  |                                    /*size*/ null, | 
					
						
							|  |  |  |                                    /*nullable*/ false, | 
					
						
							|  |  |  |                                    /*key*/ 'PRI', | 
					
						
							|  |  |  |                                    /*default*/ '0', | 
					
						
							|  |  |  |                                    /*extra*/ null, | 
					
						
							|  |  |  |                                    /*auto_increment*/ true), | 
					
						
							|  |  |  |                      new ColumnDef('profile_id', 'integer', | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |                                    null, true, 'UNI'), | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |                      new ColumnDef('group_id', 'integer', | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |                                    null, true, 'UNI'), | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      new ColumnDef('feeduri', 'varchar', | 
					
						
							|  |  |  |                                    255, false, 'UNI'), | 
					
						
							|  |  |  |                      new ColumnDef('homeuri', 'varchar', | 
					
						
							|  |  |  |                                    255, false), | 
					
						
							| 
									
										
										
										
											2010-02-11 20:12:48 +00:00
										 |  |  |                      new ColumnDef('huburi', 'text', | 
					
						
							|  |  |  |                                    null, true), | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      new ColumnDef('verify_token', 'varchar', | 
					
						
							|  |  |  |                                    32, true), | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |                      new ColumnDef('secret', 'varchar', | 
					
						
							|  |  |  |                                    64, true), | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |                      new ColumnDef('sub_state', "enum('subscribe','active','unsubscribe')", | 
					
						
							|  |  |  |                                    null, true), | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      new ColumnDef('sub_start', 'datetime', | 
					
						
							|  |  |  |                                    null, true), | 
					
						
							|  |  |  |                      new ColumnDef('sub_end', 'datetime', | 
					
						
							|  |  |  |                                    null, true), | 
					
						
							| 
									
										
										
										
											2010-02-11 20:12:48 +00:00
										 |  |  |                      new ColumnDef('salmonuri', 'text', | 
					
						
							|  |  |  |                                    null, true), | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |                      new ColumnDef('created', 'datetime', | 
					
						
							|  |  |  |                                    null, false), | 
					
						
							|  |  |  |                      new ColumnDef('lastupdate', 'datetime', | 
					
						
							|  |  |  |                                    null, false)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * return key definitions for DB_DataObject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * DB_DataObject needs to know about keys that the table has; this function
 | 
					
						
							|  |  |  |      * defines them. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array key definitions | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function keys() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |         return array_keys($this->keyTypes()); | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * return key definitions for Memcached_DataObject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Our caching system uses the same key definitions, but uses a different | 
					
						
							|  |  |  |      * method to get them. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array key definitions | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function keyTypes() | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |         return array('id' => 'K', 'profile_id' => 'U', 'group_id' => 'U', 'feeduri' => 'U'); | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function sequenceKey() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array('id', true, false); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-04 10:30:19 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Fetch the StatusNet-side profile for this feed | 
					
						
							|  |  |  |      * @return Profile | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |     public function localProfile() | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |         if ($this->profile_id) { | 
					
						
							|  |  |  |             return Profile::staticGet('id', $this->profile_id); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Fetch the StatusNet-side profile for this feed | 
					
						
							|  |  |  |      * @return Profile | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function localGroup() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($this->group_id) { | 
					
						
							|  |  |  |             return User_group::staticGet('id', $this->group_id); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return null; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param FeedMunger $munger | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |      * @param boolean $isGroup is this a group record? | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |      * @return Ostatus_profile | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public static function ensureProfile($munger) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |         $profile = $munger->ostatusProfile(); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |         $current = self::staticGet('feeduri', $profile->feeduri); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         if ($current) { | 
					
						
							|  |  |  |             // @fixme we should probably update info as necessary
 | 
					
						
							|  |  |  |             return $current; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |         $profile->query('BEGIN'); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |         // Awful hack! Awful hack!
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |         $profile->verify = common_good_rand(16); | 
					
						
							|  |  |  |         $profile->secret = common_good_rand(32); | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |             $local = $munger->profile(); | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |             if ($entity->isGroup()) { | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |                 $group = new User_group(); | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |                 $group->nickname = $local->nickname . '@remote'; // @fixme
 | 
					
						
							|  |  |  |                 $group->fullname = $local->fullname; | 
					
						
							|  |  |  |                 $group->homepage = $local->homepage; | 
					
						
							|  |  |  |                 $group->location = $local->location; | 
					
						
							|  |  |  |                 $group->created = $local->created; | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |                 $group->insert(); | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |                 if (empty($result)) { | 
					
						
							|  |  |  |                     throw new FeedDBException($group); | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |                 $profile->group_id = $group->id; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $result = $local->insert(); | 
					
						
							|  |  |  |                 if (empty($result)) { | 
					
						
							|  |  |  |                     throw new FeedDBException($local); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $profile->profile_id = $local->id; | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |             $profile->created = sql_common_date(); | 
					
						
							|  |  |  |             $profile->lastupdate = sql_common_date(); | 
					
						
							|  |  |  |             $result = $profile->insert(); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             if (empty($result)) { | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |                 throw new FeedDBException($profile); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |             $entity->query('COMMIT'); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         } catch (FeedDBException $e) { | 
					
						
							|  |  |  |             common_log_db_error($e->obj, 'INSERT', __FILE__); | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |             $entity->query('ROLLBACK'); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $avatar = $munger->getAvatar(); | 
					
						
							|  |  |  |         if ($avatar) { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 $this->updateAvatar($avatar); | 
					
						
							|  |  |  |             } catch (Exception $e) { | 
					
						
							|  |  |  |                 common_log(LOG_ERR, "Exception setting OStatus avatar: " . | 
					
						
							|  |  |  |                                     $e->getMessage()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 00:22:16 +00:00
										 |  |  |         return $entity; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Download and update given avatar image | 
					
						
							|  |  |  |      * @param string $url | 
					
						
							|  |  |  |      * @throws Exception in various failure cases | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function updateAvatar($url) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // @fixme this should be better encapsulated
 | 
					
						
							|  |  |  |         // ripped from oauthstore.php (for old OMB client)
 | 
					
						
							|  |  |  |         $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar'); | 
					
						
							|  |  |  |         copy($url, $temp_filename); | 
					
						
							|  |  |  |         $imagefile = new ImageFile($profile->id, $temp_filename); | 
					
						
							|  |  |  |         $filename = Avatar::filename($profile->id, | 
					
						
							|  |  |  |                                      image_type_to_extension($imagefile->type), | 
					
						
							|  |  |  |                                      null, | 
					
						
							|  |  |  |                                      common_timestamp()); | 
					
						
							|  |  |  |         rename($temp_filename, Avatar::path($filename)); | 
					
						
							|  |  |  |         if ($this->isGroup()) { | 
					
						
							|  |  |  |             $group = $this->localGroup(); | 
					
						
							|  |  |  |             $group->setOriginal($filename); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $profile = $this->localProfile(); | 
					
						
							|  |  |  |             $profile->setOriginal($filename); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Damn dirty hack! | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function isGroup() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return (strpos($this->feeduri, '/groups/') !== false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Send a subscription request to the hub for this feed. | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |      * The hub will later send us a confirmation POST to /main/push/callback. | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool true on success, false on failure | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |     public function subscribe($mode='subscribe') | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |         if (common_config('feedsub', 'nohub')) { | 
					
						
							|  |  |  |             // Fake it! We're just testing remote feeds w/o hubs.
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         // @fixme use the verification token
 | 
					
						
							|  |  |  |         #$token = md5(mt_rand() . ':' . $this->feeduri);
 | 
					
						
							|  |  |  |         #$this->verify_token = $token;
 | 
					
						
							|  |  |  |         #$this->update(); // @fixme
 | 
					
						
							|  |  |  |         try { | 
					
						
							| 
									
										
										
										
											2010-02-08 14:06:36 -08:00
										 |  |  |             $callback = common_local_url('pushcallback', array('feed' => $this->id)); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             $headers = array('Content-Type: application/x-www-form-urlencoded'); | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |             $post = array('hub.mode' => $mode, | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |                           'hub.callback' => $callback, | 
					
						
							|  |  |  |                           'hub.verify' => 'async', | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |                           'hub.verify_token' => $this->verify_token, | 
					
						
							|  |  |  |                           'hub.secret' => $this->secret, | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |                           //'hub.lease_seconds' => 0,
 | 
					
						
							|  |  |  |                           'hub.topic' => $this->feeduri); | 
					
						
							|  |  |  |             $client = new HTTPClient(); | 
					
						
							|  |  |  |             $response = $client->post($this->huburi, $headers, $post); | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |             $status = $response->getStatus(); | 
					
						
							|  |  |  |             if ($status == 202) { | 
					
						
							|  |  |  |                 common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback'); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } else if ($status == 204) { | 
					
						
							|  |  |  |                 common_log(LOG_INFO, __METHOD__ . ': sub req ok and verified'); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |                 return true; | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |             } else if ($status >= 200 && $status < 300) { | 
					
						
							|  |  |  |                 common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP $status: " . $response->getBody()); | 
					
						
							|  |  |  |                 return false; | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |                 common_log(LOG_ERR, __METHOD__ . ": sub req failed with HTTP $status: " . $response->getBody()); | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } catch (Exception $e) { | 
					
						
							|  |  |  |             // wtf!
 | 
					
						
							|  |  |  |             common_log(LOG_ERR, __METHOD__ . ": error \"{$e->getMessage()}\" hitting hub $this->huburi subscribing to $this->feeduri"); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-12 01:11:46 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Save PuSH subscription confirmation. | 
					
						
							|  |  |  |      * Sets approximate lease start and end times and finalizes state. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param int $lease_seconds provided hub.lease_seconds parameter, if given | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function confirmSubscribe($lease_seconds=0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $original = clone($this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->sub_state = 'active'; | 
					
						
							|  |  |  |         $this->sub_start = common_sql_date(time()); | 
					
						
							|  |  |  |         if ($lease_seconds > 0) { | 
					
						
							|  |  |  |             $this->sub_end = common_sql_date(time() + $lease_seconds); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $this->sub_end = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $this->lastupdate = common_sql_date(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->update($original); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Save PuSH unsubscription confirmation. | 
					
						
							|  |  |  |      * Wipes active PuSH sub info and resets state. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function confirmUnsubscribe() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $original = clone($this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->verify_token = null; | 
					
						
							|  |  |  |         $this->secret = null; | 
					
						
							|  |  |  |         $this->sub_state = null; | 
					
						
							|  |  |  |         $this->sub_start = null; | 
					
						
							|  |  |  |         $this->sub_end = null; | 
					
						
							|  |  |  |         $this->lastupdate = common_sql_date(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->update($original); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-11 00:09:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Send an unsubscription request to the hub for this feed. | 
					
						
							|  |  |  |      * The hub will later send us a confirmation POST to /main/push/callback. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return bool true on success, false on failure | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function unsubscribe() { | 
					
						
							|  |  |  |         return $this->subscribe('unsubscribe'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Read and post notices for updates from the feed. | 
					
						
							|  |  |  |      * Currently assumes that all items in the feed are new, | 
					
						
							|  |  |  |      * coming from a PuSH hub. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $xml source of Atom or RSS feed | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |      * @param string $hmac X-Hub-Signature header, if present | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |     public function postUpdates($xml, $hmac) | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |         common_log(LOG_INFO, __METHOD__ . ": packet for \"$this->feeduri\"! $hmac $xml");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($this->secret) { | 
					
						
							|  |  |  |             if (preg_match('/^sha1=([0-9a-fA-F]{40})$/', $hmac, $matches)) { | 
					
						
							|  |  |  |                 $their_hmac = strtolower($matches[1]); | 
					
						
							| 
									
										
										
										
											2010-02-10 22:58:39 +00:00
										 |  |  |                 $our_hmac = hash_hmac('sha1', $xml, $this->secret); | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |                 if ($their_hmac !== $our_hmac) { | 
					
						
							|  |  |  |                     common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bad SHA-1 HMAC: got $their_hmac, expected $our_hmac"); | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bogus HMAC '$hmac'"); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if ($hmac) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with unexpected HMAC '$hmac'"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |         require_once "XML/Feed/Parser.php"; | 
					
						
							|  |  |  |         $feed = new XML_Feed_Parser($xml, false, false, true); | 
					
						
							|  |  |  |         $munger = new FeedMunger($feed); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         $hits = 0; | 
					
						
							|  |  |  |         foreach ($feed as $index => $entry) { | 
					
						
							|  |  |  |             // @fixme this might sort in wrong order if we get multiple updates
 | 
					
						
							| 
									
										
										
										
											2010-02-10 21:18:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             $notice = $munger->notice($index); | 
					
						
							| 
									
										
										
										
											2010-02-10 21:18:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             // Double-check for oldies
 | 
					
						
							|  |  |  |             // @fixme this could explode horribly for multiple feeds on a blog. sigh
 | 
					
						
							|  |  |  |             $dupe = new Notice(); | 
					
						
							|  |  |  |             $dupe->uri = $notice->uri; | 
					
						
							| 
									
										
										
										
											2010-02-08 11:06:03 -08:00
										 |  |  |             if ($dupe->find(true)) { | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |                 common_log(LOG_WARNING, __METHOD__ . ": tried to save dupe notice for entry {$notice->uri} of feed {$this->feeduri}"); | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-10 21:18:53 +00:00
										 |  |  |             // @fixme need to ensure that groups get handled correctly
 | 
					
						
							| 
									
										
										
										
											2010-02-11 19:44:03 +00:00
										 |  |  |             $saved = Notice::saveNew($notice->profile_id, | 
					
						
							| 
									
										
										
										
											2010-02-10 21:18:53 +00:00
										 |  |  |                                      $notice->content, | 
					
						
							|  |  |  |                                      'ostatus', | 
					
						
							|  |  |  |                                      array('is_local' => Notice::REMOTE_OMB, | 
					
						
							|  |  |  |                                            'uri' => $notice->uri, | 
					
						
							|  |  |  |                                            'lat' => $notice->lat, | 
					
						
							|  |  |  |                                            'lon' => $notice->lon, | 
					
						
							|  |  |  |                                            'location_ns' => $notice->location_ns, | 
					
						
							|  |  |  |                                            'location_id' => $notice->location_id)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  |             common_log(LOG_DEBUG, "going to check group delivery..."); | 
					
						
							|  |  |  |             if ($this->group_id) { | 
					
						
							|  |  |  |                 $group = User_group::staticGet($this->group_id); | 
					
						
							|  |  |  |                 if ($group) { | 
					
						
							|  |  |  |                     common_log(LOG_INFO, __METHOD__ . ": saving to local shadow group $group->id $group->nickname"); | 
					
						
							|  |  |  |                     $groups = array($group); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     common_log(LOG_INFO, __METHOD__ . ": lost the local shadow group?"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 common_log(LOG_INFO, __METHOD__ . ": no local shadow groups"); | 
					
						
							|  |  |  |                 $groups = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             common_log(LOG_DEBUG, "going to add to inboxes..."); | 
					
						
							|  |  |  |             $notice->addToInboxes($groups, array()); | 
					
						
							|  |  |  |             common_log(LOG_DEBUG, "added to inboxes."); | 
					
						
							| 
									
										
										
										
											2010-02-10 21:18:53 +00:00
										 |  |  |             */ | 
					
						
							| 
									
										
										
										
											2010-02-09 18:32:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 09:42:19 -08:00
										 |  |  |             $hits++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($hits == 0) { | 
					
						
							|  |  |  |             common_log(LOG_INFO, __METHOD__ . ": no updates in packet for \"$this->feeduri\"! $xml");
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |