/** * Fetch the valid tags from a list. Filters are length, censorship, perms (if desired). * * @param array Array of existing thread info (including the existing tags) * @param string|array List of tags to add (comma delimited, or an array as is). If array, ensure there are no commas. * @param array (output) List of errors that happens * @param boolean Whether to check the browsing user's create tag perms * @param boolean Whether to expand the error phrase * * @return array List of valid tags */ function fetch_valid_tags($threadinfo, $taglist, &$errors, $check_browser_perms = true, $evalerrors = true) { global $vbulletin; static $tagbadwords, $taggoodwords; $errors = array(); if (!is_array($taglist)) { $taglist = split_tag_list($taglist); } if (!trim($threadinfo['taglist'])) { $existing_tags = array(); } else { // this will always be delimited by a comma $existing_tags = explode(',', trim($threadinfo['taglist'])); } if ($vbulletin->options['tagmaxthread'] and count($existing_tags) >= $vbulletin->options['tagmaxthread']) { $errors['threadmax'] = $evalerrors ? fetch_error('thread_has_max_allowed_tags') : 'thread_has_max_allowed_tags'; return array(); } if ($vbulletin->options['tagmaxlen'] <= 0 or $vbulletin->options['tagmaxlen'] >= 100) { $vbulletin->options['tagmaxlen'] = 100; } $valid_raw = array(); // stop words: too common require DIR . '/includes/searchwords.php'; // get the stop word list; allow multiple requires // filter the stop words by adding custom stop words (tagbadwords) and allowing through exceptions (taggoodwords) if (!is_array($tagbadwords)) { $tagbadwords = preg_split('/\\s+/s', vbstrtolower($vbulletin->options['tagbadwords']), -1, PREG_SPLIT_NO_EMPTY); } if (!is_array($taggoodwords)) { $taggoodwords = preg_split('/\\s+/s', vbstrtolower($vbulletin->options['taggoodwords']), -1, PREG_SPLIT_NO_EMPTY); } // merge hard-coded badwords and tag-specific badwords $badwords = array_merge($badwords, $tagbadwords); foreach ($taglist as $tagtext) { $tagtext = trim(preg_replace('#[ \\r\\n\\t]+#', ' ', $tagtext)); if ($tagtext === '') { continue; } if (!in_array(vbstrtolower($tagtext), $taggoodwords)) { $char_strlen = vbstrlen($tagtext, true); if ($vbulletin->options['tagminlen'] and $char_strlen < $vbulletin->options['tagminlen']) { $errors['min_length'] = $evalerrors ? fetch_error('tag_too_short_min_x', $vbulletin->options['tagminlen']) : array('tag_too_short_min_x', $vbulletin->options['tagminlen']); continue; } if ($char_strlen > $vbulletin->options['tagmaxlen']) { $errors['max_length'] = $evalerrors ? fetch_error('tag_too_long_max_x', $vbulletin->options['tagmaxlen']) : array('tag_too_long_max_x', $vbulletin->options['tagmaxlen']); continue; } if (strlen($tagtext) > 100) { // only have 100 bytes to store a tag $errors['max_length'] = $evalerrors ? fetch_error('tag_too_long_max_x', $vbulletin->options['tagmaxlen']) : array('tag_too_long_max_x', $vbulletin->options['tagmaxlen']); continue; } $censored = fetch_censored_text($tagtext); if ($censored != $tagtext) { // can't have tags with censored text $errors['censor'] = $evalerrors ? fetch_error('tag_no_censored') : 'tag_no_censored'; continue; } if (count(split_tag_list($tagtext)) > 1) { // contains a delimiter character $errors['comma'] = $evalerrors ? fetch_error('tag_no_comma') : 'tag_no_comma'; continue; } if (in_array(strtolower($tagtext), $badwords)) { $errors['common'] = $evalerrors ? fetch_error('tag_x_not_be_common_words', $tagtext) : array('tag_x_not_be_common_words', $tagtext); continue; } } $valid_raw[] = $vbulletin->options['tagforcelower'] ? vbstrtolower($tagtext) : $tagtext; } // we need to essentially do a case-insensitive array_unique here $valid_unique = array_unique(array_map('vbstrtolower', $valid_raw)); $valid = array(); foreach (array_keys($valid_unique) as $key) { $valid[] = $valid_raw["{$key}"]; } $valid_unique = array_values($valid_unique); // make the keys jive with $valid if ($valid) { $existing_sql = $vbulletin->db->query_read("\n\t\t\tSELECT tag.tagtext, IF(tagthread.tagid IS NULL, 0, 1) AS taginthread\n\t\t\tFROM " . TABLE_PREFIX . "tag AS tag\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "tagthread AS tagthread ON\n\t\t\t\t(tag.tagid = tagthread.tagid AND tagthread.threadid = " . intval($threadinfo['threadid']) . ")\n\t\t\tWHERE tag.tagtext IN ('" . implode("','", array_map(array(&$vbulletin->db, 'escape_string'), $valid)) . "')\n\t\t"); if ($check_browser_perms and !($vbulletin->userinfo['permissions']['genericpermissions'] & $vbulletin->bf_ugp_genericpermissions['cancreatetag'])) { // can't create tags, need to throw errors about bad ones $new_tags = array_flip($valid_unique); while ($tag = $vbulletin->db->fetch_array($existing_sql)) { unset($new_tags[vbstrtolower($tag['tagtext'])]); } if ($new_tags) { // trying to create tags without permissions. Remove and throw an error $errors['no_create'] = $evalerrors ? fetch_error('tag_no_create') : 'tag_no_create'; foreach ($new_tags as $new_tag => $key) { // remove those that we can't add from the list unset($valid["{$key}"], $valid_unique["{$key}"]); } } } $vbulletin->db->data_seek($existing_sql, 0); // determine which tags are already in the thread and just ignore them while ($tag = $vbulletin->db->fetch_array($existing_sql)) { if ($tag['taginthread']) { // tag is in thread, find it and remove if (($key = array_search(vbstrtolower($tag['tagtext']), $valid_unique)) !== false) { unset($valid["{$key}"], $valid_unique["{$key}"]); } } } $user_tags_remain = null; if ($vbulletin->options['tagmaxthread']) { // check global limit $user_tags_remain = $vbulletin->options['tagmaxthread'] - count($existing_tags) - count($valid); } if (!can_moderate($threadinfo['forumid'], 'caneditthreads')) { $my_tag_count_array = $vbulletin->db->query_first("\n\t\t\t\tSELECT COUNT(*) AS count\n\t\t\t\tFROM " . TABLE_PREFIX . "tagthread\n\t\t\t\tWHERE threadid = " . intval($threadinfo['threadid']) . "\n\t\t\t\t\tAND userid = " . $vbulletin->userinfo['userid']); $my_tag_count = $my_tag_count_array['count'] + count($valid); $tags_remain = null; if ($vbulletin->options['tagmaxstarter'] and $threadinfo['postuserid'] == $vbulletin->userinfo['userid']) { $tags_remain = $vbulletin->options['tagmaxstarter'] - $my_tag_count; } else { if ($vbulletin->options['tagmaxuser']) { $tags_remain = $vbulletin->options['tagmaxuser'] - $my_tag_count; } } if ($tags_remain !== null) { $user_tags_remain = $user_tags_remain == null ? $tags_remain : min($tags_remain, $user_tags_remain); } } if ($user_tags_remain < 0) { $errors['threadmax'] = $evalerrors ? fetch_error('number_tags_add_exceeded_x', vb_number_format($user_tags_remain * -1)) : array('number_tags_add_exceeded_x', vb_number_format($user_tags_remain * -1)); $allowed_tag_count = count($valid) + $user_tags_remain; if ($allowed_tag_count > 0) { $valid = array_slice($valid, 0, count($valid) + $user_tags_remain); } else { $valid = array(); } } } return $valid; }
function BuildSubmittedTags($taglist) { global $vbulletin; if (function_exists(split_tag_list)) { $taglist = split_tag_list($taglist); } else { $taglist = split(',', $taglist); } return $taglist; }