diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ItemObject.php | 10 | ||||
-rw-r--r-- | include/attach.php | 1 | ||||
-rw-r--r-- | include/bbcode.php | 55 | ||||
-rw-r--r-- | include/bookmarks.php | 55 | ||||
-rw-r--r-- | include/chat.php | 8 | ||||
-rw-r--r-- | include/config.php | 8 | ||||
-rw-r--r-- | include/conversation.php | 8 | ||||
-rwxr-xr-x | include/items.php | 25 | ||||
-rw-r--r-- | include/menu.php | 39 | ||||
-rw-r--r-- | include/permissions.php | 3 | ||||
-rw-r--r-- | include/spam.php | 35 | ||||
-rwxr-xr-x | include/text.php | 80 |
12 files changed, 251 insertions, 76 deletions
diff --git a/include/ItemObject.php b/include/ItemObject.php index e9a0b65c0..9b1a6fbcd 100644 --- a/include/ItemObject.php +++ b/include/ItemObject.php @@ -171,6 +171,15 @@ class Item extends BaseObject { ); } + $has_bookmarks = false; + if(is_array($item['term'])) { + foreach($item['term'] as $t) { + if($t['type'] == TERM_BOOKMARK) + $has_bookmarks = true; + } + } + + if($this->is_commentable()) { $like = array( t("I like this \x28toggle\x29"), t("like")); $dislike = array( t("I don't like this \x28toggle\x29"), t("dislike")); @@ -237,6 +246,7 @@ class Item extends BaseObject { 'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''), 'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''), 'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''), + 'bookmark' => (($conv->get_profile_owner() == local_user() && $has_bookmarks) ? t('Bookmark Links') : ''), 'drop' => $drop, 'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''), // end toolbar buttons diff --git a/include/attach.php b/include/attach.php index dbc489a2d..af1159957 100644 --- a/include/attach.php +++ b/include/attach.php @@ -26,6 +26,7 @@ function z_mime_content_type($filename) { 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', + 'epub' => 'application/epub+zip', // images 'png' => 'image/png', diff --git a/include/bbcode.php b/include/bbcode.php index 2e2faddd6..bd2c7d11a 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -262,6 +262,56 @@ function rpost_callback($match) { } } +function bb_sanitize_style($input) { + //whitelist property limits (0 = no limitation) + $w = array( // color properties + "color" => 0, + "background-color" => 0, + // box properties + "padding" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "margin" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "border" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "float" => 0, + "clear" => 0, + // text properties + "text-decoration" => 0, + + ); + + $css_string = $input[1]; + $a = explode(';',$css_string); + foreach($a as $parts){ + list($k, $v) = explode(':', $parts); + $css[ trim($k) ] = trim($v); + } + + // sanitize properties + $b = array_merge(array_diff_key($css, $w), array_diff_key($w, $css)); + $css = array_diff_key($css, $b); + + foreach($css as $key => $value) { + if($w[$key] != null) { + foreach($w[$key] as $limit_key => $limit_value) { + //sanitize values + if(strpos($value, $limit_key)) { + $value = preg_replace_callback( + "/(\S.*?)$limit_key/ism", + function($match) use($limit_value, $limit_key) { + if($match[1] > $limit_value) { + return $limit_value . $limit_key; + } else { + return $match[1] . $limit_key; + } + }, + $value + ); + } + } + } + $css_string_san .= $key . ":" . $value ."; "; + } + return "<span style=\"" . $css_string_san . "\">" . $input[2] . "</span>"; +} // BBcode 2 HTML was written by WAY2WEB.net // extended to work with Mistpark/Friendica/Red - Mike Macgirvin @@ -576,6 +626,11 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*) float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px; float: right;" alt="' . t('Image/photo') . '" >', $Text); } + // style (sanitized) + if (strpos($Text,'[/style]') !== false) { + $Text = preg_replace_callback("(\[style=(.*?)\](.*?)\[\/style\])ism", "bb_sanitize_style", $Text); + } + // crypt if (strpos($Text,'[/crypt]') !== false) { $x = random_string(); diff --git a/include/bookmarks.php b/include/bookmarks.php new file mode 100644 index 000000000..99cb60e64 --- /dev/null +++ b/include/bookmarks.php @@ -0,0 +1,55 @@ +<?php /** @file */ + +require_once('include/menu.php'); + +function bookmark_add($channel,$sender,$taxonomy,$private) { + + $iarr = array(); + $channel_id = $channel['channel_id']; + + if($private) + $iarr['contact_allow'] = array($channel['channel_hash']); + $iarr['mitem_link'] = $taxonomy['url']; + $iarr['mitem_desc'] = $taxonomy['term']; + $iarr['mitem_flags'] = 0; + + $m = @parse_url($taxonomy['url']); + $zrl = false; + if($m['host']) { + $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1", + dbesc($m['host']) + ); + if($r) + $zrl = true; + } + + if($zrl) + $iarr['mitem_flags'] |= MENU_ITEM_ZID; + + $arr = array(); + $arr['menu_name'] = substr($sender['xchan_hash'],0,16) . ' ' . $sender['xchan_name']; + $arr['menu_desc'] = sprintf( t('%1$s\'s bookmarks'), $sender['xchan_name']); + $arr['menu_flags'] = (($sender['xchan_hash'] === $channel['channel_hash']) ? MENU_BOOKMARK : MENU_SYSTEM|MENU_BOOKMARK); + $arr['menu_channel_id'] = $channel_id; + + $x = menu_list($arr['menu_channel_id'],$arr['menu_name'],$arr['menu_flags']); + if($x) + $menu_id = $x[0]['menu_id']; + else + $menu_id = menu_create($arr); + if(! $menu_id) { + logger('bookmark_add: unable to create menu ' . $arr['menu_name']); + return; + } + logger('add_bookmark: menu_id ' . $menu_id); + $r = q("select * from menu_item where mitem_link = '%s' and mitem_menu_id = %d and mitem_channel_id = %d limit 1", + dbesc($iarr['mitem_link']), + intval($menu_id), + intval($channel_id) + ); + if($r) + logger('add_bookmark: duplicate menu entry', LOGGER_DEBUG); + if(! $r) + $r = menu_add_item($menu_id,$channel_id,$iarr); + return $r; +}
\ No newline at end of file diff --git a/include/chat.php b/include/chat.php index 08fd154b5..5af3a3a9a 100644 --- a/include/chat.php +++ b/include/chat.php @@ -122,10 +122,10 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) { intval($room_id) ); if($r) { - q("update chatpresence set cp_status = %d and cp_last = '%s' where cp_id = %d limit 1", - dbesc($status), + q("update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s' limit 1", dbesc(datetime_convert()), - intval($r[0]['cp_id']) + intval($r[0]['cp_id']), + dbesc($client) ); return true; } @@ -145,6 +145,7 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) { function chatroom_leave($observer_xchan,$room_id,$client) { if(! $room_id || ! $observer_xchan) return; + $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1", dbesc($observer_xchan), intval($room_id), @@ -155,6 +156,7 @@ function chatroom_leave($observer_xchan,$room_id,$client) { intval($r[0]['cp_id']) ); } + return true; } diff --git a/include/config.php b/include/config.php index bccf0737f..8d98d56fa 100644 --- a/include/config.php +++ b/include/config.php @@ -65,7 +65,7 @@ function get_config($family, $key) { if(! array_key_exists($key,$a->config[$family])) { return false; } - return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$family][$key])) + return ((! is_array($a->config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$family][$key])) ? unserialize($a->config[$family][$key]) : $a->config[$family][$key] ); @@ -174,8 +174,8 @@ function get_pconfig($uid,$family, $key, $instore = false) { if((! array_key_exists($family,$a->config[$uid])) || (! array_key_exists($key,$a->config[$uid][$family]))) return false; - - return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$uid][$family][$key])) + + return ((! is_array($a->config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$uid][$family][$key])) ? unserialize($a->config[$uid][$family][$key]) : $a->config[$uid][$family][$key] ); @@ -304,7 +304,7 @@ function get_xconfig($xchan,$family, $key) { if((! array_key_exists($family,$a->config[$xchan])) || (! array_key_exists($key,$a->config[$xchan][$family]))) return false; - return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$xchan][$family][$key])) + return ((! is_array($a->config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$xchan][$family][$key])) ? unserialize($a->config[$xchan][$family][$key]) : $a->config[$xchan][$family][$key] ); diff --git a/include/conversation.php b/include/conversation.php index 316bc1612..633435871 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1496,6 +1496,14 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){ 'title' => t('Events and Calendar'), 'id' => 'events-tab', ); + + $tabs[] = array( + 'label' => t('Bookmarks'), + 'url' => $a->get_baseurl() . '/bookmarks', + 'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''), + 'title' => t('Saved Bookmarks'), + 'id' => 'bookmarks-tab', + ); } if($is_owner && feature_enabled($a->profile['profile_uid'],'webpages')) { diff --git a/include/items.php b/include/items.php index a74c3d460..860d714d1 100755 --- a/include/items.php +++ b/include/items.php @@ -822,7 +822,7 @@ function encode_item_xchan($xchan) { function encode_item_terms($terms) { $ret = array(); - $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY ); + $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK ); if($terms) { foreach($terms as $term) { @@ -834,7 +834,7 @@ function encode_item_terms($terms) { } function termtype($t) { - $types = array('unknown','hashtag','mention','category','private_category','file','search'); + $types = array('unknown','hashtag','mention','category','private_category','file','search','thing','bookmark'); return(($types[$t]) ? $types[$t] : 'unknown'); } @@ -865,6 +865,12 @@ function decode_tags($t) { case 'search': $tag['type'] = TERM_SEARCH; break; + case 'thing': + $tag['type'] = TERM_THING; + break; + case 'bookmark': + $tag['type'] = TERM_BOOKMARK; + break; default: case 'unknown': $tag['type'] = TERM_UNKNOWN; @@ -2163,6 +2169,21 @@ function tag_deliver($uid,$item_id) { $item = $i[0]; + + $terms = get_terms_oftype($item['term'],TERM_BOOKMARK); + + if($terms && (! $i[0]['item_restrict'])) { + logger('tag_deliver: found bookmark'); + if(perm_is_allowed($u[0]['channel_id'],$i[0]['author_xchan'],'bookmark') && ($i[0]['author_xchan'] != $u[0]['channel_hash'])) { + require_once('include/bookmarks.php'); + require_once('include/Contact.php'); + $s = channelx_by_hash($i[0]['author_xchan']); + foreach($terms as $t) { + bookmark_add($u[0],$s[0],$t,$i[0]['item_private']); + } + } + } + if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) { // this is an update to a post which was already processed by us and has a second delivery chain // Just start the second delivery chain to deliver the updated post diff --git a/include/menu.php b/include/menu.php index d69c5d0d3..105e4216b 100644 --- a/include/menu.php +++ b/include/menu.php @@ -26,11 +26,12 @@ function menu_fetch($name,$uid,$observer_xchan) { function menu_render($menu) { if(! $menu) return ''; + for($x = 0; $x < count($menu['items']); $x ++) - if($menu['items']['mitem_flags'] & MENU_ITEM_ZID) - $menu['items']['mitem_link'] = zid($menu['items']['mitem_link']); - if($menu['items']['mitem_flags'] & MENU_ITEM_NEWWIN) - $menu['items']['newwin'] = '1'; + if($menu['items'][$x]['mitem_flags'] & MENU_ITEM_ZID) + $menu['items'][$x]['mitem_link'] = zid($menu['items'][$x]['mitem_link']); + if($menu['items'][$x]['mitem_flags'] & MENU_ITEM_NEWWIN) + $menu['items'][$x]['newwin'] = '1'; return replace_macros(get_markup_template('usermenu.tpl'),array( '$menu' => $menu['menu'], @@ -74,8 +75,7 @@ function menu_create($arr) { $r = q("select * from menu where menu_name = '%s' and menu_channel_id = %d limit 1", dbesc($menu_name), - intval($menu_channel_id), - intval($menu_flags) + intval($menu_channel_id) ); if($r) @@ -101,9 +101,17 @@ function menu_create($arr) { } -function menu_list($channel_id, $flags = 0) { +/** + * If $flags is present, check that all the bits in $flags are set + * so that MENU_SYSTEM|MENU_BOOKMARK will return entries with both + * bits set. We will use this to find system generated bookmarks. + */ + +function menu_list($channel_id, $name = '', $flags = 0) { - $sel_options = (($flags) ? " and ( menu_flags & " . intval($flags) . " ) " : ''); + $sel_options = ''; + $sel_options .= (($name) ? " and menu_name = '" . protect_sprintf(dbesc($name)) . "' " : ''); + $sel_options .= (($flags) ? " and menu_flags = " . intval($flags) . " " : ''); $r = q("select * from menu where menu_channel_id = %d $sel_options order by menu_name", intval($channel_id) @@ -152,7 +160,7 @@ function menu_edit($arr) { return false; } - return q("update menu set menu_name = '%s', menu_desc = '%s', menu_flags = %d, + return q("update menu set menu_name = '%s', menu_desc = '%s', menu_flags = %d where menu_id = %d and menu_channel_id = %d limit 1", dbesc($menu_name), dbesc($menu_desc), @@ -204,7 +212,8 @@ function menu_add_item($menu_id, $uid, $arr) { $channel = get_app()->get_channel(); } - if ((! $arr['contact_allow']) + if (($channel) + && (! $arr['contact_allow']) && (! $arr['group_allow']) && (! $arr['contact_deny']) && (! $arr['group_deny'])) { @@ -223,11 +232,11 @@ function menu_add_item($menu_id, $uid, $arr) { $str_contact_deny = perms2str($arr['contact_deny']); } - - $allow_cid = perms2str($arr['allow_cid']); - $allow_gid = perms2str($arr['allow_gid']); - $deny_cid = perms2str($arr['deny_cid']); - $deny_gid = perms2str($arr['deny_gid']); +// unused +// $allow_cid = perms2str($arr['allow_cid']); +// $allow_gid = perms2str($arr['allow_gid']); +// $deny_cid = perms2str($arr['deny_cid']); +// $deny_gid = perms2str($arr['deny_gid']); $r = q("insert into menu_item ( mitem_link, mitem_desc, mitem_flags, allow_cid, allow_gid, deny_cid, deny_gid, mitem_channel_id, mitem_menu_id, mitem_order ) values ( '%s', '%s', %d, '%s', '%s', '%s', '%s', %d, %d, %d ) ", dbesc($mitem_link), diff --git a/include/permissions.php b/include/permissions.php index 45ea7c3eb..420591c54 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -24,11 +24,12 @@ function get_perms() { 'post_mail' => array('channel_w_mail', intval(PERMS_W_MAIL), false, t('Can send me private mail messages'), ''), 'post_photos' => array('channel_w_photos', intval(PERMS_W_PHOTOS), false, t('Can post photos to my photo albums'), ''), 'tag_deliver' => array('channel_w_tagwall', intval(PERMS_W_TAGWALL), false, t('Can forward to all my channel contacts via post @mentions'), t('Advanced - useful for creating group forum channels')), - 'chat' => array('channel_w_chat', intval(PERMS_W_CHAT), false, t('Can chat with me (when available)'), t('Requires compatible chat plugin')), + 'chat' => array('channel_w_chat', intval(PERMS_W_CHAT), false, t('Can chat with me (when available)'), t('')), 'write_storage' => array('channel_w_storage', intval(PERMS_W_STORAGE), false, t('Can write to my "public" file storage'), ''), 'write_pages' => array('channel_w_pages', intval(PERMS_W_PAGES), false, t('Can edit my "public" pages'), ''), 'republish' => array('channel_a_republish', intval(PERMS_A_REPUBLISH), false, t('Can source my "public" posts in derived channels'), t('Somewhat advanced - very useful in open communities')), + 'bookmark' => array('channel_a_bookmark', intval(PERMS_A_BOOKMARK), false, t('Can send me bookmarks'), 'Bookmarks from this person will automatically be saved'), 'delegate' => array('channel_a_delegate', intval(PERMS_A_DELEGATE), false, t('Can administer my channel resources'), t('Extremely advanced. Leave this alone unless you know what you are doing')), ); $ret = array('global_permissions' => $global_perms); diff --git a/include/spam.php b/include/spam.php new file mode 100644 index 000000000..8b158b7ae --- /dev/null +++ b/include/spam.php @@ -0,0 +1,35 @@ +<?php /** @file */ + + +function string_splitter($s) { + + if(! $s) + return array(); + + $s = preg_replace('/\pP+/','',$s); + + $x = mb_split("\[|\]|\s",$s); + + $ret = array(); + if($x) { + foreach($x as $y) { + if(mb_strlen($y) > 2) + $ret[] = substr($y,0,64); + } + } + return $ret; +} + + + +function get_words($uid,$list) { + + stringify($list,true); + + $r = q("select * from spam where term in ( " . $list . ") and uid = %d", + intval($uid) + ); + + return $r; +} + diff --git a/include/text.php b/include/text.php index cf68ee121..2b334068f 100755 --- a/include/text.php +++ b/include/text.php @@ -442,7 +442,7 @@ function item_message_id() { $mid = $hash . '@' . get_app()->get_hostname(); - $r = q("SELECT `id` FROM `item` WHERE `mid` = '%s' LIMIT 1", + $r = q("SELECT id FROM item WHERE mid = '%s' LIMIT 1", dbesc($mid)); if(count($r)) $dups = true; @@ -459,7 +459,7 @@ function photo_new_resource() { do { $found = false; $resource = hash('md5',uniqid(mt_rand(),true)); - $r = q("SELECT `id` FROM `photo` WHERE `resource_id` = '%s' LIMIT 1", + $r = q("SELECT id FROM photo WHERE resource_id = '%s' LIMIT 1", dbesc($resource) ); if(count($r)) @@ -565,6 +565,10 @@ function get_tags($s) { $s = preg_replace('/\[code\](.*?)\[\/code\]/sm','',$s); + // ignore anything in [style= ] + + $s = preg_replace('/\[style=(.*?)\]/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. @@ -593,7 +597,7 @@ function get_tags($s) { if(substr($mtch,-1,1) === '.') $mtch = substr($mtch,0,-1); // ignore strictly numeric tags like #1 - if((strpos($mtch,'#') === 0) && ctype_digit(substr($mtch,1))) + if((strpos($mtch,'#') === 0) && ( ctype_digit(substr($mtch,1)) || substr($mtch,1,1) === '^')) continue; // try not to catch url fragments if(strpos($s,$mtch) && preg_match('/[a-zA-z0-9\/]/',substr($s,strpos($s,$mtch)-1,1))) @@ -601,6 +605,18 @@ function get_tags($s) { $ret[] = $mtch; } } + + // bookmarks + + if(preg_match_all('/#\^\[(url|zrl)(.*?)\](.*?)\[\/(url|zrl)\]/',$s,$match,PREG_SET_ORDER)) { + foreach($match as $mtch) { + $ret[] = $mtch[0]; + } + } + + + // logger('get_tags: ' . print_r($ret,true)); + return $ret; } @@ -889,8 +905,8 @@ function smilies($s, $sample = false) { || (local_user() && intval(get_pconfig(local_user(),'system','no_smilies')))) return $s; - $s = preg_replace_callback('{<(pre|code)>(?<target>.*?)</\1>}ism','smile_encode',$s); - $s = preg_replace_callback('/<[a-z]+ (?<target>.*?)>/ism','smile_encode',$s); + $s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism','smile_shield',$s); + $s = preg_replace_callback('/<[a-z]+ .*?>/ism','smile_shield',$s); $texts = array( '<3', @@ -981,20 +997,18 @@ function smilies($s, $sample = false) { $s = str_replace($params['texts'],$params['icons'],$params['string']); } - $s = preg_replace_callback( - '/<!--base64:(.*?)-->/ism', - function ($m) { return base64url_decode($m[1]); }, - $s - ); + $s = preg_replace_callback('/<!--base64:(.*?)-->/ism', 'smile_unshield', $s); return $s; } +function smile_shield($m) { + return '<!--base64:' . base64url_encode($m[0]) . '-->'; +} -function smile_encode($m) { - $cleartext = $m['target']; - return str_replace($cleartext,'<!--base64:' . base64url_encode($cleartext) . '-->',$m[0]); +function smile_unshield($m) { + return base64url_decode($m[1]); } // expand <3333 to the correct number of hearts @@ -1518,20 +1532,6 @@ function return_bytes ($size_str) { } } -function generate_user_guid() { - $found = true; - do { - $guid = random_string(16); - $x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1", - dbesc($guid) - ); - if(! count($x)) - $found = false; - } while ($found == true ); - return $guid; -} - - function base64url_encode($s, $strip_padding = true) { @@ -1549,23 +1549,6 @@ function base64url_decode($s) { logger('base64url_decode: illegal input: ' . print_r(debug_backtrace(), true)); return $s; } - -/* - * // Placeholder for new rev of salmon which strips base64 padding. - * // PHP base64_decode handles the un-padded input without requiring this step - * // Uncomment if you find you need it. - * - * $l = strlen($s); - * if(! strpos($s,'=')) { - * $m = $l % 4; - * if($m == 2) - * $s .= '=='; - * if($m == 3) - * $s .= '='; - * } - * - */ - return base64_decode(strtr($s,'-_','+/')); } @@ -1670,17 +1653,12 @@ function item_post_type($item) { } -function normalise_openid($s) { - return trim(str_replace(array('http://','https://'),array('',''),$s),'/'); -} - - function undo_post_tagging($s) { $matches = null; - $cnt = preg_match_all('/([@#])\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$s,$matches,PREG_SET_ORDER); + $cnt = preg_match_all('/([@#])(\!*)\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$s,$matches,PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { - $s = str_replace($mtch[0], $mtch[1] . $mtch[3],$s); + $s = str_replace($mtch[0], $mtch[1] . $mtch[2] . str_replace(' ','_',$mtch[4]),$s); } } return $s; |