public function getUrl() { if (empty($this->arguments['title'])) { $node = vB_Library::instance('node')->getNodeBare($this->arguments['nodeid']); if (empty($node) or !empty($node['errors'])) { return FALSE; } if ($node['urlident']) { $this->arguments['title'] = $node['urlident']; } else { $this->arguments['title'] = vB_String::getUrlIdent($node['title']); } } if (empty($this->arguments['userid'])) { if (!isset($node['nodeid'])) { $node = vB_Library::instance('node')->getNodeBare($this->arguments['nodeid']); } if ($node['setfor']) { $user = vB_User::fetchUserinfo($node['setfor']); $this->arguments['userid'] = $user['userid']; $this->arguments['username'] = $user['username']; } } $url = '/member/' . $this->arguments['userid'] . '-' . vB_String::getUrlIdent($this->arguments['username']) . '/visitormessage/' . $this->arguments['nodeid'] . '-' . vB_String::vBStrToLower(vB_String::htmlSpecialCharsUni(str_replace(' ', '-', $this->arguments['title']))); if (strtolower(vB_String::getCharset()) != 'utf-8') { $url = vB_String::encodeUtf8Url($url); } return $url; }
public function fetchTagByText($tagtext) { $response = array(); $tag = vB::getDbAssertor()->getRow('vBForum:tag', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'tagtext' => vB_String::vBStrToLower($tagtext))); if ($tag) { $response['tag'] = $tag; } else { throw new vB_Exception_Api("tag_not_exist"); } return $response; }
/** Get the attachment limits for an extension and usergroupid. If that usergroup does not have permission * or the extension is not in the list of allowed extensions, return false. * Note: This is only constrained to the attachmenttype and attachmentpermission tables. The create permissions * for all attachments are handled in the channels. * TODO: Make this part of the channel permissions * * @param int $group Permission group the permission is in * @param string $permission Name of permission * * @return mixed false if not enabled for the usergroupid. array of limits if its enabled. */ public function getAttachmentPermissions($usergroupid, $extension) { $extension = vB_String::vBStrToLower($extension); if (!isset($this->attachmentPermissions[$extension])) { $extensionPerms = array(); $allAttachperms = vB::getDbAssertor()->getRows('vBForum:fetchAttachPermsByExtension', array('extension' => $extension)); if (empty($allAttachperms)) { $this->attachmentPermissions[$extension] = false; } else { foreach ($allAttachperms as $attachPerms) { if (!isset($extensionPerms['default'])) { // First set the defaults set in the attachmenttype table $defaultPerms = array(); $defaultPerms['height'] = !empty($attachPerms['default_height']) ? $attachPerms['default_height'] : 0; $defaultPerms['width'] = !empty($attachPerms['default_width']) ? $attachPerms['default_width'] : 0; $defaultPerms['size'] = !empty($attachPerms['default_size']) ? $attachPerms['default_size'] : 0; $extensionPerms['default'] = $defaultPerms; } if (!empty($attachPerms['usergroupid'])) { // Now set individual permissions for the usergroups. if (empty($attachPerms['custom_permissions'])) { // The usergroup doesn't have permission to use this extension $extensionPerms[$attachPerms['usergroupid']] = false; } else { // The usergroup has permission to use this extension. $customPerms = array(); $customPerms['height'] = $attachPerms['custom_height'] !== null ? $attachPerms['custom_height'] : $extensionPerms['default']['height']; $customPerms['width'] = $attachPerms['custom_width'] !== null ? $attachPerms['custom_width'] : $extensionPerms['default']['width']; $customPerms['size'] = $attachPerms['custom_size'] !== null ? $attachPerms['custom_size'] : $extensionPerms['default']['size']; $extensionPerms[$attachPerms['usergroupid']] = $customPerms; unset($customPerms); } } } $this->attachmentPermissions[$extension] = $extensionPerms; } } if (isset($this->attachmentPermissions[$extension]) and !empty($this->attachmentPermissions[$extension])) { if (isset($this->attachmentPermissions[$extension][$usergroupid])) { // We have custom permissions, use those. Could be false if this usergroup has no permissions for this extension. return $this->attachmentPermissions[$extension][$usergroupid]; } else { // Use the defaults. Custom permissions not set, so it's allowed. return $this->attachmentPermissions[$extension]['default']; } } // This extension is not allowed. return false; }
public function getChannelPermission($permissiongroup, $permission, $nodeid, $parents = false, $parentid = false) { // comments disabled check if ($permissiongroup == 'createpermissions') { $createPerms = $this->getCanCreate($nodeid); $permission = vB_String::vBStrToLower($permission); if (isset($createPerms[$permission])) { return (bool) $createPerms[$permission]; } else { return false; } } // check if we're accessing a boolean or integer permission $isIntPermission = isset($this->countFields[$permission]); // if user is super admin and not requesting an integer permission, no need to check if (!$isIntPermission && $this->userIsSuperAdmin) { return true; } if (!$isIntPermission and ($permissiongroup == 'moderatorpermissions' or $permissiongroup == 'moderatorpermissions2') and $this->checkModPerm($permissiongroup, $permission, $nodeid)) { return true; } //If we have channel-group permissions we need to check them first. if (!empty($this->groupInTopic) and !$isIntPermission) { //groupintopic is set at the channel level. So let's get this node's channel. $gitNodeid = $this->getChannelIdOfNode($nodeid); //see if the current user has groupintopic at this level if (!empty($this->groupInTopic[$gitNodeid]) and is_array($this->groupInTopic[$gitNodeid])) { foreach ($this->groupInTopic[$gitNodeid] as $usergroupid) { $channelid = $this->channelPermsFrom[$usergroupid][$gitNodeid]; if ((bool) $this->permissionContext->getChannelPerm($usergroupid, $permissiongroup, $permission, $channelid)) { return true; } } } } // do not cast this to a boolean value, since we may be accessing an integer permission (max attachments, max tags, etc) return $this->getChannelLimitPermission($permissiongroup, $permission, $nodeid, $parents, $parentid); }
/** * Break the keyword search into words * @param string keywords -- keyword string as entered by the user * @return array -- array of word records * array('word' => $word, 'joiner' => {'', 'NOT', 'AND', 'OR'}) * The search implementation is expected to use these to build the search * query. */ private function get_words($keywords) { $is_mb = preg_match('/&#([0-9]+);|[^\\x00-\\x7F]/siU', $keywords); // @todo handleing for thousand and decimal separators for numbers // removing punctuation $origKeywords = $keywords; $keywords = preg_replace('#(?!-)[\\p{Pd}\\p{Pe}\\p{Pf}\\p{Pi}\\p{Po}\\p{Ps}]#' . ($is_mb ? 'u' : ''), ' ', $keywords); // a tokenizing based approach to building a search query preg_match_all('#("[^"]*"|[^\\s]+)#', $keywords, $matches, PREG_SET_ORDER); $token_joiner = null; $words = array(); foreach ($matches as $match) { if ($is_mb) { $match = preg_replace_callback('/&#([0-9]+);/siU', function ($matches) { return vB5_String::convertIntToUtf8($matches[1]); }, $match); } if ($is_mb) { $token = vB_String::vBStrToLower($match[1]); } else { $token = strtolower($match[1]); } //this means that we implicitly have a not joiner. if ($token[0] == '-') { //this effectively means two joiners, which is bad. if ($token_joiner) { $this->add_error('invalid_search_syntax'); } else { $token = substr($token, 1); $token_joiner = 'not'; } } switch ($token) { case 'or': case 'and': case 'not': // this isn't a searchable word, but a joiner $token_joiner = strtoupper($token); break; default: //$lowWord = strtolower($token); if (vB_Api_Search::is_index_word($token, true)) { $words[] = array('word' => $token, 'joiner' => strtoupper($token_joiner)); } else { $this->ignored_keywords[] = $match[1]; } $token_joiner = null; break; } } if (empty($matches) and !empty($origKeywords)) { $this->ignored_keywords[] = $origKeywords; } return $words; }
public static function is_index_word($word, $isLower = false) { $badwords = self::get_all_bad_words(); $goodwords = self::get_good_words(); if (!$isLower) { $word = vB_String::vBStrToLower($word); } // is the word in the goodwords array? if (in_array($word, $goodwords)) { return 1; } else { // is the word outside the min/max char lengths for indexing? $wordlength = vB_String::vbStrlen($word); $options = vB::getDatastore()->get_value('options'); if ($wordlength < $options['minsearchlength'] or $wordlength > $options['maxsearchlength']) { return 0; } else { if (in_array($word, $badwords)) { return false; } else { return 1; } } } }
/** * breaks up the text into words * @param string $text * @return string */ protected static function break_words($text) { $text = strip_tags($text); $text = strip_bbcode($text, true, false, false, true); // multibyte $is_mb = preg_match('/[^\\x00-\\x7F]/', $text); if (!$is_mb) { $is_mb = strlen($text) != vB_String::vbStrlen($text); } if ($is_mb) { $text = vB_String::toUtf8($text, vB_String::getCharSet()); if (preg_match('/&#([0-9]+);|[^\\x00-\\x7F]/esiU', $text) and function_exists('mb_decode_numericentity')) { $text = mb_decode_numericentity($text, array(0x0, 0x2ffff, 0, 0xffff), 'UTF-8'); } $pattern = '/[\\s,.!?@#$%^&*\\(\\)\\/<>"\';:\\[\\]\\{\\}\\+|-]/'; } else { $pattern = '/[^a-z0-9_]+/i'; } $words = preg_split($pattern, vB_String::vBStrToLower($text), -1, PREG_SPLIT_NO_EMPTY); foreach ($words as $index => $word) { if (!vB_Api_Search::is_index_word($word, true)) { unset($words[$index]); continue; } //$words[$index] = $is_mb ? vB_String::toUtf8($word) : $word; if (empty($words[$index])) { unset($words[$index]); continue; } } return $words; }
/** * Filters the tag list to exclude invalid tags based on the content item the tags * are assigned to. * * Calls filterTagList internally to handle invalid 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 array of tag limit constraints. If a limit is not specified a suitable * default will be used (currently unlimited, but a specific default should * not be relied on). Current limits recognized are 'content_limit' which * is the maximum number of tags for a content item and 'user_limit' which * is the maximum number of tags the current user can add to the content item. * @param int The maximum number of tags the current user can assign to this item (0 is unlimited) * @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. If there are too many tags to add, the list will * be truncated first. An error will be set in this case. */ protected function filterTagListContentLimits($taglist, $limits, &$errors, $checkBrowserPerms = true, $evalerrors = true) { $contentTagLimit = isset($limits['content_limit']) ? intval($limits['content_limit']) : 0; $userTagLimit = isset($limits['user_limit']) ? intval($limits['user_limit']) : 0; //Note that this call ensures we have loaded content, so no need to check that later $existingTagCount = $this->fetchExistingTagCount(); if ($contentTagLimit and $existingTagCount >= $contentTagLimit) { // $errors['threadmax'] = $evalerrors ? fetch_error('item_has_max_allowed_tags') : 'item_has_max_allowed_tags'; $errors['threadmax'] = 'item_has_max_allowed_tags'; return array(); } $validTags = $this->filterTagList($taglist, $errors, $evalerrors); $validTagsLower = array_map('vB_String::vBStrToLower', $validTags); if ($validTags) { if ($checkBrowserPerms and !$this->canAddTag()) { // can't create tags, need to throw errors about bad ones $newTags = array_flip($validTagsLower); foreach ($this->contentinfo as $tag) { unset($newTags[vB_String::vBStrToLower($tag['tagtext'])]); $tag = $existing->next(); } if ($newTags) { // trying to create tags without permissions. Remove and throw an error // $errors['no_create'] = $evalerrors ? fetch_error('tag_no_create') : 'tag_no_create'; $errors['no_create'] = 'tag_no_create'; foreach ($newTags as $newTag => $key) { // remove those that we can't add from the list unset($validTags["{$key}"], $validTagsLower["{$key}"]); } } } // determine which tags are already in the thread and just ignore them $userTagCount = 0; if ($this->contentinfo === null) { $this->loadContentInfo(); } foreach ($this->contentinfo as $tag) { if ($tag['userid'] == $this->currentUserId) { $userTagCount++; } // tag is in thread, find it and remove if (($key = array_search(vB_String::vBStrToLower($tag['tagtext']), $validTagsLower)) !== false) { unset($validTags["{$key}"], $validTagsLower["{$key}"]); } } //approximate "unlimited" as PHP_INT_MAX -- makes the min logic cleaner $contentTagsRemaining = PHP_INT_MAX; if ($contentTagLimit) { $contentTagsRemaining = $contentTagLimit - $existingTagCount - count($validTags); } $userTagsRemaining = PHP_INT_MAX; if ($userTagLimit) { $userTagsRemaining = $userTagLimit - $userTagCount - count($validTags); } $remainingTags = min($contentTagsRemaining, $userTagsRemaining); if ($remainingTags < 0) { // $errors['threadmax'] = $evalerrors ? // fetch_error('number_tags_add_exceeded_x', vb_number_format($remainingTags * -1)) : // array('number_tags_add_exceeded_x', vb_number_format($remainingTags * -1)); $errors['threadmax'] = array('number_tags_add_exceeded_x', vb_number_format($remainingTags * -1)); $allowedTagCount = count($validTags) + $remainingTags; if ($allowedTagCount > 0) { $validTags = array_slice($validTags, 0, count($validTags) + $remainingTags); } else { $validTags = array(); } } } return $validTags; }