diff options
Diffstat (limited to 'include')
43 files changed, 1512 insertions, 882 deletions
diff --git a/include/Import/refimport.php b/include/Import/refimport.php index 181b2b398..b9b6bf639 100644 --- a/include/Import/refimport.php +++ b/include/Import/refimport.php @@ -174,7 +174,7 @@ function reflect_photo_callback($matches) { 'resource_id' => str_replace('-','',$hash), 'filename' => $hash . '.jpg', 'type' => 'image/jpeg', - 'not_visible' => true + 'visible' => false ) ); diff --git a/include/ItemObject.php b/include/ItemObject.php index 1785d55e7..4fc01e6d4 100644 --- a/include/ItemObject.php +++ b/include/ItemObject.php @@ -672,7 +672,7 @@ class Item extends BaseObject { '$edquote' => t('Quote'), '$edcode' => t('Code'), '$edimg' => t('Image'), - '$edurl' => t('Link'), + '$edurl' => t('Insert Link'), '$edvideo' => t('Video'), '$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''), '$indent' => $indent, diff --git a/include/RedDAV/RedFile.php b/include/RedDAV/RedFile.php index 9ce6490a7..b7aa5473a 100644 --- a/include/RedDAV/RedFile.php +++ b/include/RedDAV/RedFile.php @@ -80,7 +80,8 @@ class RedFile extends DAV\Node implements DAV\IFile { $newName = str_replace('/', '%2F', $newName); $r = q("UPDATE attach SET filename = '%s' WHERE hash = '%s' AND id = %d", - dbesc($this->data['filename']), + dbesc($newName), + dbesc($this->data['hash']), intval($this->data['id']) ); } diff --git a/include/account.php b/include/account.php index 19c13d5bd..caac0b178 100644 --- a/include/account.php +++ b/include/account.php @@ -523,9 +523,7 @@ function downgrade_accounts() { $basic = get_config('system','default_service_class'); - foreach($r as $rr) { - if(($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) { $x = q("UPDATE account set account_service_class = '%s', account_expires = '%s' where account_id = %d", @@ -550,74 +548,98 @@ function downgrade_accounts() { } +/** + * @brief Check service_class restrictions. + * + * If there are no service_classes defined, everything is allowed. + * If $usage is supplied, we check against a maximum count and return true if + * the current usage is less than the subscriber plan allows. Otherwise we + * return boolean true or false if the property is allowed (or not) in this + * subscriber plan. An unset property for this service plan means the property + * is allowed, so it is only necessary to provide negative properties for each + * plan, or what the subscriber is not allowed to do. + * + * Like account_service_class_allows() but queries directly by account rather + * than channel. Service classes are set for accounts, so we look up the + * account for the channel and fetch the service class restrictions of the + * account. + * + * @see account_service_class_allows() if you have a channel_id already + * @see service_class_fetch() + * + * @param int $uid The channel_id to check + * @param string $property The service class property to check for + * @param string|boolean $usage (optional) The value to check against + * @return boolean + */ +function service_class_allows($uid, $property, $usage = false) { + $limit = service_class_fetch($uid, $property); -// check service_class restrictions. If there are no service_classes defined, everything is allowed. -// if $usage is supplied, we check against a maximum count and return true if the current usage is -// less than the subscriber plan allows. Otherwise we return boolean true or false if the property -// is allowed (or not) in this subscriber plan. An unset property for this service plan means -// the property is allowed, so it is only necessary to provide negative properties for each plan, -// or what the subscriber is not allowed to do. - - -function service_class_allows($uid,$property,$usage = false) { - $a = get_app(); - if($uid == local_channel()) { - $service_class = $a->account['account_service_class']; - } - else { - $r = q("select account_service_class as service_class - from channel c, account a - where c.channel_account_id=a.account_id and c.channel_id= %d limit 1", - intval($uid) - ); - if($r !== false and count($r)) { - $service_class = $r[0]['service_class']; - } - } - if(! x($service_class)) - return true; // everything is allowed - - $arr = get_config('service_class',$service_class); - if(! is_array($arr) || (! count($arr))) - return true; + if($limit === false) + return true; // No service class set => everything is allowed - if($usage === false) - return ((x($arr[$property])) ? (bool) $arr[$property] : true); - else { - if(! array_key_exists($property,$arr)) - return true; - return (((intval($usage)) < intval($arr[$property])) ? true : false); + if($usage === false) { + // We use negative values for not allowed properties in a subscriber plan + return ((x($limit)) ? (bool) $limit : true); + } else { + return (((intval($usage)) < intval($limit)) ? true : false); } } -// like service_class_allows but queries by account rather than channel -function account_service_class_allows($aid,$property,$usage = false) { - $a = get_app(); - $r = q("select account_service_class as service_class from account where account_id = %d limit 1", - intval($aid) - ); - if($r !== false and count($r)) { - $service_class = $r[0]['service_class']; - } +/** + * @brief Check service class restrictions by account. + * + * If there are no service_classes defined, everything is allowed. + * If $usage is supplied, we check against a maximum count and return true if + * the current usage is less than the subscriber plan allows. Otherwise we + * return boolean true or false if the property is allowed (or not) in this + * subscriber plan. An unset property for this service plan means the property + * is allowed, so it is only necessary to provide negative properties for each + * plan, or what the subscriber is not allowed to do. + * + * Like service_class_allows() but queries directly by account rather than channel. + * + * @see service_class_allows() if you have a channel_id instead of an account_id + * @see account_service_class_fetch() + * + * @param int $aid The account_id to check + * @param string $property The service class property to check for + * @param int|boolean $usage, (optional) The value to check against + * @return boolean + */ +function account_service_class_allows($aid, $property, $usage = false) { - if(! x($service_class)) - return true; // everything is allowed + $limit = account_service_class_fetch($aid, $property); - $arr = get_config('service_class',$service_class); - if(! is_array($arr) || (! count($arr))) - return true; + if($limit === false) + return true; // No service class is set => everything is allowed - if($usage === false) - return ((x($arr[$property])) ? (bool) $arr[$property] : true); - else { - if(! array_key_exists($property,$arr)) - return true; - return (((intval($usage)) < intval($arr[$property])) ? true : false); + if($usage === false) { + // We use negative values for not allowed properties in a subscriber plan + return ((x($limit)) ? (bool) $limit : true); + } else { + return (((intval($usage)) < intval($limit)) ? true : false); } } - -function service_class_fetch($uid,$property) { +/** + * @brief Queries a service class value for a channel and property. + * + * Service classes are set for accounts, so look up the account for this channel + * and fetch the service classe of the account. + * + * If no service class is available it returns false and everything should be + * allowed. + * + * @see account_service_class_fetch() + * + * @param int $uid The channel_id to query + * @param string $property The service property name to check for + * @return boolean|int + * + * @todo Should we merge this with account_service_class_fetch()? + */ +function service_class_fetch($uid, $property) { $a = get_app(); if($uid == local_channel()) { $service_class = $a->account['account_service_class']; @@ -635,17 +657,27 @@ function service_class_fetch($uid,$property) { if(! x($service_class)) return false; // everything is allowed - $arr = get_config('service_class',$service_class); + $arr = get_config('service_class', $service_class); if(! is_array($arr) || (! count($arr))) return false; - return((array_key_exists($property,$arr)) ? $arr[$property] : false); + return((array_key_exists($property, $arr)) ? $arr[$property] : false); } -// like service_class_fetch but queries by account rather than channel - -function account_service_class_fetch($aid,$property) { +/** + * @brief Queries a service class value for an account and property. + * + * Like service_class_fetch() but queries by account rather than channel. + * + * @see service_class_fetch() if you have channel_id. + * @see account_service_class_allows() + * + * @param int $aid The account_id to query + * @param string $property The service property name to check for + * @return boolean|int + */ +function account_service_class_fetch($aid, $property) { $r = q("select account_service_class as service_class from account where account_id = %d limit 1", intval($aid) @@ -657,17 +689,17 @@ function account_service_class_fetch($aid,$property) { if(! x($service_class)) return false; // everything is allowed - $arr = get_config('service_class',$service_class); + $arr = get_config('service_class', $service_class); if(! is_array($arr) || (! count($arr))) return false; - return((array_key_exists($property,$arr)) ? $arr[$property] : false); + return((array_key_exists($property, $arr)) ? $arr[$property] : false); } function upgrade_link($bbcode = false) { - $l = get_config('service_class','upgrade_link'); + $l = get_config('service_class', 'upgrade_link'); if(! $l) return ''; if($bbcode) @@ -685,4 +717,4 @@ function upgrade_message($bbcode = false) { function upgrade_bool_message($bbcode = false) { $x = upgrade_link($bbcode); return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ; -} +}
\ No newline at end of file diff --git a/include/api.php b/include/api.php index d0c4ed0aa..8c0e32ecc 100644 --- a/include/api.php +++ b/include/api.php @@ -663,8 +663,8 @@ require_once('include/items.php'); $a->argv[1] = $user_info['screen_name']; $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo - require_once('mod/wall_upload.php'); - $posted = wall_upload_post($a); + require_once('mod/wall_attach.php'); + $posted = wall_attach_post($a); //now that we have the img url in bbcode we can add it to the status and insert the wall item. $_REQUEST['body']=$txt."\n\n".$posted; diff --git a/include/attach.php b/include/attach.php index 43b56e4f6..1daa42aef 100644 --- a/include/attach.php +++ b/include/attach.php @@ -275,7 +275,11 @@ function attach_by_hash($hash, $rev = 0) { * * @see attach_by_hash() * @param $hash - * @param $ref + * @param $rev revision default 0 + * @return array Everything except data. + * * \e boolean \b success boolean true or false + * * \e string \b message (optional) only when success is false + * * \e array \b data array of attach DB entry without data component */ function attach_by_hash_nodata($hash, $rev = 0) { @@ -318,6 +322,7 @@ function attach_by_hash_nodata($hash, $rev = 0) { $ret['success'] = true; $ret['data'] = $r[0]; + return $ret; } @@ -361,6 +366,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $existing_size = 0; if($options === 'replace') { + /** @BUG $replace is undefined here */ $x = q("select id, hash, filesize from attach where id = %d and uid = %d limit 1", intval($replace), intval($channel_id) @@ -373,7 +379,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $existing_size = intval($x[0]['filesize']); $hash = $x[0]['hash']; } - + if($options === 'revise' || $options === 'update') { $sql_options = " order by revision desc "; if($options === 'update' && $arr && array_key_exists('revision',$arr)) @@ -513,22 +519,24 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { } /** - * Read a virtual directory and return contents, checking permissions of all parent components. - * @function z_readdir + * @brief Read a virtual directory and return contents. + * + * Also checking permissions of all parent components. + * * @param integer $channel_id * @param string $observer_hash hash of current observer * @param string $pathname * @param string $parent_hash (optional) * - * @returns array $ret - * $ret['success'] = boolean true or false - * $ret['message'] = error message if success is false - * $ret['data'] = array of attach DB entries without data component + * @return array $ret + * * \e boolean \b success boolean true or false + * * \e string \b message error message if success is false + * * \e array \b data array of attach DB entries without data component */ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { $ret = array('success' => false); - if(! perm_is_allowed($r[0]['uid'], get_observer_hash(), 'view_storage')) { + if(! perm_is_allowed($channel_id, get_observer_hash(), 'view_storage')) { $ret['message'] = t('Permission denied.'); return $ret; } @@ -827,18 +835,20 @@ function attach_delete($channel_id, $resource) { intval($channel_id) ); - file_activity($channel_id, $object, $allow_cid='', $allow_gid='', $deny_cid='', $deny_gid='', 'update', $no_activity=false); + file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $no_activity=false); } /** * @brief Returns path to file in cloud/. - * This function cannot be used with mod/dav as it always returns a path valid under mod/cloud + * + * @warning This function cannot be used with mod/dav as it always returns a + * path valid under mod/cloud. * - * @param array - * $arr[uid] int the channels uid - * $arr[folder] string - * $arr[filename]] string + * @param array assoziative array with: + * * \e int \b uid the channel's uid + * * \e string \b folder + * * \e string \b filename * @return string * path to the file in cloud/ */ @@ -895,6 +905,7 @@ function get_cloudpath($arr) { * @return string with the full folder path */ function get_parent_cloudpath($channel_id, $channel_name, $attachHash) { + $parentFullPath = ''; // build directory tree $parentHash = $attachHash; do { @@ -933,9 +944,9 @@ function find_folder_hash_by_attach_hash($channel_id, $attachHash) { /** * @brief Returns the filename of an attachment in a given channel. * - * @param mixed $channel_id + * @param int $channel_id * The id of the channel - * @param mixed $attachHash + * @param string $attachHash * The hash of the attachment * @return string * The filename of the attachment @@ -949,6 +960,7 @@ function find_filename_by_hash($channel_id, $attachHash) { if ($r) { $filename = $r[0]['filename']; } + return $filename; } @@ -974,10 +986,14 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, if(!$object) return; - //filter out receivers which do not have permission to view filestorage + //turn strings into arrays $arr_allow_cid = expand_acl($allow_cid); + $arr_allow_gid = expand_acl($allow_gid); + $arr_deny_cid = expand_acl($deny_cid); + $arr_deny_gid = expand_acl($deny_gid); + + //filter out receivers which do not have permission to view filestorage $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); - $allow_cid = perms2str($arr_allow_cid); $is_dir = (($object['flags'] & ATTACH_FLAG_DIR) ? true : false); @@ -990,15 +1006,16 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $folder_hash = $object['folder']; - $r_perms = recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_gid, $folder_hash); + $r_perms = recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash); - //filter out receivers which do not have permission to view filestorage - $r_perms['allow_cid'] = check_list_permissions($channel_id, $r_perms['allow_cid'], 'view_storage'); + //split up returned perms + $arr_allow_cid = $r_perms['allow_cid']; + $arr_allow_gid = $r_perms['allow_gid']; + $arr_deny_cid = $r_perms['deny_cid']; + $arr_deny_gid = $r_perms['deny_gid']; - $allow_cid = perms2str($r_perms['allow_cid']); - $allow_gid = perms2str($r_perms['allow_gid']); - $deny_cid = perms2str($r_perms['deny_cid']); - $deny_gid = perms2str($r_perms['deny_gid']); + //filter out receivers which do not have permission to view filestorage + $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); } @@ -1008,7 +1025,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $item_flags = ITEM_WALL|ITEM_ORIGIN; - $private = (($allow_cid || $allow_gid || $deny_cid || $deny_gid) ? 1 : 0); + $private = (($arr_allow_cid[0] || $arr_allow_gid[0] || $arr_deny_cid[0] || $arr_deny_gid[0]) ? 1 : 0); $jsonobject = json_encode($object); @@ -1037,6 +1054,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, if($update && $verb == 'post' ) { //send update activity and create a new one + //updates should be sent to everybody with recursive perms and all eventual former allowed members ($object['allow_cid'] etc.). + $u_arr_allow_cid = array_unique(array_merge($arr_allow_cid, expand_acl($object['allow_cid']))); + $u_arr_allow_gid = array_unique(array_merge($arr_allow_gid, expand_acl($object['allow_gid']))); + $u_arr_deny_cid = array_unique(array_merge($arr_deny_cid, expand_acl($object['deny_cid']))); + $u_arr_deny_gid = array_unique(array_merge($arr_deny_gid, expand_acl($object['deny_gid']))); + $u_mid = item_message_id(); $arr = array(); @@ -1050,13 +1073,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; $arr['title'] = ''; - //updates should be visible to everybody -> perms may have changed - $arr['allow_cid'] = ''; - $arr['allow_gid'] = ''; - $arr['deny_cid'] = ''; - $arr['deny_gid'] = ''; + $arr['allow_cid'] = perms2str($u_arr_allow_cid); + $arr['allow_gid'] = perms2str($u_arr_allow_gid); + $arr['deny_cid'] = perms2str($u_arr_deny_cid); + $arr['deny_gid'] = perms2str($u_arr_deny_gid); $arr['item_restrict'] = ITEM_HIDDEN; - $arr['item_private'] = 0; + $arr['item_private'] = $private; $arr['verb'] = ACTIVITY_UPDATE; $arr['obj_type'] = $objtype; $arr['object'] = $u_jsonobject; @@ -1093,10 +1115,10 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; $arr['title'] = ''; - $arr['allow_cid'] = $allow_cid; - $arr['allow_gid'] = $allow_gid; - $arr['deny_cid'] = $deny_cid; - $arr['deny_gid'] = $deny_gid; + $arr['allow_cid'] = perms2str($arr_allow_cid); + $arr['allow_gid'] = perms2str($arr_allow_gid); + $arr['deny_cid'] = perms2str($arr_deny_cid); + $arr['deny_gid'] = perms2str($arr_deny_gid); $arr['item_restrict'] = ITEM_HIDDEN; $arr['item_private'] = $private; $arr['verb'] = (($update) ? ACTIVITY_UPDATE : ACTIVITY_POST); @@ -1123,7 +1145,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, function get_file_activity_object($channel_id, $hash, $cloudpath) { - $x = q("SELECT creator, filename, filetype, filesize, revision, folder, flags, created, edited FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1", + $x = q("SELECT creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1", intval($channel_id), dbesc($hash) ); @@ -1152,28 +1174,28 @@ function get_file_activity_object($channel_id, $hash, $cloudpath) { 'folder' => $x[0]['folder'], 'flags' => $x[0]['flags'], 'created' => $x[0]['created'], - 'edited' => $x[0]['edited'] + 'edited' => $x[0]['edited'], + 'allow_cid' => $x[0]['allow_cid'], + 'allow_gid' => $x[0]['allow_gid'], + 'deny_cid' => $x[0]['deny_cid'], + 'deny_gid' => $x[0]['deny_gid'] ); return $object; } -function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_gid, $folder_hash) { +function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash) { + $ret = array(); + $parent_arr = array(); $poster = get_app()->get_observer(); - $arr_allow_cid = expand_acl($allow_cid); - $arr_allow_gid = expand_acl($allow_gid); - //turn allow_gid into allow_cid's foreach($arr_allow_gid as $gid) { $in_group = in_group($gid); $arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group)); } - $arr_deny_cid = expand_acl($deny_cid); - $arr_deny_gid = expand_acl($deny_gid); - $count = 0; while($folder_hash) { $x = q("SELECT allow_cid, allow_gid, deny_cid, deny_gid, folder FROM attach WHERE hash = '%s' LIMIT 1", @@ -1186,8 +1208,10 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_ $parent_arr['allow_cid'][] = expand_acl($x[0]['allow_cid']); $parent_arr['allow_gid'][] = expand_acl($x[0]['allow_gid']); - //TODO: should find a much better solution for the allow_cid <-> allow_gid problem. - //Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid. + /** + * @TODO should find a much better solution for the allow_cid <-> allow_gid problem. + * Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid. + * */ if($parent_arr['allow_gid']) { foreach($parent_arr['allow_gid'][$count] as $gid) { $in_group = in_group($gid); @@ -1199,11 +1223,9 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_ $parent_arr['deny_gid'][] = expand_acl($x[0]['deny_gid']); $count++; - } $folder_hash = $x[0]['folder']; - } //if none of the parent folders is private just return file perms @@ -1271,11 +1293,12 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_ } return $ret; - } function in_group($group_id) { - //TODO: make these two queries one with a join. + $group_members = array(); + + /** @TODO make these two queries one with a join. */ $x = q("SELECT id FROM groups WHERE hash = '%s'", dbesc($group_id) ); diff --git a/include/bbcode.php b/include/bbcode.php index 9a607c80d..6f7ef8973 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -469,10 +469,10 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // Perform URL Search - $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]'; + $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@]'; if (strpos($Text,'http') !== false) { - $Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" >$2</a>', $Text); + $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" >$2</a>', $Text); } if (strpos($Text,'[/qr]') !== false) { @@ -756,11 +756,17 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // html5 video and audio if (strpos($Text,'[/video]') !== false) { - $Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4))\[\/video\]/ism", 'tryzrlvideo', $Text); + $Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/video\]/ism", 'tryzrlvideo', $Text); } if (strpos($Text,'[/audio]') !== false) { $Text = preg_replace_callback("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/audio\]/ism", 'tryzrlaudio', $Text); } + if (strpos($Text,'[/zvideo]') !== false) { + $Text = preg_replace_callback("/\[zvideo\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/zvideo\]/ism", 'tryzrlvideo', $Text); + } + if (strpos($Text,'[/zaudio]') !== false) { + $Text = preg_replace_callback("/\[zaudio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/zaudio\]/ism", 'tryzrlaudio', $Text); + } // Try to Oembed if ($tryoembed) { @@ -771,6 +777,13 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { if (strpos($Text,'[/audio]') !== false) { $Text = preg_replace_callback("/\[audio\](.*?)\[\/audio\]/ism", 'tryoembed', $Text); } + + if (strpos($Text,'[/zvideo]') !== false) { + $Text = preg_replace_callback("/\[zvideo\](.*?)\[\/zvideo\]/ism", 'tryoembed', $Text); + } + if (strpos($Text,'[/zaudio]') !== false) { + $Text = preg_replace_callback("/\[zaudio\](.*?)\[\/zaudio\]/ism", 'tryoembed', $Text); + } } // if video couldn't be embedded, link to it instead. @@ -781,6 +794,13 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1">$1</a>', $Text); } + if (strpos($Text,'[/zvideo]') !== false) { + $Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1">$1</a>', $Text); + } + if (strpos($Text,'[/zaudio]') !== false) { + $Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1">$1</a>', $Text); + } + @@ -864,7 +884,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // fix any escaped ampersands that may have been converted into links $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text); - $Text = preg_replace("/\<(.*?)(src|href)=\"[^hfm#](.*?)\>/ism",'<$1$2="">',$Text); + $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism",'<$1$2="">',$Text); $Text = bb_replace_images($Text,$saved_images); diff --git a/include/bookmarks.php b/include/bookmarks.php index e70158476..c6e8e86f2 100644 --- a/include/bookmarks.php +++ b/include/bookmarks.php @@ -9,7 +9,7 @@ function bookmark_add($channel,$sender,$taxonomy,$private,$opts = null) { $ischat = false; if(is_array($opts)) { - $menu_id = ((x($opts,'menu_id')) ? intval($opt['menu_id']) : 0); + $menu_id = ((x($opts,'menu_id')) ? intval($opts['menu_id']) : 0); $menu_name = ((x($opts,'menu_name')) ? escape_tags($opts['menu_name']) : ''); $ischat = ((x($opts,'ischat')) ? intval($opts['ischat']) : 0); } diff --git a/include/chat.php b/include/chat.php index b19d495bb..05bb02bb9 100644 --- a/include/chat.php +++ b/include/chat.php @@ -1,7 +1,20 @@ -<?php /** @file */ +<?php +/** + * @file include/chat.php + * @brief Chat related functions. + */ -function chatroom_create($channel,$arr) { +/** + * @brief Creates a chatroom. + * + * @param array $channel + * @param array $arr + * @return An associative array containing: + * - success: A boolean + * - message: (optional) A string + */ +function chatroom_create($channel, $arr) { $ret = array('success' => false); @@ -24,14 +37,14 @@ function chatroom_create($channel,$arr) { intval($channel['channel_account_id']) ); if($r) - $limit = service_class_fetch($channel_id,'chatrooms'); + $limit = service_class_fetch($channel['channel_id'], 'chatrooms'); - if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) { - $ret['message'] = upgrade_message(); - return $ret; - } + if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) { + $ret['message'] = upgrade_message(); + return $ret; + } - if(! array_key_exists('expire',$arr)) + if(! array_key_exists('expire', $arr)) $arr['expire'] = 120; // minutes, e.g. 2 hours $created = datetime_convert(); @@ -60,6 +73,7 @@ function chatroom_create($channel,$arr) { function chatroom_destroy($channel,$arr) { $ret = array('success' => false); + if(intval($arr['cr_id'])) $sql_extra = " and cr_id = " . intval($arr['cr_id']) . " "; elseif(trim($arr['cr_name'])) @@ -72,7 +86,7 @@ function chatroom_destroy($channel,$arr) { $r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1", intval($channel['channel_id']) ); - if(! $r) { + if(! $r) { $ret['message'] = t('Invalid room specifier.'); return $ret; } @@ -88,12 +102,13 @@ function chatroom_destroy($channel,$arr) { intval($r[0]['cr_id']) ); } + $ret['success'] = true; return $ret; } -function chatroom_enter($observer_xchan,$room_id,$status,$client) { +function chatroom_enter($observer_xchan, $room_id, $status, $client) { if(! $room_id || ! $observer_xchan) return; @@ -117,7 +132,7 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) { return false; } - $limit = service_class_fetch($r[0]['cr_uid'],'chatters_inroom'); + $limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom'); if($limit !== false) { $y = q("select count(*) as total from chatpresence where cp_room = %d", intval($room_id) @@ -157,12 +172,12 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) { dbesc($status), dbesc($client) ); - + return $r; } -function chatroom_leave($observer_xchan,$room_id,$client) { +function chatroom_leave($observer_xchan, $room_id, $client) { if(! $room_id || ! $observer_xchan) return; @@ -208,7 +223,7 @@ function chatroom_list_count($uid) { * It is the caller's responsibility to enter the room. */ -function chat_message($uid,$room_id,$xchan,$text) { +function chat_message($uid, $room_id, $xchan, $text) { $ret = array('success' => false); @@ -230,14 +245,14 @@ function chat_message($uid,$room_id,$xchan,$text) { 'chat_text' => $text ); - call_hooks('chat_message',$arr); + call_hooks('chat_message', $arr); $x = q("insert into chat ( chat_room, chat_xchan, created, chat_text ) values( %d, '%s', '%s', '%s' )", intval($room_id), dbesc($xchan), dbesc(datetime_convert()), - dbesc($arr['chat_text']) + dbesc($arr['chat_text']) ); $ret['success'] = true; diff --git a/include/comanche.php b/include/comanche.php index b181d415a..1ddabb693 100644 --- a/include/comanche.php +++ b/include/comanche.php @@ -15,23 +15,22 @@ require_once('include/widgets.php'); // page layout from the given description -function pdl_selector($uid,$current="") { - +function pdl_selector($uid, $current="") { $o = ''; $sql_extra = item_permissions_sql($uid); - $r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' order by sid asc", - intval($owner) + $r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' $sql_extra order by sid asc", + intval($uid) ); $arr = array('channel_id' => $uid, 'current' => $current, 'entries' => $r); call_hooks('pdl_selector',$arr); $entries = $arr['entries']; - $current = $arr['current']; - - $o .= "<select name=\"pdl_select\" id=\"pdl_select\" size=\"1\" >"; + $current = $arr['current']; + + $o .= '<select name="pdl_select" id="pdl_select" size="1">'; $entries[] = array('title' => t('Default'), 'mid' => ''); foreach($entries as $selection) { $selected = (($selection == $current) ? ' selected="selected" ' : ''); @@ -40,56 +39,61 @@ function pdl_selector($uid,$current="") { $o .= '</select>'; return $o; -} +} -function comanche_parser(&$a,$s) { +function comanche_parser(&$a, $s, $pass = 0) { + $matches = array(); $cnt = preg_match_all("/\[comment\](.*?)\[\/comment\]/ism", $s, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { - $s = str_replace($mtch[0],'',$s); + $s = str_replace($mtch[0], '', $s); } } - $cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches); - if($cnt) - $a->page['template'] = trim($matches[1]); + if($pass == 0) { + $cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches); + if($cnt) + $a->page['template'] = trim($matches[1]); - $cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches); - if($cnt) { - $a->page['template'] = trim($matches[2]); - $a->page['template_style'] = trim($matches[2]) . '_' . $matches[1]; - } + $cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches); + if($cnt) { + $a->page['template'] = trim($matches[2]); + $a->page['template_style'] = trim($matches[2]) . '_' . $matches[1]; + } - $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches); - if($cnt) { - $a->page['template'] = trim($matches[1]); - } + $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches); + if($cnt) { + $a->page['template'] = trim($matches[1]); + } - $cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches); - if($cnt) { - $a->layout['schema'] = trim($matches[1]); - $a->layout['theme'] = trim($matches[2]); - } + $cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches); + if($cnt) { + $a->layout['schema'] = trim($matches[1]); + $a->layout['theme'] = trim($matches[2]); + } - $cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches); - if($cnt) - $a->layout['theme'] = trim($matches[1]); + $cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches); + if($cnt) + $a->layout['theme'] = trim($matches[1]); - $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER); - if($cnt) { - foreach($matches as $mtch) { - $a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]); - } } + else { + $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]); + } + } - $cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER); - if($cnt) { - // only the last webpage definition is used if there is more than one - foreach($matches as $mtch) { - $a->layout['webpage'] = comanche_webpage($a,$mtch[1]); + $cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER); + if($cnt) { + // only the last webpage definition is used if there is more than one + foreach($matches as $mtch) { + $a->layout['webpage'] = comanche_webpage($a,$mtch[1]); + } } } @@ -99,14 +103,14 @@ function comanche_parser(&$a,$s) { function comanche_menu($name,$class = '') { $channel_id = comanche_get_channel_id(); if($channel_id) { - $m = menu_fetch($name,$channel_id,get_observer_hash()); - return menu_render($m,$class); + $m = menu_fetch($name,$channel_id, get_observer_hash()); + return menu_render($m, $class); } } function comanche_replace_region($match) { $a = get_app(); - if(array_key_exists($match[1],$a->page)) { + if(array_key_exists($match[1], $a->page)) { return $a->page[$match[1]]; } } @@ -121,15 +125,15 @@ function comanche_get_channel_id() { $channel_id = ((is_array(get_app()->profile)) ? get_app()->profile['profile_uid'] : 0); if((! $channel_id) && (local_channel())) $channel_id = local_channel(); + return $channel_id; } function comanche_block($name) { - + $o = ''; $channel_id = comanche_get_channel_id(); - + if($channel_id) { - $o = ''; $r = q("select * from item inner join item_id on iid = item.id and item_id.uid = item.uid and item.uid = %d and service = 'BUILDBLOCK' and sid = '%s' limit 1", intval($channel_id), dbesc($name) @@ -138,11 +142,12 @@ function comanche_block($name) { $o = '<div class="widget bblock">'; if($r[0]['title']) $o .= '<h3>' . $r[0]['title'] . '</h3>'; - $o .= prepare_text($r[0]['body'],$r[0]['mimetype']); - $o .= '</div>'; + $o .= prepare_text($r[0]['body'], $r[0]['mimetype']); + $o .= '</div>'; } } + return $o; } @@ -154,8 +159,9 @@ function comanche_block($name) { // of what template and webpage options we might desire. function comanche_webpage(&$a,$s) { - $ret = array(); + $matches = array(); + $cnt = preg_match_all("/\[authored\](.*?)\[\/authored\]/ism", $s, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { @@ -170,9 +176,10 @@ function comanche_webpage(&$a,$s) { // the global app environment, or config storage until we implement argument passing -function comanche_widget($name,$text) { - $a = get_app(); +function comanche_widget($name, $text) { $vars = array(); + $matches = array(); + $cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $text, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { @@ -186,12 +193,13 @@ function comanche_widget($name,$text) { } -function comanche_region(&$a,$s) { +function comanche_region(&$a, $s) { + $matches = array(); $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { - $s = str_replace($mtch[0],comanche_menu(trim($mtch[1])),$s); + $s = str_replace($mtch[0], comanche_menu(trim($mtch[1])), $s); } } @@ -244,7 +252,3 @@ function register_page_template($arr) { get_app()->page_layouts[$arr['template']] = array($arr['variant']); return; } - - - - diff --git a/include/conversation.php b/include/conversation.php index 8bc42b34b..8a834f339 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -205,22 +205,22 @@ function localize_item(&$item){ $item['body'] .= "\n\n\n" . $Bphoto; } - if (stristr($item['verb'],ACTIVITY_POKE)) { + if (stristr($item['verb'], ACTIVITY_POKE)) { - // FIXME for obscured private posts, until then leave untranslated + /** @FIXME for obscured private posts, until then leave untranslated */ return; $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1)); if(! $verb) return; + if ($item['obj_type']=="" || $item['obj_type']!== ACTIVITY_OBJ_PERSON) return; $Aname = $item['author']['xchan_name']; $Alink = $item['author']['xchan_url']; - $obj= json_decode_plus($item['object']); - + $Blink = $Bphoto = ''; if($obj['link']) { @@ -246,7 +246,6 @@ function localize_item(&$item){ $item['body'] = $item['localize'] = sprintf($txt, $A, $B); $item['body'] .= "\n\n\n" . $Bphoto; - } if (stristr($item['verb'],ACTIVITY_MOOD)) { $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1)); @@ -375,54 +374,72 @@ function localize_item(&$item){ && strlen($item['body']) && (! strpos($item['body'],'data'))) { $item['body'] = json_encode(crypto_encapsulate($item['body'],get_config('system','pubkey'))); } - } /** - * Count the total of comments on this item and its desendants + * @brief Count the total of comments on this item and its desendants. + * + * @param array $item an assoziative item-array which provides: + * * \e array \b children + * @return number */ function count_descendants($item) { $total = count($item['children']); - if($total > 0) { - foreach($item['children'] as $child) { - if(! visible_activity($child)) - $total --; - $total += count_descendants($child); - } - } + if ($total > 0) { + foreach ($item['children'] as $child) { + if (! visible_activity($child)) + $total --; + + $total += count_descendants($child); + } + } return $total; } +/** + * @brief Check if the activity of the item is visible. + * + * likes (etc.) can apply to other things besides posts. Check if they are post + * children, in which case we handle them specially. + * + * @param array $item + * @return boolean + */ function visible_activity($item) { - - // likes (etc.) can apply to other things besides posts. Check if they are post children, - // in which case we handle them specially - $hidden_activities = array(ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE); - foreach($hidden_activities as $act) { - if((activity_match($item['verb'],$act)) && ($item['mid'] != $item['parent_mid'])) { + + foreach ($hidden_activities as $act) { + if ((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) { return false; } } + return true; } /** - * "Render" a conversation or list of items for HTML display. + * @brief "Render" a conversation or list of items for HTML display. + * * There are two major forms of display: - * - Sequential or unthreaded ("New Item View" or search results) - * - conversation view + * - Sequential or unthreaded ("New Item View" or search results) + * - conversation view + * * The $mode parameter decides between the various renderings and also * figures out how to determine page owner and other contextual items * that are based on unique features of the calling module. * + * @param App &$a + * @param array $items + * @param string $mode + * @param boolean $update + * @param string $page_mode default traditional + * @param string $prepared_item + * @return string */ - - function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $prepared_item = '') { $content_html = ''; @@ -432,39 +449,38 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $ssl_state = ((local_channel()) ? true : false); - if(local_channel()) + if (local_channel()) load_pconfig(local_channel(),''); $arr_blocked = null; - if(local_channel()) + if (local_channel()) $str_blocked = get_pconfig(local_channel(),'system','blocked'); - if(! local_channel() && ($mode == 'network')) { + if (! local_channel() && ($mode == 'network')) { $sys = get_sys_channel(); $id = $sys['channel_id']; $str_blocked = get_pconfig($id,'system','blocked'); } - - if($str_blocked) { - $arr_blocked = explode(',',$str_blocked); - for($x = 0; $x < count($arr_blocked); $x ++) + + if ($str_blocked) { + $arr_blocked = explode(',',$str_blocked); + for ($x = 0; $x < count($arr_blocked); $x ++) $arr_blocked[$x] = trim($arr_blocked[$x]); } - - $profile_owner = 0; - $page_writeable = false; + $profile_owner = 0; + $page_writeable = false; $live_update_div = ''; $preview = (($page_mode === 'preview') ? true : false); $previewing = (($preview) ? ' preview ' : ''); - if($mode === 'network') { + if ($mode === 'network') { $profile_owner = local_channel(); $page_writeable = true; - if(!$update) { + if (!$update) { // The special div is needed for liveUpdate to kick in for this page. // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). @@ -490,13 +506,13 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ } } - elseif($mode === 'channel') { + elseif ($mode === 'channel') { $profile_owner = $a->profile['profile_uid']; $page_writeable = ($profile_owner == local_channel()); - if(!$update) { + if (!$update) { $tab = notags(trim($_GET['tab'])); - if($tab === 'posts') { + if ($tab === 'posts') { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. @@ -507,23 +523,23 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ } } - elseif($mode === 'display') { + elseif ($mode === 'display') { $profile_owner = local_channel(); $page_writeable = false; $live_update_div = '<div id="live-display"></div>' . "\r\n"; } - elseif($mode === 'page') { + elseif ($mode === 'page') { $profile_owner = $a->profile['uid']; $page_writeable = ($profile_owner == local_channel()); $live_update_div = '<div id="live-page"></div>' . "\r\n"; } - elseif($mode === 'search') { + elseif ($mode === 'search') { $live_update_div = '<div id="live-search"></div>' . "\r\n"; } - elseif($mode === 'photos') { + elseif ($mode === 'photos') { $profile_onwer = $a->profile['profile_uid']; $page_writeable = ($profile_owner == local_channel()); $live_update_div = '<div id="live-photos"></div>' . "\r\n"; @@ -533,12 +549,12 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $page_dropping = ((local_channel() && local_channel() == $profile_owner) ? true : false); - if(! feature_enabled($profile_owner,'multi_delete')) + if (! feature_enabled($profile_owner,'multi_delete')) $page_dropping = false; $channel = $a->get_channel(); - $observer = $a->get_observer(); + $observer = $a->get_observer(); if($update) $return_url = $_SESSION['return_url']; @@ -637,7 +653,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ else $dropping = false; - $drop = array( 'pagedropping' => $page_dropping, 'dropping' => $dropping, @@ -647,7 +662,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $star = false; $isstarred = "unstarred icon-star-empty"; - + $lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) ? t('Private Message') : false @@ -659,17 +674,14 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $verified = (($item['item_flags'] & ITEM_VERIFIED) ? t('Message signature validated') : ''); $forged = ((($item['sig']) && (! ($item['item_flags'] & ITEM_VERIFIED))) ? t('Message signature incorrect') : ''); - $unverified = ''; - $tags=array(); $terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN)); if(count($terms)) foreach($terms as $tag) $tags[] = format_term_for_display($tag); - $body = prepare_body($item,true); $tmp_item = array( @@ -731,12 +743,9 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ // $threads[$threadsid]['id'] = $item['item_id']; $threads[] = $arr['output']; - } - } - else - { + else { // Normal View // logger('conv: items: ' . print_r($items,true)); @@ -751,7 +760,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ if($mode === 'display' && $items) $conv->set_profile_owner($items[0]['uid']); - // get all the topmost parents // this shouldn't be needed, as we should have only them in our array // But for now, this array respects the old style, just in case @@ -831,20 +839,19 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ // logger('nouveau: ' . print_r($threads,true)); - $o .= replace_macros($page_template, array( - '$baseurl' => $a->get_baseurl($ssl_state), + $o .= replace_macros($page_template, array( + '$baseurl' => $a->get_baseurl($ssl_state), '$photo_item' => $content_html, - '$live_update' => $live_update_div, - '$remove' => t('remove'), - '$mode' => $mode, - '$user' => $a->user, - '$threads' => $threads, + '$live_update' => $live_update_div, + '$remove' => t('remove'), + '$mode' => $mode, + '$user' => $a->user, + '$threads' => $threads, '$wait' => t('Loading...'), - '$dropping' => ($page_dropping?t('Delete Selected Items'):False), - )); + '$dropping' => ($page_dropping?t('Delete Selected Items'):False), + )); return $o; - } @@ -892,7 +899,6 @@ function item_photo_menu($item){ $vsrc_link = ""; $follow_url = ""; - $local_channel = local_channel(); if($local_channel) { @@ -910,7 +916,7 @@ function item_photo_menu($item){ } } - $profile_link = chanlink_hash($item['author_xchan']); + $profile_link = chanlink_hash($item['author_xchan']); if($item['uid'] > 0) $pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan']; @@ -927,7 +933,6 @@ function item_photo_menu($item){ $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $contact['abook_id']; $clean_url = normalise_link($item['author-link']); - } $menu = Array( @@ -943,7 +948,6 @@ function item_photo_menu($item){ t("Poke") => $poke_link ); - $args = array('item' => $item, 'menu' => $menu); call_hooks('item_photo_menu', $args); @@ -958,17 +962,17 @@ function item_photo_menu($item){ } elseif ($v!="") $o .= "<li><a href=\"$v\">$k</a></li>\n"; } + return $o; } /** * @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.) + * * Increments the count of each matching activity and adds a link to the author as needed. * - * @param array $a (not used) * @param array $item * @param array &$conv_responses (already created with builtin activity structure) - * @return void */ function builtin_activity_puller($item, &$conv_responses) { @@ -1011,11 +1015,7 @@ function builtin_activity_puller($item, &$conv_responses) { break; } - - if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) { - - $name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown')); $url = (($item['author']['xchan_url']) ? '<a href="' . chanlink_url($item['author']['xchan_url']) . '">' . $name . '</a>' @@ -1041,31 +1041,33 @@ function builtin_activity_puller($item, &$conv_responses) { $conv_responses[$mode][$item['thr_parent'] . '-l'][] = $url; // there can only be one activity verb per item so if we found anything, we can stop looking - $return; + return; } } } -// Format the like/dislike text for a profile item -// $cnt = number of people who like/dislike the item -// $arr = array of pre-linked names of likers/dislikers -// $type = one of 'like, 'dislike' -// $id = item id -// returns formatted text - -function format_like($cnt,$arr,$type,$id) { +/** + * @brief Format the like/dislike text for a profile item. + * + * @param int $cnt number of people who like/dislike the item + * @param array $arr array of pre-linked names of likers/dislikers + * @param string $typ eone of 'like, 'dislike' + * @param int $id item id + * @return string formatted text + */ +function format_like($cnt, $arr, $type, $id) { $o = ''; - if($cnt == 1) + if ($cnt == 1) { $o .= (($type === 'like') ? sprintf( t('%s likes this.'), $arr[0]) : sprintf( t('%s doesn\'t like this.'), $arr[0])) . EOL ; - else { + } else { $spanatts = 'class="fakelink" onclick="openClose(\'' . $type . 'list-' . $id . '\');"'; $o .= (($type === 'like') ? sprintf( tt('<span %1$s>%2$d people</span> like this.','<span %1$s>%2$d people</span> like this.',$cnt), $spanatts, $cnt) : sprintf( tt('<span %1$s>%2$d people</span> don\'t like this.','<span %1$s>%2$d people</span> don\'t like this.',$cnt), $spanatts, $cnt) ); - $o .= EOL ; + $o .= EOL; $total = count($arr); if($total >= MAX_LIKERS) $arr = array_slice($arr, 0, MAX_LIKERS - 1); @@ -1077,11 +1079,12 @@ function format_like($cnt,$arr,$type,$id) { $str = (($type === 'like') ? sprintf( t('%s like this.'), $str) : sprintf( t('%s don\'t like this.'), $str)); $o .= "\t" . '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>'; } + return $o; } -function status_editor($a,$x,$popup=false) { +function status_editor($a, $x, $popup = false) { $o = ''; @@ -1092,28 +1095,28 @@ function status_editor($a,$x,$popup=false) { // if(feature_enabled(local_channel(),'richtext')) // $plaintext = false; - $voting = feature_enabled(local_channel(),'consensus_tools'); + $voting = feature_enabled(local_channel(), 'consensus_tools'); $mimeselect = ''; - if(array_key_exists('mimetype',$x) && $x['mimetype']) { + if(array_key_exists('mimetype', $x) && $x['mimetype']) { if($x['mimetype'] != 'text/bbcode') $plaintext = true; - if($x['mimetype'] === 'choose') { + if($x['mimetype'] === 'choose') { $mimeselect = mimetype_select($x['profile_uid']); } else - $mimeselect = '<input type="hidden" name="mimetype" value="' . $x['mimetype'] . '" />'; + $mimeselect = '<input type="hidden" name="mimetype" value="' . $x['mimetype'] . '" />'; } $layoutselect = ''; - if(array_key_exists('layout',$x) && $x['layout']) { + if(array_key_exists('layout', $x) && $x['layout']) { if($x['layout'] === 'choose') { $layoutselect = layout_select($x['profile_uid']); } else - $layoutselect = '<input type="hidden" name="layout_mid" value="' . $x['layout'] . '" />'; + $layoutselect = '<input type="hidden" name="layout_mid" value="' . $x['layout'] . '" />'; } - + if(array_key_exists('channel_select',$x) && $x['channel_select']) { require_once('include/identity.php'); @@ -1126,7 +1129,7 @@ function status_editor($a,$x,$popup=false) { $webpage = ((x($x,'webpage')) ? $x['webpage'] : ''); $tpl = get_markup_template('jot-header.tpl'); - + $a->page['htmlhead'] .= replace_macros($tpl, array( '$newpost' => 'true', '$baseurl' => $a->get_baseurl(true), @@ -1135,8 +1138,8 @@ function status_editor($a,$x,$popup=false) { '$nickname' => $x['nickname'], '$ispublic' => t('Visible to <strong>everybody</strong>'), '$linkurl' => t('Please enter a link URL:'), - '$vidurl' => t("Please enter a video link/URL:"), - '$audurl' => t("Please enter an audio link/URL:"), + '$vidurl' => t('Please enter a video link/URL:'), + '$audurl' => t('Please enter an audio link/URL:'), '$term' => t('Tag term:'), '$fileas' => t('Save to Folder:'), '$whereareu' => t('Where are you right now?'), @@ -1144,35 +1147,40 @@ function status_editor($a,$x,$popup=false) { )); - $tpl = get_markup_template("jot.tpl"); + $tpl = get_markup_template('jot.tpl'); $jotplugins = ''; $jotnets = ''; $preview = t('Preview'); // $preview = ((feature_enabled($x['profile_uid'],'preview')) ? t('Preview') : ''); - if(x($x,'nopreview')) + if(x($x, 'nopreview')) $preview = ''; - $defexpire = ((($z = get_pconfig($x['profile_uid'],'system','default_post_expire')) && (! $webpage)) ? $z : ''); - + $defexpire = ((($z = get_pconfig($x['profile_uid'], 'system', 'default_post_expire')) && (! $webpage)) ? $z : ''); - $cipher = get_pconfig($x['profile_uid'],'system','default_cipher'); + $cipher = get_pconfig($x['profile_uid'], 'system', 'default_cipher'); if(! $cipher) $cipher = 'aes256'; call_hooks('jot_tool', $jotplugins); call_hooks('jot_networks', $jotnets); - $o .= replace_macros($tpl,array( - '$return_path' => ((x($x,'return_path')) ? $x['return_path'] : $a->query_string), + $o .= replace_macros($tpl, array( + '$return_path' => ((x($x, 'return_path')) ? $x['return_path'] : $a->query_string), '$action' => $a->get_baseurl(true) . '/item', '$share' => (x($x,'button') ? $x['button'] : t('Share')), '$webpage' => $webpage, '$placeholdpagetitle' => ((x($x,'ptlabel')) ? $x['ptlabel'] : t('Page link title')), - '$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''), + '$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''), '$id_select' => $id_select, '$id_seltext' => t('Post as'), + '$writefiles' => (perm_is_allowed($x['profile_uid'], get_observer_hash(), 'post_photos') || perm_is_allowed($x['profile_uid'], get_observer_hash(), 'write_storage')), + '$bold' => t('Bold'), + '$italic' => t('Italic'), + '$underline' => t('Underline'), + '$quote' => t('Quote'), + '$code' => t('Code'), '$upload' => t('Upload photo'), '$shortupload' => t('upload photo'), '$attach' => t('Attach file'), @@ -1188,11 +1196,11 @@ function status_editor($a,$x,$popup=false) { '$voting' => t('Toggle voting'), '$feature_voting' => $voting, '$consensus' => 0, - '$noloc' => ((get_pconfig($x['profile_uid'],'system','use_browser_location')) ? t('Clear browser location') : ''), + '$noloc' => ((get_pconfig($x['profile_uid'], 'system', 'use_browser_location')) ? t('Clear browser location') : ''), '$shortnoloc' => t('clear location'), - '$title' => ((x($x,'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''), + '$title' => ((x($x, 'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''), '$placeholdertitle' => t('Title (optional)'), - '$catsenabled' => ((feature_enabled($x['profile_uid'],'categories') && (! $webpage)) ? 'categories' : ''), + '$catsenabled' => ((feature_enabled($x['profile_uid'], 'categories') && (! $webpage)) ? 'categories' : ''), '$category' => "", '$placeholdercategory' => t('Categories (optional, comma-separated list)'), '$wait' => t('Please wait'), @@ -1211,26 +1219,24 @@ function status_editor($a,$x,$popup=false) { '$acl' => $x['acl'], '$mimeselect' => $mimeselect, '$layoutselect' => $layoutselect, - '$showacl' => ((array_key_exists('showacl',$x)) ? $x['showacl'] : true), + '$showacl' => ((array_key_exists('showacl', $x)) ? $x['showacl'] : true), '$bang' => $x['bang'], '$profile_uid' => $x['profile_uid'], '$preview' => $preview, - '$source' => ((x($x,'source')) ? $x['source'] : ''), + '$source' => ((x($x, 'source')) ? $x['source'] : ''), '$jotplugins' => $jotplugins, '$defexpire' => $defexpire, - '$feature_expire' => ((feature_enabled($x['profile_uid'],'content_expire') && (! $webpage)) ? true : false), + '$feature_expire' => ((feature_enabled($x['profile_uid'], 'content_expire') && (! $webpage)) ? true : false), '$expires' => t('Set expiration date'), - '$feature_encrypt' => ((feature_enabled($x['profile_uid'],'content_encrypt') && (! $webpage)) ? true : false), + '$feature_encrypt' => ((feature_enabled($x['profile_uid'], 'content_encrypt') && (! $webpage)) ? true : false), '$encrypt' => t('Encrypt text'), '$cipher' => $cipher, '$expiryModalOK' => t('OK'), '$expiryModalCANCEL' => t('Cancel') )); - - if ($popup==true){ - $o = '<div id="jot-popup" style="display: none;">'.$o.'</div>'; - + if ($popup === true) { + $o = '<div id="jot-popup" style="display:none">' . $o . '</div>'; } return $o; @@ -1279,13 +1285,12 @@ function add_children_to_list($children, &$arr) { } } -function conv_sort($arr,$order) { +function conv_sort($arr, $order) { if((!(is_array($arr) && count($arr)))) return array(); $parents = array(); - $children = array(); foreach($arr as $x) if($x['id'] == $x['parent']) @@ -1340,6 +1345,7 @@ function find_thread_parent_index($arr,$x) { foreach($arr as $k => $v) if($v['id'] == $x['parent']) return $k; + return false; } @@ -1368,11 +1374,11 @@ function render_location_default($item) { else $location = '<span class="smalltext">' . $coord . '</span>'; } + return $location; } - function prepare_page($item) { $a = get_app(); $naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0); @@ -1389,14 +1395,15 @@ function prepare_page($item) { // prepare_body calls unobscure() as a side effect. Do it here so that // the template will get passed an unobscured title. - $body = prepare_body($item,true); - $tpl = get_pconfig($item['uid'],'system','pagetemplate'); - if (! $tpl) - $tpl = 'page_display.tpl'; - return replace_macros(get_markup_template($tpl),array( + $body = prepare_body($item, true); + $tpl = get_pconfig($item['uid'], 'system', 'pagetemplate'); + if (! $tpl) + $tpl = 'page_display.tpl'; + + return replace_macros(get_markup_template($tpl), array( '$author' => (($naked) ? '' : $item['author']['xchan_name']), '$auth_url' => (($naked) ? '' : zid($item['author']['xchan_url'])), - '$date' => (($naked) ? '' : datetime_convert('UTC',date_default_timezone_get(),$item['created'],'Y-m-d H:i')), + '$date' => (($naked) ? '' : datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'Y-m-d H:i')), '$title' => smilies(bbcode($item['title'])), '$body' => $body, '$preview' => $preview, @@ -1420,15 +1427,15 @@ function network_tabs() { if(x($_GET,'new')) { $new_active = 'active'; } - + if(x($_GET,'search')) { $search_active = 'active'; } - + if(x($_GET,'star')) { $starred_active = 'active'; } - + if(x($_GET,'conv')) { $conv_active = 'active'; } @@ -1441,8 +1448,6 @@ function network_tabs() { $public_active = 'active'; } - - if (($new_active == '') && ($starred_active == '') && ($conv_active == '') @@ -1458,7 +1463,7 @@ function network_tabs() { case 'comment' : $all_active = 'active'; $no_active=''; break; } } - + if ($no_active=='active') $all_active='active'; $cmd = $a->cmd; @@ -1469,22 +1474,22 @@ function network_tabs() { if(! get_config('system','disable_discover_tab')) { $tabs[] = array( 'label' => t('Discover'), - 'url'=>z_root() . '/' . $cmd . '?f=&fh=1' , - 'sel'=> $public_active, - 'title'=> t('Imported public streams'), + 'url' => z_root() . '/' . $cmd . '?f=&fh=1' , + 'sel' => $public_active, + 'title' => t('Imported public streams'), ); } $tabs[] = array( 'label' => t('Commented Order'), - 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), + 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), 'sel'=>$all_active, 'title'=> t('Sort by Comment Date'), ); - + $tabs[] = array( 'label' => t('Posted Order'), - 'url'=>z_root() . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), + 'url'=>z_root() . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), 'sel'=>$postord_active, 'title' => t('Sort by Post Date'), ); @@ -1498,7 +1503,7 @@ function network_tabs() { ); } - if(feature_enabled(local_channel(),'new_tab')) { + if(feature_enabled(local_channel(),'new_tab')) { $tabs[] = array( 'label' => t('New'), 'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), @@ -1524,39 +1529,43 @@ function network_tabs() { 'sel'=> $spam_active, 'title' => t('Posts flagged as SPAM'), ); - } + } $arr = array('tabs' => $tabs); call_hooks('network_tabs', $arr); $tpl = get_markup_template('common_tabs.tpl'); - return replace_macros($tpl,array('$tabs' => $arr['tabs'])); - + return replace_macros($tpl, array('$tabs' => $arr['tabs'])); } - - -function profile_tabs($a, $is_owner=False, $nickname=Null){ +/** + * @brief + * + * @param App $a + * @param boolean $is_owner default false + * @param string $nickname default null + * @return void|string + */ +function profile_tabs($a, $is_owner = false, $nickname = null){ // Don't provide any profile tabs if we're running as the sys channel - - if($a->is_sys) + if ($a->is_sys) return; - + $channel = $a->get_channel(); if (is_null($nickname)) $nickname = $channel['channel_address']; $uid = (($a->profile['profile_uid']) ? $a->profile['profile_uid'] : local_channel()); - - if (get_pconfig($uid,'system','noprofiletabs')) + + if (get_pconfig($uid, 'system', 'noprofiletabs')) return; - - if(x($_GET,'tab')) + + if (x($_GET, 'tab')) $tab = notags(trim($_GET['tab'])); - + $url = $a->get_baseurl() . '/channel/' . $nickname; $pr = $a->get_baseurl() . '/profile/' . $nickname; @@ -1572,42 +1581,42 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){ $p = get_all_perms($uid,get_observer_hash()); - if($p['view_profile']) { + if ($p['view_profile']) { $tabs[] = array( 'label' => t('About'), - 'url' => $pr, - 'sel' => ((argv(0) == 'profile') ? 'active' : ''), + 'url' => $pr, + 'sel' => ((argv(0) == 'profile') ? 'active' : ''), 'title' => t('Profile Details'), 'id' => 'profile-tab', ); } - if($p['view_photos']) { + if ($p['view_photos']) { $tabs[] = array( 'label' => t('Photos'), - 'url' => $a->get_baseurl() . '/photos/' . $nickname, - 'sel' => ((argv(0) == 'photos') ? 'active' : ''), + 'url' => $a->get_baseurl() . '/photos/' . $nickname, + 'sel' => ((argv(0) == 'photos') ? 'active' : ''), 'title' => t('Photo Albums'), 'id' => 'photo-tab', ); } - if($p['view_storage']) { + if ($p['view_storage']) { $tabs[] = array( 'label' => t('Files'), - 'url' => $a->get_baseurl() . '/cloud/' . $nickname . ((get_observer_hash()) ? '' : '?f=&davguest=1'), - 'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''), + 'url' => $a->get_baseurl() . '/cloud/' . $nickname . ((get_observer_hash()) ? '' : '?f=&davguest=1'), + 'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''), 'title' => t('Files and Storage'), 'id' => 'files-tab', ); } - if($p['chat']) { + if ($p['chat']) { require_once('include/chat.php'); $has_chats = chatroom_list_count($uid); if ($has_chats) { $tabs[] = array( 'label' => t('Chatrooms'), - 'url' => $a->get_baseurl() . '/chat/' . $nickname, - 'sel' => ((argv(0) == 'chat') ? 'active' : '' ), + 'url' => $a->get_baseurl() . '/chat/' . $nickname, + 'sel' => ((argv(0) == 'chat') ? 'active' : '' ), 'title' => t('Chatrooms'), 'id' => 'chat-tab', ); @@ -1616,33 +1625,29 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){ require_once('include/menu.php'); $has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK); - if($is_owner && $has_bookmarks) { + if ($is_owner && $has_bookmarks) { $tabs[] = array( 'label' => t('Bookmarks'), - 'url' => $a->get_baseurl() . '/bookmarks', - 'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''), + 'url' => $a->get_baseurl() . '/bookmarks', + 'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''), 'title' => t('Saved Bookmarks'), 'id' => 'bookmarks-tab', ); } - - if($is_owner && feature_enabled($uid,'webpages')) { + if ($is_owner && feature_enabled($uid,'webpages')) { $tabs[] = array( 'label' => t('Webpages'), - 'url' => $a->get_baseurl() . '/webpages/' . $nickname, - 'sel' => ((argv(0) == 'webpages') ? 'active' : ''), + 'url' => $a->get_baseurl() . '/webpages/' . $nickname, + 'sel' => ((argv(0) == 'webpages') ? 'active' : ''), 'title' => t('Manage Webpages'), 'id' => 'webpages-tab', ); - } - - else { - // FIXME - // we probably need a listing of events that were created by - // this channel and are visible to the observer - - + } else { + /** + * @FIXME we probably need a listing of events that were created by + * this channel and are visible to the observer + */ } $arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs); @@ -1665,8 +1670,7 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) { $ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS); array_push($ret[$v]['list_part'], '<a href="#" data-toggle="modal" data-target="#' . $v . 'Modal-' . (($ob) ? $ob->get_id() : $item['id']) . '"><b>' . t('View all') . '</b></a>'); - } - else { + } else { $ret[$v]['list_part'] = ''; } $ret[$v]['button'] = get_response_button_text($v,$ret[$v]['count']); @@ -1674,9 +1678,9 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) { } $count = 0; - foreach($ret as $key) { - if ($key['count'] == true) - $count++; + foreach ($ret as $key) { + if ($key['count'] == true) + $count++; } $ret['count'] = $count; diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php index 4a0f5e37b..708d8e709 100755 --- a/include/dba/dba_driver.php +++ b/include/dba/dba_driver.php @@ -24,7 +24,6 @@ function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) { $dba = null; - $dbtype = intval($dbtype); if($dbtype == DBTYPE_POSTGRES) { @@ -59,7 +58,7 @@ abstract class dba_driver { const INSTALL_SCRIPT='install/schema_mysql.sql'; const NULL_DATE = '0000-00-00 00:00:00'; const UTC_NOW = 'UTC_TIMESTAMP()'; - + protected $debug = 0; protected $db; public $connected = false; @@ -121,11 +120,11 @@ abstract class dba_driver { function get_null_date() { return static::NULL_DATE; } - + function get_install_script() { return static::INSTALL_SCRIPT; } - + function utcnow() { return static::UTC_NOW; } @@ -145,6 +144,7 @@ abstract class dba_driver { return false; } } + return true; } @@ -166,19 +166,19 @@ abstract class dba_driver { function quote_interval($txt) { return $txt; } - + function optimize_table($table) { q('OPTIMIZE TABLE '.$table); } - + function concat($fld, $sep) { return 'GROUP_CONCAT(DISTINCT '.$fld.' SEPARATOR \''.$sep.'\')'; } - + function escapebin($str) { return $this->escape($str); } - + function unescapebin($str) { return $str; } @@ -193,6 +193,7 @@ function printable($s) { $s = str_replace("\x00",'.',$s); if(x($_SERVER,'SERVER_NAME')) $s = escape_tags($s); + return $s; } @@ -252,7 +253,7 @@ function db_quoteinterval($txt) { function dbesc_identifier($str) { global $db; - return $db->escape_identifier($txt); + return $db->escape_identifier($str); } function db_utcnow() { @@ -349,6 +350,7 @@ function dbesc_array_cb(&$item, $key) { $item = '0001-01-01 00:00:00'; else if($item == '0001-01-01 00:00:00' && ACTIVE_DBTYPE == DBTYPE_MYSQL) $item = '0000-00-00 00:00:00'; + $item = dbesc($item); } } @@ -382,8 +384,7 @@ function db_getfunc($f) { $f = strtolower($f); if(isset($lookup[$f]) && isset($lookup[$f][ACTIVE_DBTYPE])) return $lookup[$f][ACTIVE_DBTYPE]; - + logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG); return $f; } - diff --git a/include/deliver.php b/include/deliver.php index 47d8562df..0fb7a4aeb 100644 --- a/include/deliver.php +++ b/include/deliver.php @@ -20,6 +20,32 @@ function deliver_run($argv, $argc) { dbesc($argv[$x]) ); if($r) { + + /** + * Check to see if we have any recent communications with this hub (in the last month). + * If not, reduce the outq_priority. + */ + + $h = parse_url($r[0]['outq_posturl']); + if($h) { + $base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : ''); + if($base !== z_root()) { + $y = q("select site_update from site where site_url = '%s' ", + dbesc($base) + ); + if($y && $y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) { + q("update outq set outq_priority = %d where outq_hash = '%s'", + intval($r[0]['outq_priority'] + 10), + dbesc($r[0]['outq_hash']) + ); + logger('immediate delivery deferred for site ' . $base); + continue; + } + } + } + + // "post" queue driver - used for diaspora and friendica-over-diaspora communications. + if($r[0]['outq_driver'] === 'post') { $result = z_post_url($r[0]['outq_posturl'],$r[0]['outq_msg']); if($result['success'] && $result['return_code'] < 300) { @@ -74,9 +100,11 @@ function deliver_run($argv, $argc) { logger('deliver: dest: ' . $r[0]['outq_posturl'], LOGGER_DEBUG); $result = zot_zot($r[0]['outq_posturl'],$r[0]['outq_notify']); if($result['success']) { + logger('deliver: remote zot delivery succeeded to ' . $r[0]['outq_posturl']); zot_process_response($r[0]['outq_posturl'],$result, $r[0]); } else { + logger('deliver: remote zot delivery failed to ' . $r[0]['outq_posturl']); $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", dbesc(datetime_convert()), dbesc($argv[$x]) diff --git a/include/diaspora.php b/include/diaspora.php index 553c7474c..1e0e48a86 100755 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -709,13 +709,19 @@ function diaspora_request($importer,$xml) { $their_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES; + + $closeness = get_pconfig($importer['channel_id'],'system','new_abook_closeness'); + if($closeness === false) + $closeness = 80; + + $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_rating, abook_created, abook_updated, abook_connected, abook_dob, abook_flags) values ( %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', %d )", intval($importer['channel_account_id']), intval($importer['channel_id']), dbesc($ret['xchan_hash']), intval($default_perms), intval($their_perms), - intval(99), + intval($closeness), intval(0), dbesc(datetime_convert()), dbesc(datetime_convert()), @@ -799,11 +805,6 @@ function diaspora_post($importer,$xml,$msg) { } - if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) { - logger('diaspora_post: Ignoring this author.'); - return 202; - } - $search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid); $r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", @@ -844,8 +845,9 @@ function diaspora_post($importer,$xml,$msg) { // Look for tags and linkify them $results = linkify_tags(get_app(), $body, $importer['channel_id']); + $datarray['term'] = array(); + if($results) { - $datarray['term'] = array(); foreach($results as $result) { $success = $result['success']; if($success['replaced']) { @@ -860,6 +862,37 @@ function diaspora_post($importer,$xml,$msg) { } } + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + + + + $plink = service_plink($contact,$guid); @@ -883,6 +916,15 @@ function diaspora_post($importer,$xml,$msg) { $datarray['item_flags'] = ITEM_THREAD_TOP; $datarray['item_unseen'] = 1; + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) { + logger('diaspora_post: Ignoring this author.'); + return 202; + } + + $result = item_store($datarray); return; @@ -949,11 +991,6 @@ function diaspora_reshare($importer,$xml,$msg) { if(! $contact) return; - if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) { - logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true)); - return 202; - } - $search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid); $r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", intval($importer['channel_id']), @@ -1027,8 +1064,9 @@ function diaspora_reshare($importer,$xml,$msg) { // Look for tags and linkify them $results = linkify_tags(get_app(), $body, $importer['channel_id']); + $datarray['term'] = array(); + if($results) { - $datarray['term'] = array(); foreach($results as $result) { $success = $result['success']; if($success['replaced']) { @@ -1043,6 +1081,38 @@ function diaspora_reshare($importer,$xml,$msg) { } } + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + + + + + $newbody = "[share author='" . urlencode($orig_author_name) . "' profile='" . $orig_author_link . "' avatar='" . $orig_author_photo @@ -1066,6 +1136,15 @@ function diaspora_reshare($importer,$xml,$msg) { $datarray['app'] = 'Diaspora'; + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) { + logger('diaspora_post: Ignoring this author.'); + return 202; + } + + $result = item_store($datarray); return; @@ -1223,15 +1302,6 @@ function diaspora_comment($importer,$xml,$msg) { if(intval($parent_item['item_private'])) $pubcomment = 0; - // So basically if something arrives at the sys channel it's by definition public and we allow it. - // If $pubcomment and the parent was public, we allow it. - // In all other cases, honour the permissions for this Diaspora connection - - if((! $importer['system']) && (! $pubcomment) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments'))) { - logger('diaspora_comment: Ignoring this author.'); - return 202; - } - $search_guid = $guid; if(strlen($guid) == 64) $search_guid = $guid . '%'; @@ -1281,6 +1351,12 @@ function diaspora_comment($importer,$xml,$msg) { // our post, so he/she must be a contact of ours and his/her public key // should be in $msg['key'] + if($importer['system']) { + // don't relay to the sys channel + logger('diaspora_comment: relay to sys channel blocked.'); + return; + } + $author_signature = base64_decode($author_signature); if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) { @@ -1323,8 +1399,9 @@ function diaspora_comment($importer,$xml,$msg) { // Look for tags and linkify them $results = linkify_tags(get_app(), $body, $importer['channel_id']); + $datarray['term'] = array(); + if($results) { - $datarray['term'] = array(); foreach($results as $result) { $success = $result['success']; if($success['replaced']) { @@ -1339,6 +1416,34 @@ function diaspora_comment($importer,$xml,$msg) { } } + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + $datarray['uid'] = $importer['channel_id']; $datarray['verb'] = ACTIVITY_POST; $datarray['mid'] = $guid; @@ -1370,6 +1475,22 @@ function diaspora_comment($importer,$xml,$msg) { $datarray['diaspora_meta'] = json_encode(crypto_encapsulate(json_encode($x),$key)); } + + + // So basically if something arrives at the sys channel it's by definition public and we allow it. + // If $pubcomment and the parent was public, we allow it. + // In all other cases, honour the permissions for this Diaspora connection + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! $pubcomment) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments')) && (! $tgroup)) { + logger('diaspora_comment: Ignoring this author.'); + return 202; + } + + + + $result = item_store($datarray); if($result && $result['success']) diff --git a/include/dir_fns.php b/include/dir_fns.php index 686c5140f..4c6c40f15 100644 --- a/include/dir_fns.php +++ b/include/dir_fns.php @@ -48,7 +48,7 @@ function check_upstream_directory() { if($directory) { $h = parse_url($directory); if($h) { - $x = zot_finger('sys@' . $h['host']); + $x = zot_finger('[system]@' . $h['host']); if($x['success']) { $j = json_decode($x['body'],true); if(array_key_exists('site',$j) && array_key_exists('directory_mode',$j['site'])) { @@ -65,6 +65,35 @@ function check_upstream_directory() { return; } +function get_globaldir_setting($observer) { + + if($observer) + $globaldir = get_xconfig($observer,'directory','globaldir'); + else + $globaldir = ((array_key_exists('globaldir',$_SESSION)) ? intval($_SESSION['globaldir']) : false); + + if($globaldir === false) + $globaldir = get_config('directory','globaldir'); + + return $globaldir; +} + +function get_safemode_setting($observer) { + + if ($observer) + $safe_mode = get_xconfig($observer,'directory','safe_mode'); + else + $safe_mode = ((array_key_exists('safemode',$_SESSION)) ? intval($_SESSION['safemode']) : false); + + if($safe_mode === false) + $safe_mode = get_config('directory','safe_mode'); + + if($safe_mode === false) + $safe_mode = 1; + + return $safe_mode; +} + /** * @function dir_sort_links() * Called by the directory_sort widget @@ -74,10 +103,17 @@ function check_upstream_directory() { function dir_sort_links() { - // Build urls without order and pubforums so it's easy to tack on the changed value + $safe_mode = 1; + + $observer = get_observer_hash(); + + $safe_mode = get_safemode_setting($observer); + $globaldir = get_globaldir_setting($observer); + + // Build urls without order and pubforums so it's easy to tack on the changed value // Probably there's an easier way to do this - $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'normal'); + $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'date'); $url = 'directory?f='; $tmp = array_merge($_GET,$_POST); @@ -88,6 +124,8 @@ function dir_sort_links() { $tmp = array_merge($_GET,$_POST); unset($tmp['pubforums']); + unset($tmp['global']); + unset($tmp['safe']); unset($tmp['q']); unset($tmp['f']); $forumsurl = $url . http_build_query($tmp); @@ -98,34 +136,18 @@ function dir_sort_links() { '$reverse' => t('Reverse Alphabetic'), '$date' => t('Newest to Oldest'), '$reversedate' => t('Oldest to Newest'), - '$pubforums' => t('Public Forums Only'), - '$pubforumsonly' => x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : '', '$sort' => t('Sort'), '$selected_sort' => $current_order, '$sorturl' => $sorturl, '$forumsurl' => $forumsurl, + '$safemode' => array('safemode', t('Safe Mode'),$safe_mode,'','',' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''), + '$pubforums' => array('pubforums', t('Public Forums Only'),(x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : ''),'','',' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''), + '$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'','',' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''), )); return $o; } -function dir_safe_mode() { - $observer = get_observer_hash(); - if (! $observer) - return; - if ($observer) - $safe_mode = get_xconfig($observer,'directory','safe_mode'); - if($safe_mode === '0') - $toggle = t('Enable Safe Search'); - else - $toggle = t('Disable Safe Search'); - $o = replace_macros(get_markup_template('safesearch.tpl'), array( - '$safemode' => t('Safe Mode'), - '$toggle' => $toggle, - )); - - return $o; -} /** * @function sync_directories($mode) @@ -166,20 +188,23 @@ function sync_directories($dirmode) { // FIXME - what to do if we're in a different realm? if((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { - $r = array( + $r = array(); + $r[] = array( 'site_url' => DIRECTORY_FALLBACK_MASTER, 'site_flags' => DIRECTORY_MODE_PRIMARY, 'site_update' => NULL_DATE, 'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch', - 'site_realm' => DIRECTORY_REALM + 'site_realm' => DIRECTORY_REALM, + 'site_valid' => 1 ); - $x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm ) + $x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm, site_valid ) values ( '%s', %d', '%s', '%s', '%s' ) ", dbesc($r[0]['site_url']), intval($r[0]['site_flags']), dbesc($r[0]['site_update']), dbesc($r[0]['site_directory']), - dbesc($r[0]['site_realm']) + dbesc($r[0]['site_realm']), + intval($r[0]['site_valid']) ); $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s'", @@ -201,8 +226,11 @@ function sync_directories($dirmode) { // It will take about a month for a new directory to obtain the full current repertoire of channels. // FIXME - go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. + $token = get_config('system','realm_token'); + + $syncdate = (($rr['site_sync'] === NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']); - $x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate)); + $x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : '')); if(! $x['success']) continue; diff --git a/include/features.php b/include/features.php index fc14858a8..3a1752052 100644 --- a/include/features.php +++ b/include/features.php @@ -44,6 +44,7 @@ function get_features() { array('webpages', t('Web Pages'), t('Provide managed web pages on your channel'),false), array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders'),false), array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false), + array('photo_location', t('Photo Location'), t('If location data is available on uploaded photos, link this to a map.'),false), //FIXME - needs a description, but how the hell do we explain this to normals? diff --git a/include/fixd.php b/include/fixd.php deleted file mode 100644 index bce5eb348..000000000 --- a/include/fixd.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - - require_once('include/cli_startup.php'); - - cli_startup(); - - $rand = db_getfunc('RAND'); - $r = q("select xchan_addr, hubloc_url from xchan left join hubloc on hubloc_hash = xchan_hash where xchan_network like '%%diaspora%%' order by $rand"); - - if(! $r) - killme(); - - require_once('include/network.php'); - $total = 0; - foreach ($r as $rr) { - if($rr['hubloc_url']) { - continue; - } - $total ++; - } - - print $total . "\n"; - - foreach ($r as $rr) { - if($rr['hubloc_url']) { - continue; - } - - $webbie = $rr['xchan_addr']; - print $webbie . ' '; - - discover_by_webbie($webbie); - } diff --git a/include/follow.php b/include/follow.php index 2d6791420..fd4e1597a 100644 --- a/include/follow.php +++ b/include/follow.php @@ -227,10 +227,16 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) ); } else { - $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_flags, abook_their_perms, abook_my_perms, abook_created, abook_updated ) - values( %d, %d, '%s', %d, %d, %d, '%s', '%s' ) ", + + $closeness = get_pconfig($uid,'system','new_abook_closeness'); + if($closeness === false) + $closeness = 80; + + $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_flags, abook_their_perms, abook_my_perms, abook_created, abook_updated ) + values( %d, %d, %d, '%s', %d, %d, %d, '%s', '%s' ) ", intval($aid), intval($uid), + intval($closeness), dbesc($xchan_hash), intval(($is_http) ? ABOOK_FLAG_FEED : 0), intval(($is_http) ? $their_perms|PERMS_R_STREAM|PERMS_A_REPUBLISH : $their_perms), diff --git a/include/group.php b/include/group.php index be19f6efe..70668a355 100644 --- a/include/group.php +++ b/include/group.php @@ -254,7 +254,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id 'text' => t('All Channels'), 'id' => 0, 'selected' => (($group_id == 0) ? 'group-selected' : ''), - 'href' => $every, + 'href' => $every . (($every === 'network') ? '?f=&gid=0' : ''), ); diff --git a/include/hubloc.php b/include/hubloc.php index b5a3d47c5..98c1a21f3 100644 --- a/include/hubloc.php +++ b/include/hubloc.php @@ -170,7 +170,17 @@ function hubloc_change_primary($hubloc) { return true; } - + +// We use the post url to distinguish between http and https hublocs. +// The https might be alive, and the http dead. + +function hubloc_mark_as_down($posturl) { + $r = q("update hubloc set hubloc_status = ( hubloc_status | %d ) where hubloc_callback = '%s'", + intval(HUBLOC_OFFLINE), + dbesc($posturl) + ); +} + function xchan_store($arr) { diff --git a/include/identity.php b/include/identity.php index 415e85f2f..079c1a245 100644 --- a/include/identity.php +++ b/include/identity.php @@ -724,12 +724,13 @@ function profile_load(&$a, $nickname, $profile = '') { $p[0]['extra_fields'] = $extra_fields; - $z = q("select xchan_photo_date from xchan where xchan_hash = '%s' limit 1", + $z = q("select xchan_photo_date, xchan_addr from xchan where xchan_hash = '%s' limit 1", dbesc($p[0]['channel_hash']) ); - if($z) + if($z) { $p[0]['picdate'] = $z[0]['xchan_photo_date']; - + $p[0]['reddress'] = str_replace('@','@',$z[0]['xchan_addr']); + } // fetch user tags if this isn't the default profile @@ -817,6 +818,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { $location = false; $address = false; $pdesc = true; + $reddress = true; if((! is_array($profile)) && (! count($profile))) return $o; @@ -893,7 +895,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { || (x($profile,'country_name') == 1)) $location = t('Location:'); - $profile['homepage'] = linkify($profile['homepage']); + $profile['homepage'] = linkify($profile['homepage'],true); $gender = ((x($profile,'gender') == 1) ? t('Gender:') : False); $marital = ((x($profile,'marital') == 1) ? t('Status:') : False); @@ -906,7 +908,7 @@ logger('online: ' . $profile['online']); } if(($profile['hidewall'] && (! local_channel()) && (! remote_channel())) || $block ) { - $location = $pdesc = $gender = $marital = $homepage = $online = False; + $location = $reddress = $pdesc = $gender = $marital = $homepage = $online = False; } $firstname = ((strpos($profile['channel_name'],' ')) @@ -957,6 +959,7 @@ logger('online: ' . $profile['online']); '$homepage' => $homepage, '$chanmenu' => $channel_menu, '$diaspora' => $diaspora, + '$reddress' => $reddress, '$rating' => $z, '$contact_block' => $contact_block, )); diff --git a/include/items.php b/include/items.php index 18ce149ed..8e293d761 100755 --- a/include/items.php +++ b/include/items.php @@ -1945,7 +1945,7 @@ function item_store($arr,$allow_exec = false) { $arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : ''); - $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? $arr['body'] : ''); + $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : ''); $arr['diaspora_meta'] = ((x($arr,'diaspora_meta')) ? $arr['diaspora_meta'] : ''); $arr['allow_cid'] = ((x($arr,'allow_cid')) ? trim($arr['allow_cid']) : ''); @@ -2087,6 +2087,16 @@ function item_store($arr,$allow_exec = false) { if($r) { + // in case item_store was killed before the parent's parent attribute got set, + // set it now. This happens with some regularity on Dreamhost. This will keep + // us from getting notifications for threads that exist but which we can't see. + + if(($r[0]['mid'] === $r[0]['parent_mid']) && (! intval($r[0]['parent']))) { + q("update item set parent = id where id = %d", + intval($r[0]['id']) + ); + } + if(comments_are_now_closed($r[0])) { logger('item_store: comments closed'); $ret['message'] = 'Comments closed.'; @@ -2450,7 +2460,7 @@ function item_store_update($arr,$allow_exec = false) { $arr['item_private'] = ((array_key_exists('item_private',$arr)) ? intval($arr['item_private']) : $orig[0]['item_private']); $arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : ''); - $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? $arr['body'] : ''); + $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : ''); $arr['attach'] = ((x($arr,'attach')) ? notags(trim($arr['attach'])) : $orig[0]['attach']); $arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : $orig[0]['app']); // $arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict']) : $orig[0]['item_restrict'] ); @@ -3073,7 +3083,16 @@ function start_delivery_chain($channel,$item,$item_id,$parent) { if((! $private) && $new_public_policy) $private = 1; - $flag_bits = $item['item_flags'] | ITEM_WALL|ITEM_ORIGIN; + $flag_bits = $item['item_flags'] | ITEM_WALL; + + // The message didn't necessarily originate on this site, (we'll honour it if it did), + // but the parent post of this thread will be reset as a local post, as it is the top of + // this delivery chain and is coming from this site, regardless of where the original + // originated. + + if(! $parent) + $flag_bits = $flag_bits | ITEM_ORIGIN; + // unset the nocomment bit if it's there. @@ -3136,6 +3155,8 @@ function start_delivery_chain($channel,$item,$item_id,$parent) { intval($item_id) ); + + if($r) proc_run('php','include/notifier.php','tgroup',$item_id); else @@ -4788,3 +4809,18 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, } } } + + +/* + * We can't trust ITEM_ORIGIN to tell us if this is a local comment + * which needs to be relayed, because it was misconfigured at one point for several + * months and set for some remote items (in alternate delivery chains). This could + * cause looping, so use this hackish but accurate method. + */ + + +function comment_local_origin($item) { + if(stripos($item['mid'],get_app()->get_hostname()) && ($item['parent'] != $item['id'])) + return true; + return false; +} diff --git a/include/js_strings.php b/include/js_strings.php index 56ffa9536..84c1d70fb 100644 --- a/include/js_strings.php +++ b/include/js_strings.php @@ -20,6 +20,7 @@ function js_strings() { '$rating_val' => t('Rating'), '$rating_text' => t('Describe (optional)'), '$submit' => t('Submit'), + '$linkurl' => t('Please enter a link URL'), '$t01' => ((t('timeago.prefixAgo') != 'timeago.prefixAgo') ? t('timeago.prefixAgo') : ''), '$t02' => ((t('timeago.prefixFromNow') != 'timeago.prefixFromNow') ? t('timeago.prefixFromNow') : ''), diff --git a/include/language.php b/include/language.php index f5ee3471e..ec5fa84fa 100644 --- a/include/language.php +++ b/include/language.php @@ -24,6 +24,7 @@ */ function get_browser_language() { $langs = array(); + $lang_parse = array(); if (x($_SERVER,'HTTP_ACCEPT_LANGUAGE')) { // break up string into pieces (languages and q factors) @@ -33,7 +34,7 @@ function get_browser_language() { if (count($lang_parse[1])) { // create a list like "en" => 0.8 $langs = array_combine($lang_parse[1], $lang_parse[4]); - + // set default to 1 for any without q factor foreach ($langs as $lang => $val) { if ($val === '') $langs[$lang] = 1; @@ -144,16 +145,16 @@ function load_translation_table($lang, $install = false) { /** * @brief translate string if translation exists. * - * @param $s string that should get translated - * @param $ctx optional context to appear in po file + * @param string $s string that should get translated + * @param string $ctx optional context to appear in po file * @return translated string if exists, otherwise return $s * */ -function t($s,$ctx = '') { +function t($s, $ctx = '') { global $a; - $cs = $ctx?"__ctx:".$ctx."__ ".$s:$s; - if(x($a->strings,$cs)) { + $cs = $ctx ? '__ctx:' . $ctx . '__ ' . $s : $s; + if(x($a->strings, $cs)) { $t = $a->strings[$cs]; return is_array($t) ? $t[0] : $t; } @@ -218,7 +219,7 @@ function detect_language($s) { // strip off bbcode $naked_body = preg_replace('/\[(.+?)\]/', '', $naked_body); if(mb_strlen($naked_body) < intval($min_length)) { - logger('detect language: string length less than ' . intval($min_length), LOGGER_DATA); + logger('string length less than ' . intval($min_length), LOGGER_DATA); return ''; } diff --git a/include/nav.php b/include/nav.php index 5e8317cfa..1134d1b48 100644 --- a/include/nav.php +++ b/include/nav.php @@ -176,10 +176,8 @@ EOT; if(local_channel()) { - $network_options = get_pconfig(local_channel(),'system','network_page_default'); - $nav['network'] = array('network' . (($network_options) ? '?f=&' . $network_options : ''), - t('Matrix'), "", t('Your matrix'),'network_nav_btn'); + $nav['network'] = array('network', t('Matrix'), "", t('Your matrix'),'network_nav_btn'); $nav['network']['mark'] = array('', t('Mark all matrix notifications seen'), '',''); $nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'),'home_nav_btn'); diff --git a/include/network.php b/include/network.php index a7127c1a2..6aefc0b30 100644 --- a/include/network.php +++ b/include/network.php @@ -19,6 +19,7 @@ function get_capath() { * 'timeout' => int seconds, default system config value or 60 seconds * 'http_auth' => username:password * 'novalidate' => do not validate SSL certs, default is to validate using our CA list + * 'nobody' => only return the header * * @returns array * 'return_code' => HTTP return code or 0 if timeout or failure @@ -31,8 +32,6 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => ""); - $a = get_app(); - $ch = @curl_init($url); if(($redirects > 8) || (! $ch)) return false; @@ -51,6 +50,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { if(x($opts,'headers')) @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); + if(x($opts,'nobody')) + @curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']); + if(x($opts,'timeout') && intval($opts['timeout'])) { @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']); } @@ -67,7 +69,6 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, ((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true)); - $prx = get_config('system','proxy'); if(strlen($prx)) { @curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); @@ -109,7 +110,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $url_parsed = @parse_url($newurl); if (isset($url_parsed)) { @curl_close($ch); - return z_fetch_url($newurl,$binary,$redirects++,$opts); + return z_fetch_url($newurl,$binary,++$redirects,$opts); } } @@ -182,6 +183,9 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { if(x($opts,'headers')) @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); + if(x($opts,'nobody')) + @curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']); + if(x($opts,'timeout') && intval($opts['timeout'])) { @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']); } @@ -239,7 +243,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { if($http_code == 303) { return z_fetch_url($newurl,false,$redirects++,$opts); } else { - return z_post_url($newurl,$params,$redirects++,$opts); + return z_post_url($newurl,$params,++$redirects,$opts); } } } @@ -511,6 +515,7 @@ function allowed_email($email) { function avatar_img($email) { + $avatar = array(); $a = get_app(); $avatar['size'] = 175; @@ -520,10 +525,11 @@ function avatar_img($email) { call_hooks('avatar_lookup', $avatar); - if(! $avatar['success']) + if (! $avatar['success']) $avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo(); logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); + return $avatar['url']; } diff --git a/include/notifier.php b/include/notifier.php index fe6ac33c0..bec18142a 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -100,10 +100,14 @@ function notifier_run($argv, $argc){ // Get the recipient $r = q("select abook.*, hubloc.* from abook left join hubloc on hubloc_hash = abook_xchan - where abook_id = %d and not ( abook_flags & %d )>0 limit 1", + where abook_id = %d and not ( abook_flags & %d ) > 0 + and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0 limit 1", intval($item_id), - intval(ABOOK_FLAG_SELF) + intval(ABOOK_FLAG_SELF), + intval(HUBLOC_FLAGS_DELETED), + intval(HUBLOC_OFFLINE) ); + if($r) { // Get the sender $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", @@ -116,8 +120,11 @@ function notifier_run($argv, $argc){ } else { // send a refresh message to each hub they have registered here - $h = q("select * from hubloc where hubloc_hash = '%s'", - dbesc($r[0]['hubloc_hash']) + $h = q("select * from hubloc where hubloc_hash = '%s' + and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0", + dbesc($r[0]['hubloc_hash']), + intval(HUBLOC_FLAGS_DELETED), + intval(HUBLOC_OFFLINE) ); if($h) { foreach($h as $hh) { @@ -128,17 +135,31 @@ function notifier_run($argv, $argc){ )); if($data) { $result = zot_zot($hh['hubloc_callback'],$data); -// zot_queue_item is not yet written -// if(! $result['success']) -// zot_queue_item(); + // if immediate delivery failed, stick it in the queue to try again later. + + if(! $result['success']) { + $hash = random_string(); + q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) + values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", + dbesc($hash), + intval($s[0]['channel_account_id']), + intval($s[0]['channel_id']), + dbesc('zot'), + dbesc($hh['hubloc_callback']), + intval(1), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($data), + dbesc('') + ); + } } } } } } } - return; } @@ -315,9 +336,12 @@ function notifier_run($argv, $argc){ $r = fetch_post_tags($r); $target_item = $r[0]; + $deleted_item = false; - if($target_item['item_restrict'] & ITEM_DELETED) + if($target_item['item_restrict'] & ITEM_DELETED) { logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG); + $deleted_item = true; + } $unforwardable = ITEM_UNPUBLISHED|ITEM_DELAYED_PUBLISH|ITEM_WEBPAGE|ITEM_BUILDBLOCK|ITEM_PDL; if($target_item['item_restrict'] & $unforwardable) { @@ -363,7 +387,19 @@ function notifier_run($argv, $argc){ $encoded_item = encode_item($target_item); - $relay_to_owner = (((! $top_level_post) && ($target_item['item_flags'] & ITEM_ORIGIN)) ? true : false); + // Send comments to the owner to re-deliver to everybody in the conversation + // We only do this if the item in question originated on this site. This prevents looping. + // To clarify, a site accepting a new comment is responsible for sending it to the owner for relay. + // Relaying should never be initiated on a post that arrived from elsewhere. + + // We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this + // flag on comments for an extended period. So we'll also call comment_local_origin() which looks at + // the hostname in the message_id and provides a second (fallback) opinion. + + $relay_to_owner = (((! $top_level_post) && ($target_item['item_flags'] & ITEM_ORIGIN) && comment_local_origin($target_item)) + ? true + : false + ); $uplink = false; @@ -476,6 +512,9 @@ function notifier_run($argv, $argc){ logger('notifier: hub choice: ' . intval($relay_to_owner) . ' ' . intval($private) . ' ' . $cmd, LOGGER_DEBUG); + // FIXME: I think we need to remove the private bit or this clause will never execute. Needs more coffee to think it through. + // We may in fact have to send it to clones in case the one we pick recently died. + if($relay_to_owner && (! $private) && ($cmd !== 'relay')) { // If sending a followup to the post owner, only send it to one channel clone - to avoid race conditions. diff --git a/include/oembed.php b/include/oembed.php index 38c433e99..0628afaa9 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -8,13 +8,25 @@ function oembed_replacecb($matches){ } +// if the url is embeddable with oembed, return the bbcode link. + +function oembed_process($url) { + $j = oembed_fetch_url($url); + logger('oembed_process: ' . print_r($j,true)); + if($j && $j->type !== 'error') + return '[embed]' . $url . '[/embed]'; + return false; +} + + + function oembed_fetch_url($embedurl){ $a = get_app(); $txt = Cache::get($a->videowidth . $embedurl); - if(strstr($txt,'youtu')) { + if(strstr($txt,'youtu') && strstr(z_root(),'https:')) { $txt = str_replace('http:','https:',$txt); } @@ -105,7 +117,7 @@ function oembed_format_object($j){ $th=120; $tw = $th*$tr; $tpl=get_markup_template('oembed_video.tpl'); - if(strstr($embedurl,'youtu')) { + if(strstr($embedurl,'youtu') && strstr(z_root(),'https:')) { $embedurl = str_replace('http:','https:',$embedurl); $j->thumbnail_url = str_replace('http:','https:', $j->thumbnail_url); $jhtml = str_replace('http:','https:', $jhtml); @@ -142,7 +154,7 @@ function oembed_format_object($j){ // add link to source if not present in "rich" type if ( $j->type!='rich' || !strpos($j->html,$embedurl) ){ $embedlink = (isset($j->title))?$j->title:$embedurl; - $ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>"; + $ret .= '<span class="bookmark-identifier">#^</span>' . "<a href='$embedurl' rel='oembed'>$embedlink</a>"; $ret .= "<br>"; if (isset($j->author_name)) $ret.=" by ".$j->author_name; if (isset($j->provider_name)) $ret.=" on ".$j->provider_name; diff --git a/include/permissions.php b/include/permissions.php index ccbde1a7c..4d7def346 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -578,18 +578,18 @@ function get_role_perms($role) { $ret['channel_r_profile'] = PERMS_PUBLIC; $ret['channel_r_photos'] = PERMS_PUBLIC; $ret['channel_r_abook'] = PERMS_PUBLIC; - $ret['channel_w_stream'] = 0; + $ret['channel_w_stream'] = PERMS_SPECIFIC; $ret['channel_w_wall'] = PERMS_SPECIFIC; $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_NETWORK; @@ -610,18 +610,18 @@ function get_role_perms($role) { $ret['channel_r_profile'] = PERMS_PUBLIC; $ret['channel_r_photos'] = PERMS_PUBLIC; $ret['channel_r_abook'] = PERMS_PUBLIC; - $ret['channel_w_stream'] = 0; + $ret['channel_w_stream'] = PERMS_SPECIFIC; $ret['channel_w_wall'] = PERMS_SPECIFIC; $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_SPECIFIC; @@ -642,18 +642,18 @@ function get_role_perms($role) { $ret['channel_r_profile'] = PERMS_SPECIFIC; $ret['channel_r_photos'] = PERMS_SPECIFIC; $ret['channel_r_abook'] = PERMS_SPECIFIC; - $ret['channel_w_stream'] = 0; + $ret['channel_w_stream'] = PERMS_SPECIFIC; $ret['channel_w_wall'] = PERMS_SPECIFIC; - $ret['channel_w_tagwall'] = 0; + $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_SPECIFIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_SPECIFIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_SPECIFIC; @@ -736,18 +736,18 @@ function get_role_perms($role) { $ret['channel_r_profile'] = PERMS_PUBLIC; $ret['channel_r_photos'] = PERMS_PUBLIC; $ret['channel_r_abook'] = PERMS_PUBLIC; - $ret['channel_w_stream'] = 0; - $ret['channel_w_wall'] = 0; - $ret['channel_w_tagwall'] = 0; - $ret['channel_w_comment'] = 0; - $ret['channel_w_mail'] = 0; - $ret['channel_w_photos'] = 0; - $ret['channel_w_chat'] = 0; - $ret['channel_a_delegate'] = 0; + $ret['channel_w_stream'] = PERMS_SPECIFIC; + $ret['channel_w_wall'] = PERMS_SPECIFIC; + $ret['channel_w_tagwall'] = PERMS_SPECIFIC; + $ret['channel_w_comment'] = PERMS_SPECIFIC; + $ret['channel_w_mail'] = PERMS_SPECIFIC; + $ret['channel_w_photos'] = PERMS_SPECIFIC; + $ret['channel_w_chat'] = PERMS_SPECIFIC; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_NETWORK; @@ -775,7 +775,7 @@ function get_role_perms($role) { $ret['channel_w_mail'] = PERMS_SPECIFIC; $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index e63125671..6f508bf72 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -241,9 +241,9 @@ abstract class photo_driver { if((! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg')) return; - $exif = @exif_read_data($filename); + $exif = @exif_read_data($filename,null,true); if($exif) { - $ort = $exif['Orientation']; + $ort = $exif['IFD0']['Orientation']; switch($ort) { @@ -280,7 +280,14 @@ abstract class photo_driver { $this->rotate(90); break; } + + // logger('exif: ' . print_r($exif,true)); + return $exif; + } + + return false; + } diff --git a/include/photos.php b/include/photos.php index ee94bac60..c4d5a33aa 100644 --- a/include/photos.php +++ b/include/photos.php @@ -31,31 +31,13 @@ function photo_upload($channel, $observer, $args) { if($newalbum) $album = $newalbum; else - $album = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y'); + $album = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y-m'); } - /** - * - * We create a wall item for every photo, but we don't want to - * overwhelm the data stream with a hundred newly uploaded photos. - * So we will make the first photo uploaded to this album in the last several hours - * visible by default, the rest will become visible over time when and if - * they acquire comments, likes, dislikes, and/or tags - * - */ - - $r = q("SELECT * FROM photo WHERE album = '%s' AND uid = %d AND created > %s - INTERVAL %s ", - dbesc($album), - intval($channel_id), - db_utcnow(), db_quoteinterval('3 HOUR') - ); - if((! $r) || ($album == t('Profile Photos'))) + if(intval($args['visible']) || $args['visible'] === 'true') $visible = 1; else $visible = 0; - - if(intval($args['not_visible']) || $args['not_visible'] === 'true') - $visible = 0; $str_group_allow = perms2str(((is_array($args['group_allow'])) ? $args['group_allow'] : explode(',',$args['group_allow']))); $str_contact_allow = perms2str(((is_array($args['contact_allow'])) ? $args['contact_allow'] : explode(',',$args['contact_allow']))); @@ -98,7 +80,6 @@ function photo_upload($channel, $observer, $args) { logger('photo_upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG); - $maximagesize = get_config('system','maximagesize'); if(($maximagesize) && ($filesize > $maximagesize)) { @@ -133,7 +114,6 @@ function photo_upload($channel, $observer, $args) { call_hooks('photo_post_end',$ret); return $ret; } - $ph = photo_factory($imagedata, $type); @@ -145,7 +125,9 @@ function photo_upload($channel, $observer, $args) { return $ret; } - $ph->orient($src); + $exif = $ph->orient($src); + + @unlink($src); $max_length = get_config('system','max_image_length'); @@ -185,7 +167,7 @@ function photo_upload($channel, $observer, $args) { $r1 = $ph->save($p); if(! $r1) $errors = true; - + if(($width > 640 || $height > 640) && (! $errors)) { $ph->scaleImage(640); $p['scale'] = 1; @@ -204,7 +186,6 @@ function photo_upload($channel, $observer, $args) { $errors = true; } - if($errors) { q("delete from photo where resource_id = '%s' and uid = %d", dbesc($photo_hash), @@ -220,18 +201,31 @@ function photo_upload($channel, $observer, $args) { $width_x_height = $ph->getWidth() . 'x' . $ph->getHeight(); - $basename = basename($filename); $mid = item_message_id(); // Create item container + $lat = $lon = null; + + if($exif && $exif['GPS']) { + if(feature_enabled($channel_id,'photo_location')) { + $lat = getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']); + $lon = getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']); + } + } + + + $item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP; - $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); + $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); $title = ''; $mid = item_message_id(); - + $arr = array(); + if($lat && $lon) + $arr['coord'] = $lat . ' ' . $lon; + $arr['aid'] = $account_id; $arr['uid'] = $channel_id; $arr['mid'] = $mid; @@ -254,7 +248,7 @@ function photo_upload($channel, $observer, $args) { // We should also put a width_x_height on large photos. Left as an exercise for // devs looking fo simple stuff to fix. - $larger = feature_enabled($channel['channel_id'],'large_photos'); + $larger = feature_enabled($channel['channel_id'], 'large_photos'); if($larger) { $tag = '[zmg]'; if($r2) @@ -273,7 +267,7 @@ function photo_upload($channel, $observer, $args) { $arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]' . '[/zrl]'; - + $result = item_store($arr); $item_id = $result['item_id']; @@ -291,15 +285,23 @@ function photo_upload($channel, $observer, $args) { return $ret; } - - - -function photos_albums_list($channel,$observer) { +/** + * @brief Returns a list with all photo albums observer is allowed to see. + * + * Returns an associative array with all albums where observer has permissions. + * + * @param array $channel + * @param array $observer + * @return bool|array false if no view_photos permission or an array + * * success (bool) + * * albums (array) + */ +function photos_albums_list($channel, $observer) { $channel_id = $channel['channel_id']; $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); - if(! perm_is_allowed($channel_id,$observer_xchan,'view_photos')) + if(! perm_is_allowed($channel_id, $observer_xchan, 'view_photos')) return false; // FIXME - create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status @@ -310,7 +312,6 @@ function photos_albums_list($channel,$observer) { intval($channel_id), intval(PHOTO_NORMAL), intval(PHOTO_PROFILE) - ); // add various encodings to the array so we can just loop through and pick them out in a template @@ -330,8 +331,8 @@ function photos_albums_list($channel,$observer) { $ret['albums'][] = $entry; } } - return $ret; + return $ret; } function photos_album_widget($channelx,$observer,$albums = null) { @@ -395,17 +396,32 @@ function photos_list_photos($channel,$observer,$album = '') { return $ret; } - - -function photos_album_exists($channel_id,$album) { - $r = q("SELECT id from photo where album = '%s' and uid = %d limit 1", +/** + * @brief Check if given photo album exists in channel. + * + * @param int $channel_id id of the channel + * @param string $album name of the album + * @return boolean + */ +function photos_album_exists($channel_id, $album) { + $r = q("SELECT id FROM photo WHERE album = '%s' AND uid = %d limit 1", dbesc($album), intval($channel_id) ); + return (($r) ? true : false); } -function photos_album_rename($channel_id,$oldname,$newname) { +/** + * @brief Renames a photo album in a channel. + * + * @todo Do we need to check if new album name already exists? + * @param int $channel_id id of the channel + * @param string $oldname The name of the album to rename + * @param string $newname The new name of the album + * @return bool|array + */ +function photos_album_rename($channel_id, $oldname, $newname) { return q("UPDATE photo SET album = '%s' WHERE album = '%s' AND uid = %d", dbesc($newname), dbesc($oldname), @@ -437,8 +453,8 @@ function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') { $str = implode(',',$arr); return $str; } - return false; + return false; } function photos_create_item($channel, $creator_hash, $photo, $visible = false) { @@ -446,11 +462,10 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) { // Create item container $item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP; - $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); + $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); - $title = ''; $mid = item_message_id(); - + $arr = array(); $arr['aid'] = $channel['channel_account_id']; @@ -470,13 +485,40 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) { $arr['deny_gid'] = $photo['deny_gid']; $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; - + $arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['scale'] . '[/zmg]' . '[/zrl]'; - + $result = item_store($arr); $item_id = $result['item_id']; + return $item_id; +} + + +function getGps($exifCoord, $hemi) { + + $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; + $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; + $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; + + $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; + + return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600))); } + +function gps2Num($coordPart) { + + $parts = explode('/', $coordPart); + + if (count($parts) <= 0) + return 0; + + if (count($parts) == 1) + return $parts[0]; + + return floatval($parts[0]) / floatval($parts[1]); +} + diff --git a/include/plugin.php b/include/plugin.php index 08decc8e3..b6cfc8d89 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -38,7 +38,7 @@ function uninstall_plugin($plugin) { return false; logger("Addons: uninstalling " . $plugin); - $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); + //$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php'); if(function_exists($plugin . '_uninstall')) { $func = $plugin . '_uninstall'; @@ -68,7 +68,7 @@ function install_plugin($plugin) { $func(); } - $plugin_admin = (function_exists($plugin . "_plugin_admin") ? 1 : 0); + $plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0); $r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ", dbesc($plugin), @@ -91,7 +91,7 @@ function load_plugin($plugin) { return false; logger("Addons: loading " . $plugin, LOGGER_DEBUG); - $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); + //$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php'); if(function_exists($plugin . '_load')) { $func = $plugin . '_load'; @@ -120,6 +120,7 @@ function plugin_is_installed($name) { ); if($r) return true; + return false; } @@ -189,7 +190,7 @@ function register_hook($hook, $file, $function, $priority = 0) { if(count($r)) return true; - $r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' ) ", + $r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )", dbesc($hook), dbesc($file), dbesc($function), @@ -228,11 +229,13 @@ function load_hooks() { $a = get_app(); // if(! is_array($a->hooks)) $a->hooks = array(); + $r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC"); if($r) { foreach($r as $rr) { if(! array_key_exists($rr['hook'],$a->hooks)) $a->hooks[$rr['hook']] = array(); + $a->hooks[$rr['hook']][] = array($rr['file'],$rr['function']); } } @@ -256,32 +259,41 @@ function load_hooks() { * name of hook to attach callback * @param string $fn; * function name of callback handler - * */ -function insert_hook($hook,$fn) { +function insert_hook($hook, $fn) { $a = get_app(); if(! is_array($a->hooks)) $a->hooks = array(); - if(! array_key_exists($hook,$a->hooks)) + + if(! array_key_exists($hook, $a->hooks)) $a->hooks[$hook] = array(); - $a->hooks[$hook][] = array('',$fn); -} + $a->hooks[$hook][] = array('', $fn); +} +/** + * @brief Calls a hook. + * + * Use this function when you want to be able to allow a hook to manipulate + * the provided data. + * + * @param string $name of the hook to call + * @param string|array &$data to transmit to the callback handler + */ function call_hooks($name, &$data = null) { $a = get_app(); - if((is_array($a->hooks)) && (array_key_exists($name,$a->hooks))) { + if((is_array($a->hooks)) && (array_key_exists($name, $a->hooks))) { foreach($a->hooks[$name] as $hook) { if($hook[0]) @include_once($hook[0]); + if(function_exists($hook[1])) { $func = $hook[1]; - $func($a,$data); - } - else { + $func($a, $data); + } else { // remove orphan hooks - q("delete from hook where hook = '%s' and file = '$s' and function = '%s' limit 1", + q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND function = '%s'", dbesc($name), dbesc($hook[0]), dbesc($hook[1]) @@ -308,16 +320,18 @@ function call_hooks($name, &$data = null) { * @return array with the plugin information */ function get_plugin_info($plugin){ - $info = Array( + $m = array(); + $info = array( 'name' => $plugin, - 'description' => "", + 'description' => '', 'author' => array(), - 'version' => "", - 'compat' => "" + 'version' => '', + 'compat' => '' ); - if (!is_file("addon/$plugin/$plugin.php")) return $info; - + if (!is_file("addon/$plugin/$plugin.php")) + return $info; + $f = file_get_contents("addon/$plugin/$plugin.php"); $r = preg_match("|/\*.*\*/|msU", $f, $m); @@ -328,7 +342,7 @@ function get_plugin_info($plugin){ if ($l != ""){ list($k, $v) = array_map("trim", explode(":", $l, 2)); $k = strtolower($k); - if ($k == "author"){ + if ($k == 'author'){ $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['author'][] = array('name' => $m[1], 'link' => $m[2]); @@ -343,6 +357,7 @@ function get_plugin_info($plugin){ } } } + return $info; } @@ -363,13 +378,14 @@ function get_plugin_info($plugin){ * @return array */ function get_theme_info($theme){ - $info=Array( + $m = array(); + $info = array( 'name' => $theme, - 'description' => "", + 'description' => '', 'author' => array(), - 'version' => "", - 'compat' => "", - 'credits' => "", + 'version' => '', + 'compat' => '', + 'credits' => '', 'maintainer' => array(), 'experimental' => false, 'unsupported' => false @@ -377,10 +393,12 @@ function get_theme_info($theme){ if(file_exists("view/theme/$theme/experimental")) $info['experimental'] = true; + if(file_exists("view/theme/$theme/unsupported")) $info['unsupported'] = true; - if (!is_file("view/theme/$theme/php/theme.php")) return $info; + if (!is_file("view/theme/$theme/php/theme.php")) + return $info; $f = file_get_contents("view/theme/$theme/php/theme.php"); $r = preg_match("|/\*.*\*/|msU", $f, $m); @@ -392,7 +410,7 @@ function get_theme_info($theme){ if ($l != ""){ list($k, $v) = array_map("trim", explode(":", $l, 2)); $k = strtolower($k); - if ($k == "author"){ + if ($k == 'author'){ $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['author'][] = array('name' => $m[1], 'link' => $m[2]); @@ -400,7 +418,7 @@ function get_theme_info($theme){ $info['author'][] = array('name' => $v); } } - elseif ($k == "maintainer"){ + elseif ($k == 'maintainer'){ $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['maintainer'][] = array('name' => $m[1], 'link' => $m[2]); @@ -415,10 +433,18 @@ function get_theme_info($theme){ } } } + return $info; } - +/** + * @brief Returns the theme's screenshot. + * + * The screenshot is expected as view/theme/$theme/img/screenshot.[png|jpg]. + * + * @param sring $theme The name of the theme + * @return string + */ function get_theme_screenshot($theme) { $a = get_app(); $exts = array('.png', '.jpg'); @@ -426,6 +452,7 @@ function get_theme_screenshot($theme) { if(file_exists('view/theme/' . $theme . '/img/screenshot' . $ext)) return($a->get_baseurl() . '/view/theme/' . $theme . '/img/screenshot' . $ext); } + return($a->get_baseurl() . '/images/blank.png'); } @@ -458,7 +485,7 @@ function head_get_css() { } function format_css_if_exists($source) { - if(strpos($source[0],'/') !== false) + if(strpos($source[0], '/') !== false) $path = $source[0]; else $path = theme_include($source[0]); diff --git a/include/poller.php b/include/poller.php index fd78ce087..43cc3f3c0 100644 --- a/include/poller.php +++ b/include/poller.php @@ -150,6 +150,7 @@ function poller_run($argv, $argc){ call_hooks('cron_weekly',datetime_convert()); + z_check_cert(); require_once('include/hubloc.php'); prune_hub_reinstalls(); @@ -165,8 +166,8 @@ function poller_run($argv, $argc){ ); $dirmode = intval(get_config('system','directory_mode')); - if($dirmode == DIRECTORY_MODE_SECONDARY) { - logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . z_root() . '&realm=' . get_directory_realm()),true)); + if($dirmode === DIRECTORY_MODE_SECONDARY) { + logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true)); } /** diff --git a/include/queue.php b/include/queue.php index b6a540ef9..7d2ad3b2d 100644 --- a/include/queue.php +++ b/include/queue.php @@ -39,12 +39,25 @@ function queue_run($argv, $argc){ // so that we don't start off a thousand deliveries for a couple of dead hubs. // The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made). // Other drivers will have to do something different here and may need their own query. + + // Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the + // "every 15 minutes" category. We probably need to prioritise them when inserted into the queue + // or just prior to this query based on recent and long-term delivery history. If we have good reason to believe + // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once + // or twice a day. + + // FIXME: can we sort postgres on outq_priority and maintain the 'distinct' ? + // The order by max(outq_priority) might be a dodgy query because of the group by. + // The desired result is to return a sequence in the order most likely to be delivered in this run. + // If a hub has already been sitting in the queue for a few days, they should be delivered last; + // hence every failure should drop them further down the priority list. + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { $prefix = 'DISTINCT ON (outq_posturl)'; $suffix = 'ORDER BY outq_posturl'; } else { $prefix = ''; - $suffix = 'GROUP BY outq_posturl'; + $suffix = 'GROUP BY outq_posturl ORDER BY max(outq_priority)'; } $r = q("SELECT $prefix * FROM outq WHERE outq_delivered = 0 and (( outq_created > %s - INTERVAL %s and outq_updated < %s - INTERVAL %s ) OR ( outq_updated < %s - INTERVAL %s )) $suffix", db_utcnow(), db_quoteinterval('12 HOUR'), @@ -69,7 +82,7 @@ function queue_run($argv, $argc){ } else { logger('queue: queue post returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG); - $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", + $y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'", dbesc(datetime_convert()), dbesc($rr['outq_hash']) ); @@ -78,11 +91,13 @@ function queue_run($argv, $argc){ } $result = zot_zot($rr['outq_posturl'],$rr['outq_notify']); if($result['success']) { + logger('queue: deliver zot success to ' . $rr['outq_posturl'], LOGGER_DEBUG); zot_process_response($rr['outq_posturl'],$result, $rr); } else { $deadguys[] = $rr['outq_posturl']; - $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", + logger('queue: deliver zot returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG); + $y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'", dbesc(datetime_convert()), dbesc($rr['outq_hash']) ); diff --git a/include/ratenotif.php b/include/ratenotif.php index 4fa0077a6..63fd7c2ee 100644 --- a/include/ratenotif.php +++ b/include/ratenotif.php @@ -76,8 +76,8 @@ function ratenotif_run($argv, $argc){ if($j && $j['success'] && is_array($j['directories'])) { foreach($j['directories'] as $h) { -// if($h == z_root()) -// continue; + if($h == z_root()) + continue; $hash = random_string(); $n = zot_build_packet($channel,'notify',null,null,$hash); @@ -94,21 +94,21 @@ function ratenotif_run($argv, $argc){ dbesc($n), dbesc(json_encode($encoded_item)) ); - } - $deliver[] = $hash; - if(count($deliver) >= $deliveries_per_process) { - proc_run('php','include/deliver.php',$deliver); - $deliver = array(); - if($interval) - @time_sleep_until(microtime(true) + (float) $interval); - } + $deliver[] = $hash; + if(count($deliver) >= $deliveries_per_process) { + proc_run('php','include/deliver.php',$deliver); + $deliver = array(); + if($interval) + @time_sleep_until(microtime(true) + (float) $interval); + } + } // catch any stragglers if(count($deliver)) { - proc_run('php','include/deliver.php',$deliver); + proc_run('php','include/deliver.php',$deliver); } } } diff --git a/include/security.php b/include/security.php index 216299099..e9b41dcf9 100644 --- a/include/security.php +++ b/include/security.php @@ -22,7 +22,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive $a->account = $user_record; $_SESSION['account_id'] = $user_record['account_id']; $_SESSION['authenticated'] = 1; - + if($login_initial || $update_lastlog) { q("update account set account_lastlog = '%s' where account_id = %d", dbesc(datetime_convert()), @@ -150,11 +150,7 @@ function change_channel($change_channel) { */ function permissions_sql($owner_id, $remote_verified = false, $groups = null) { - if(defined('STATUSNET_PRIVACY_COMPATIBILITY')) - return ''; - $local_channel = local_channel(); - $remote_channel = remote_channel(); /** * Construct permissions @@ -173,7 +169,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) { */ if(($local_channel) && ($local_channel == $owner_id)) { - $sql = ''; + $sql = ''; } /** @@ -194,7 +190,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) { if(is_array($groups) && count($groups)) { foreach($groups as $g) $gs .= '|<' . $g . '>'; - } + } $regexop = db_getfunc('REGEXP'); $sql = sprintf( " AND ( NOT (deny_cid like '%s' OR deny_gid $regexop '%s') @@ -223,11 +219,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) { */ function item_permissions_sql($owner_id, $remote_verified = false, $groups = null) { - if(defined('STATUSNET_PRIVACY_COMPATIBILITY')) - return ''; - $local_channel = local_channel(); - $remote_channel = remote_channel(); /** * Construct permissions @@ -246,7 +238,7 @@ function item_permissions_sql($owner_id, $remote_verified = false, $groups = nul } /** - * Authenticated visitor. Unless pre-verified, + * Authenticated visitor. Unless pre-verified, * check that the contact belongs to this $owner_id * and load the groups the visitor belongs to. * If pre-verified, the caller is expected to have already @@ -330,7 +322,7 @@ function public_permissions_sql($observer_hash) { */ function get_form_security_token($typename = '') { $a = get_app(); - + $timestamp = time(); $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); @@ -340,16 +332,16 @@ function get_form_security_token($typename = '') { function check_form_security_token($typename = '', $formname = 'form_security_token') { if (!x($_REQUEST, $formname)) return false; $hash = $_REQUEST[$formname]; - + $max_livetime = 10800; // 3 hours - + $a = get_app(); - + $x = explode('.', $hash); if (time() > (IntVal($x[0]) + $max_livetime)) return false; - + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); - + return ($sec_hash == $x[1]); } @@ -417,7 +409,7 @@ function stream_perms_api_uids($perms = NULL ) { if($r) { foreach($r as $rr) if(! in_array($rr['channel_id'], $ret)) - $ret[] = $rr['channel_id']; + $ret[] = $rr['channel_id']; } $str = ''; @@ -425,7 +417,7 @@ function stream_perms_api_uids($perms = NULL ) { foreach($ret as $rr) { if($str) $str .= ','; - $str .= intval($rr); + $str .= intval($rr); } } logger('stream_perms_api_uids: ' . $str, LOGGER_DEBUG); @@ -447,7 +439,7 @@ function stream_perms_xchans($perms = NULL ) { if($r) { foreach($r as $rr) if(! in_array($rr['channel_hash'], $ret)) - $ret[] = $rr['channel_hash']; + $ret[] = $rr['channel_hash']; } $str = ''; @@ -455,7 +447,7 @@ function stream_perms_xchans($perms = NULL ) { foreach($ret as $rr) { if($str) $str .= ','; - $str .= "'" . dbesc($rr) . "'"; + $str .= "'" . dbesc($rr) . "'"; } } logger('stream_perms_xchans: ' . $str, LOGGER_DEBUG); diff --git a/include/session.php b/include/session.php index ed4dfdd16..31b3f0614 100644 --- a/include/session.php +++ b/include/session.php @@ -1,24 +1,29 @@ -<?php /** @file */ - -// Session management functions. These provide database storage of PHP -// session info. +<?php +/** + * @file include/session.php + * + * @brief This file includes session related functions. + * + * Session management functions. These provide database storage of PHP + * session info. + */ $session_exists = 0; $session_expire = 180000; - - - function new_cookie($time) { - $old_sid = session_id(); + $old_sid = session_id(); // ??? This shouldn't have any effect if called after session_start() // We probably need to set the session expiration and change the PHPSESSID cookie. - session_set_cookie_params($time); - session_regenerate_id(false); + session_set_cookie_params($time); + session_regenerate_id(false); - q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid)); + q("UPDATE session SET sid = '%s' WHERE sid = '%s'", + dbesc(session_id()), + dbesc($old_sid) + ); if (x($_COOKIE, 'jsAvailable')) { if ($time) { @@ -31,62 +36,72 @@ function new_cookie($time) { } -function ref_session_open ($s,$n) { - return true; +function ref_session_open ($s, $n) { + return true; } function ref_session_read ($id) { - global $session_exists; - if(x($id)) - $r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id)); - if(count($r)) { - $session_exists = true; - return $r[0]['data']; - } - return ''; + global $session_exists; + if(x($id)) + $r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id)); + + if(count($r)) { + $session_exists = true; + return $r[0]['data']; + } + + return ''; } -function ref_session_write ($id,$data) { - global $session_exists, $session_expire; - if(! $id || ! $data) { - return false; - } +function ref_session_write ($id, $data) { + global $session_exists, $session_expire; - $expire = time() + $session_expire; - $default_expire = time() + 300; + if(! $id || ! $data) { + return false; + } - if($session_exists) - $r = q("UPDATE `session` - SET `data` = '%s', `expire` = '%s' - WHERE `sid` = '%s'", - dbesc($data), dbesc($expire), dbesc($id)); - else - $r = q("INSERT INTO `session` (sid, expire, data) values ('%s', '%s', '%s')", - //SET `sid` = '%s', `expire` = '%s', `data` = '%s'", - dbesc($id), dbesc($default_expire), dbesc($data)); + $expire = time() + $session_expire; + $default_expire = time() + 300; + + if($session_exists) { + q("UPDATE `session` + SET `data` = '%s', `expire` = '%s' WHERE `sid` = '%s'", + dbesc($data), + dbesc($expire), + dbesc($id) + ); + } else { + q("INSERT INTO `session` (sid, expire, data) values ('%s', '%s', '%s')", + //SET `sid` = '%s', `expire` = '%s', `data` = '%s'", + dbesc($id), + dbesc($default_expire), + dbesc($data) + ); + } - return true; + return true; } function ref_session_close() { - return true; + return true; } function ref_session_destroy ($id) { - q("DELETE FROM `session` WHERE `sid` = '%s'", dbesc($id)); - return true; + q("DELETE FROM `session` WHERE `sid` = '%s'", dbesc($id)); + return true; } function ref_session_gc($expire) { - q("DELETE FROM session WHERE expire < %d", dbesc(time())); - if (! get_config('system','innodb')) - db_optimizetable('session'); - return true; + q("DELETE FROM session WHERE expire < %d", dbesc(time())); + if (! get_config('system', 'innodb')) + db_optimizetable('session'); + + return true; } $gc_probability = 50; @@ -95,5 +110,14 @@ ini_set('session.gc_probability', $gc_probability); ini_set('session.use_only_cookies', 1); ini_set('session.cookie_httponly', 1); - -session_set_save_handler ('ref_session_open', 'ref_session_close', 'ref_session_read', 'ref_session_write', 'ref_session_destroy', 'ref_session_gc'); +/* + * PHP function which sets our user-level session storage functions. + */ +session_set_save_handler( + 'ref_session_open', + 'ref_session_close', + 'ref_session_read', + 'ref_session_write', + 'ref_session_destroy', + 'ref_session_gc' +);
\ No newline at end of file diff --git a/include/sharedwithme.php b/include/sharedwithme.php new file mode 100644 index 000000000..3936dc90f --- /dev/null +++ b/include/sharedwithme.php @@ -0,0 +1,32 @@ +<?php + +function apply_updates() { + + //check for updated items and remove them + $x = q("SELECT mid, object FROM item WHERE verb = '%s' AND obj_type = '%s' GROUP BY mid", + dbesc(ACTIVITY_UPDATE), + dbesc(ACTIVITY_OBJ_FILE) + ); + + if($x) { + + foreach($x as $xx) { + + $object = json_decode($xx['object'],true); + + $d_mid = $object['d_mid']; + $u_mid = $xx['mid']; + + $y = q("DELETE FROM item WHERE obj_type = '%s' AND (verb = '%s' AND mid = '%s') OR (verb = '%s' AND mid = '%s')", + dbesc(ACTIVITY_OBJ_FILE), + dbesc(ACTIVITY_POST), + dbesc($d_mid), + dbesc(ACTIVITY_UPDATE), + dbesc($u_mid) + ); + + } + + } + +} diff --git a/include/socgraph.php b/include/socgraph.php index 59830ef1b..7f03f8696 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -3,7 +3,7 @@ require_once('include/dir_fns.php'); require_once('include/zot.php'); -/* +/** * poco_load * * xchan is your connection @@ -21,13 +21,10 @@ require_once('include/zot.php'); * the given uid, cid to the global contact entry. There can be many uid/cid combinations * pointing to the same global contact id. * + * @param string $xchan + * @param string $url */ - - - - -function poco_load($xchan = '',$url = null) { - $a = get_app(); +function poco_load($xchan = '', $url = null) { if($xchan && ! $url) { $r = q("select xchan_connurl from xchan where xchan_hash = '%s' limit 1", @@ -43,7 +40,6 @@ function poco_load($xchan = '',$url = null) { return; } - $url = $url . '?f=&fields=displayName,hash,urls,photos,rating' ; logger('poco_load: ' . $url, LOGGER_DEBUG); @@ -148,7 +144,7 @@ function poco_load($xchan = '',$url = null) { logger('poco_load: missing data'); continue; } - + $x = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($hash) ); @@ -182,9 +178,8 @@ function poco_load($xchan = '',$url = null) { continue; } } - - $total ++; + $total ++; } logger("poco_load: loaded $total entries",LOGGER_DEBUG); @@ -193,7 +188,6 @@ function poco_load($xchan = '',$url = null) { db_utcnow(), db_quoteinterval('2 DAY') ); - } @@ -230,7 +224,6 @@ function common_friends($uid,$xchan,$start = 0,$limit=100000000,$shuffle = false ); return $r; - } @@ -246,8 +239,8 @@ function count_common_friends_zcid($uid,$zcid) { if(count($r)) return $r[0]['total']; - return 0; + return 0; } function common_friends_zcid($uid,$zcid,$start = 0, $limit = 9999,$shuffle = false) { @@ -269,7 +262,6 @@ function common_friends_zcid($uid,$zcid,$start = 0, $limit = 9999,$shuffle = fal ); return $r; - } @@ -284,8 +276,8 @@ function count_all_friends($uid,$cid) { if(count($r)) return $r[0]['total']; - return 0; + return 0; } @@ -358,9 +350,7 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) { function update_suggestions() { - $a = get_app(); - - $dirmode = get_config('system','directory_mode'); + $dirmode = get_config('system', 'directory_mode'); if($dirmode === false) $dirmode = DIRECTORY_MODE_NORMAL; @@ -374,8 +364,6 @@ function update_suggestions() { if(! $url) return; - - $ret = z_fetch_url($url); if($ret['success']) { @@ -388,7 +376,6 @@ function update_suggestions() { db_utcnow(), db_quoteinterval('7 DAY') ); - $j = json_decode($ret['body'],true); if($j && $j['success']) { foreach($j['entries'] as $host) { @@ -422,7 +409,6 @@ function poco($a,$extended = false) { $system_mode = true; } - $format = (($_REQUEST['format']) ? $_REQUEST['format'] : 'json'); $justme = false; @@ -437,7 +423,7 @@ function poco($a,$extended = false) { } if(argc() > 4 && intval(argv(4)) && $justme == false) $cid = intval(argv(4)); - + if(! $system_mode) { $r = q("SELECT channel_id from channel where channel_address = '%s' limit 1", @@ -487,8 +473,8 @@ function poco($a,$extended = false) { $startIndex = intval($_GET['startIndex']); if(! $startIndex) $startIndex = 0; - $itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults); + $itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults); if($system_mode) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where ( abook_flags & " . ABOOK_FLAG_SELF . @@ -496,8 +482,7 @@ function poco($a,$extended = false) { intval($itemsPerPage), intval($startIndex) ); - } - else { + } else { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $sql_extra LIMIT %d OFFSET %d", intval($channel_id), @@ -525,8 +510,7 @@ function poco($a,$extended = false) { } } - $ret['entry'] = array(); - + $ret['entry'] = array(); $fields_ret = array( 'id' => false, @@ -540,10 +524,10 @@ function poco($a,$extended = false) { 'rating' => false ); - if((! x($_GET,'fields')) || ($_GET['fields'] === '@all')) + if((! x($_GET,'fields')) || ($_GET['fields'] === '@all')) { foreach($fields_ret as $k => $v) $fields_ret[$k] = true; - else { + } else { $fields_req = explode(',',$_GET['fields']); foreach($fields_req as $f) $fields_ret[trim($f)] = true; diff --git a/include/taxonomy.php b/include/taxonomy.php index d36c05db2..4333cdf03 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -38,6 +38,7 @@ function term_query($table,$s,$type = TERM_UNKNOWN) { function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') { if(! $term) return false; + $r = q("select * from term where uid = %d and oid = %d and otype = %d and type = %d and term = '%s' and url = '%s' ", @@ -50,6 +51,7 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') { ); if($r) return false; + $r = q("insert into term (uid, oid, otype, type, term, url) values( %d, %d, %d, %d, '%s', '%s') ", intval($uid), @@ -59,9 +61,11 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') { dbesc($term), dbesc($url) ); + return $r; } - + + function get_terms_oftype($arr,$type) { $ret = array(); if(! (is_array($arr) && count($arr))) @@ -74,6 +78,7 @@ function get_terms_oftype($arr,$type) { foreach($arr as $x) if($x['type'] == $t) $ret[] = $x; + return $ret; } @@ -99,7 +104,7 @@ function format_term_for_display($term) { function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $type = TERM_HASHTAG) { require_once('include/security.php'); - + if(! perm_is_allowed($uid,get_observer_hash(),'view_stream')) return array(); @@ -112,6 +117,7 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $ if($authors) { if(! is_array($authors)) $authors = array($authors); + stringify_array_elms($authors,true); $sql_options .= " and author_xchan in (" . implode(',',$authors) . ") "; } @@ -131,8 +137,8 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $ if(! $r) return array(); - - // Find minimum and maximum log-count. + + // Find minimum and maximum log-count. $tags = array(); $min = 1e9; $max = -1e9; @@ -152,22 +158,23 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $ $range = max(.01, $max - $min) * 1.0001; for($x = 0; $x < count($tags); $x ++) { - $tags[$x][2] = 1 + floor(5 * ($tags[$x][1] - $min) / $range); + $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); } return $tags; } + function tags_sort($a,$b) { - if(strtolower($a[0]) == strtolower($b[0])) - return 0; - return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); + if(strtolower($a[0]) == strtolower($b[0])) + return 0; + + return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); } function dir_tagadelic($count = 0) { - $sql_options = ''; $count = intval($count); // Fetch tags @@ -178,8 +185,8 @@ function dir_tagadelic($count = 0) { if(! $r) return array(); - - // Find minimum and maximum log-count. + + // Find minimum and maximum log-count. $tags = array(); $min = 1e9; $max = -1e9; @@ -199,7 +206,7 @@ function dir_tagadelic($count = 0) { $range = max(.01, $max - $min) * 1.0001; for($x = 0; $x < count($tags); $x ++) { - $tags[$x][2] = 1 + floor(5 * ($tags[$x][1] - $min) / $range); + $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); } return $tags; @@ -207,65 +214,66 @@ function dir_tagadelic($count = 0) { function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_HASHTAG) { - $o = ''; - $tab = 0; - $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); - - if($r) { - $o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">'; - foreach($r as $rr) { - $o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + $o = ''; + + $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); + + if($r) { + $o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">'; + foreach($r as $rr) { + $o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + } + $o .= '</div></div>'; } - $o .= '</div></div>'; - } + return $o; } + function wtagblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_HASHTAG) { - $o = ''; - $tab = 0; - $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); + $o = ''; - if($r) { - $c = q("select channel_address from channel where channel_id = %d limit 1", - intval($uid) - ); + $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); - $o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">'; - foreach($r as $rr) { - $o .= '<span class="tag' . $rr[2] . '">#</span><a href="channel/' . $c[0]['channel_address'] . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + if($r) { + $c = q("select channel_address from channel where channel_id = %d limit 1", + intval($uid) + ); + + $o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">'; + foreach($r as $rr) { + $o .= '<span class="tag' . $rr[2] . '">#</span><a href="channel/' . $c[0]['channel_address'] . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + } + $o .= '</div></div>'; } - $o .= '</div></div>'; - } + return $o; } function catblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_CATEGORY) { - $o = ''; - $tab = 0; + $o = ''; - $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); + $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type); - if($r) { - $c = q("select channel_address from channel where channel_id = %d limit 1", - intval($uid) - ); - - $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">'; - foreach($r as $rr) { - $o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + if($r) { + $c = q("select channel_address from channel where channel_id = %d limit 1", + intval($uid) + ); + + $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">'; + foreach($r as $rr) { + $o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n"; + } + $o .= '</div></div>'; } - $o .= '</div></div>'; - } + return $o; } - function dir_tagblock($link,$r) { $o = ''; - $tab = 0; if(! $r) $r = get_app()->data['directory_keywords']; @@ -277,14 +285,12 @@ function dir_tagblock($link,$r) { } $o .= '</div></div>'; } + return $o; } - - - /** * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants" * We use the first person form when creating an activity, but the third person for use in activities @@ -292,8 +298,6 @@ function dir_tagblock($link,$r) { * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module. */ - - function obj_verbs() { $verbs = array( 'has' => array( t('have'), t('has')), @@ -304,26 +308,27 @@ function obj_verbs() { $arr = array('verbs' => $verbs); call_hooks('obj_verbs', $arr); + return $arr['verbs']; } function obj_verb_selector($current = '') { $verbs = obj_verbs(); - $o .= '<select class="obj-verb-selector" name="verb" >'; + $o = '<select class="obj-verb-selector" name="verb">'; foreach($verbs as $k => $v) { $selected = (($k == $current) ? ' selected="selected" ' : ''); $o .= '<option value="' . urlencode($k) . '"' . $selected . '>' . $v[1] . '</option>'; } $o .= '</select>'; - return $o; + return $o; } function get_things($profile_hash,$uid) { $sql_extra = (($profile_hash) ? " and obj_page = '" . $profile_hash . "' " : ''); - + $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and uid = %d and obj_type = %d $sql_extra order by obj_verb, term", intval($uid), intval(TERM_OBJ_THING) @@ -379,11 +384,11 @@ function get_things($profile_hash,$uid) { for($x = 0; $x < count($l); $x ++) $l[$x]['xchan_url'] = zid($l[$x]['xchan_url']); - + if(! $things[$rr['obj_verb']]) $things[$rr['obj_verb']] = array(); - $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['term_hash'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun')); + $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['term_hash'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun')); } $sorted_things = array(); if($things) { @@ -395,6 +400,6 @@ function get_things($profile_hash,$uid) { } } //logger('things: ' . print_r($sorted_things,true)); - return $sorted_things; + return $sorted_things; }
\ No newline at end of file diff --git a/include/text.php b/include/text.php index c93bc4e70..86da3ee42 100644 --- a/include/text.php +++ b/include/text.php @@ -110,8 +110,6 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { - - function purify_html($s) { require_once('library/HTMLPurifier.auto.php'); require_once('include/html2bbcode.php'); @@ -360,8 +358,6 @@ function paginate(&$a) { function alt_pager(&$a, $i, $more = '', $less = '') { - $o = ''; - if(! $more) $more = t('older'); if(! $less) @@ -370,10 +366,10 @@ function alt_pager(&$a, $i, $more = '', $less = '') { $stripped = preg_replace('/(&page=[0-9]*)/','',$a->query_string); $stripped = str_replace('q=','',$stripped); $stripped = trim($stripped,'/'); - $pagenum = $a->pager['page']; + //$pagenum = $a->pager['page']; $url = $a->get_baseurl() . '/' . $stripped; - return replace_macros(get_markup_template('alt_pager.tpl'),array( + return replace_macros(get_markup_template('alt_pager.tpl'), array( '$has_less' => (($a->pager['page'] > 1) ? true : false), '$has_more' => (($i > 0 && $i >= $a->pager['itemspage']) ? true : false), '$less' => $less, @@ -600,6 +596,7 @@ function activity_match($haystack,$needle) { function get_tags($s) { $ret = array(); + $match = array(); // ignore anything in a code block @@ -739,7 +736,7 @@ function contact_block() { if((! is_array($a->profile)) || ($a->profile['hide_friends'])) return $o; - $r = q("SELECT COUNT(abook_id) AS total FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and not ( abook_flags & %d )>0 and not (xchan_flags & %d)>0", + $r = q("SELECT COUNT(abook_id) AS total FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and ( abook_flags & %d ) = 0 and ( xchan_flags & %d ) = 0", intval($a->profile['uid']), intval($abook_flags), intval($xchan_flags) @@ -751,12 +748,10 @@ function contact_block() { $contacts = t('No connections'); $micropro = null; } else { - if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { - $randfunc = 'RANDOM()'; - } else { - $randfunc = 'RAND()'; - } - $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash WHERE abook_channel = %d AND not ( abook_flags & %d)>0 and not (xchan_flags & %d )>0 ORDER BY $randfunc LIMIT %d", + + $randfunc = db_getfunc('RAND'); + + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash WHERE abook_channel = %d AND ( abook_flags & %d ) = 0 and ( xchan_flags & %d ) = 0 ORDER BY $randfunc LIMIT %d", intval($a->profile['uid']), intval($abook_flags|ABOOK_FLAG_ARCHIVED), intval($xchan_flags), @@ -873,8 +868,8 @@ function valid_email($x){ */ -function linkify($s) { - $s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+]*)/", ' <a href="$1" >$1</a>', $s); +function linkify($s,$me = false) { + $s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/", (($me) ? ' <a href="$1" rel="me" >$1</a>' : ' <a href="$1" >$1</a>'), $s); $s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s); return($s); } @@ -1061,7 +1056,6 @@ function list_smilies() { * */ function smilies($s, $sample = false) { - $a = get_app(); if(intval(get_config('system','no_smilies')) || (local_channel() && intval(get_pconfig(local_channel(),'system','no_smilies')))) @@ -2111,6 +2105,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { $replaced = false; $r = null; + $match = array(); $termtype = ((strpos($tag,'#') === 0) ? TERM_HASHTAG : TERM_UNKNOWN); $termtype = ((strpos($tag,'@') === 0) ? TERM_MENTION : $termtype); @@ -2354,7 +2349,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { function linkify_tags($a, &$body, $uid) { $str_tags = ''; $tagged = array(); - $result = array(); + $results = array(); $tags = get_tags($body); @@ -2375,18 +2370,22 @@ function linkify_tags($a, &$body, $uid) { if($fullnametagged) continue; - $success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : $profile_uid , $tag); + $success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : $a->profile_uid , $tag); $results[] = array('success' => $success, 'access_tag' => $access_tag); if($success['replaced']) $tagged[] = $tag; } } + return $results; } /** - * @brief returns icon name for use with e.g. font-awesome based on mime-type + * @brief returns icon name for use with e.g. font-awesome based on mime-type. + * + * These are the the font-awesome names of version 3.2.1. The newer font-awesome + * 4 has different names. * - * @param string $type + * @param string $type mime type * @return string */ function getIconFromType($type) { @@ -2439,10 +2438,10 @@ function getIconFromType($type) { * @brief Returns a human readable formatted string for filesizes. * * @param int $size filesize in bytes - * @return string + * @return string human readable formatted filesize */ function userReadableSize($size) { - $ret = ""; + $ret = ''; if (is_numeric($size)) { $incr = 0; $k = 1024; @@ -2451,7 +2450,8 @@ function userReadableSize($size) { $incr++; $size = round($size / $k, 2); } - $ret = $size . " " . $unit[$incr]; + $ret = $size . ' ' . $unit[$incr]; } + return $ret; } diff --git a/include/widgets.php b/include/widgets.php index fbbc74224..243c4a25e 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -233,7 +233,6 @@ function widget_savedsearch($arr) { $srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $hasq = ((strpos($srchurl,'?') !== false) ? true : false); $srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is','',$srchurl),'&'); - $hasq = ((strpos($srchurl,'?') !== false) ? true : false); $srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&'); @@ -241,7 +240,10 @@ function widget_savedsearch($arr) { $hasq = ((strpos($srchurl,'?') !== false) ? true : false); + $hasamp = ((strpos($srchurl,'&') !== false) ? true : false); + if(($hasamp) && (! $hasq)) + $srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1); $o = ''; @@ -257,8 +259,8 @@ function widget_savedsearch($arr) { $saved[] = array( 'id' => $rr['tid'], 'term' => $rr['term'], - 'dellink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&searchremove=1&search=' . urlencode($rr['term']), - 'srchlink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&search=' . urlencode($rr['term']), + 'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&searchremove=1&search=' . urlencode($rr['term']), + 'srchlink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&search=' . urlencode($rr['term']), 'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'), 'encodedterm' => urlencode($rr['term']), 'delete' => t('Remove term'), @@ -605,9 +607,6 @@ function widget_vcard($arr) { * The following directory widgets are only useful on the directory page */ -function widget_dirsafemode($arr) { - return dir_safe_mode(); -} function widget_dirsort($arr) { return dir_sort_links(); diff --git a/include/zot.php b/include/zot.php index 98b54a04c..99a787cd9 100644 --- a/include/zot.php +++ b/include/zot.php @@ -464,9 +464,15 @@ function zot_refresh($them,$channel = null, $force = false) { // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'],$x['hash']); - $y = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_dob, abook_flags ) values ( %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d )", + + $closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness'); + if($closeness === false) + $closeness = 80; + + $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_dob, abook_flags ) values ( %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d )", intval($channel['channel_account_id']), intval($channel['channel_id']), + intval($closeness), dbesc($x['hash']), intval($their_perms), intval($default_perms), @@ -984,6 +990,14 @@ function zot_process_response($hub,$arr,$outq) { logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA); } + // update the timestamp for this site + + $r = q("update site set site_update = '%s' where site_url = '%s'", + dbesc(datetime_convert()), + dbesc(dirname($hub)) + ); + + // synchronous message types are handled immediately // async messages remain in the queue until processed. @@ -1270,12 +1284,13 @@ function zot_import($arr, $sender_url) { // A public message with no listed recipients can be delivered to anybody who -// has PERMS_NETWORK for that type of post, or PERMS_SITE and is one the same +// has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are +// by definition authenticated) or PERMS_SITE and is one the same // site, or PERMS_SPECIFIC and the sender is a contact who is granted // permissions via their connection permissions in the address book. // Here we take a given message and construct a list of hashes of everybody -// on the site that we should deliver to. - +// on the site that we should try and deliver to. +// Some of these will be rejected, but this gives us a place to start. function public_recips($msg) { @@ -1294,11 +1309,31 @@ function public_recips($msg) { $check_mentions = true; } else { + + // This doesn't look like it works so I have to explain what happened. These are my + // notes (below) from when I got this section of code working. You would think that + // we only have to find those with the requisite stream or comment permissions, + // depending on whether this is a top-level post or a comment - but you would be wrong. + + // ... so public_recips and allowed_public_recips is working so much better + // than before, but was still not quite right. We seem to be getting all the right + // results for top-level posts now, but comments aren't getting through on channels + // for which we've allowed them to send us their stream, but not comment on our posts. + // The reason is we were seeing if they could comment - and we only need to do that if + // we own the post. If they own the post, we only need to check if they can send us their stream. + // if this is a comment and it wasn't sent by the post owner, check to see who is allowing them to comment. - // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up their software. - // We may need this step to protect us from bad guys intentionally stuffing up their software. - // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the - // owner's stream (which was already set above) - as they control the comment permissions + // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up + // their software. We may need this step to protect us from bad guys intentionally stuffing up their software. + // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the + // owner's stream (which was already set above) - as they control the comment permissions, not us. + + // Note that by doing this we introduce another bug because some public forums have channel_w_stream + // permissions set to themselves only. We also need in this function to add these public forums to the + // public recipient list based on if they are tagged or not and have tag permissions. This is complicated + // by the fact that this activity doesn't have the public forum tag. It's the parent activity that + // contains the tag. we'll solve that further below. + if($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) { $col = 'channel_w_comment'; $field = PERMS_W_COMMENT; @@ -1313,21 +1348,38 @@ function public_recips($msg) { if(! $col) return NULL; - + $col = dbesc($col); + + // First find those channels who are accepting posts from anybody, or at least + // something greater than just their connections. + if($msg['notify']['sender']['url'] === z_root()) - $sql = " where (( " . $col . " & " . PERMS_NETWORK . " )>0 or ( " . $col . " & " . PERMS_SITE . " )>0 or ( " . $col . " & " . PERMS_PUBLIC . ")>0 or ( " . $col . " & " . PERMS_AUTHED . ")>0) "; + $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 + or ( " . $col . " & " . intval(PERMS_SITE) . " ) > 0 + or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 + or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) "; else - $sql = " where (( " . $col . " & " . PERMS_NETWORK . " )>0 or ( " . $col . " & " . PERMS_PUBLIC . ")>0 or ( " . $col . " & " . PERMS_AUTHED . ")>0) "; + $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 + or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 + or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) "; - $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s' ", + $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s' + and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 ", dbesc($msg['notify']['sender']['hash']) ); if(! $r) $r = array(); - $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & " . PAGE_REMOVED . " )>0 and (( " . $col . " & " . PERMS_SPECIFIC . " )>0 and ( abook_my_perms & " . $field . " )>0) OR ( " . $col . " & " . PERMS_PENDING . " )>0 OR (( " . $col . " & " . PERMS_CONTACTS . " )>0 and not ( abook_flags & " . ABOOK_FLAG_PENDING . " )>0) ", + // Now we have to get a bit dirty. Find every channel that has the sender in their connections (abook) + // and is allowing this sender at least at a high level. + + $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id + where abook_xchan = '%s' and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 + and (( " . $col . " & " . intval(PERMS_SPECIFIC) . " ) > 0 and ( abook_my_perms & " . intval($field) . " ) > 0 ) + OR ( " . $col . " & " . intval(PERMS_PENDING) . " ) > 0 + OR (( " . $col . " & " . intval(PERMS_CONTACTS) . " ) > 0 and ( abook_flags & " . intval(ABOOK_FLAG_PENDING) . " ) = 0 ) ", dbesc($msg['notify']['sender']['hash']) ); @@ -1347,22 +1399,55 @@ function public_recips($msg) { // look for any public mentions on this site // They will get filtered by tgroup_check() so we don't need to check permissions now - if($check_mentions && $msg['message']['tags']) { - if(is_array($msg['message']['tags']) && $msg['message']['tags']) { - foreach($msg['message']['tags'] as $tag) { - if(($tag['type'] === 'mention') && (strpos($tag['url'],z_root()) !== false)) { - $address = basename($tag['url']); - if($address) { - $z = q("select channel_hash as hash from channel where channel_address = '%s' limit 1", - dbesc($address) - ); - if($z) - $r = array_merge($r,$z); + if($check_mentions) { + // It's a top level post. Look at the tags. See if any of them are mentions and are on this hub. + if($msg['message']['tags']) { + if(is_array($msg['message']['tags']) && $msg['message']['tags']) { + foreach($msg['message']['tags'] as $tag) { + if(($tag['type'] === 'mention') && (strpos($tag['url'],z_root()) !== false)) { + $address = basename($tag['url']); + if($address) { + $z = q("select channel_hash as hash from channel where channel_address = '%s' limit 1", + dbesc($address) + ); + if($z) + $r = array_merge($r,$z); + } } } } } } + else { + // This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return + // everybody that stored a copy of the parent. This way we know we're covered. We'll check the + // comment permissions when we deliver them. + + if($msg['message']['message_top']) { + $z = q("select owner_xchan as hash from item where parent_mid = '%s' ", + dbesc($msg['message']['message_top']), + intval(ITEM_UPLINK) + ); + if($z) + $r = array_merge($r,$z); + } + } + + // There are probably a lot of duplicates in $r at this point. We need to filter those out. + // It's a bit of work since it's a multi-dimensional array + + if($r) { + $uniq = array(); + + foreach($r as $rr) { + if(! in_array($rr['hash'],$uniq)) + $uniq[] = $rr['hash']; + } + $r = array(); + foreach($uniq as $rr) { + $r[] = array('hash' => $rr); + } + } logger('public_recips: ' . print_r($r,true), LOGGER_DATA); return $r; @@ -1373,9 +1458,16 @@ function public_recips($msg) { function allowed_public_recips($msg) { - logger('allowed_public_recips: ' . print_r($msg,true),LOGGER_DATA); + if(array_key_exists('public_scope',$msg['message'])) + $scope = $msg['message']['public_scope']; + + // Mail won't have a public scope. + // in fact, it's doubtful mail will ever get here since it almost universally + // has a recipient, but in fact we don't require this, so it's technically + // possible to send mail to anybody that's listening. + $recips = public_recips($msg); if(! $recips) @@ -1384,11 +1476,6 @@ function allowed_public_recips($msg) { if($msg['message']['type'] === 'mail') return $recips; - if(array_key_exists('public_scope',$msg['message'])) - $scope = $msg['message']['public_scope']; - - $hash = make_xchan_hash($msg['notify']['sender']['guid'],$msg['notify']['sender']['guid_sig']); - if($scope === 'public' || $scope === 'network: red' || $scope === 'authenticated') return $recips; @@ -1399,19 +1486,23 @@ function allowed_public_recips($msg) { return array(); } + $hash = make_xchan_hash($msg['notify']['sender']['guid'],$msg['notify']['sender']['guid_sig']); + if($scope === 'self') { foreach($recips as $r) if($r['hash'] === $hash) return array('hash' => $hash); } - if($scope === 'contacts') { + // note: we shouldn't ever see $scope === 'specific' in this function, but handle it anyway + + if($scope === 'contacts' || $scope === 'any connections' || $scope === 'specific') { $condensed_recips = array(); foreach($recips as $rr) $condensed_recips[] = $rr['hash']; $results = array(); - $r = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & %d )>0 ", + $r = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & %d ) > 0 ", dbesc($hash), intval(PAGE_REMOVED) ); @@ -1423,6 +1514,7 @@ function allowed_public_recips($msg) { return $results; } + return array(); } @@ -1455,8 +1547,11 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque $channel = $r[0]; - // allow public postings to the sys channel regardless of permissions - if(($channel['channel_pageflags'] & PAGE_SYSTEM) && (! $arr['item_private'])) { + // allow public postings to the sys channel regardless of permissions, but not + // for comments travelling upstream. Wait and catch them on the way down. + // They may have been blocked by the owner. + + if(($channel['channel_pageflags'] & PAGE_SYSTEM) && (! $arr['item_private']) && (! $relay)) { $local_public = true; $r = q("select xchan_flags from xchan where xchan_hash = '%s' limit 1", @@ -1626,6 +1721,13 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque else { $arr['aid'] = $channel['channel_account_id']; $arr['uid'] = $channel['channel_id']; + + // if it's a sourced post, call the post_local hooks as if it were + // posted locally so that crosspost connectors will be triggered. + + if(check_item_source($arr['uid'],$arr)) + call_hooks('post_local',$arr); + $item_result = item_store($arr); $item_id = 0; if($item_result['success']) { @@ -1770,7 +1872,23 @@ function delete_imported_item($sender,$item,$uid,$relay) { logger('delete_imported_item: item was already deleted'); if(! $relay) return false; + + // This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised + // a bit further. We're going to strip the ITEM_ORIGIN on this item if it's a comment, because + // it was already deleted, and we're already relaying, and this ensures that no other process or + // code path downstream can relay it again (causing a loop). Since it's already gone it's not coming + // back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing + // this information from the metadata should have no other discernible impact. + + if(($r[0]['id'] != $r[0]['parent']) && ($r[0]['item_flags'] & ITEM_ORIGIN)) { + $x = q("update item set item_flags = %d where id = %d and uid = %d", + intval($r[0]['item_flags'] ^ ITEM_ORIGIN), + intval($r[0]['id']), + intval($r[0]['uid']) + ); + } } + require_once('include/items.php'); @@ -1935,7 +2053,7 @@ function sync_locations($sender,$arr,$absolute = false) { $ret = array(); if($arr['locations']) { - + $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'", dbesc($sender['hash']) ); @@ -1999,19 +2117,21 @@ function sync_locations($sender,$arr,$absolute = false) { // update connection timestamp if this is the site we're talking to // This only happens when called from import_xchan + $current_site = false; + if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) { q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($r[0]['hubloc_id']) ); + $current_site = true; } - // if it's marked offline/dead, bring it back - // Should we do this? It's basically saying that the channel knows better than - // the directory server if the site is alive. + // If it is the site we're currently talking to, and it's marked offline, + // either we have some bad information - or the thing came back to life. - if($r[0]['hubloc_status'] & HUBLOC_OFFLINE) { + if(($current_site) && ($r[0]['hubloc_status'] & HUBLOC_OFFLINE)) { q("update hubloc set hubloc_status = (hubloc_status & ~%d) where hubloc_id = %d", intval(HUBLOC_OFFLINE), intval($r[0]['hubloc_id']) @@ -2244,10 +2364,11 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ dbesc($hash) ); - $age = intval($arr['xprof_age']); - if($age > 150) - $age = 150; - + if($arr['xprof_age'] > 150) + $arr['xprof_age'] = 150; + if($arr['xprof_age'] < 0) + $arr['xprof_age'] = 0; + if($r) { $update = false; foreach($r[0] as $k => $v) { @@ -2276,7 +2397,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ where xprof_hash = '%s'", dbesc($arr['xprof_desc']), dbesc($arr['xprof_dob']), - $age, + intval($arr['xprof_age']), dbesc($arr['xprof_gender']), dbesc($arr['xprof_marital']), dbesc($arr['xprof_sexual']), @@ -2299,7 +2420,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ dbesc($arr['xprof_hash']), dbesc($arr['xprof_desc']), dbesc($arr['xprof_dob']), - $age, + intval($arr['xprof_age']), dbesc($arr['xprof_gender']), dbesc($arr['xprof_marital']), dbesc($arr['xprof_sexual']), @@ -2415,6 +2536,9 @@ function import_site($arr,$pubkey) { if($arr['directory_mode'] == 'standalone') $site_directory = DIRECTORY_MODE_STANDALONE; + + + $register_policy = 0; if($arr['register_policy'] == 'closed') $register_policy = REGISTER_CLOSED; @@ -2452,6 +2576,17 @@ function import_site($arr,$pubkey) { $site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false); $site_realm = htmlspecialchars($arr['realm'],ENT_COMPAT,'UTF-8',false); + // You can have one and only one primary directory per realm. + // Downgrade any others claiming to be primary. As they have + // flubbed up this badly already, don't let them be directory servers at all. + + if(($site_directory === DIRECTORY_MODE_PRIMARY) + && ($site_realm === get_directory_realm()) + && ($arr['url'] != get_directory_primary())) { + $site_directory = DIRECTORY_MODE_NORMAL; + } + + if($exists) { if(($siterecord['site_flags'] != $site_directory) || ($siterecord['site_access'] != $access_policy) @@ -2481,6 +2616,13 @@ function import_site($arr,$pubkey) { logger('import_site: update failed. ' . print_r($arr,true)); } } + else { + // update the timestamp to indicate we communicated with this site + q("update site set site_update = '%s' where site_url = '%s'", + dbesc(datetime_convert()), + dbesc($url) + ); + } } else { $update = true; @@ -2793,6 +2935,9 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { if(count($clean)) { foreach($clean as $k => $v) { + if($k == 'abook_dob') + $v = dbescdate($v); + $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); } |