Exemple #1
0
 public function getCanonicalRoute()
 {
     if (!isset($this->canonicalRoute)) {
         if (empty($this->arguments['nodeid'])) {
             throw new vB_Exception_NodePermission();
         }
         $nodeApi = vB_Api::instanceInternal('node');
         try {
             // this method will return an error if the user does not have permission
             $node = $nodeApi->getNode($this->arguments['nodeid']);
         } catch (vB_Exception_Api $ex) {
             // throw the proper NodePermission exception to return a 403 status instead of a 500 internal error
             if ($ex->has_errors('no_permission')) {
                 throw new vB_Exception_NodePermission($this->arguments['nodeid']);
             } else {
                 // otherwise, just let the caller catch the exception
                 throw $ex;
             }
         }
         $contentApi = vB_Api_Content::getContentApi($node['contenttypeid']);
         if (!$contentApi->validate($node, vB_Api_Content::ACTION_VIEW, $node['nodeid'], array($node['nodeid'] => $node))) {
             throw new vB_Exception_NodePermission($node['nodeid']);
         }
         $parent = $nodeApi->getNode($node['starter']);
         $parent['innerPost'] = $this->arguments['nodeid'];
         $this->canonicalRoute = self::getRoute($node['routeid'], $parent, $this->queryParameters);
     }
     return $this->canonicalRoute;
 }
Exemple #2
0
 /**
  * This was a function wrapper for listPendingPosts but used for current user.
  * Now returns different information due to post processing steps.
  *
  */
 public function listPendingPostsForCurrentUser($options = array())
 {
     $result = $this->listPendingPosts(vB::getCurrentSession()->get('userid'), $options);
     if (isset($result['totalcount'])) {
         $totalCount = intval($result['totalcount']);
     }
     if (isset($result['pageInfo'])) {
         $pageInfo = $result['pageInfo'];
     }
     $contenttypes = array();
     $nodes = array();
     foreach ($result['nodes'] as $node) {
         $contenttypeid = $node['contenttypeid'];
         $nodeid = $node['nodeid'];
         if (!isset($contenttypes[$contenttypeid])) {
             $contenttypes[$contenttypeid] = array();
         }
         $contenttypes[$contenttypeid][] = $nodeid;
         $nodes[$nodeid] = $node;
     }
     //For each type, get the content detail.
     foreach ($contenttypes as $contenttypeid => $nodeList) {
         if (!empty($nodes)) {
             $contentApi = vB_Api_Content::getContentApi($contenttypeid);
             $contentList = $contentApi->getFullContent($nodeList);
             foreach ($nodes as $nodeid => $node) {
                 foreach ($contentList as $key => $content) {
                     if ($content['nodeid'] == $nodeid) {
                         $nodes[$nodeid]['content'] = $content;
                         break;
                     }
                 }
             }
         }
     }
     $userApi = vB_Api::instanceInternal('user');
     $pmContentType = vB_Types::instance()->getContentTypeId('vBForum_PrivateMessage');
     //We need a list of parents for nodes that are neither starters nor replies.
     $parents = array();
     //add parent, visitormessage, and author information
     foreach ($nodes as $nodeid => $node) {
         if ($node['content']['starter'] != $node['content']['nodeid'] and $node['content']['starter'] != $node['content']['parentid']) {
             $parents[$nodeid] = $node['content']['parentid'];
         }
         $nodes[$nodeid]['isVisitorMessage'] = $nodes[$nodeid]['content']['isVisitorMessage'] = !empty($node['content']['setfor']);
         $nodes[$nodeid]['userinfo'] = array('avatar' => $userApi->fetchAvatar($node['content']['userid'], array('avatar'), $node['content']['userinfo']), 'userid' => $node['content']['userid'], 'username' => $node['content']['userinfo']['username']);
     }
     //See if we need to add some parent information
     if (!empty($parents)) {
         $parentInfo = vB_Api::instanceInternal('node')->getNodes($parents);
         foreach ($parents as $nodeid => $parentid) {
             foreach ($parentInfo as $info) {
                 if ($info['nodeid'] == $parentid) {
                     $nodes[$nodeid]['parent'] = $info;
                 }
             }
         }
     }
     $this->addOptionalContentInfo($nodes, $options);
     $this->markSubscribed($nodes);
     $return = array('nodes' => $nodes);
     if (isset($totalCount)) {
         $return['totalcount'] = $totalCount;
     } else {
         $return['totalcount'] = count($nodes);
     }
     if (isset($pageInfo) and !empty($pageInfo)) {
         $return['pageInfo'] = $pageInfo;
     }
     return $return;
 }
Exemple #3
0
 /**
  * Fetch image information about an attachment
  *
  * @param  int    Node ID
  * @param  string Thumbnail version/size requested (SIZE_* constanst in vB_Api_Filedata)
  * @param  bool   Should we include the image content
  *
  * @return mixed  Array of data, includes:
  *                filesize, dateline, htmltype, filename, extension, and filedataid
  */
 public function fetchImage($id, $type = vB_Api_Filedata::SIZE_FULL, $includeData = true)
 {
     if (empty($id) or !intval($id)) {
         throw new vB_Exception_Api('invalid_request');
     }
     $type = vB_Api::instanceInternal('filedata')->sanitizeFiletype($type);
     $userContext = vB::getUserContext();
     $attachdata = vB::getDbAssertor()->getRow('vBForum:fetchAttachForLoad', array('nodeid' => $id));
     $extension = $attachdata['extension'];
     /*
      *	This might get a bit confusing. Some files, like PDFs, might have an image thumbnail.
      *	In such a case, we treat the thumbnail as an image in terms of permissions. To change
      *	this policy, remove $type.
      */
     $isImg = $this->imageHandler->isImage($extension, $type);
     if (!$isImg and !$userContext->getChannelPermission('forumpermissions', 'cangetattachment', $id) or $isImg and !$userContext->getChannelPermission('forumpermissions2', 'cangetimgattachment', $id)) {
         if ($attachdata['userid'] != $userContext->fetchUserId()) {
             throw new vB_Exception_Api('no_view_permissions');
         }
     }
     $parent = vB_Api::instanceInternal('node')->getNode($attachdata['parentid']);
     $contentApi = vB_Api_Content::getContentApi($parent['contenttypeid']);
     $valid = $contentApi->validate($parent, vB_Api_Content::ACTION_VIEW, $parent['nodeid'], array($parent['nodeid'] => $parent));
     //allow viewing attachments for nodes set to public preview even if the node itself
     //can't be viewed.
     if (!$valid and empty($parent['public_preview'])) {
         throw new vB_Exception_Api('no_view_permissions');
     }
     //If the record belongs to this user, or if this user can view attachments
     //in this section, then this is O.K.
     if (!empty($attachdata) && $attachdata['filedataid']) {
         $params = array('filedataid' => $attachdata['filedataid'], 'type' => $type);
         $record = vB::getDbAssertor()->getRow('vBForum:getFiledataContent', $params);
     }
     if (empty($record)) {
         return false;
     }
     return vB_Image::instance()->loadFileData($record, $type, $includeData);
 }
Exemple #4
0
 /**
  * Get the nodes from a search resultId
  *
  * @param  int   $resultId id of the search result
  * @param  int   $perpage pagination - the number of results per page
  * @param  int   $pagenumber pagination - the page number
  *
  * @return array List of nodes in the resultId
  */
 public function getMoreResults($resultId, $perpage = false, $pagenumber = false, $getStarterInfo = false)
 {
     $return_structure = $this->getMoreNodes($resultId, $perpage, $pagenumber);
     $return_structure['results'] = vB_Library::instance('Node')->getFullContentforNodes($return_structure['nodeIds'], array('withParent' => $getStarterInfo, 'showVM' => 1));
     //note that getFullContentforNodes returns an element ['content']['permissions']['canviewthreads']
     $userContext = vB::getUserContext();
     foreach ($return_structure['results'] as $key => $result) {
         vB_Api_Content::getContentApi($result['contenttypeid'])->cleanPreviewContent($return_structure['results'][$key]);
     }
     return $return_structure;
 }
Exemple #5
0
 /**
  *	This gets a content record based on nodeid including channel and starter information.
  *
  *	@param	int $nodeid
  *	@param	bool	$contenttypeid optional, defaults to false
  *	@param	array optional	Options flags:
  *		showVm => appends visitor message node info.
  *				Such as isVisitorMessage flag indicating if node is visitor message and vm_userInfo from the user the visitor message was posted for.
  *	withParent => appends information from the parent. This info will append the 'parentConversation' info if the node is a comment.
  *
  *	@return array node list ($nodeid=>node record) will only have one item
  *
  ***/
 public function getNodeFullContent($nodeid, $contenttypeid = false, $options = array())
 {
     if (!is_numeric($nodeid)) {
         throw new vB_Exception_Api('invalid_data');
     }
     $nodeid = intval($nodeid);
     $result = $this->library->getNodeFullContent($nodeid, $contenttypeid, $options);
     //Can happen with a damaged node
     if (empty($result) or empty($result[$nodeid]) or empty($result[$nodeid]['nodeid'])) {
         return array();
     }
     foreach ($result as $key => $node) {
         $contentApi = vB_Api_Content::getContentApi($node['contenttypeid']);
         if (!$contentApi->validate($node, vB_Api_Content::ACTION_VIEW, $node['nodeid'], array($node['nodeid'] => $node))) {
             throw new vB_Exception_Api('no_permission');
         }
     }
     $this->library->removePrivateDataFromNodeList($result);
     return $result;
 }
 public function __construct($routeInfo, $matches, $queryString = '', $anchor = '')
 {
     parent::__construct($routeInfo, $matches, $queryString, $anchor);
     if (isset($this->arguments['channelid'])) {
         $cache = vB_Cache::instance(vB_Cache::CACHE_FAST);
         $hashKey = 'vbRouteChannelInfo_' . $this->arguments['channelid'];
         $channelInfo = $cache->read($hashKey);
         if (empty($channelInfo)) {
             // check if we need to force a styleid
             $channel = vB_Library::instance('Content_Channel')->getBareContent($this->arguments['channelid']);
             $channel = array_pop($channel);
             $channelInfo['styleid'] = $channel['styleid'];
             $channelInfo['options'] = $channel['options'];
             $channelInfo['routeid'] = $channel['routeid'];
             $channelInfo['rss_enabled'] = $channel['rss_enabled'];
             $channelInfo['rss_route'] = $channel['rss_route'];
             $channelInfo['title'] = $channel['title'];
             $cache->write($hashKey, $channelInfo, 1440, array('routeChg_' . $channelInfo['routeid'], 'nodeChg_' . $channelInfo['routeid']));
         }
         if (!empty($channelInfo['styleid'])) {
             if ($channelInfo['options']['styleoverride']) {
                 // the channel must force the style
                 $this->arguments['forceStyleId'] = $channelInfo['styleid'];
             } else {
                 // the channel suggests to use this style
                 $this->arguments['routeStyleId'] = $channelInfo['styleid'];
             }
         }
         // rss info
         $this->arguments['rss_enabled'] = $channelInfo['rss_enabled'];
         $this->arguments['rss_route'] = $channelInfo['rss_route'];
         $this->arguments['rss_title'] = $channelInfo['title'];
         $this->setPageKey('pageid', 'channelid', 'nodeid');
     }
     if (isset($this->arguments['nodeid'])) {
         if (!empty($this->arguments['userid']) && !empty($this->arguments['contenttypeid']) && !empty($this->arguments['title']) && !empty($this->arguments['parentid'])) {
             $node['userid'] = $this->arguments['userid'];
             $node['contenttypeid'] = $this->arguments['contenttypeid'];
             $node['title'] = $this->arguments['title'];
             $node['parentid'] = $this->arguments['parentid'];
         } else {
             try {
                 $node = vB_Library::instance('node')->getNodeBare($this->arguments['nodeid']);
             } catch (vB_Exception_Api $e) {
                 if ($e->has_error('invalid_node_id')) {
                     // the node does not exist, send a 404
                     throw new vB_Exception_404('invalid_page_url');
                 } else {
                     // rethrow exception
                     throw $e;
                 }
             }
         }
         // privacy check
         $albumChannel = vB_Api::instance('node')->fetchAlbumChannel($node['nodeid']);
         if ($node['parentid'] == $albumChannel) {
             $userInfo = vB_Api::instance('user')->fetchProfileInfo($node['userid']);
             if ($node['contenttypeid'] == vB_Types::instance()->getContentTypeID('vBForum_Video') and !$userInfo['showVideos'] or $node['contenttypeid'] == vB_Types::instance()->getContentTypeID('vBForum_Gallery') and (!$userInfo['showPhotos'] or !vB::getUserContext()->hasPermission('albumpermissions', 'canviewalbum'))) {
                 throw new vB_Exception_NodePermission($node['nodeid']);
             }
         }
         $contentApi = vB_Api_Content::getContentApi($node['contenttypeid']);
         if (!$contentApi->validate($node, vB_Api_Content::ACTION_VIEW, $node['nodeid'], array($node['nodeid'] => $node)) and empty($node['public_preview'])) {
             throw new vB_Exception_NodePermission($node['nodeid']);
         }
         if (!empty($this->queryParameters)) {
             $this->arguments['noindex'] = 1;
         }
         if (!empty($node['description'])) {
             $this->arguments['metadescription'] = $node['description'];
         }
         // set user action
         $this->setUserAction('viewing_topic_x', $node['title'], $this->getFullUrl('fullurl'));
         // set last crumb
         $this->breadcrumbs[] = array('title' => $node['title'], 'url' => '');
     }
     $this->arguments['pageSchema'] = 'http://schema.org/ItemPage';
 }
 /**
  * Returns an array of all users participating in a discussion
  *
  * @param  int   the nodeid of the discussion
  *
  * @return array of user information
  *               * following -- is the participant a follower of the current user (may be NULL)
  *               * userid -- ID of the participant
  *               * username -- Name of the participant
  *               * avatarurl -- Url for the participant's avatar
  *               * starter -- ID of the starter for $nodeid
  */
 public function fetchParticipants($nodeid)
 {
     if (!intval($nodeid)) {
         throw new vB_Exception_Api('invalid_data');
     }
     $currentUser = vB::getCurrentSession()->get('userid');
     //We always should have something in $exclude.
     $exclude = array('-1');
     if (intval($currentUser)) {
         $options = vB::getDatastore()->get_value('options');
         if (trim($options['globalignore']) != '') {
             $exclude = preg_split('#\\s+#s', $options['globalignore'], -1, PREG_SPLIT_NO_EMPTY);
         }
     }
     $node = vB_Api::instanceInternal('node')->getNode($nodeid);
     $contentApi = vB_Api_Content::getContentApi($node['contenttypeid']);
     $valid = $contentApi->validate($node, vB_Api_Content::ACTION_VIEW, $node['nodeid'], array($node['nodeid'] => $node));
     //if the user can't see the node, then don't allow them to see the participants.
     if (!$valid) {
         throw new vB_Exception_Api('no_permission');
     }
     $nodeCTClass = vB_Types::instance()->getContentTypeClass($node['contenttypeid']);
     switch ($nodeCTClass) {
         case self::PARTICIPANTS_PM:
             $queryPart = 'vBForum:getPMRecipientsForMessageOverlay';
             $params = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $nodeid);
             break;
         case self::PARTICIPANTS_POLL:
             // this seems a bit sketchy. This works (I think) because polls are always the starter due to
             // frontend restrictions, and no current notification will expect anything different when
             // calling this on a poll post, but if we have poll replies, and a notification called this function
             // expecting to get the thread participants, NOT poll voters, this would be a bug...
             $queryPart = 'vBForum:getNotificationPollVoters';
             $params = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $nodeid);
             break;
             //for a channel we will quietly fail.  Trying to look up the participants is too expensive, is a potential DOS
             //and we don't really need it.
         //for a channel we will quietly fail.  Trying to look up the participants is too expensive, is a potential DOS
         //and we don't really need it.
         case self::PARTICIPANTS_CHANNEL:
             return array();
             break;
         default:
             // private messages should've been caught by the first case. At this point, we should only be concerned with content
             // nodes (excluding polls)
             $queryPart = 'vBForum:fetchParticipants';
             $params = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $nodeid, 'currentuser' => $currentUser, 'exclude' => $exclude);
             break;
     }
     $members = vB::getDbAssertor()->getRows($queryPart, $params);
     $participants = array();
     foreach ($members as $member) {
         if (isset($participants[$member['userid']])) {
             continue;
         }
         $participants[$member['userid']] = $member;
     }
     $userApi = vB_Api::instanceInternal('user');
     foreach ($participants as $uid => $participant) {
         $participants[$uid]['avatarurl'] = $userApi->fetchAvatar($uid, true, $participant);
     }
     return $participants;
 }