X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Ftext.php;h=c1e01343a8cd856134a3d68ca7f45a3975197b5d;hb=ddf1caf0fd9ea4fc97147ba7b45587bcf7a6fab4;hp=83819d095071f678df7bb3f298bf9777884a421a;hpb=b11f3b702f40f28a1962fd8f1087d97237b3a405;p=friendica.git diff --git a/include/text.php b/include/text.php index 83819d0950..628b4fc2da 100644 --- a/include/text.php +++ b/include/text.php @@ -6,22 +6,32 @@ // returns substituted string. // WARNING: this is pretty basic, and doesn't properly handle search strings that are substrings of each other. // For instance if 'test' => "foo" and 'testing' => "bar", testing could become either bar or fooing, -// depending on the order in which they were declared in the array. +// depending on the order in which they were declared in the array. require_once("include/template_processor.php"); +require_once("include/friendica_smarty.php"); -if(! function_exists('replace_macros')) { +if(! function_exists('replace_macros')) { +/** + * This is our template processor + * + * @param string|FriendicaSmarty $s the string requiring macro substitution, + * or an instance of FriendicaSmarty + * @param array $r key value pairs (search => replace) + * @return string substituted string + */ function replace_macros($s,$r) { - global $t; - //$ts = microtime(); - $r = $t->replace($s,$r); - //$tt = microtime() - $ts; - - //$a = get_app(); - //$a->page['debug'] .= "$tt
\n"; - return template_unescape($r); + $stamp1 = microtime(true); + $a = get_app(); + + $t = $a->template_engine(); + $output = $t->replace_macros($s,$r); + + $a->save_timestamp($stamp1, "rendering"); + + return $output; }} @@ -39,6 +49,7 @@ function random_string($size = 64,$type = RANDOM_STRING_HEX) { return(substr($s,0,$size)); }} +if(! function_exists('notags')) { /** * This is our primary input filter. * @@ -53,9 +64,9 @@ function random_string($size = 64,$type = RANDOM_STRING_HEX) { * They will be replaced with safer brackets. This may be filtered further * if these are not allowed either. * + * @param string $string Input string + * @return string Filtered string */ - -if(! function_exists('notags')) { function notags($string) { return(str_replace(array("<",">"), array('[',']'), $string)); @@ -64,13 +75,18 @@ function notags($string) { // return(str_replace(array("<",">","\xBA","\xBC","\xBE"), array('[',']','','',''), $string)); }} -// use this on "body" or "content" input where angle chars shouldn't be removed, -// and allow them to be safely displayed. + if(! function_exists('escape_tags')) { +/** + * use this on "body" or "content" input where angle chars shouldn't be removed, + * and allow them to be safely displayed. + * @param string $string + * @return string + */ function escape_tags($string) { - return(htmlspecialchars($string)); + return(htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false)); }} @@ -78,6 +94,12 @@ function escape_tags($string) { // used to generate initial passwords if(! function_exists('autoname')) { +/** + * generate a string that's random, but usually pronounceable. + * used to generate initial passwords + * @param int $len + * @return string + */ function autoname($len) { if($len <= 0) @@ -153,11 +175,17 @@ function autoname($len) { // returns escaped text. if(! function_exists('xmlify')) { +/** + * escape text ($str) for XML transport + * @param string $str + * @return string Escaped text. + */ function xmlify($str) { - $buffer = ''; +/* $buffer = ''; - for($x = 0; $x < mb_strlen($str); $x ++) { - $char = $str[$x]; + $len = mb_strlen($str); + for($x = 0; $x < $len; $x ++) { + $char = mb_substr($str,$x,1); switch( $char ) { @@ -185,24 +213,41 @@ function xmlify($str) { $buffer .= $char; break; } - } + }*/ + + $buffer = mb_ereg_replace("&", "&", $str); + $buffer = mb_ereg_replace("'", "'", $buffer); + $buffer = mb_ereg_replace("\"", """, $buffer); + $buffer = mb_ereg_replace("<", "<", $buffer); + $buffer = mb_ereg_replace(">", ">", $buffer); + $buffer = trim($buffer); return($buffer); }} -// undo an xmlify -// pass xml escaped text ($s), returns unescaped text - if(! function_exists('unxmlify')) { +/** + * undo an xmlify + * @param string $s xml escaped text + * @return string unescaped text + */ function unxmlify($s) { - $ret = str_replace('&','&', $s); - $ret = str_replace(array('<','>','"','''),array('<','>','"',"'"),$ret); +// $ret = str_replace('&','&', $s); +// $ret = str_replace(array('<','>','"','''),array('<','>','"',"'"),$ret); + $ret = mb_ereg_replace('&', '&', $s); + $ret = mb_ereg_replace(''', "'", $ret); + $ret = mb_ereg_replace('"', '"', $ret); + $ret = mb_ereg_replace('<', "<", $ret); + $ret = mb_ereg_replace('>', ">", $ret); return $ret; }} -// convenience wrapper, reverse the operation "bin2hex" - if(! function_exists('hex2bin')) { +/** + * convenience wrapper, reverse the operation "bin2hex" + * @param string $s + * @return number + */ function hex2bin($s) { if(! (is_string($s) && strlen($s))) return ''; @@ -214,17 +259,23 @@ function hex2bin($s) { return(pack("H*",$s)); }} -// Automatic pagination. -// To use, get the count of total items. -// Then call $a->set_pager_total($number_items); -// Optionally call $a->set_pager_itemspage($n) to the number of items to display on each page -// Then call paginate($a) after the end of the display loop to insert the pager block on the page -// (assuming there are enough items to paginate). -// When using with SQL, the setting LIMIT %d, %d => $a->pager['start'],$a->pager['itemspage'] -// will limit the results to the correct items for the current page. -// The actual page handling is then accomplished at the application layer. if(! function_exists('paginate')) { +/** + * Automatic pagination. + * + * To use, get the count of total items. + * Then call $a->set_pager_total($number_items); + * Optionally call $a->set_pager_itemspage($n) to the number of items to display on each page + * Then call paginate($a) after the end of the display loop to insert the pager block on the page + * (assuming there are enough items to paginate). + * When using with SQL, the setting LIMIT %d, %d => $a->pager['start'],$a->pager['itemspage'] + * will limit the results to the correct items for the current page. + * The actual page handling is then accomplished at the application layer. + * + * @param App $a App instance + * @return string html for pagination #FIXME remove html + */ function paginate(&$a) { $o = ''; $stripped = preg_replace('/(&page=[0-9]*)/','',$a->query_string); @@ -281,6 +332,12 @@ function paginate(&$a) { }} if(! function_exists('alt_pager')) { +/** + * Alternative pager + * @param App $a App instance + * @param int $i + * @return string html for pagination #FIXME remove html + */ function alt_pager(&$a, $i) { $o = ''; $stripped = preg_replace('/(&page=[0-9]*)/','',$a->query_string); @@ -292,11 +349,11 @@ function alt_pager(&$a, $i) { $o .= '
'; if($a->pager['page']>1) - $o .= "pager['page'] - 1).'">' . t('newer') . ''; + $o .= "pager['page'] - 1).'" class="pager_newer">' . t('newer') . ''; if($i>0) { if($a->pager['page']>1) $o .= " - "; - $o .= "pager['page'] + 1).'">' . t('older') . ''; + $o .= "pager['page'] + 1).'" class="pager_older">' . t('older') . ''; } @@ -305,9 +362,14 @@ function alt_pager(&$a, $i) { return $o; }} -// Turn user/group ACLs stored as angle bracketed text into arrays if(! function_exists('expand_acl')) { +/** + * Turn user/group ACLs stored as angle bracketed text into arrays + * + * @param string $s + * @return array + */ function expand_acl($s) { // turn string array of angle-bracketed elements into numeric array // e.g. "<1><2><3>" => array(1,2,3); @@ -324,9 +386,11 @@ function expand_acl($s) { return $ret; }} -// Used to wrap ACL elements in angle brackets for storage - if(! function_exists('sanitise_acl')) { +/** + * Wrap ACL elements in angle brackets for storage + * @param string $item + */ function sanitise_acl(&$item) { if(intval($item)) $item = '<' . intval(notags(trim($item))) . '>'; @@ -335,12 +399,23 @@ function sanitise_acl(&$item) { }} -// Convert an ACL array to a storable string - if(! function_exists('perms2str')) { +/** + * Convert an ACL array to a storable string + * + * Normally ACL permissions will be an array. + * We'll also allow a comma-separated string. + * + * @param string|array $p + * @return string + */ function perms2str($p) { $ret = ''; - $tmp = $p; + if(is_array($p)) + $tmp = $p; + else + $tmp = explode(',',$p); + if(is_array($tmp)) { array_walk($tmp,'sanitise_acl'); $ret = implode('',$tmp); @@ -348,10 +423,16 @@ function perms2str($p) { return $ret; }} -// generate a guaranteed unique (for this domain) item ID for ATOM -// safe from birthday paradox if(! function_exists('item_new_uri')) { +/** + * generate a guaranteed unique (for this domain) item ID for ATOM + * safe from birthday paradox + * + * @param string $hostname + * @param int $uid + * @return string + */ function item_new_uri($hostname,$uid) { do { @@ -372,6 +453,12 @@ function item_new_uri($hostname,$uid) { // safe from birthday paradox if(! function_exists('photo_new_resource')) { +/** + * Generate a guaranteed unique photo ID. + * safe from birthday paradox + * + * @return string + */ function photo_new_resource() { do { @@ -387,72 +474,172 @@ function photo_new_resource() { }} -// wrapper to load a view template, checking for alternate -// languages before falling back to the default - -// obsolete, deprecated. - if(! function_exists('load_view_file')) { +/** + * @deprecated + * wrapper to load a view template, checking for alternate + * languages before falling back to the default + * + * @global string $lang + * @global App $a + * @param string $s view name + * @return string + */ function load_view_file($s) { global $lang, $a; if(! isset($lang)) $lang = 'en'; $b = basename($s); $d = dirname($s); - if(file_exists("$d/$lang/$b")) - return file_get_contents("$d/$lang/$b"); - + if(file_exists("$d/$lang/$b")) { + $stamp1 = microtime(true); + $content = file_get_contents("$d/$lang/$b"); + $a->save_timestamp($stamp1, "file"); + return $content; + } + $theme = current_theme(); - - if(file_exists("$d/theme/$theme/$b")) - return file_get_contents("$d/theme/$theme/$b"); - - return file_get_contents($s); + + if(file_exists("$d/theme/$theme/$b")) { + $stamp1 = microtime(true); + $content = file_get_contents("$d/theme/$theme/$b"); + $a->save_timestamp($stamp1, "file"); + return $content; + } + + $stamp1 = microtime(true); + $content = file_get_contents($s); + $a->save_timestamp($stamp1, "file"); + return $content; }} if(! function_exists('get_intltext_template')) { +/** + * load a view template, checking for alternate + * languages before falling back to the default + * + * @global string $lang + * @param string $s view path + * @return string + */ function get_intltext_template($s) { global $lang; + $a = get_app(); + $engine = ''; + if($a->theme['template_engine'] === 'smarty3') + $engine = "/smarty3"; + if(! isset($lang)) $lang = 'en'; - if(file_exists("view/$lang/$s")) - return file_get_contents("view/$lang/$s"); - elseif(file_exists("view/en/$s")) - return file_get_contents("view/en/$s"); - else - return file_get_contents("view/$s"); + if(file_exists("view/$lang$engine/$s")) { + $stamp1 = microtime(true); + $content = file_get_contents("view/$lang$engine/$s"); + $a->save_timestamp($stamp1, "file"); + return $content; + } elseif(file_exists("view/en$engine/$s")) { + $stamp1 = microtime(true); + $content = file_get_contents("view/en$engine/$s"); + $a->save_timestamp($stamp1, "file"); + return $content; + } else { + $stamp1 = microtime(true); + $content = file_get_contents("view$engine/$s"); + $a->save_timestamp($stamp1, "file"); + return $content; + } }} if(! function_exists('get_markup_template')) { -function get_markup_template($s) { - $a=get_app(); - $theme = current_theme(); +/** + * load template $s + * + * @param string $s + * @param string $root + * @return string + */ +function get_markup_template($s, $root = '') { + $stamp1 = microtime(true); + + $a = get_app(); + $t = $a->template_engine(); + + $template = $t->get_template_file($s, $root); + + $a->save_timestamp($stamp1, "file"); - if(file_exists("view/theme/$theme/$s")) - return file_get_contents("view/theme/$theme/$s"); - elseif (x($a->theme_info,"extends") && file_exists("view/theme/".$a->theme_info["extends"]."/$s")) - return file_get_contents("view/theme/".$a->theme_info["extends"]."/$s"); + return $template; + /* + + if($a->theme['template_engine'] === 'smarty3') { + $template_file = get_template_file($a, 'smarty3/' . $s, $root); + + $template = new FriendicaSmarty(); + $template->filename = $template_file; + $a->save_timestamp($stamp1, "rendering"); + + return $template; + } + else { + $template_file = get_template_file($a, $s, $root); + $a->save_timestamp($stamp1, "rendering"); + + $stamp1 = microtime(true); + $content = file_get_contents($template_file); + $a->save_timestamp($stamp1, "file"); + return $content; + + } + */ +}} + +if(! function_exists("get_template_file")) { +/** + * + * @param App $a + * @param string $filename + * @param string $root + * @return string + */ +function get_template_file($a, $filename, $root = '') { + $theme = current_theme(); + + // Make sure $root ends with a slash / + if($root !== '' && $root[strlen($root)-1] !== '/') + $root = $root . '/'; + + if(file_exists("{$root}view/theme/$theme/$filename")) + $template_file = "{$root}view/theme/$theme/$filename"; + elseif (x($a->theme_info,"extends") && file_exists("{$root}view/theme/{$a->theme_info["extends"]}/$filename")) + $template_file = "{$root}view/theme/{$a->theme_info["extends"]}/$filename"; else - return file_get_contents("view/$s"); + $template_file = "{$root}view/$filename"; + return $template_file; }} -// for html,xml parsing - let's say you've got -// an attribute foobar="class1 class2 class3" -// and you want to find out if it contains 'class3'. -// you can't use a normal sub string search because you -// might match 'notclass3' and a regex to do the job is -// possible but a bit complicated. -// pass the attribute string as $attr and the attribute you -// are looking for as $s - returns true if found, otherwise false + if(! function_exists('attribute_contains')) { +/** + * for html,xml parsing - let's say you've got + * an attribute foobar="class1 class2 class3" + * and you want to find out if it contains 'class3'. + * you can't use a normal sub string search because you + * might match 'notclass3' and a regex to do the job is + * possible but a bit complicated. + * pass the attribute string as $attr and the attribute you + * are looking for as $s - returns true if found, otherwise false + * + * @param string $attr attribute value + * @param string $s string to search + * @return boolean True if found, False otherwise + */ function attribute_contains($attr,$s) { $a = explode(' ', $attr); if(count($a) && in_array($s,$a)) @@ -461,6 +648,19 @@ function attribute_contains($attr,$s) { }} if(! function_exists('logger')) { +/** + * log levels: + * LOGGER_NORMAL (default) + * LOGGER_TRACE + * LOGGER_DEBUG + * LOGGER_DATA + * LOGGER_ALL + * + * @global App $a + * @global dba $db + * @param string $msg + * @param int $level + */ function logger($msg,$level = 0) { // turn off logger in install mode global $a; @@ -474,13 +674,22 @@ function logger($msg,$level = 0) { if((! $debugging) || (! $logfile) || ($level > $loglevel)) return; - + + $stamp1 = microtime(true); @file_put_contents($logfile, datetime_convert() . ':' . session_id() . ' ' . $msg . "\n", FILE_APPEND); + $a->save_timestamp($stamp1, "file"); return; }} if(! function_exists('activity_match')) { +/** + * Compare activity uri. Knows about activity namespace. + * + * @param string $haystack + * @param string $needle + * @return boolean + */ function activity_match($haystack,$needle) { if(($haystack === $needle) || ((basename($needle) === $haystack) && strstr($needle,NAMESPACE_ACTIVITY_SCHEMA))) return true; @@ -488,22 +697,30 @@ function activity_match($haystack,$needle) { }} -// Pull out all #hashtags and @person tags from $s; -// We also get @person@domain.com - which would make -// the regex quite complicated as tags can also -// end a sentence. So we'll run through our results -// and strip the period from any tags which end with one. -// Returns array of tags found, or empty array. - - if(! function_exists('get_tags')) { +/** + * Pull out all #hashtags and @person tags from $s; + * We also get @person@domain.com - which would make + * the regex quite complicated as tags can also + * end a sentence. So we'll run through our results + * and strip the period from any tags which end with one. + * Returns array of tags found, or empty array. + * + * @param string $s + * @return array + */ function get_tags($s) { $ret = array(); // ignore anything in a code block - $s = preg_replace('/\[code\](.*?)\[\/code\]/sm','',$s); + // Force line feeds at bbtags + $s = str_replace(array("[", "]"), array("\n[", "]\n"), $s); + + // ignore anything in a bbtag + $s = preg_replace('/\[(.*?)\]/sm','',$s); + // Match full names against @tags including the space between first and last // We will look these up afterward to see if they are full names or not recognisable. @@ -544,9 +761,15 @@ function get_tags($s) { }} -// quick and dirty quoted_printable encoding +// if(! function_exists('qp')) { +/** + * quick and dirty quoted_printable encoding + * + * @param string $s + * @return string + */ function qp($s) { return str_replace ("%","=",rawurlencode($s)); }} @@ -554,6 +777,10 @@ return str_replace ("%","=",rawurlencode($s)); if(! function_exists('get_mentions')) { +/** + * @param array $item + * @return string html for mentions #FIXME: remove html + */ function get_mentions($item) { $o = ''; if(! strlen($item['tag'])) @@ -571,6 +798,13 @@ function get_mentions($item) { }} if(! function_exists('contact_block')) { +/** + * Get html for contact block. + * + * @template contact_block.tpl + * @hook contact_block_end (contacts=>array, output=>string) + * @return string + */ function contact_block() { $o = ''; $a = get_app(); @@ -623,6 +857,14 @@ function contact_block() { }} if(! function_exists('micropro')) { +/** + * + * @param array $contact + * @param boolean $redirect + * @param string $class + * @param boolean $textmode + * @return string #FIXME: remove html + */ function micropro($contact, $redirect = false, $class = '', $textmode = false) { if($class) @@ -667,6 +909,15 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) { if(! function_exists('search')) { +/** + * search box + * + * @param string $s search query + * @param string $id html id + * @param string $url search url + * @param boolean $save show save search button + * @return string html for search box #FIXME: remove html + */ function search($s,$id='search-box',$url='/search',$save = false) { $a = get_app(); $o = '
'; @@ -680,6 +931,12 @@ function search($s,$id='search-box',$url='/search',$save = false) { }} if(! function_exists('valid_email')) { +/** + * Check if $x is a valid email string + * + * @param string $x + * @return boolean + */ function valid_email($x){ if(get_config('system','disable_email_validation')) @@ -691,15 +948,12 @@ function valid_email($x){ }} +if(! function_exists('linkify')) { /** - * - * Function: linkify - * * Replace naked text hyperlink with HTML formatted hyperlink * + * @param string $s */ - -if(! function_exists('linkify')) { function linkify($s) { $s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\'\%\$\!\+]*)/", ' $1', $s); $s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s); @@ -708,16 +962,69 @@ function linkify($s) { /** - * - * Function: smilies + * Load poke verbs * - * Description: + * @return array index is present tense verb + value is array containing past tense verb, translation of present, translation of past + * @hook poke_verbs pokes array + */ +function get_poke_verbs() { + + // index is present tense verb + // value is array containing past tense verb, translation of present, translation of past + + $arr = array( + 'poke' => array( 'poked', t('poke'), t('poked')), + 'ping' => array( 'pinged', t('ping'), t('pinged')), + 'prod' => array( 'prodded', t('prod'), t('prodded')), + 'slap' => array( 'slapped', t('slap'), t('slapped')), + 'finger' => array( 'fingered', t('finger'), t('fingered')), + 'rebuff' => array( 'rebuffed', t('rebuff'), t('rebuffed')), + ); + call_hooks('poke_verbs', $arr); + return $arr; +} + +/** + * Load moods + * @return array index is mood, value is translated mood + * @hook mood_verbs moods array + */ +function get_mood_verbs() { + + $arr = array( + 'happy' => t('happy'), + 'sad' => t('sad'), + 'mellow' => t('mellow'), + 'tired' => t('tired'), + 'perky' => t('perky'), + 'angry' => t('angry'), + 'stupefied' => t('stupified'), + 'puzzled' => t('puzzled'), + 'interested' => t('interested'), + 'bitter' => t('bitter'), + 'cheerful' => t('cheerful'), + 'alive' => t('alive'), + 'annoyed' => t('annoyed'), + 'anxious' => t('anxious'), + 'cranky' => t('cranky'), + 'disturbed' => t('disturbed'), + 'frustrated' => t('frustrated'), + 'motivated' => t('motivated'), + 'relaxed' => t('relaxed'), + 'surprised' => t('surprised'), + ); + + call_hooks('mood_verbs', $arr); + return $arr; +} + + + +if(! function_exists('smilies')) { +/** * Replaces text emoticons with graphical images * - * @Parameter: string $s - * - * Returns string - * * It is expected that this function will be called using HTML text. * We will escape text between HTML pre and code blocks from being * processed. @@ -726,11 +1033,12 @@ function linkify($s) { * function from being executed by the prepare_text() routine when preparing * bbcode source for HTML display * + * @param string $s + * @param boolean $sample + * @return string + * @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array, 'string' => $s) */ - -if(! function_exists('smilies')) { function smilies($s, $sample = false) { - $a = get_app(); if(intval(get_config('system','no_smilies')) @@ -773,7 +1081,6 @@ function smilies($s, $sample = false) { ':facepalm', ':like', ':dislike', - '~friendika', '~friendica' ); @@ -811,7 +1118,6 @@ function smilies($s, $sample = false) { ':facepalm', ':like', ':dislike', - '~friendika ~friendika', '~friendica ~friendica' ); @@ -844,8 +1150,13 @@ function smile_decode($m) { return(str_replace($m[1],base64url_decode($m[1]),$m[0])); } -// expand <3333 to the correct number of hearts +/** + * expand <3333 to the correct number of hearts + * + * @param string $x + * @return string + */ function preg_heart($x) { $a = get_app(); if(strlen($x[1]) == 1) @@ -859,6 +1170,12 @@ function preg_heart($x) { if(! function_exists('day_translate')) { +/** + * Translate days and months names + * + * @param string $s + * @return string + */ function day_translate($s) { $ret = str_replace(array('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'), array( t('Monday'), t('Tuesday'), t('Wednesday'), t('Thursday'), t('Friday'), t('Saturday'), t('Sunday')), @@ -873,52 +1190,108 @@ function day_translate($s) { if(! function_exists('normalise_link')) { +/** + * Normalize url + * + * @param string $url + * @return string + */ function normalise_link($url) { $ret = str_replace(array('https:','//www.'), array('http:','//'), $url); return(rtrim($ret,'/')); }} + + +if(! function_exists('link_compare')) { /** - * * Compare two URLs to see if they are the same, but ignore * slight but hopefully insignificant differences such as if one * is https and the other isn't, or if one is www.something and * the other isn't - and also ignore case differences. * - * Return true if the URLs match, otherwise false. + * @param string $a first url + * @param string $b second url + * @return boolean True if the URLs match, otherwise False * - */ - -if(! function_exists('link_compare')) { + */ function link_compare($a,$b) { if(strcasecmp(normalise_link($a),normalise_link($b)) === 0) return true; return false; }} + +if(! function_exists('redir_private_images')) { +/** + * Find any non-embedded images in private items and add redir links to them + * + * @param App $a + * @param array $item + */ +function redir_private_images($a, &$item) { + + $matches = false; + $cnt = preg_match_all('|\[img\](http[^\[]*?/photo/[a-fA-F0-9]+?(-[0-9]\.[\w]+?)?)\[\/img\]|', $item['body'], $matches, PREG_SET_ORDER); + if($cnt) { + //logger("redir_private_images: matches = " . print_r($matches, true)); + foreach($matches as $mtch) { + if(strpos($mtch[1], '/redir') !== false) + continue; + + if((local_user() == $item['uid']) && ($item['private'] != 0) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN)) { + //logger("redir_private_images: redir"); + $img_url = $a->get_baseurl() . '/redir?f=1&quiet=1&url=' . $mtch[1] . '&conurl=' . $item['author-link']; + $item['body'] = str_replace($mtch[0], "[img]".$img_url."[/img]", $item['body']); + } + } + } + +}} + + // Given an item array, convert the body element from bbcode to html and add smilie icons. // If attach is true, also add icons for item attachments - if(! function_exists('prepare_body')) { +/** + * Given an item array, convert the body element from bbcode to html and add smilie icons. + * If attach is true, also add icons for item attachments + * + * @param array $item + * @param boolean $attach + * @return string item body html + * @hook prepare_body_init item array before any work + * @hook prepare_body ('item'=>item array, 'html'=>body string) after first bbcode to html + * @hook prepare_body_final ('item'=>item array, 'html'=>body string) after attach icons and blockquote special case handling (spoiler, author) + */ function prepare_body($item,$attach = false) { $a = get_app(); - call_hooks('prepare_body_init', $item); + call_hooks('prepare_body_init', $item); - $cache = get_config('system','itemcache'); + //$cachefile = get_cachefile($item["guid"]."-".strtotime($item["edited"])."-".hash("crc32", $item['body'])); + $cachefile = get_cachefile($item["guid"]."-".hash("md5", $item['body'])); - if (($cache != '')) { - $cachefile = $cache."/".$item["guid"]."-".strtotime($item["edited"])."-".hash("crc32", $item['body']); - - if (file_exists($cachefile)) + if (($cachefile != '')) { + if (file_exists($cachefile)) { + $stamp1 = microtime(true); $s = file_get_contents($cachefile); - else { + $a->save_timestamp($stamp1, "file"); + } else { + redir_private_images($a, $item); $s = prepare_text($item['body']); + + $stamp1 = microtime(true); file_put_contents($cachefile, $s); + $a->save_timestamp($stamp1, "file"); + + logger('prepare_body: put item '.$item["id"].' into cachefile '.$cachefile); } - } else + } else { + redir_private_images($a, $item); $s = prepare_text($item['body']); + } $prep_arr = array('item' => $item, 'html' => $s); @@ -926,19 +1299,33 @@ function prepare_body($item,$attach = false) { $s = $prep_arr['html']; if(! $attach) { + // Replace the blockquotes with quotes that are used in mails + $mailquote = '
'; + $s = str_replace(array('
', '
', '
'), array($mailquote, $mailquote, $mailquote), $s); return $s; } - $arr = explode(',',$item['attach']); + $arr = explode('[/attach],',$item['attach']); if(count($arr)) { $s .= '
'; foreach($arr as $r) { $matches = false; $icon = ''; - $cnt = preg_match_all('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"\[\/attach\]|',$r,$matches, PREG_SET_ORDER); + $cnt = preg_match_all('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { - $icontype = strtolower(substr($mtch[3],0,strpos($mtch[3],'/'))); + $filetype = strtolower(substr( $mtch[3], 0, strpos($mtch[3],'/') )); + if($filetype) { + $filesubtype = strtolower(substr( $mtch[3], strpos($mtch[3],'/') + 1 )); + $filesubtype = str_replace('.', '-', $filesubtype); + } + else { + $filetype = 'unkn'; + $filesubtype = 'unkn'; + } + + $icon = '
'; + /*$icontype = strtolower(substr($mtch[3],0,strpos($mtch[3],'/'))); switch($icontype) { case 'video': case 'audio': @@ -949,10 +1336,11 @@ function prepare_body($item,$attach = false) { default: $icon = '
'; break; - } + }*/ + $title = ((strlen(trim($mtch[4]))) ? escape_tags(trim($mtch[4])) : escape_tags($mtch[1])); $title .= ' ' . $mtch[2] . ' ' . t('bytes'); - if((local_user() == $item['uid']) && $item['contact-id'] != $a->contact['id']) + if((local_user() == $item['uid']) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN)) $the_url = $a->get_baseurl() . '/redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1]; else $the_url = $mtch[1]; @@ -963,35 +1351,8 @@ function prepare_body($item,$attach = false) { } $s .= '
'; } - $matches = false; - $cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER); - if($cnt) { -// logger('prepare_text: categories: ' . print_r($matches,true), LOGGER_DEBUG); - foreach($matches as $mtch) { - if(strlen($x)) - $x .= ','; - $x .= xmlify(file_tag_decode($mtch[1])) - . ((local_user() == $item['uid']) ? ' ' . t('[remove]') . '' : ''); - } - if(strlen($x)) - $s .= '
' . t('Categories:') . ' ' . $x . '
'; - } - $matches = false; - $x = ''; - $cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER); - if($cnt) { -// logger('prepare_text: filed_under: ' . print_r($matches,true), LOGGER_DEBUG); - foreach($matches as $mtch) { - if(strlen($x)) - $x .= '   '; - $x .= xmlify(file_tag_decode($mtch[1])) . ' ' . t('[remove]') . ''; - } - if(strlen($x) && (local_user() == $item['uid'])) - $s .= '
' . t('Filed under:') . ' ' . $x . '
'; - } - // Look for spoiler $spoilersearch = '
'; @@ -1029,9 +1390,13 @@ function prepare_body($item,$attach = false) { }} -// Given a text string, convert from bbcode to html and add smilie icons. - if(! function_exists('prepare_text')) { +/** + * Given a text string, convert from bbcode to html and add smilie icons. + * + * @param string $text + * @return string + */ function prepare_text($text) { require_once('include/bbcode.php'); @@ -1045,11 +1410,86 @@ function prepare_text($text) { }} + /** - * return atom link elements for all of our hubs + * return array with details for categories and folders for an item + * + * @param array $item + * @return array + * + * [ + * [ // categories array + * { + * 'name': 'category name', + * 'removeurl': 'url to remove this category', + * 'first': 'is the first in this array? true/false', + * 'last': 'is the last in this array? true/false', + * } , + * .... + * ], + * [ //folders array + * { + * 'name': 'folder name', + * 'removeurl': 'url to remove this folder', + * 'first': 'is the first in this array? true/false', + * 'last': 'is the last in this array? true/false', + * } , + * .... + * ] + * ] */ +function get_cats_and_terms($item) { + + $a = get_app(); + $categories = array(); + $folders = array(); + + $matches = false; $first = true; + $cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $categories[] = array( + 'name' => xmlify(file_tag_decode($mtch[1])), + 'url' => "#", + 'removeurl' => ((local_user() == $item['uid'])?$a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])):""), + 'first' => $first, + 'last' => false + ); + $first = false; + } + } + if (count($categories)) $categories[count($categories)-1]['last'] = true; + + + if(local_user() == $item['uid']) { + $matches = false; $first = true; + $cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $folders[] = array( + 'name' => xmlify(file_tag_decode($mtch[1])), + 'url' => "#", + 'removeurl' => ((local_user() == $item['uid'])?$a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])):""), + 'first' => $first, + 'last' => false + ); + $first = false; + } + } + } + + if (count($folders)) $folders[count($folders)-1]['last'] = true; + + return array($categories, $folders); +} + + if(! function_exists('feed_hublinks')) { +/** + * return atom link elements for all of our hubs + * @return string hub link xml elements + */ function feed_hublinks() { $hub = get_config('system','huburl'); @@ -1069,9 +1509,13 @@ function feed_hublinks() { return $hubxml; }} -/* return atom link elements for salmon endpoints */ if(! function_exists('feed_salmonlinks')) { +/** + * return atom link elements for salmon endpoints + * @param string $nick user nickname + * @return string salmon link xml elements + */ function feed_salmonlinks($nick) { $a = get_app(); @@ -1086,6 +1530,11 @@ function feed_salmonlinks($nick) { }} if(! function_exists('get_plink')) { +/** + * get private link for item + * @param array $item + * @return boolean|array False if item has not plink, otherwise array('href'=>plink url, 'title'=>translated title) + */ function get_plink($item) { $a = get_app(); if (x($item,'plink') && ($item['private'] != 1)) { @@ -1100,6 +1549,11 @@ function get_plink($item) { }} if(! function_exists('unamp')) { +/** + * replace html amp entity with amp char + * @param string $s + * @return string + */ function unamp($s) { return str_replace('&', '&', $s); }} @@ -1108,6 +1562,12 @@ function unamp($s) { if(! function_exists('lang_selector')) { +/** + * get html for language selector + * @global string $lang + * @return string + * @template lang_selector.tpl + */ function lang_selector() { global $lang; @@ -1144,6 +1604,11 @@ function lang_selector() { if(! function_exists('return_bytes')) { +/** + * return number of bytes in size (K, M, G) + * @param string $size_str + * @return number + */ function return_bytes ($size_str) { switch (substr ($size_str, -1)) { @@ -1154,6 +1619,9 @@ function return_bytes ($size_str) { } }} +/** + * @return string + */ function generate_user_guid() { $found = true; do { @@ -1168,7 +1636,11 @@ function generate_user_guid() { } - +/** + * @param string $s + * @param boolean $strip_padding + * @return string + */ function base64url_encode($s, $strip_padding = false) { $s = strtr(base64_encode($s),'+/','-_'); @@ -1179,6 +1651,10 @@ function base64url_encode($s, $strip_padding = false) { return $s; } +/** + * @param string $s + * @return string + */ function base64url_decode($s) { if(is_array($s)) { @@ -1207,6 +1683,16 @@ function base64url_decode($s) { if (!function_exists('str_getcsv')) { + /** + * Parse csv string + * + * @param string $input + * @param string $delimiter + * @param string $enclosure + * @param string $escape + * @param string $eol + * @return boolean|array False on error, otherwise array[row][column] + */ function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = '\\', $eol = '\n') { if (is_string($input) && !empty($input)) { $output = array(); @@ -1263,6 +1749,11 @@ if (!function_exists('str_getcsv')) { } } +/** + * return div element with class 'clear' + * @return string + * @deprecated + */ function cleardiv() { return '
'; } @@ -1299,6 +1790,8 @@ function html2bb_video($s) { /** * apply xmlify() to all values of array $val, recursively + * @param array $val + * @return array */ function array_xmlify($val){ if (is_bool($val)) return $val?"true":"false"; @@ -1307,6 +1800,13 @@ function array_xmlify($val){ } +/** + * transorm link href and img src from relative to absolute + * + * @param string $text + * @param string $base base url + * @return string + */ function reltoabs($text, $base) { if (empty($base)) @@ -1339,6 +1839,12 @@ function reltoabs($text, $base) return $text; } +/** + * get translated item type + * + * @param array $itme + * @return string + */ function item_post_type($item) { if(intval($item['event-id'])) return t('event'); @@ -1562,7 +2068,7 @@ function undo_post_tagging($s) { function fix_mce_lf($s) { $s = str_replace("\r\n","\n",$s); - $s = str_replace("\n\n","\n",$s); +// $s = str_replace("\n\n","\n",$s); return $s; }