diff options
-rw-r--r-- | Zotlabs/Access/AccessList.php | 8 | ||||
-rw-r--r-- | Zotlabs/Access/PermissionLimits.php | 83 | ||||
-rw-r--r-- | Zotlabs/Lib/MarkdownSoap.php | 65 | ||||
-rw-r--r-- | Zotlabs/Lib/Permcat.php | 78 | ||||
-rw-r--r-- | Zotlabs/Module/Acl.php | 43 | ||||
-rw-r--r-- | Zotlabs/Thumbs/Epubthumb.php | 40 | ||||
-rwxr-xr-x | boot.php | 5 | ||||
-rwxr-xr-x | include/plugin.php | 11 | ||||
-rw-r--r-- | include/text.php | 122 |
9 files changed, 336 insertions, 119 deletions
diff --git a/Zotlabs/Access/AccessList.php b/Zotlabs/Access/AccessList.php index 6471b0b1d..7cf7b5587 100644 --- a/Zotlabs/Access/AccessList.php +++ b/Zotlabs/Access/AccessList.php @@ -3,10 +3,14 @@ namespace Zotlabs\Access; /** - * @brief AccessList class. + * @brief AccessList class which represents individual content ACLs. * * A class to hold an AccessList object with allowed and denied contacts and * groups. + * + * After evaluating @ref ::Zotlabs::Access::PermissionLimits "PermissionLimits" + * and @ref ::Zotlabs::Lib::Permcat "Permcat"s individual content ACLs are evaluated. + * These answer the question "Can Joe view *this* album/photo?". */ class AccessList { /** @@ -103,7 +107,7 @@ class AccessList { * @brief Return an array consisting of the current access list components * where the elements are directly storable. * - * @return Associative array with: + * @return array An associative array with: * * \e string \b allow_cid => string of allowed cids * * \e string \b allow_gid => string of allowed gids * * \e string \b deny_cid => string of denied cids diff --git a/Zotlabs/Access/PermissionLimits.php b/Zotlabs/Access/PermissionLimits.php index 8caeedb91..9ee0656b1 100644 --- a/Zotlabs/Access/PermissionLimits.php +++ b/Zotlabs/Access/PermissionLimits.php @@ -2,35 +2,90 @@ namespace Zotlabs\Access; -use \Zotlabs\Lib as ZLib; +use Zotlabs\Lib\PConfig; +/** + * @brief Permission limits. + * + * Permission limits are a very high level permission setting. They are hard + * limits by design. + * "Who can view my photos (at all)?" + * "Who can post photos in my albums (at all)?" + * + * For viewing permissions we generally set these to 'anybody' and for write + * permissions we generally set them to 'those I allow', though many people + * restrict the viewing permissions further for things like 'Can view my connections'. + * + * People get confused enough by permissions that we wanted a place to set their + * privacy expectations once and be done with it. + * + * Connection related permissions like "Can Joe view my photos?" are handled by + * @ref ::Zotlabs::Lib::Permcat "Permcat" and inherit from the channel's Permission + * limits. + * + * @see Permissions + */ class PermissionLimits { + /** + * @brief Get standard permission limits. + * + * Viewing permissions and post_comments permission are set to 'anybody', + * other permissions are set to 'those I allow'. + * + * The list of permissions comes from Permissions::Perms(). + * + * @return array + */ static public function Std_Limits() { + $limits = []; $perms = Permissions::Perms(); - $limits = array(); + foreach($perms as $k => $v) { - if(strstr($k,'view') || $k === 'post_comments') + if(strstr($k, 'view') || $k === 'post_comments') $limits[$k] = PERMS_PUBLIC; else $limits[$k] = PERMS_SPECIFIC; } + return $limits; } - static public function Set($channel_id,$perm,$perm_limit) { - ZLib\PConfig::Set($channel_id,'perm_limits',$perm,$perm_limit); + /** + * @brief Sets a permission limit for a channel. + * + * @param int $channel_id + * @param string $perm + * @param int $perm_limit one of PERMS_* constants + */ + static public function Set($channel_id, $perm, $perm_limit) { + PConfig::Set($channel_id, 'perm_limits', $perm, $perm_limit); } - static public function Get($channel_id,$perm = '') { + /** + * @brief Get a channel's permission limits. + * + * Return a channel's permission limits from PConfig. If $perm is set just + * return this permission limit, if not set, return an array with all + * permission limits. + * + * @param int $channel_id + * @param string $perm (optional) + * @return + * * \b boolean false if no perm_limits set for this channel + * * \b int if $perm is set, return one of PERMS_* constants for this permission + * * \b array with all permission limits, if $perm is not set + */ + static public function Get($channel_id, $perm = '') { if($perm) { - return Zlib\PConfig::Get($channel_id,'perm_limits',$perm); - } - else { - Zlib\PConfig::Load($channel_id); - if(array_key_exists($channel_id,\App::$config) && array_key_exists('perm_limits',\App::$config[$channel_id])) - return \App::$config[$channel_id]['perm_limits']; - return false; + return PConfig::Get($channel_id, 'perm_limits', $perm); } - } + + PConfig::Load($channel_id); + if(array_key_exists($channel_id, \App::$config) + && array_key_exists('perm_limits', \App::$config[$channel_id])) + return \App::$config[$channel_id]['perm_limits']; + + return false; + } }
\ No newline at end of file diff --git a/Zotlabs/Lib/MarkdownSoap.php b/Zotlabs/Lib/MarkdownSoap.php index fa279b07c..a58a5753a 100644 --- a/Zotlabs/Lib/MarkdownSoap.php +++ b/Zotlabs/Lib/MarkdownSoap.php @@ -3,51 +3,66 @@ namespace Zotlabs\Lib; /** - * MarkdownSoap + * @brief MarkdownSoap class. + * * Purify Markdown for storage + * @code{.php} * $x = new MarkdownSoap($string_to_be_cleansed); * $text = $x->clean(); - * + * @endcode * What this does: * 1. extracts code blocks and privately escapes them from processing * 2. Run html purifier on the content * 3. put back the code blocks * 4. run htmlspecialchars on the entire content for safe storage * - * At render time: + * At render time: + * @code{.php} * $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text); * $html = \Michelf\MarkdownExtra::DefaultTransform($markdown); + * @endcode */ - - - class MarkdownSoap { + /** + * @var string + */ + private $str; + /** + * @var string + */ private $token; - private $str; function __construct($s) { - $this->str = $s; + $this->str = $s; $this->token = random_string(20); } - function clean() { $x = $this->extract_code($this->str); $x = $this->purify($x); - $x = $this->putback_code($x); + $x = $this->putback_code($x); $x = $this->escape($x); - + return $x; } + /** + * @brief Extracts code blocks and privately escapes them from processing. + * + * @see encode_code() + * @see putback_code() + * + * @param string $s + * @return string + */ function extract_code($s) { - + $text = preg_replace_callback('{ (?:\n\n|\A\n?) ( # $1 = the code block -- one or more lines, starting with a space/tab @@ -62,7 +77,7 @@ class MarkdownSoap { return $text; } - + function encode_code($matches) { return $this->token . ';' . base64_encode($matches[0]) . ';' ; } @@ -71,8 +86,17 @@ class MarkdownSoap { return base64_decode($matches[1]); } + /** + * @brief Put back the code blocks. + * + * @see extract_code() + * @see decode_code() + * + * @param string $s + * @return string + */ function putback_code($s) { - $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s); + $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm', [ $this, 'decode_code' ], $s); return $text; } @@ -84,20 +108,25 @@ class MarkdownSoap { } function protect_autolinks($s) { - $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s); + $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/', '[$1$2]($1$2)', $s); return $s; } function unprotect_autolinks($s) { return $s; - } function escape($s) { - return htmlspecialchars($s,ENT_QUOTES,'UTF-8',false); + return htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false); } + /** + * @brief Converts special HTML entities back to characters. + * + * @param string $s + * @return string + */ static public function unescape($s) { - return htmlspecialchars_decode($s,ENT_QUOTES); + return htmlspecialchars_decode($s, ENT_QUOTES); } } diff --git a/Zotlabs/Lib/Permcat.php b/Zotlabs/Lib/Permcat.php index 505ee2cfc..ca4aed9ed 100644 --- a/Zotlabs/Lib/Permcat.php +++ b/Zotlabs/Lib/Permcat.php @@ -2,12 +2,36 @@ namespace Zotlabs\Lib; -use \Zotlabs\Access as Zaccess; - +use Zotlabs\Access\PermissionRoles; +use Zotlabs\Access\Permissions; + +/** + * @brief Permission Categories. Permission rules for various classes of connections. + * + * Connection permissions answer the question "Can Joe view my photos?" + * + * Some permissions may be inherited from the channel's "privacy settings" + * (@ref ::Zotlabs::Access::PermissionLimits "PermissionLimits") "Who can view my + * photos (at all)?" which have higher priority than individual connection settings. + * We evaluate permission limits first, and then fall through to connection + * permissions if the permission limits didn't already make a definitive decision. + * + * After PermissionLimits and connection permissions are evaluated, individual + * content ACLs are evaluated (@ref ::Zotlabs::Access::AccessList "AccessList"). + * These answer the question "Can Joe view *this* album/photo?". + */ class Permcat { + /** + * @var array + */ private $permcats = []; + /** + * @brief Permcat constructor. + * + * @param int $channel_id + */ public function __construct($channel_id) { $perms = []; @@ -16,16 +40,16 @@ class Permcat { $role = get_pconfig($channel_id,'system','permissions_role'); if($role) { - $x = Zaccess\PermissionRoles::role_perms($role); + $x = PermissionRoles::role_perms($role); if($x['perms_connect']) { - $perms = Zaccess\Permissions::FilledPerms($x['perms_connect']); + $perms = Permissions::FilledPerms($x['perms_connect']); } } // if no role perms it may be a custom role, see if there any autoperms if(! $perms) { - $perms = Zaccess\Permissions::FilledAutoPerms($channel_id); + $perms = Permissions::FilledAutoPerms($channel_id); } // if no autoperms it may be a custom role with manual perms @@ -50,13 +74,13 @@ class Permcat { // nothing was found - create a filled permission array where all permissions are 0 if(! $perms) { - $perms = Zaccess\Permissions::FilledPerms([]); + $perms = Permissions::FilledPerms([]); } $this->permcats[] = [ 'name' => 'default', 'localname' => t('default','permcat'), - 'perms' => Zaccess\Permissions::Operms($perms), + 'perms' => Permissions::Operms($perms), 'system' => 1 ]; @@ -67,26 +91,39 @@ class Permcat { $this->permcats[] = [ 'name' => $p[$x][0], 'localname' => $p[$x][1], - 'perms' => Zaccess\Permissions::Operms(Zaccess\Permissions::FilledPerms($p[$x][2])), + 'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])), 'system' => intval($p[$x][3]) ]; } } } - + /** + * @brief Return array with permcats. + * + * @return array + */ public function listing() { return $this->permcats; } + /** + * @brief + * + * @param string $name + * @return array + * * \e array with permcats + * * \e bool \b error if $name not found in permcats true + */ public function fetch($name) { if($name && $this->permcats) { foreach($this->permcats as $permcat) { - if(strcasecmp($permcat['name'],$name) === 0) { + if(strcasecmp($permcat['name'], $name) === 0) { return $permcat; } } } + return ['error' => true]; } @@ -118,29 +155,32 @@ class Permcat { $permcats[] = [ $xv['k'], $xv['k'], $value, 0 ]; } } - } + } - call_hooks('permcats',$permcats); + /** + * @hooks permcats + * * \e array + */ + call_hooks('permcats', $permcats); return $permcats; - } - static public function find_permcat($arr,$name) { + static public function find_permcat($arr, $name) { if((! $arr) || (! $name)) return false; + foreach($arr as $p) if($p['name'] == $name) return $p['value']; } - static public function update($channel_id, $name,$permarr) { - PConfig::Set($channel_id,'permcat',$name,$permarr); + static public function update($channel_id, $name, $permarr) { + PConfig::Set($channel_id, 'permcat', $name, $permarr); } - static public function delete($channel_id,$name) { - PConfig::Delete($channel_id,'permcat',$name); + static public function delete($channel_id, $name) { + PConfig::Delete($channel_id, 'permcat', $name); } - }
\ No newline at end of file diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index ad1c8b8cd..fae7e2e44 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -1,36 +1,39 @@ <?php + namespace Zotlabs\Module; -/* - * ACL selector json backend +require_once 'include/acl_selectors.php'; +require_once 'include/group.php'; + +/** + * @brief ACL selector json backend. + * * This module provides JSON lists of connections and local/remote channels * (xchans) to populate various tools such as the ACL (AccessControlList) popup - * and various auto-complete functions (such as email recipients, search, and + * and various auto-complete functions (such as email recipients, search, and * mention targets. + * * There are two primary output structural formats. One for the ACL widget and * the other for auto-completion. - * Many of the behaviour variations are triggered on the use of single character keys - * however this functionality has grown in an ad-hoc manner and has gotten quite messy over time. + * + * Many of the behaviour variations are triggered on the use of single character + * keys however this functionality has grown in an ad-hoc manner and has gotten + * quite messy over time. */ - -require_once("include/acl_selectors.php"); -require_once("include/group.php"); - - class Acl extends \Zotlabs\Web\Controller { function init() { - + logger('mod_acl: ' . print_r($_REQUEST,true)); - + $start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0); $count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500); $search = (x($_REQUEST,'search') ? $_REQUEST['search'] : ''); $type = (x($_REQUEST,'type') ? $_REQUEST['type'] : ''); - $noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false); + $noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false); - // $type = + // $type = // '' => standard ACL request // 'g' => Groups only ACL request // 'f' => forums only ACL request @@ -382,15 +385,13 @@ class Acl extends \Zotlabs\Web\Controller { 'count' => $count, 'items' => $items, ); - - - + echo json_encode($o); - + killme(); } - - + + function navbar_complete(&$a) { // logger('navbar_complete'); @@ -447,5 +448,5 @@ class Acl extends \Zotlabs\Web\Controller { } return array(); } - + } diff --git a/Zotlabs/Thumbs/Epubthumb.php b/Zotlabs/Thumbs/Epubthumb.php index 4213b5267..22f1a5e8f 100644 --- a/Zotlabs/Thumbs/Epubthumb.php +++ b/Zotlabs/Thumbs/Epubthumb.php @@ -2,36 +2,54 @@ namespace Zotlabs\Thumbs; -require_once('library/epub-meta/epub.php'); +require_once 'library/epub-meta/epub.php'; +/** + * @brief Thumbnail creation for epub files. + * + */ class Epubthumb { + /** + * @brief Match for application/epub+zip. + * + * @param string $type MimeType + * @return boolean + */ function Match($type) { return(($type === 'application/epub+zip') ? true : false ); } - function Thumb($attach,$preview_style,$height = 300, $width = 300) { + /** + * @brief + * + * @param array $attach + * @param number $preview_style unused + * @param number $height (optional) default 300 + * @param number $width (optional) default 300 + */ + function Thumb($attach, $preview_style, $height = 300, $width = 300) { $photo = false; - $ep = new \Epub(dbunescbin($attach['content'])); + $ep = new \EPub(dbunescbin($attach['content'])); $data = $ep->Cover(); if($data['found']) { $photo = $data['data']; } - if($photo) { + if($photo) { $image = imagecreatefromstring($photo); - $dest = imagecreatetruecolor( $width, $height ); - $srcwidth = imagesx($image); - $srcheight = imagesy($image); + $dest = imagecreatetruecolor($width, $height); + $srcwidth = imagesx($image); + $srcheight = imagesy($image); - imagealphablending($dest, false); + imagealphablending($dest, false); imagesavealpha($dest, true); - imagecopyresampled($dest, $image, 0, 0, 0, 0, $width, $height, $srcwidth, $srcheight); - imagedestroy($image); - imagejpeg($dest,dbunescbin($attach['content']) . '.thumb'); + imagecopyresampled($dest, $image, 0, 0, 0, 0, $width, $height, $srcwidth, $srcheight); + imagedestroy($image); + imagejpeg($dest, dbunescbin($attach['content']) . '.thumb'); } } } @@ -2010,7 +2010,7 @@ function build_querystring($params, $name = null) { } -/* +/** * @brief Much better way of dealing with c-style args. */ function argc() { @@ -2031,6 +2031,8 @@ function dba_timer() { /** * @brief Returns xchan_hash from the observer. * + * Observer can be a local or remote channel. + * * @return string xchan_hash from observer, otherwise empty string if no observer */ function get_observer_hash() { @@ -2041,7 +2043,6 @@ function get_observer_hash() { return ''; } - /** * @brief Returns the complete URL of the current page, e.g.: http(s)://something.com/network * diff --git a/include/plugin.php b/include/plugin.php index 379d8e799..95afdaeb5 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -47,7 +47,10 @@ function uninstall_plugin($plugin) { } /** - * @brief installs an addon. + * @brief Installs an addon. + * + * This function is called once to install the addon (either from the cli or via + * the web admin). This will also call load_plugin() once. * * @param string $plugin name of the addon * @return bool @@ -188,7 +191,9 @@ function visible_plugin_list() { /** - * @brief registers a hook. + * @brief Registers a hook. + * + * @see ::Zotlabs::Extend::Hook::register() * * @param string $hook the name of the hook * @param string $file the name of the file that hooks into @@ -219,6 +224,8 @@ function register_hook($hook, $file, $function, $priority = 0) { /** * @brief unregisters a hook. * + * @see ::Zotlabs::Extend::Hook::unregister + * * @param string $hook the name of the hook * @param string $file the name of the file that hooks into * @param string $function the name of the function that the hook called diff --git a/include/text.php b/include/text.php index 107efe0cb..956f42f7d 100644 --- a/include/text.php +++ b/include/text.php @@ -24,12 +24,20 @@ define('RANDOM_STRING_TEXT', 0x01 ); * @return string substituted string */ function replace_macros($s, $r) { + $arr = [ + 'template' => $s, + 'params' => $r + ]; - $arr = array('template' => $s, 'params' => $r); + /** + * @hooks replace_macros + * * \e string \b template + * * \e array \b params + */ call_hooks('replace_macros', $arr); $t = App::template_engine(); - $output = $t->replace_macros($arr['template'],$arr['params']); + $output = $t->replace_macros($arr['template'], $arr['params']); return $output; } @@ -301,12 +309,16 @@ function purify_html($s, $allow_position = false) { /** - * @brief generate a string that's random, but usually pronounceable. + * @brief Generate a string that's random, but usually pronounceable. * * Used to generate initial passwords. * - * @param int $len - * @return string + * @note In order to create "pronounceable" strings some consonant pairs or + * letters that does not make a very good word ending are chopped off, so that + * the returned string length can be lower than $len. + * + * @param int $len max length of generated string + * @return string Genereated random, but usually pronounceable string */ function autoname($len) { @@ -343,6 +355,7 @@ function autoname($len) { $midcons = array('ck','ct','gn','ld','lf','lm','lt','mb','mm', 'mn','mp', 'nd','ng','nk','nt','rn','rp','rt'); + // avoid these consonant pairs at the end of the string $noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr', 'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh'); @@ -355,7 +368,7 @@ function autoname($len) { $word = ''; for ($x = 0; $x < $len; $x ++) { - $r = mt_rand(0,count($table) - 1); + $r = mt_rand(0, count($table) - 1); $word .= $table[$r]; if ($table == $vowels) @@ -364,14 +377,15 @@ function autoname($len) { $table = $vowels; } - $word = substr($word,0,$len); + $word = substr($word, 0, $len); foreach ($noend as $noe) { - if ((strlen($word) > 2) && (substr($word,-2) == $noe)) { - $word = substr($word,0,-1); + if ((strlen($word) > 2) && (substr($word, -2) == $noe)) { + $word = substr($word, 0, -1); break; } } + // avoid the letter 'q' as it does not make a very good word ending if (substr($word, -1) == 'q') $word = substr($word, 0, -1); @@ -1094,17 +1108,19 @@ function sslify($s) { return $s; } - +/** + * @brief Get an array of poke verbs. + * + * @return array + * * \e index is present tense verb + * * \e value is array containing past tense verb, translation of present, translation of past + */ function get_poke_verbs() { - // index is present tense verb - // value is array containing past tense verb, translation of present, translation of past - - if(get_config('system','poke_basic')) { + if (get_config('system', 'poke_basic')) { $arr = array( - 'poke' => array( 'poked', t('poke'), t('poked')), + 'poke' => array('poked', t('poke'), t('poked')), ); - } - else { + } else { $arr = array( 'poke' => array( 'poked', t('poke'), t('poked')), 'ping' => array( 'pinged', t('ping'), t('pinged')), @@ -1114,15 +1130,26 @@ function get_poke_verbs() { 'rebuff' => array( 'rebuffed', t('rebuff'), t('rebuffed')), ); + /** + * @hooks poke_verbs + * * \e array associative array with another array as value + */ call_hooks('poke_verbs', $arr); } return $arr; } +/** + * @brief Get an array of mood verbs. + * + * @return array + * * \e index is the verb + * * \e value is the translated verb + */ function get_mood_verbs() { - $arr = array( + $arr = [ 'happy' => t('happy'), 'sad' => t('sad'), 'mellow' => t('mellow'), @@ -1144,9 +1171,14 @@ function get_mood_verbs() { 'motivated' => t('motivated'), 'relaxed' => t('relaxed'), 'surprised' => t('surprised'), - ); + ]; + /** + * @hooks mood_verbs + * * \e array associative array with mood verbs + */ call_hooks('mood_verbs', $arr); + return $arr; } @@ -1513,14 +1545,37 @@ function format_filer(&$item) { function generate_map($coord) { $coord = trim($coord); $coord = str_replace(array(',','/',' '),array(' ',' ',' '),$coord); - $arr = array('lat' => trim(substr($coord,0,strpos($coord,' '))), 'lon' => trim(substr($coord,strpos($coord,' ')+1)), 'html' => ''); - call_hooks('generate_map',$arr); + + $arr = [ + 'lat' => trim(substr($coord, 0, strpos($coord, ' '))), + 'lon' => trim(substr($coord, strpos($coord, ' ')+1)), + 'html' => '' + ]; + + /** + * @hooks generate_map + * * \e string \b lat + * * \e string \b lon + * * \e string \b html the parsed HTML to return + */ + call_hooks('generate_map', $arr); + return (($arr['html']) ? $arr['html'] : $coord); } function generate_named_map($location) { - $arr = array('location' => $location, 'html' => ''); - call_hooks('generate_named_map',$arr); + $arr = [ + 'location' => $location, + 'html' => '' + ]; + + /** + * @hooks generate_named_map + * * \e string \b location + * * \e string \b html the parsed HTML to return + */ + call_hooks('generate_named_map', $arr); + return (($arr['html']) ? $arr['html'] : $location); } @@ -1626,13 +1681,11 @@ function prepare_binary($item) { } - - /** * @brief Given a text string, convert from bbcode to html and add smilie icons. * * @param string $text - * @param sting $content_type (optional) default text/bbcode + * @param string $content_type (optional) default text/bbcode * @param boolean $cache (optional) default false * * @return string @@ -3033,8 +3086,19 @@ function text_highlight($s, $lang) { $s = jindent($s); } - $arr = [ 'text' => $s, 'language' => $lang, 'success' => false ]; - call_hooks('text_highlight',$arr); + $arr = [ + 'text' => $s, + 'language' => $lang, + 'success' => false + ]; + + /** + * @hooks text_highlight + * * \e string \b text + * * \e string \b language + * * \e boolean \b success default false + */ + call_hooks('text_highlight', $arr); if($arr['success']) $o = $arr['text']; @@ -3117,7 +3181,6 @@ function share_unshield($m) { function cleanup_bbcode($body) { - /** * fix naked links by passing through a callback to see if this is a hubzilla site * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both. @@ -3155,7 +3218,6 @@ function cleanup_bbcode($body) { return $body; - } function gen_link_id($mid) { |