Exemplo n.º 1
0
 protected function buildOutputFromItems($items, $options)
 {
     parent::buildOutputFromItems($items, $options);
     $xml = new vB_Xml_Builder();
     $xml->add_group('rss', array('version' => '0.91'));
     $xml->add_group('channel');
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->add_tag('description', $this->rssinfo['description']);
     $xml->add_tag('language', $this->defaultLang['languagecode']);
     $xml->add_group('image');
     $xml->add_tag('url', $this->rssinfo['icon']);
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->close_group('image');
     $dateformat = vB::getDatastore()->getOption('dateformat');
     $timeformat = vB::getDatastore()->getOption('timeformat');
     // gather channel info
     $channelsInfo = $this->getItemsChannelInfo($items);
     $items = $this->formatItems($items, $options);
     foreach ($items as $id => $item) {
         $item = $item['content'];
         $xml->add_group('item');
         $xml->add_tag('title', $item['external_prefix_plain'] . vB_String::htmlSpecialCharsUni($item['external_title']));
         $xml->add_tag('link', vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid']), array(), false, true);
         $xml->add_tag('description', vB_Phrase::fetchSinglePhrase('rss_91_forum_w_posted_by_x_post_time_y_at_z', array($channelsInfo[$item['channelid']]['htmltitle'], $item['authorname'], $this->callvBDate($dateformat, $item['publishdate']), $this->callvBDate($timeformat, $item['publishdate']))));
         $xml->close_group('item');
     }
     $xml->close_group('channel');
     $xml->close_group('rss');
     $output .= '<!DOCTYPE rss PUBLIC "-//RSS Advisory Board//DTD RSS 0.91//EN" "http://www.rssboard.org/rss-0.91.dtd">' . "\r\n";
     $output .= $xml->output();
     return $xml->fetch_xml_tag() . $output;
 }
Exemplo n.º 2
0
 protected function buildOutputFromItems($items, $options)
 {
     parent::buildOutputFromItems($items, $options);
     if ($this->rssinfo['ttl'] <= 60) {
         $updateperiod = 'hourly';
         $updatefrequency = round(60 / $this->rssinfo['ttl']);
     } else {
         $updateperiod = 'daily';
         $updatefrequency = round(1440 / $this->rssinfo['ttl']);
     }
     $xml = new vB_Xml_Builder();
     $xml->add_group('rdf:RDF', array('xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/', 'xmlns:syn' => 'http://purl.org/rss/1.0/modules/syndication/', 'xmlns:content' => 'http://purl.org/rss/1.0/modules/content/', 'xmlns' => 'http://purl.org/rss/1.0/'));
     $xml->add_group('channel', array('rdf:about' => $this->rssinfo['link']));
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->add_tag('description', $this->rssinfo['description']);
     $xml->add_tag('syn:updatePeriod', $updateperiod);
     $xml->add_tag('syn:updateFrequency', $updatefrequency);
     $xml->add_tag('syn:updateBase', '1970-01-01T00:00Z');
     $xml->add_tag('dc:language', $this->defaultLang['languagecode']);
     $xml->add_tag('dc:creator', 'vBulletin');
     $xml->add_tag('dc:date', gmdate('Y-m-d\\TH:i:s') . 'Z');
     $xml->add_group('items');
     $xml->add_group('rdf:Seq');
     $xml->add_tag('rdf:li', '', array('rdf:resource' => $this->rssinfo['link'] . '/'));
     $xml->close_group('rdf:Seq');
     $xml->close_group('items');
     $xml->add_group('image');
     $xml->add_tag('url', $this->rssinfo['icon']);
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->close_group('image');
     $xml->close_group('channel');
     // gather channel info
     $channelsInfo = $this->getItemsChannelInfo($items);
     $items = $this->formatItems($items, $options);
     foreach ($items as $id => $item) {
         $item = $item['content'];
         $xml->add_group('item', array('rdf:about' => vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid'])));
         $xml->add_tag('title', $item['external_prefix_plain'] . vB_String::htmlSpecialCharsUni($item['external_title']));
         $xml->add_tag('link', vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid']), array(), false, true);
         $xml->add_tag('description', $this->getItemDescription($item['rawtext'], $options));
         if (empty($options['nohtml'])) {
             $xml->add_tag('content:encoded', vB_Library::instance('bbcode')->doParse($item['rawtext']));
         }
         $xml->add_tag('dc:date', gmdate('Y-m-d\\TH:i:s', $item['publishdate']) . 'Z');
         $xml->add_tag('dc:creator', vB_String::unHtmlSpecialChars($item['authorname']));
         $xml->add_tag('dc:subject', $channelsInfo[$item['channelid']]['htmltitle']);
         $xml->close_group('item');
     }
     $xml->close_group('rdf:RDF');
     return $xml->fetch_xml();
 }
Exemplo n.º 3
0
 protected function buildOutputFromItems($items, $options)
 {
     $output = $this->threadObj;
     $output .= "var threads = new Array(" . sizeof($items) . ");\r\n";
     $itemnum = 0;
     $items = $this->formatItems($items, $options);
     foreach ($items as $item) {
         $item = $item['content'];
         $item['title'] = vB_Library_Functions::addSlashesJs(vB_String::htmlSpecialCharsUni($item['external_prefix_plain']) . $item['external_title']);
         $item['authorname'] = vB_Library_Functions::addSlashesJs($item['authorname']);
         $output .= "\tthreads[{$itemnum}] = new thread({$item['external_nodeid']}, '{$item['title']}', '{$item['authorname']}', '" . vB_Library_Functions::addSlashesJs($this->callvBDate(vB::getDatastore()->getOption('dateformat'), $item['publishdate'])) . "', '" . vB_Library_Functions::addSlashesJs($this->callvBDate(vB::getDatastore()->getOption('timeformat'), $item['publishdate'])) . "');\r\n";
         $itemnum++;
     }
     return $output;
 }
Exemplo n.º 4
0
 /**
  * Returns a hierarchical array of smilie data for displaying the smilies panel.
  *
  * @return array The smilies
  */
 public function fetchAllSmilies()
 {
     $smilies = vB::get_db_assertor()->getRows('vBForum:fetchImagesSortedLimited', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'table' => 'smilie'));
     $options = vB::getDatastore()->get_value('options');
     $smilieInfo = array();
     $previewSmilies = array();
     $previewCount = 0;
     $smilieCount = 0;
     foreach ($smilies as $smilie) {
         if (!isset($smilieInfo[$smilie['category']])) {
             $smilieInfo[$smilie['category']] = array();
         }
         $smilieInfo[$smilie['category']][$smilie['smilieid']] = array('image' => $smilie['smiliepath'], 'description' => vB_String::htmlSpecialCharsUni($smilie['title'] . ' ' . $smilie['smilietext']));
         ++$smilieCount;
         if ($previewCount < $options['wysiwyg_smtotal']) {
             $previewSmilies[$smilie['smilieid']] = $smilieInfo[$smilie['category']][$smilie['smilieid']];
         }
         ++$previewCount;
     }
     return array('categories' => $smilieInfo, 'previewSmilies' => $previewSmilies, 'categoryCount' => count($smilieInfo), 'smilieCount' => $smilieCount, 'previewCount' => count($previewSmilies), 'moreSmilies' => $smilieCount > count($previewSmilies));
 }
Exemplo n.º 5
0
 protected function buildOutputFromItems($items, $options)
 {
     parent::buildOutputFromItems($items, $options);
     $xml = new vB_Xml_Builder();
     $xml->add_group('rss', array('version' => '2.0', 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/', 'xmlns:content' => 'http://purl.org/rss/1.0/modules/content/'));
     $xml->add_group('channel');
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->add_tag('description', $this->rssinfo['description']);
     $xml->add_tag('language', $this->defaultLang['languagecode']);
     $xml->add_tag('lastBuildDate', gmdate('D, d M Y H:i:s') . ' GMT');
     $xml->add_tag('generator', 'vBulletin');
     $xml->add_tag('ttl', $this->rssinfo['ttl']);
     $xml->add_group('image');
     $xml->add_tag('url', $this->rssinfo['icon']);
     $xml->add_tag('title', $this->rssinfo['title']);
     $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true);
     $xml->close_group('image');
     // gather channel info
     $channelsInfo = $this->getItemsChannelInfo($items);
     $items = $this->formatItems($items, $options);
     foreach ($items as $id => $item) {
         $item = $item['content'];
         $xml->add_group('item');
         $xml->add_tag('title', $item['external_prefix_plain'] . vB_String::htmlSpecialCharsUni($item['external_title']));
         $xml->add_tag('link', vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid']), array(), false, true);
         $xml->add_tag('pubDate', gmdate('D, d M Y H:i:s', $item['publishdate']) . ' GMT');
         $xml->add_tag('description', $this->getItemDescription($item['rawtext'], $options));
         if (empty($options['nohtml'])) {
             $xml->add_tag('content:encoded', vB_Library::instance('bbcode')->doParse($item['rawtext']));
         }
         $xml->add_tag('category', $channelsInfo[$item['channelid']]['htmltitle'], array('domain' => vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['channelid'])));
         $xml->add_tag('dc:creator', vB_String::unHtmlSpecialChars($item['authorname']));
         $xml->add_tag('guid', vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid']), array('isPermaLink' => 'true'));
         $xml->close_group('item');
     }
     $xml->close_group('channel');
     $xml->close_group('rss');
     return $xml->fetch_xml();
 }
Exemplo n.º 6
0
 /**
  * Does the actual work to make a variable safe
  *
  * @param	mixed	The data we want to make safe
  * @param	integer	The type of the data
  *
  * @return	mixed
  */
 protected function &doClean(&$data, $type)
 {
     static $booltypes = array('1', 'yes', 'y', 'true', 'on');
     switch ($type) {
         case self::TYPE_NUM:
         case self::TYPE_UNUM:
             $userinfo = vB::getCurrentSession()->fetch_userinfo();
             // Account for language specific separators
             if (isset($userinfo['lang_decimalsep']) and $userinfo['lang_decimalsep'] != '') {
                 $data = strtr($data, array($userinfo['lang_decimalsep'] => '.', $userinfo['lang_thousandsep'] => ''));
             }
     }
     switch ($type) {
         case self::TYPE_INT:
             $data = intval($data);
             break;
         case self::TYPE_UINT:
             $data = ($data = intval($data)) < 0 ? 0 : $data;
             break;
         case self::TYPE_NUM:
             $data = strval($data) + 0;
             break;
         case self::TYPE_UNUM:
             $data = strval($data) + 0;
             $data = $data < 0 ? 0 : $data;
             break;
         case self::TYPE_BINARY:
             $data = strval($data);
             break;
         case self::TYPE_STR:
             $data = trim(strval($data));
             break;
         case self::TYPE_NOTRIM:
             $data = strval($data);
             break;
         case self::TYPE_NOHTML:
             $data = vB_String::htmlSpecialCharsUni(trim(strval($data)));
             break;
         case self::TYPE_BOOL:
             $data = in_array(strtolower($data), $booltypes) ? 1 : 0;
             break;
         case self::TYPE_ARRAY:
             $data = is_array($data) ? $data : array();
             break;
         case self::TYPE_NOHTMLCOND:
             $data = trim(strval($data));
             if (strcspn($data, '<>"') < strlen($data) or strpos($data, '&') !== false and !preg_match('/&(#[0-9]+|amp|lt|gt|quot);/si', $data)) {
                 // data is not htmlspecialchars because it still has characters or entities it shouldn't
                 $data = vB_String::htmlSpecialCharsUni($data);
             }
             break;
         case self::TYPE_FILE:
             // perhaps redundant :p
             if (is_array($data)) {
                 if (is_array($data['name'])) {
                     $files = count($data['name']);
                     for ($index = 0; $index < $files; $index++) {
                         $data['name']["{$index}"] = trim(strval($data['name']["{$index}"]));
                         $data['type']["{$index}"] = trim(strval($data['type']["{$index}"]));
                         $data['tmp_name']["{$index}"] = trim(strval($data['tmp_name']["{$index}"]));
                         $data['error']["{$index}"] = intval($data['error']["{$index}"]);
                         $data['size']["{$index}"] = intval($data['size']["{$index}"]);
                     }
                 } else {
                     $data['name'] = trim(strval($data['name']));
                     $data['type'] = trim(strval($data['type']));
                     $data['tmp_name'] = trim(strval($data['tmp_name']));
                     $data['error'] = intval($data['error']);
                     $data['size'] = intval($data['size']);
                 }
             } else {
                 $data = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 0, 'size' => 4);
             }
             break;
         case self::TYPE_UNIXTIME:
             if (is_array($data)) {
                 $data = $this->clean($data, vB_Cleaner::TYPE_ARRAY_UINT);
                 if ($data['month'] and $data['day'] and $data['year']) {
                     require_once DIR . '/includes/functions_misc.php';
                     $data = vbmktime($data['hour'], $data['minute'], $data['second'], $data['month'], $data['day'], $data['year']);
                 } else {
                     $data = 0;
                 }
             } else {
                 $data = ($data = intval($data)) < 0 ? 0 : $data;
             }
             break;
             // null actions should be deifned here so we can still catch typos below
         // null actions should be deifned here so we can still catch typos below
         case self::TYPE_NOCLEAN:
             break;
         default:
             if ($config = vB::getConfig() and $config['Misc']['debug']) {
                 trigger_error('vB_Cleaner::doClean() Invalid data type specified', E_USER_WARNING);
             }
     }
     // strip out characters that really have no business being in non-binary data
     switch ($type) {
         case self::TYPE_STR:
         case self::TYPE_NOTRIM:
         case self::TYPE_NOHTML:
         case self::TYPE_NOHTMLCOND:
             $data = str_replace(chr(0), '', $data);
     }
     return $data;
 }
Exemplo n.º 7
0
 /**
  * Validates and sets custom user profile fields
  *
  * @param	array	Array of values for profile fields. Example: array('field1' => 'One', 'field2' => array(0 => 'a', 1 => 'b'), 'field2_opt' => 'c')
  * @param	bool	Whether or not to verify the data actually matches any specified regexes or required fields
  * @param	string	What type of editable value to apply (admin, register, normal)
  * @param	bool	Whether or not to skip verification of required fields that are not present, used for linking facebook accounts
  *
  * @return	string	Textual description of set profile fields (for email phrase)
  */
 function set_userfields(&$values, $verify = true, $all_fields = 'normal', $skip_unset_required_fields = false)
 {
     global $vbphrase;
     if (!is_array($values)) {
         $this->error('::$values for profile fields is not an array::');
         return false;
     }
     $customfields = '';
     $field_ids = array();
     foreach (array_keys($values) as $key) {
         if (preg_match('#^field(\\d+)\\w*$#', $key, $match)) {
             $field_ids["{$match['1']}"] = $match[1];
         }
     }
     if (empty($field_ids) and $all_fields != 'register') {
         return false;
     }
     switch ($all_fields) {
         case 'admin':
             $all_fields_sql = array('profilefieldid' => $field_ids);
             break;
         case 'register':
             // must read all fields in order to set defaults for fields that don't display
             //$all_fields_sql = "WHERE editable IN (1,2)";
             $all_fields_sql = array();
             // we need to ensure that each field the user could edit is sent through and processed,
             // so ensure that we process everyone one of these fields
             $profilefields = $this->assertor->getRows('vBForum:profilefield', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'editable', 'value' => 0, 'operator' => 'GT'), array('field' => 'required', 'value' => 0, 'operator' => 'NE'))));
             foreach ($profilefields as $profilefield) {
                 $field_ids["{$profilefield['profilefieldid']}"] = $profilefield['profilefieldid'];
             }
             break;
         case 'normal':
         default:
             $all_fields_sql = array('profilefieldid' => $field_ids, 'editable' => array(1, 2));
             break;
     }
     // check extra profile fields
     $profilefields = $this->assertor->getRows('vBForum:profilefield', $all_fields_sql, 'displayorder');
     foreach ($profilefields as $profilefield) {
         $varname = 'field' . $profilefield['profilefieldid'];
         $value =& $values["{$varname}"];
         $regex_check = false;
         if ($all_fields != 'admin' and $profilefield['editable'] == 2 and !empty($this->existing["{$varname}"])) {
             continue;
         }
         $title = vB_Api::instanceInternal('phrase')->fetch($varname . '_title');
         $profilefield['title'] = !empty($title) ? $title[$varname . '_title'] : $varname;
         unset($title);
         $optionalvar = 'field' . $profilefield['profilefieldid'] . '_opt';
         $value_opt =& $values["{$optionalvar}"];
         // text box / text area
         if ($profilefield['type'] == 'input' or $profilefield['type'] == 'textarea') {
             if (in_array($profilefield['profilefieldid'], $field_ids) and ($all_fields != 'register' or $profilefield['editable'])) {
                 $value = trim(substr(fetch_censored_text($value), 0, $profilefield['maxlength']));
                 $value = (empty($value) and $value != '0') ? false : $value;
             } else {
                 if ($all_fields == 'register' and $profilefield['data'] !== '') {
                     $value = unhtmlspecialchars($profilefield['data']);
                 } else {
                     continue;
                 }
             }
             $customfields .= "{$profilefield['title']} : {$value}\n";
             $regex_check = true;
         } else {
             if ($profilefield['type'] == 'radio' or $profilefield['type'] == 'select') {
                 if ($profilefield['optional'] and $value_opt != '') {
                     $value = trim(substr(fetch_censored_text($value_opt), 0, $profilefield['maxlength']));
                     $value = (empty($value) and $value != '0') ? false : $value;
                     $regex_check = true;
                 } else {
                     $data = unserialize($profilefield['data']);
                     $value -= 1;
                     if (in_array($profilefield['profilefieldid'], $field_ids) and ($all_fields != 'register' or $profilefield['editable'])) {
                         if (isset($data["{$value}"])) {
                             $value = unhtmlspecialchars(trim($data["{$value}"]));
                         } else {
                             $value = false;
                         }
                     } else {
                         if ($all_fields == 'register' and $profilefield['def']) {
                             $value = unhtmlspecialchars($data[0]);
                         } else {
                             continue;
                         }
                     }
                 }
                 $customfields .= "{$profilefield['title']} : {$value}\n";
             } else {
                 if (($profilefield['type'] == 'checkbox' or $profilefield['type'] == 'select_multiple') and in_array($profilefield['profilefieldid'], $field_ids)) {
                     if (is_array($value)) {
                         if ($profilefield['size'] == 0 or sizeof($value) <= $profilefield['size']) {
                             $data = unserialize($profilefield['data']);
                             $bitfield = 0;
                             $cfield = '';
                             foreach ($value as $key => $val) {
                                 $val--;
                                 $bitfield += pow(2, $val);
                                 $cfield .= (!empty($cfield) ? ', ' : '') . $data["{$val}"];
                             }
                             $value = $bitfield;
                         } else {
                             $this->error('checkboxsize', $profilefield['size'], $profilefield['title']);
                             $value = false;
                         }
                         $customfields .= "{$profilefield['title']} : {$cfield}\n";
                     } else {
                         $value = false;
                     }
                 } else {
                     continue;
                 }
             }
         }
         // check for regex compliance
         if ($verify and $profilefield['regex'] and $regex_check) {
             if (!preg_match('#' . str_replace('#', '\\#', $profilefield['regex']) . '#siU', $value)) {
                 $this->error('regexincorrect', $profilefield['title']);
                 $value = false;
             }
         }
         // check for empty required fields
         if (($profilefield['required'] == 1 or $profilefield['required'] == 3) and $value === false and $verify) {
             if ($skip_unset_required_fields and !isset($values["{$varname}"])) {
                 continue;
             }
             $this->error('required_field_x_missing_or_invalid', $profilefield['title']);
         }
         $this->setfields["{$varname}"] = true;
         $this->userfield["{$varname}"] = vB_String::htmlSpecialCharsUni($value);
     }
     //$this->dbobject->free_result($profilefields);
     return $customfields;
 }
Exemplo n.º 8
0
 public function fetchHistoryComparison($nodeid, $oldpost, $newpost)
 {
     if (!$this->canViewPostHistory($nodeid)) {
         throw new Exception('no_permission');
     }
     $_posthistory = vB::getDbAssertor()->getRows('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array('nodeid' => $nodeid, 'postedithistoryid' => array($oldpost, $newpost)), vB_dB_Query::COLUMNS_KEY => array('postedithistoryid', 'reason', 'dateline', 'username', 'original', 'pagetext')), array('field' => 'postedithistoryid', 'direction' => vB_dB_Query::SORT_ASC));
     if (!$_posthistory) {
         throw new Exception('no_permission');
     }
     $posthistory = array();
     $key = 1;
     foreach ($_posthistory as $info) {
         $posthistory['post' . $key] = $info;
         $key++;
     }
     require_once DIR . '/includes/class_diff.php';
     if ($posthistory['post2']) {
         $textdiff_obj = new vB_Text_Diff($posthistory['post1']['pagetext'], $posthistory['post2']['pagetext']);
     } else {
         $textdiff_obj = new vB_Text_Diff($posthistory['post1']['pagetext'], $posthistory['post1']['pagetext']);
     }
     $results = array();
     $diff = $textdiff_obj->fetch_diff();
     foreach ($diff as $diffrow) {
         $compare_show = array();
         if ($diffrow->old_class == 'unchanged' and $diffrow->new_class == 'unchanged') {
             // no change
             $results[] = array('unchanged_olddata' => vB_String::fetchWordWrappedString(nl2br(vB_String::htmlSpecialCharsUni(implode("\n", $diffrow->fetch_data_old())))));
         } else {
             // something has changed
             $results[] = array('changed_olddata' => vB_String::fetchWordWrappedString(nl2br(vB_String::htmlSpecialCharsUni(implode("\n", $diffrow->fetch_data_old())))), 'changed_newdata' => vB_String::fetchWordWrappedString(nl2br(vB_String::htmlSpecialCharsUni(implode("\n", $diffrow->fetch_data_new())))));
         }
     }
     return $results;
 }
Exemplo n.º 9
0
 /**
  * Reverse an infraction
  *
  * @param  int    The infraction nodeid
  * @param  string Reason for the reversal
  *
  * @return int    The number of rows that were affected
  */
 public function reverseInfraction($nodeid, $reason)
 {
     if (!$this->canReverseInfraction()) {
         throw new vB_Exception_Api('no_permission');
     }
     $nodeid = (int) $nodeid;
     $reason = vB_String::htmlSpecialCharsUni($reason);
     if ($nodeid < 1) {
         throw new vB_Exception_Api('invalid_node');
     }
     return $this->library->reverseInfraction($nodeid, $reason);
 }
Exemplo n.º 10
0
 protected function attachReplaceCallback($matches)
 {
     $align = $matches[1];
     $showOldImage = false;
     $tempid = false;
     // used if this attachment hasn't been saved yet (ex. going back & forth between source mode & wysiwyg on a new content)
     $filedataid = false;
     $attachmentid = false;
     // Same as before: are we looking at a legacy attachment?
     if (preg_match('#^n(\\d+)$#', $matches[2], $matches2)) {
         // if the id has 'n' as prefix, it's a nodeid
         $attachmentid = intval($matches2[1]);
     } else {
         if (preg_match('#^temp_(\\d+)_(\\d+)_(\\d+)$#', $matches[2], $matches2)) {
             // if the id is in the form temp_##_###_###, it's a temporary id that links to hidden inputs that contain
             // the stored settings that will be saved when it becomes a new attachment @ post save.
             $tempid = $matches2[0];
             $filedataid = intval($matches2[1]);
         } else {
             // it's a legacy attachmentid, get the new id
             if (isset($this->oldAttachments[intval($matches[2])])) {
                 // key should be nodeid, not filedataid.
                 $attachmentid = $this->oldAttachments[intval($matches[2])]['nodeid'];
                 $showOldImage = $this->oldAttachments[intval($matches[2])]['cangetattachment'];
             }
         }
     }
     $cangetattachment = $this->options['do_imgcode'];
     $canseethumbnails = true;
     if ($attachmentid === false and $tempid === false) {
         // No data match was found for the attachment, so just return nothing
         return '';
     } else {
         if (!empty($this->attachments["{$attachmentid}"])) {
             // attachment specified by [attach] tag belongs to this post
             $attachment =& $this->attachments["{$attachmentid}"];
             $filedataid = $attachment['filedataid'];
             // remove attachment from array
             if ($this->unsetattach) {
                 unset($this->attachments["{$attachmentid}"]);
                 unset($this->filedataidsToAttachmentids[$filedataid][$attachmentid]);
             } else {
                 $this->delayedUnsetAttachments[$attachmentid] = array('attachmentid' => $attachmentid, 'filedataid' => $filedataid);
             }
             if (!empty($attachment['settings']) and strtolower($align) == 'config') {
                 $settings = unserialize($attachment['settings']);
             } elseif (!empty($matches['settings'])) {
                 $settings = array();
                 // Currently strictly used by VBV-12051, replacing [IMG]...?filedataid=...[/IMG] with corresponding attachment image
                 // when &amp;type=[a-z]+ or &amp;thumb=1 is part of the image url, that size is passed into us as settings from handle_bbcode_img()
                 // Nothing else AFAIK should be able to pass in the settings, but if we do add this as a main feature,
                 // we should be sure to scrub this well (either via the regex pattern or actual cleaning) to prevent xss.
                 if (isset($matches['settings']['size'])) {
                     // This cleaning is not strictly necessary since the switch-case below that uses this restricts the string to a small set, so xss is not possible.
                     $size = Api_InterfaceAbstract::instance()->callApi('filedata', 'sanitizeFiletype', array($matches['settings']['size']));
                     $settings['size'] = $size;
                 }
             } else {
                 $settings = '';
             }
             if (!$attachment['visible'] and $attachment['userid'] != self::getUserValue('userid')) {
                 // Don't show inline unless the poster is viewing the post (post preview)
                 return '';
             }
             $forceimage = false;
             if ($cangetattachment and $canseethumbnails and $attachment['resize_filesize'] == $attachment['filesize']) {
                 $attachment['hasthumbnail'] = false;
                 $forceimage = self::$viewAttachedImages;
             } else {
                 if (!$canseethumbnails) {
                     $attachment['hasthumbnail'] = false;
                 }
             }
             if (empty($attachment['extension'])) {
                 $attachment['filename'] = $this->fetchCensoredText(vB_String::htmlSpecialCharsUni($attachment['filename']));
                 $attachment['extension'] = strtolower(file_extension($attachment['filename']));
             }
             $attachment['filesize'] = vb_number_format($attachment['filesize'], 1, true);
             $lightbox_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png', 'bmp');
             $fullsize = false;
             $imgSrcSuffix = '';
             switch ($attachment['extension']) {
                 case 'gif':
                 case 'jpg':
                 case 'jpeg':
                 case 'jpe':
                 case 'png':
                 case 'bmp':
                 case 'tiff':
                 case 'tif':
                 case 'psd':
                 case 'pdf':
                     $imgclass = array();
                     $alt_text = $title_text = $caption_tag = $styles = '';
                     if ($settings) {
                         if ($settings['alignment']) {
                             switch ($settings['alignment']) {
                                 case 'left':
                                     $imgclass[] = 'align_left';
                                     break;
                                 case 'center':
                                     $imgclass[] = 'align_center';
                                     break;
                                 case 'right':
                                     $imgclass[] = 'align_right';
                                     break;
                             }
                         }
                         if (isset($settings['size'])) {
                             switch ($settings['size']) {
                                 case 'icon':
                                     // AFAIK vB4 didn't have this size, but vB5 does.
                                     $imgSrcSuffix = '&amp;type=icon';
                                     break;
                                 case 'thumb':
                                     // I think 'thumbnail' was used mostly in vB4. We lean towards the usage of 'thumb' instead in vB5.
                                 // I think 'thumbnail' was used mostly in vB4. We lean towards the usage of 'thumb' instead in vB5.
                                 case 'thumbnail':
                                     $imgSrcSuffix = '&amp;type=thumb';
                                     $imgclass[] = 'size_thumbnail';
                                     break;
                                 case 'small':
                                     // AFAIK vB4 didn't have this size, but vB5 does.
                                     $imgSrcSuffix = '&amp;type=small';
                                     break;
                                 case 'medium':
                                     $imgSrcSuffix = '&amp;type=medium';
                                     $imgclass[] = 'size_medium';
                                     break;
                                 case 'large':
                                     $imgSrcSuffix = '&amp;type=large';
                                     $imgclass[] = 'size_large';
                                     break;
                                 case 'full':
                                     // I think 'fullsize' was used mostly in vB4. We lean towards the usage of 'full' instead in vB5.
                                 // I think 'fullsize' was used mostly in vB4. We lean towards the usage of 'full' instead in vB5.
                                 case 'fullsize':
                                     $imgSrcSuffix = '&amp;type=full';
                                     $fullsize = true;
                                     break;
                                 default:
                                     break;
                             }
                         }
                         //						if ($settings['caption'])
                         //						{
                         //							$caption_tag = "<p class=\"caption $size_class\">$settings[caption]</p>";
                         //						}
                         $alt_text = $settings['title'];
                         $description_text = $settings['description'];
                         $title_text = $settings['title'];
                         $styles = $settings['styles'];
                     }
                     if (($settings or self::$viewAttachedImages == 1 and $attachment['hasthumbnail']) and self::getUserValue('showimages') and $cangetattachment) {
                         $suffixAlreadyAppended = false;
                         if (empty($link)) {
                             $link = vB_String::htmlSpecialCharsUni($this->getAttachmentLink($attachment));
                             $suffixAlreadyAppended = true;
                         }
                         if (!empty($attachment['nodeid'])) {
                             $id = 'attachment' . $attachment['nodeid'];
                         } else {
                             $id = 'filedata' . $attachment['filedataid'];
                         }
                         $link .= $imgSrcSuffix;
                         if (!empty($this->sessionSuffix) and !$suffixAlreadyAppended) {
                             // This is going into src/href attributes in HTML
                             $link .= vB_String::htmlSpecialCharsUni($this->sessionSuffix);
                         }
                         $lightbox = (!$fullsize and $cangetattachment and in_array($attachment['extension'], $lightbox_extensions));
                         $hrefbits = array('href' => "{$link}&amp;d={$attachment['dateline']}", 'id' => $id, 'class' => 'bbcode-attachment');
                         if ($lightbox) {
                             $hrefbits["rel"] = 'Lightbox_' . $this->containerid;
                         } else {
                             $hrefbits["rel"] = "nofollow";
                         }
                         //						if ($addnewwindow)
                         //						{
                         //							$hrefbits['target'] = '_blank';
                         //						}
                         $atag = '';
                         foreach ($hrefbits as $tag => $value) {
                             $atag .= "{$tag}=\"{$value}\" ";
                         }
                         $imgbits = array('src' => "{$link}&amp;d={$attachment['resize_dateline']}", 'border' => '0', 'alt' => $alt_text ? $alt_text : $this->getPhrase('image_larger_version_x_y_z', $attachment['filename'], $attachment['counter'], $attachment['filesize'], $attachment['filedataid']));
                         if (!$settings and !$this->displayimage) {
                             $imgbits['src'] .= '&amp;thumb=1';
                         }
                         if (!empty($imgclass)) {
                             $imgbits['class'] = implode(' ', $imgclass);
                         } else {
                             $imgbits['class'] = 'thumbnail';
                         }
                         if ($title_text) {
                             $imgbits['title'] = $title_text;
                         } else {
                             if (isset($description_text) and !empty($description_text)) {
                                 $imgbits['title'] = $description_text;
                             }
                         }
                         if (isset($description_text) and !empty($description_text)) {
                             $imgbits['description'] = $description_text;
                         }
                         if ($styles) {
                             $imgbits['style'] = $styles;
                         } else {
                             if (!$settings and $align and $align != '=CONFIG') {
                                 $imgbits['style'] = "float:{$align}";
                             }
                         }
                         $imgtag = '';
                         foreach ($imgbits as $tag => $value) {
                             $imgtag .= "{$tag}=\"{$value}\" ";
                         }
                         if ($fullsize) {
                             return ($fullsize ? '<div class="size_fullsize">' : '') . "<img {$imgtag}/>" . ($fullsize ? '</div>' : '');
                         } else {
                             if (isset($settings['alignment']) && $settings['alignment'] == 'center') {
                                 return "<div class=\"img_align_center " . ($fullsize ? 'size_fullsize' : '') . "\"><a {$atag}><img {$imgtag}/></a></div>";
                             } else {
                                 return ($fullsize ? '<div class="size_fullsize">' : '') . "<a {$atag}><img {$imgtag}/></a>" . ($fullsize ? '</div>' : '');
                             }
                         }
                     } else {
                         if (self::getUserValue('showimages') and ($forceimage or self::$viewAttachedImages == 3) and !in_array($attachment['extension'], array('tiff', 'tif', 'psd', 'pdf')) and $cangetattachment) {
                             $link = vB_String::htmlSpecialCharsUni($this->getAttachmentLink($attachment));
                             return ($fullsize ? '<div class="size_fullsize">' : '') . "<img src=\"" . $link . "&amp;d={$attachment['dateline']}\" border=\"0\" alt=\"" . $this->getPhrase('image_x_y_z', $attachment['filename'], $attachment['counter'], $attachment['filesize']) . "\" " . (!empty($align) ? " style=\"float: {$align}\"" : '') . " />";
                             $fullsize ? '</div>' : '';
                         } else {
                             $link = vB_String::htmlSpecialCharsUni($this->getAttachmentLink($attachment));
                             return ($fullsize ? '<div class="size_fullsize">' : '') . "<a href=\"" . $link . "&amp;d={$attachment['dateline']}\" title=\"" . $this->getPhrase('image_x_y_z', $attachment['filename'], $attachment['counter'], $attachment['filesize']) . "\">{$attachment['filename']}</a>" . ($fullsize ? '</div>' : '');
                         }
                     }
                     break;
                 default:
                     $link = vB_String::htmlSpecialCharsUni($this->getAttachmentLink($attachment));
                     return ($fullsize ? '<div class="size_fullsize">' : '') . "<a href=\"" . $link . "&amp;d={$attachment['dateline']}\" title=\"" . $this->getPhrase('image_x_y_z', $attachment['filename'], $attachment['counter'], $attachment['filesize']) . "\">{$attachment['filename']}</a>" . ($fullsize ? '</div>' : '');
             }
         } else {
             // if we have a temporaryid, then we're probably editing a post with a new attachment that doesn't have
             // a node created for the attachment yet. Let's return a basic image tag and let JS handle fixing it.
             if ($tempid and $filedataid) {
                 return "<img class=\"bbcode-attachment js-need-data-att-update\" src=\"" . self::$frontendurl . "/filedata/fetch?filedataid={$filedataid}\" data-tempid=\"" . $tempid . "\" />";
             } else {
                 // Belongs to another post so we know nothing about it ... or we are not displying images so always show a link
                 return "<a href=\"" . self::$frontendurl . "/filedata/fetch?filedataid={$attachmentid}\">" . $this->getPhrase('attachment') . " </a>";
             }
         }
     }
 }
Exemplo n.º 11
0
 /**
  *	Set the user filter
  *
  * @param string $username.  The name of the user.
  * @param bool $exactname.  If we should only look for an exact match
  * @param enum $groupuser.  If we should only search for the group user, the item user,
  *  or the default for the search type. On of the group constants in vB_Search_Core
  */
 public function add_user_filter($username, $exactmatch)
 {
     //we don't actually have a username, do nothing.
     if (!trim($username)) {
         return;
     }
     if (!$exactmatch and strlen($username) < 3) {
         $this->add_error('searchnametooshort');
         return array();
     }
     $username = vB_String::htmlSpecialCharsUni($username);
     if ($exactmatch) {
         $user = vB_Api::instanceInternal("User")->fetchByUsername($username, array(vB_Api_User::USERINFO_AVATAR));
         $userid = empty($user['userid']) ? false : $user['userid'];
     } else {
         $userid = vB::getDbAssertor()->getColumn('user', 'userid', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'username', 'value' => "{$username}", 'operator' => vB_dB_Query::OPERATOR_INCLUDES)), array('field' => 'username', 'direction' => vB_dB_Query::SORT_ASC)));
     }
     if (empty($userid)) {
         $this->add_null_filter("{$username} not found");
     } else {
         $this->add_filter('userid', vB_Search_Core::OP_EQ, $userid, true);
     }
     return $userid;
 }
Exemplo n.º 12
0
             $channel["{$title}"] = $newchannel["{$title}"];
         }
     }
     // Legacy Hook 'channeladmin_add_default' Removed //
     print_form_header('forum', 'update');
     print_table_header($vbphrase['add_new_forum_gforum']);
 } else {
     $channel = vB_Library::instance('Content_Channel')->getContent($vbulletin->GPC['nodeid']);
     if (is_array($channel)) {
         $channel = array_pop($channel);
     }
     if (empty($channel)) {
         print_stop_message2('invalid_channel_specified');
     }
     print_form_header('forum', 'update');
     print_table_header(construct_phrase($vbphrase['x_y_id_z'], $vbphrase['channel'], vB_String::htmlSpecialCharsUni($channel['title']), $channel['nodeid']));
     construct_hidden_code('nodeid', $vbulletin->GPC['nodeid']);
 }
 $channel['title'] = str_replace('&amp;', '&', $channel['title']);
 $channel['description'] = str_replace('&amp;', '&', $channel['description']);
 print_input_row($vbphrase['title'], 'channel[title]', $channel['title']);
 print_textarea_row($vbphrase['description_gcpglobal'], 'channel[description]', $channel['description']);
 //print_input_row($vbphrase['forum_link'], 'forum[link]', $forum['link']);
 print_input_row("{$vbphrase['display_order']}<dfn>{$vbphrase['zero_equals_no_display']}</dfn>", 'channel[displayorder]', $channel['displayorder']);
 //print_input_row($vbphrase['default_view_age'], 'forum[daysprune]', $forum['daysprune']);
 if ($vbulletin->GPC['nodeid'] != -1) {
     if (!isset($channel['guid']) or $channel['guid'] != vB_Channel::MAIN_CHANNEL and !in_array($channel['nodeid'], vB_Api::instance('content_channel')->fetchTopLevelChannelIds())) {
         print_channel_chooser($vbphrase['parent_forum'], 'channel[parentid]', $channel['parentid'], false, false, false, null, true);
     }
 } else {
     construct_hidden_code('parentid', 0);
Exemplo n.º 13
0
 /**
  * Builds description tag content used in RSS outputs.
  *
  * 	@param 		String 	Text to build description from.
  *	@param 		Array 	Options to consider building description.
  *
  * 	@return 	String 	Description.
  *
  */
 protected function getItemDescription($text, $options)
 {
     // @TODO VBV-11108 description should be plain text only, replace this to use plain text parser when implemented
     if (!empty($options['fulldesc'])) {
         $description = vB_String::htmlSpecialCharsUni(vB_String::fetchCensoredText(vB_String::stripBbcode($text, true, false, true, true)));
     } else {
         $description = vB_String::htmlSpecialCharsUni(vB_String::fetchCensoredText(vB_String::fetchTrimmedTitle(vB_String::stripBbcode($text, true, false, true, true), vB::getDatastore()->getOption('threadpreview'))));
     }
     return $description;
 }
Exemplo n.º 14
0
    $anncdata->set('pagetext', $vbulletin->GPC['pagetext']);
    $anncdata->set('nodeid', $vbulletin->GPC['nodeid']);
    $anncdata->set('startdate', $vbulletin->GPC['startdate']);
    $anncdata->set('enddate', $vbulletin->GPC['enddate'] + 86399);
    foreach ($vbulletin->GPC['announcementoptions'] as $key => $val) {
        $anncdata->set_bitfield('announcementoptions', $key, $val);
    }
    $announcementid = $anncdata->save();
    if ($original_data) {
        if ($vbulletin->GPC['reset_views']) {
            // @TODO define how we dealing with this...
            $assertor->delete("vBForum:announcementread", array('announcementid' => $vbulletin->GPC['announcementid']));
        }
    }
    vB_Cache::instance(vB_Cache::CACHE_STD)->event('vB_AnnouncementChg');
    print_stop_message2(array('saved_announcement_x_successfully', vB_String::htmlSpecialCharsUni($vbulletin->GPC['title'])), 'announcement');
}
// ###################### Start Remove #######################
if ($_REQUEST['do'] == 'remove') {
    $vbulletin->input->clean_array_gpc('r', array('announcementid' => vB_Cleaner::TYPE_UINT));
    print_delete_confirmation('announcement', $vbulletin->GPC['announcementid'], 'announcement', 'kill', 'announcement');
}
// ###################### Start Kill #######################
if ($_POST['do'] == 'kill') {
    $vbulletin->input->clean_array_gpc('p', array('announcementid' => vB_Cleaner::TYPE_UINT));
    $announcement = vB::getDbAssertor()->assertQuery('vBForum:announcement', array(vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'announcementid', 'operator' => vB_dB_Query::OPERATOR_EQ, 'value' => $vbulletin->GPC['announcementid']))));
    if ($announcement and $announcement->valid()) {
        $announcement = $announcement->current();
        $anncdata =& datamanager_init('Announcement', $vbulletin, vB_DataManager_Constants::ERRTYPE_CP);
        $anncdata->set_existing($announcement);
        $anncdata->delete();
Exemplo n.º 15
0
 private function json2criteria(&$json)
 {
     if (is_string($json)) {
         $search_structure = json_decode($json, true);
     } else {
         $search_structure = $json;
     }
     if (empty($search_structure) or !is_array($search_structure)) {
         throw new vB_Exception_Api('invalid_search_syntax', array($json));
     }
     $criteria = new vB_Search_Criteria();
     $def_sort_field = 'created';
     $def_sort_dir = 'DESC';
     $currentUserId = vB::getCurrentSession()->get('userid');
     $criteria->setUser($currentUserId);
     $normalized_criteria = array();
     if (!empty($search_structure['keywords'])) {
         $words = $criteria->add_keyword_filter($search_structure['keywords'], !empty($search_structure['title_only']));
         $def_sort_field = 'lastcontent';
         if (!empty($words)) {
             $normalized_criteria['keywords'] = '';
             $separator = '';
             foreach ($words as $word) {
                 if (!empty($word['joiner'])) {
                     $normalized_criteria['keywords'] .= $separator . strtoupper($word['joiner']);
                     $separator = ' ';
                 }
                 $normalized_criteria['keywords'] .= $separator . $word['word'];
                 $separator = ' ';
             }
             if (!empty($search_structure['title_only'])) {
                 $normalized_criteria['title_only'] = 1;
             }
         } else {
             $normalized_criteria['error'] = 'ignored_search_keywords';
         }
         $ignored_words = $criteria->get_ignored_keywords();
         if (!empty($ignored_words)) {
             $normalized_criteria['ignored_words'] = $ignored_words;
             $normalized_criteria['original_keywords'] = $search_structure['keywords'];
         }
     }
     if (!empty($search_structure['contenttypeid'])) {
         $search_structure['type'] = vB_Types::instance()->getContentTypeClasses($search_structure['contenttypeid']);
         if (count($search_structure['type']) == 1) {
             $search_structure['type'] = array_pop($search_structure['type']);
         }
         unset($search_structure['contenttypeid']);
     }
     if (!empty($search_structure['type'])) {
         $contentypeids = $criteria->add_contenttype_filter($search_structure['type']);
         $normalized_criteria['type'] = $search_structure['type'];
         $pmcontentypeid = vB_Types::instance()->getContentTypeID('vBForum_PrivateMessage');
         if (in_array($pmcontentypeid, $contentypeids)) {
             if (count($contentypeids) == 1) {
                 $search_structure['private_messages_only'] = 1;
             } else {
                 $search_structure['include_private_messages'] = 1;
             }
         }
         $vmcontentypeid = vB_Types::instance()->getContentTypeID('vBForum_VisitorMessage');
         if (in_array($vmcontentypeid, $contentypeids)) {
             if (count($contentypeids) == 1) {
                 $search_structure['visitor_messages_only'] = 1;
             } else {
                 $search_structure['include_visitor_messages'] = 1;
             }
         }
         $photocontentypeid = vB_Api::instanceInternal('contenttype')->fetchContentTypeIdFromClass('Photo');
         if (in_array($photocontentypeid, $contentypeids)) {
             $search_structure['include_attach'] = 1;
         }
     } elseif (empty($search_structure['exclude_type']) or is_string($search_structure['exclude_type']) and $search_structure['exclude_type'] != 'vBForum_PrivateMessage' or is_array($search_structure['exclude_type']) and !in_array('vBForum_PrivateMessage', $search_structure['exclude_type'])) {
         $search_structure['include_private_messages'] = 1;
     } elseif (!empty($search_structure['exclude_type']) and (is_string($search_structure['exclude_type']) and $search_structure['exclude_type'] == 'vBForum_VisitorMessage' or is_array($search_structure['exclude_type']) and in_array('vBForum_VisitorMessage', $search_structure['exclude_type']))) {
         $search_structure['exclude_visitor_messages'] = 1;
     }
     if (empty($search_structure['type']) and empty($search_structure['exclude_visitor_messages']) and (empty($search_structure['exclude_type']) or is_string($search_structure['exclude_type']) and $search_structure['exclude_type'] != 'vBForum_VisitorMessage' or is_array($search_structure['exclude_type']) and !in_array('vBForum_VisitorMessage', $search_structure['exclude_type']))) {
         $search_structure['include_visitor_messages'] = 1;
     }
     // author by username
     if (!empty($search_structure['author'])) {
         //reducing users from array to single
         if (is_array($search_structure['author']) and count($search_structure['author']) == 1) {
             $search_structure['author'] = array_pop($search_structure['author']);
             $search_structure['exactname'] = 1;
         }
         // only one username
         if (is_string($search_structure['author'])) {
             // it's an exact username - no partial match
             if (!empty($search_structure['exactname'])) {
                 $search_structure['author'] = trim($search_structure['author']);
                 switch ($search_structure['author']) {
                     case 'myFriends':
                         $userid = array();
                         if (!empty($currentUserId)) {
                             $userid = vB::getDbAssertor()->getColumn('userlist', 'relationid', array('userid' => $currentUserId, 'friend' => 'yes'), false, 'relationid');
                         }
                         $criteria->add_filter('userid', vB_Search_Core::OP_EQ, $userid, true);
                         break;
                     case 'iFollow':
                         if (empty($search_structure[self::FILTER_FOLLOW])) {
                             $search_structure[self::FILTER_FOLLOW] = self::FILTER_FOLLOWING_USERS;
                         } elseif ($search_structure[self::FILTER_FOLLOW] == self::FILTER_FOLLOWING_CHANNEL) {
                             $search_structure[self::FILTER_FOLLOW] = self::FILTER_FOLLOWING_BOTH;
                         }
                         break;
                     default:
                         $criteria->add_user_filter($search_structure['author'], !empty($search_structure['exactname']));
                         break;
                 }
                 $normalized_criteria['author'] = strtolower($search_structure['author']);
                 $normalized_criteria['exactname'] = 1;
             } elseif (vb_String::vbStrlen($search_structure['author']) >= 3) {
                 $criteria->add_user_filter($search_structure['author'], !empty($search_structure['exactname']));
                 $normalized_criteria['author'] = strtolower($search_structure['author']);
             }
         } elseif (is_array($search_structure['author'])) {
             $user_names = array();
             foreach ($search_structure['author'] as $author) {
                 $author = vB_String::htmlSpecialCharsUni($author);
                 $user = vB_Api::instanceInternal("User")->fetchByUsername($author);
                 $userid = false;
                 if (!empty($user['userid'])) {
                     $user_ids[] = $user['userid'];
                     $user_names[] = $user['username'];
                 }
             }
             if (!empty($user_ids)) {
                 $criteria->add_filter('userid', vB_Search_Core::OP_EQ, $user_ids, true);
             } else {
                 $criteria->add_null_filter('no record matches usernames');
             }
             sort($user_names);
             $normalized_criteria['author'] = $user_names;
         }
     }
     // author by userid
     if (!empty($search_structure['authorid'])) {
         //reducing users from array to single
         if (is_array($search_structure['authorid']) and count($search_structure['authorid']) == 1) {
             $search_structure['authorid'] = array_pop($search_structure['authorid']);
         }
         if (is_numeric($search_structure['authorid'])) {
             if (!empty($search_structure['visitor_messages_only'])) {
                 $criteria->add_filter('visitor_messages_only', vB_Search_Core::OP_EQ, $search_structure['authorid']);
                 $normalized_criteria['visitor_messages_only'] = 1;
             } elseif (!empty($search_structure['include_visitor_messages'])) {
                 $criteria->add_filter('include_visitor_messages', vB_Search_Core::OP_EQ, $search_structure['authorid']);
                 $normalized_criteria['include_visitor_messages'] = 1;
             } else {
                 $criteria->add_filter('userid', vB_Search_Core::OP_EQ, $search_structure['authorid'], true);
             }
             if (!empty($search_structure['exclude_visitor_messages'])) {
                 $criteria->add_filter('exclude_visitor_messages', vB_Search_Core::OP_EQ, $search_structure['authorid']);
                 $normalized_criteria['exclude_visitor_messages'] = 1;
             }
             $normalized_criteria['authorid'] = $search_structure['authorid'];
         } elseif (is_array($search_structure['authorid'])) {
             $user_ids = array();
             foreach ($search_structure['authorid'] as $author) {
                 if (is_numeric($author)) {
                     $user_ids[] = intval($author);
                 }
             }
             $criteria->add_filter('userid', vB_Search_Core::OP_EQ, $user_ids, true);
             $normalized_criteria['authorid'] = sort($user_ids);
         }
     } else {
         if (!empty($search_structure['exclude_visitor_messages'])) {
             $criteria->add_filter('exclude_visitor_messages', vB_Search_Core::OP_EQ, 0);
             $normalized_criteria['exclude_visitor_messages'] = 1;
         }
     }
     // channel owner filter
     if (!empty($search_structure['my_channels'])) {
         $temp = array();
         // restrict 'type' to string 'blog' or 'group', else default to 'blog'
         if (isset($search_structure['my_channels']['type']) and ($search_structure['my_channels']['type'] == 'blog' or $search_structure['my_channels']['type'] == 'group')) {
             $temp['type'] = $search_structure['my_channels']['type'];
         } else {
             $temp['type'] = 'blog';
         }
         $normalized_criteria['my_channels'] = $temp;
         $criteria->add_filter('my_channels', vB_Search_Core::OP_EQ, $temp);
         unset($temp);
     }
     if (!empty($search_structure['private_messages_only'])) {
         $criteria->add_filter('private_messages_only', vB_Search_Core::OP_EQ, $currentUserId);
         $normalized_criteria['private_messages_only'] = 1;
     }
     // visitor message recipient
     if (!empty($search_structure['sentto'])) {
         //reducing users from array to single
         if (is_array($search_structure['sentto']) and count($search_structure['sentto']) == 1) {
             $search_structure['sentto'] = array_pop($search_structure['sentto']);
         }
         if (is_numeric($search_structure['sentto'])) {
             $criteria->add_filter('sentto', vB_Search_Core::OP_EQ, intval($search_structure['sentto']));
             $normalized_criteria['visitor_messages_only'] = 1;
             $normalized_criteria['sentto'] = intval($search_structure['sentto']);
         } elseif (is_array($search_structure['sentto'])) {
             $user_ids = array_map('intval', $search_structure['sentto']);
             sort($user_ids);
             $criteria->add_filter('sentto', vB_Search_Core::OP_EQ, $user_ids);
             $normalized_criteria['visitor_messages_only'] = 1;
             $normalized_criteria['sentto'] = $user_ids;
         }
     }
     if (!empty($search_structure['tag'])) {
         if (is_array($search_structure['tag'])) {
             foreach ($search_structure['tag'] as $index => $tag) {
                 $search_structure['tag'][$index] = vB_String::htmlSpecialCharsUni(trim($tag));
             }
         } else {
             $search_structure['tag'] = vB_String::htmlSpecialCharsUni(trim($search_structure['tag']));
         }
         $existing_tags = $criteria->add_tag_filter($search_structure['tag']);
         $normalized_criteria['tag'] = array_keys($existing_tags);
         vB_Api::instanceInternal('Tags')->logSearchTags($existing_tags);
     }
     if (!empty($search_structure['date'])) {
         if ($search_structure['date'] == self::FILTER_LASTVISIT) {
             $current_user = new vB_Legacy_CurrentUser();
             $dateline = $current_user->get_field('lastvisit');
             if (empty($dateline)) {
                 $dateline = vB::getRequest()->getTimeNow() - 86400 * 14;
             }
             $criteria->add_date_filter(vB_Search_Core::OP_GT, $dateline);
             $normalized_criteria['date'] = self::FILTER_LASTVISIT;
         }
         if ($search_structure['date'] == self::FILTER_TOPICAGE) {
             $age = vB::getDatastore()->getOption('max_age_topic');
             if (intval($age) == 0) {
                 $age = 60;
             }
             $criteria->add_date_filter(vB_Search_Core::OP_GT, vB::getRequest()->getTimeNow() - 86400 * $age);
             $normalized_criteria['date'] = self::FILTER_TOPICAGE;
         }
         if ($search_structure['date'] == self::FILTER_CHANNELAGE) {
             $age = vB::getDatastore()->getOption('max_age_channel');
             if (intval($age) == 0) {
                 $age = 60;
             }
             $criteria->add_date_filter(vB_Search_Core::OP_GT, vB::getRequest()->getTimeNow() - 86400 * $age);
             $normalized_criteria['date'] = self::FILTER_CHANNELAGE;
         }
         // forcing to get the whole date spectrum; activity stream view enforces a date range so this is the workaround
         if (!empty($search_structure['date']) and is_string($search_structure['date']) and $search_structure['date'] == self::FILTER_DATEALL) {
             $criteria->add_date_filter(vB_Search_Core::OP_EQ, self::FILTER_DATEALL);
             $normalized_criteria['date'] = self::FILTER_DATEALL;
         }
         if (is_array($search_structure['date']) and !empty($search_structure['date']['from'])) {
             $dateline = $this->computeDateLine($search_structure['date']['from']);
             if (!empty($dateline)) {
                 $criteria->add_date_filter(vB_Search_Core::OP_GT, $dateline);
                 $normalized_criteria['date']['from'] = $search_structure['date']['from'];
             }
         }
         if (is_array($search_structure['date']) and !empty($search_structure['date']['to'])) {
             $dateline = $this->computeDateLine($search_structure['date']['to'], true);
             if (!empty($dateline)) {
                 $criteria->add_date_filter(vB_Search_Core::OP_LT, $dateline);
                 $normalized_criteria['date']['to'] = $search_structure['date']['to'];
             }
         }
     }
     if (!empty($search_structure['last'])) {
         if (is_array($search_structure['last']) and !empty($search_structure['last']['from'])) {
             $dateline = $this->computeDateLine($search_structure['last']['from']);
             if (!empty($dateline)) {
                 $criteria->add_last_filter(vB_Search_Core::OP_GT, $dateline);
                 $normalized_criteria['last']['from'] = $search_structure['last']['from'];
             }
         }
         if (is_array($search_structure['last']) and !empty($search_structure['last']['to'])) {
             $dateline = $this->computeDateLine($search_structure['last']['to'], true);
             if (!empty($dateline)) {
                 $criteria->add_last_filter(vB_Search_Core::OP_LT, $dateline);
                 $normalized_criteria['last']['to'] = $search_structure['last']['to'];
             }
         }
     }
     if (!empty($search_structure['exclude'])) {
         $criteria->add_exclude_filter($search_structure['exclude']);
         $normalized_criteria['exclude'] = $search_structure['exclude'];
     }
     if (empty($search_structure['sort'])) {
         $search_structure['sort'] = array($def_sort_field => $def_sort_dir);
     }
     if (!is_array($search_structure['sort'])) {
         $sort_dir = $def_sort_dir;
         if (strtolower($search_structure['sort']) == 'title') {
             $sort_dir = 'ASC';
         }
         $search_structure['sort'] = array($search_structure['sort'] => $sort_dir);
     }
     foreach ($search_structure['sort'] as $sort_field => $sort_dir) {
         $criteria->set_sort($sort_field, strtoupper($sort_dir));
     }
     if ($sort_field != $def_sort_field or $sort_dir != $def_sort_dir) {
         $normalized_criteria['sort'] = array($sort_field => strtoupper($sort_dir));
     }
     if (!empty($search_structure['view'])) {
         if ($search_structure['view'] == vB_Api_Search::FILTER_VIEW_CONVERSATION_STREAM and !empty($search_structure['channel'])) {
             $search_structure['depth'] = 2;
             $search_structure['include_starter'] = true;
         } elseif ($search_structure['view'] == vB_Api_Search::FILTER_VIEW_CONVERSATION_THREAD and !empty($search_structure['channel'])) {
             $search_structure['depth'] = 1;
             $search_structure['include_starter'] = true;
         } else {
             $criteria->add_view_filter($search_structure['view']);
             $normalized_criteria['view'] = $search_structure['view'];
         }
     }
     if (!empty($search_structure['starter_only'])) {
         $criteria->add_filter('starter_only', vB_Search_Core::OP_EQ, true);
         $search_structure['include_starter'] = true;
         $normalized_criteria['starter_only'] = 1;
     }
     if (!empty($search_structure['reply_only'])) {
         $criteria->add_filter('reply_only', vB_Search_Core::OP_EQ, true);
         $search_structure['include_starter'] = false;
         $normalized_criteria['reply_only'] = 1;
     }
     if (!empty($search_structure['comment_only'])) {
         $criteria->add_filter('comment_only', vB_Search_Core::OP_EQ, true);
         $search_structure['include_starter'] = false;
         $normalized_criteria['comment_only'] = 1;
     }
     if (!empty($search_structure['channel'])) {
         $criteria->add_channel_filter($search_structure['channel'], empty($search_structure['depth']) ? false : $search_structure['depth'], empty($search_structure['include_starter']) ? false : true, empty($search_structure['depth_exact']) ? false : true);
         $normalized_criteria['channel'] = $search_structure['channel'];
         if (!empty($search_structure['depth'])) {
             $normalized_criteria['depth'] = $search_structure['depth'];
         }
         if (!empty($search_structure['depth_exact'])) {
             $normalized_criteria['depth_exact'] = true;
         }
         if (!empty($search_structure['include_starter'])) {
             $normalized_criteria['include_starter'] = 1;
         }
     }
     if (!empty($search_structure['featured'])) {
         $criteria->add_filter('featured', vB_Search_Core::OP_EQ, $search_structure['featured']);
         $normalized_criteria['featured'] = 1;
     }
     if (!empty($search_structure[self::FILTER_FOLLOW])) {
         if (is_string($search_structure[self::FILTER_FOLLOW]) and !empty($currentUserId)) {
             $criteria->add_follow_filter($search_structure[self::FILTER_FOLLOW], $currentUserId);
             $normalized_criteria[self::FILTER_FOLLOW] = $search_structure[self::FILTER_FOLLOW];
         } elseif (is_array($search_structure[self::FILTER_FOLLOW])) {
             list($type, $userid) = each($search_structure[self::FILTER_FOLLOW]);
             //if ($userid == $currentUserId)
             //{
             $criteria->add_follow_filter($type, $userid);
             $normalized_criteria[self::FILTER_FOLLOW] = $search_structure[self::FILTER_FOLLOW];
             //}
         }
     }
     if (!empty($search_structure['my_following']) and !empty($currentUserId)) {
         $criteria->add_follow_filter(self::FILTER_FOLLOWING_CHANNEL, $currentUserId);
         $normalized_criteria['my_following'] = $search_structure['my_following'];
     }
     if (!empty($search_structure['exclude_type'])) {
         $criteria->add_contenttype_filter($search_structure['exclude_type'], vB_Search_Core::OP_NEQ);
         $normalized_criteria['exclude_type'] = $search_structure['exclude_type'];
     }
     if (!empty($search_structure['sticky_only'])) {
         $criteria->add_filter('sticky', vB_Search_Core::OP_EQ, '1');
         $normalized_criteria['sticky_only'] = 1;
     }
     if (!empty($search_structure['exclude_sticky'])) {
         $criteria->add_filter('sticky', vB_Search_Core::OP_NEQ, '1');
         $normalized_criteria['exclude_sticky'] = 1;
     }
     if (!empty($search_structure['include_sticky'])) {
         $criteria->set_include_sticky();
         $normalized_criteria['include_sticky'] = 1;
     }
     if (empty($search_structure['include_blocked']) or empty($currentUserId) or !vB::getUserContext()->hasPermission('moderatorpermissions', 'canbanusers')) {
         //block people on the global ignore list.
         $globalignore = trim(vB::getDatastore()->getOption('globalignore'));
         if (!empty($globalignore)) {
             $blocked = preg_split('#\\s+#s', $globalignore, -1, PREG_SPLIT_NO_EMPTY);
             //the user can always see their own posts, so if they are in the blocked list we remove them
             if (!empty($currentUserId)) {
                 $bbuserkey = array_search($currentUserId, $blocked);
                 if ($bbuserkey !== FALSE and $bbuserkey !== NULL) {
                     unset($blocked["{$bbuserkey}"]);
                 }
             }
             //Make sure we didn't just empty the list
             if (!empty($blocked)) {
                 $criteria->add_filter('userid', vB_Search_Core::OP_NEQ, $blocked, false, true);
             }
         }
     } elseif (!empty($currentUserId) and vB::getUserContext()->hasPermission('moderatorpermissions', 'canbanusers')) {
         $normalized_criteria['include_blocked'] = 1;
     }
     if (empty($search_structure['include_blocked']) and !empty($currentUserId)) {
         $currentUserInfo = vB_User::fetchUserinfo($currentUserId);
         if (!empty($currentUserInfo['ignorelist'])) {
             $criteria->add_filter('userid', vB_Search_Core::OP_NEQ, explode(' ', $currentUserInfo['ignorelist']), false, true);
         }
     }
     if (!empty($search_structure['ignore_protected'])) {
         $criteria->add_filter('protected', vB_Search_Core::OP_NEQ, '1');
         $normalized_criteria['ignore_protected'] = 1;
     }
     if (!empty($search_structure['deleted_only']) and !empty($currentUserId) and vB::getUserContext()->hasPermission('moderatorpermissions', 'canremoveposts')) {
         $criteria->add_filter('showpublished', vB_Search_Core::OP_EQ, '0');
         $criteria->add_filter('deleteuserid', vB_Search_Core::OP_NEQ, '0');
         $normalized_criteria['deleted_only'] = 1;
     }
     if (!empty($search_structure['exclude_deleted'])) {
         $criteria->add_filter('showpublished', vB_Search_Core::OP_EQ, '1');
         $normalized_criteria['exclude_deleted'] = 1;
     }
     if (empty($search_structure['include_attach'])) {
         $criteria->add_filter('inlist', vB_Search_Core::OP_EQ, 1);
     } else {
         $normalized_criteria['include_attach'] = 1;
     }
     if (!empty($search_structure['unapproved_only']) and !empty($currentUserId) and vB::getUserContext()->hasPermission('moderatorpermissions', 'canmanagethreads')) {
         $criteria->add_filter('approved', vB_Search_Core::OP_NEQ, '1');
         $normalized_criteria['unapproved_only'] = 1;
     }
     if (!empty($search_structure['unread_only']) and !empty($currentUserId) and vB::getDatastore()->getOption('threadmarking') > 0) {
         $criteria->add_filter('marked', vB_Search_Core::OP_EQ, self::FILTER_MARKED_UNREAD);
         $normalized_criteria['unread_only'] = 1;
     }
     if (!empty($search_structure['specific'])) {
         $criteria->add_filter('nodeid', vB_Search_Core::OP_EQ, $search_structure['specific']);
         $normalized_criteria['specific'] = $search_structure['specific'];
     }
     if (!empty($search_structure['prefix'])) {
         $normalized_criteria['prefix'] = $search_structure['prefix'];
         $criteria->add_filter('prefixid', vB_Search_Core::OP_EQ, $search_structure['prefix']);
     }
     if (!empty($search_structure['has_prefix'])) {
         $normalized_criteria['has_prefix'] = 1;
         $criteria->add_filter('prefixid', vB_Search_Core::OP_NEQ, '');
     }
     if (!empty($search_structure['no_prefix'])) {
         $normalized_criteria['no_prefix'] = 0;
         $criteria->add_filter('prefixid', vB_Search_Core::OP_EQ, '');
     }
     // private messages are included by default. Use the exclude_type filter to exlude them
     // they are not included if a specific channel is requested OR looking for visitor messages
     if (!empty($search_structure['include_private_messages']) and empty($normalized_criteria['private_messages_only']) and empty($normalized_criteria['sentto']) and (empty($normalized_criteria['channel']) or is_numeric($normalized_criteria['channel']) and !in_array($normalized_criteria['channel'], array(vB_Channel::MAIN_CHANNEL, vB_Channel::DEFAULT_CHANNEL_PARENT, vB_Channel::PRIVATEMESSAGE_CHANNEL)) or is_array($normalized_criteria['channel']) and count(array_intersect($normalized_criteria['channel'], array(vB_Channel::MAIN_CHANNEL, vB_Channel::DEFAULT_CHANNEL_PARENT, vB_Channel::PRIVATEMESSAGE_CHANNEL))) == 0) and empty($normalized_criteria['my_channels'])) {
         $criteria->add_filter('include_private_messages', vB_Search_Core::OP_EQ, $currentUserId);
     }
     if (!empty($search_structure['nolimit']) and !empty($normalized_criteria['channel']) and (empty($normalized_criteria['view']) or $normalized_criteria['view'] != self::FILTER_VIEW_ACTIVITY) and empty($search_structure['author']) and empty($search_structure['authorid']) and empty($search_structure['keywords']) and empty($search_structure['sentto']) and empty($search_structure['private_messages_only']) and empty($search_structure['tag']) and empty($search_structure['featured']) and empty($search_structure['my_following']) and empty($search_structure['unapproved_only']) and empty($search_structure['unread_only'])) {
         $normalized_criteria['nolimit'] = 1;
         $criteria->setNoLimit();
     }
     // Two pass caching can be disabled by either ignore_cache which
     // also disabled the searchlog table or by specifying 'disable_two_pass'
     // Two pass caching can be forced on when 'ignore_cache' has been called
     // by specifying 'force_two_pass' (for unit testing the two pass cache functionality itself)
     if (!empty($search_structure['ignore_cache']) or self::IGNORE_CACHE) {
         $normalized_criteria['disable_two_pass'] = 1;
         $criteria->setIgnoreCache(true);
     }
     if (!empty($search_structure['disable_two_pass'])) {
         $normalized_criteria['disable_two_pass'] = 1;
     }
     if (!empty($search_structure['force_two_pass']) and !empty($normalized_criteria['disable_two_pass'])) {
         unset($normalized_criteria['disable_two_pass']);
     }
     //checking for a restrictive filter
     if (empty($normalized_criteria['keywords']) and empty($normalized_criteria['authorid']) and empty($normalized_criteria['author']) and empty($normalized_criteria['private_messages_only']) and empty($normalized_criteria['visitor_messages_only']) and empty($normalized_criteria['sentto']) and empty($normalized_criteria['tag']) and (empty($normalized_criteria['date']) or is_string($normalized_criteria['date']) and $normalized_criteria['date'] == self::FILTER_DATEALL) and (empty($normalized_criteria['last']) or is_string($normalized_criteria['last']) and $normalized_criteria['last'] == self::FILTER_DATEALL) and empty($normalized_criteria['channel']) and empty($normalized_criteria['featured']) and empty($normalized_criteria[self::FILTER_FOLLOW]) and empty($normalized_criteria['my_following']) and empty($normalized_criteria['sticky_only']) and empty($normalized_criteria['deleted_only']) and empty($normalized_criteria['unapproved_only']) and empty($normalized_criteria['unread_only']) and empty($normalized_criteria['specific']) and empty($normalized_criteria['prefix']) and empty($normalized_criteria['has_prefix']) and empty($normalized_criteria['no_prefix']) and empty($normalized_criteria['my_channels'])) {
         //temporary solution for VBV-10061
         if ($normalized_criteria['view'] == self::FILTER_VIEW_ACTIVITY) {
             $dateline = $this->computeDateLine(self::FILTER_LASTMONTH);
             if (!empty($dateline)) {
                 $criteria->add_date_filter(vB_Search_Core::OP_GT, $dateline);
             }
         } else {
             throw new vB_Exception_Api('criteria_not_restrictive', array($normalized_criteria));
         }
     }
     $criteria->setJSON($normalized_criteria);
     $json = $normalized_criteria;
     // allow the clients to send custom fields that will be preserved
     if (!empty($search_structure['custom'])) {
         $json['custom'] = $search_structure['custom'];
     }
     return $criteria;
 }
Exemplo n.º 16
0
 /**
  * This is copied from the blog bbcode parser. We either have a specific
  * amount of text, or [PRBREAK][/PRBREAK].
  *
  * @param	string	text to parse
  * @param	integer	Length of the text before parsing (optional)
  * @param	boolean Flag to indicate whether do html or not
  * @param	boolean Flag to indicate whether to convert new lines to <br /> or not
  * @param	string	Defines how to handle html while parsing.
  * @param	array	Extra options for parsing.
  * 					'do_smilies' => boolean used to handle the smilies display
  *
  * @return	array	Tokens, chopped to the right length.
  */
 public function getPreview($pagetext, $initial_length = 0, $do_html = false, $do_nl2br = true, $htmlstate = null, $options = array())
 {
     if ($htmlstate) {
         switch ($htmlstate) {
             case 'on':
                 $do_nl2br = false;
                 break;
             case 'off':
                 $do_html = false;
                 break;
             case 'on_nl2br':
                 $do_nl2br = true;
                 break;
         }
     }
     $do_smilies = isset($options['do_smilies']) ? (bool) $options['do_smilies'] : true;
     $this->options = array('do_html' => $do_html, 'do_smilies' => $do_smilies, 'do_bbcode' => true, 'do_imgcode' => false, 'do_nl2br' => $do_nl2br, 'cachable' => true);
     if (!$do_html) {
         $pagetext = vB_String::htmlSpecialCharsUni($pagetext);
     }
     $html_count = 0;
     $pagetext = $this->parse_whitespace_newlines(trim(strip_quotes($pagetext)), $do_nl2br);
     $tokens = $this->fix_tags($this->build_parse_array($pagetext));
     if ($do_html) {
         // Count the number of html tag chars
         $html_count = strlen($pagetext) - strlen(strip_tags($pagetext));
     }
     $counter = 0;
     $stack = array();
     $new = array();
     $over_threshold = false;
     if (!empty($options['allowPRBREAK']) and strpos($pagetext, '[PRBREAK][/PRBREAK]')) {
         $this->snippet_length = strlen($pagetext);
     } else {
         if (intval($initial_length)) {
             $this->snippet_length = $initial_length + $html_count;
         } else {
             if (empty($this->default_previewlen)) {
                 $this->default_previewlen = vB::getDatastore()->getOption('previewLength');
                 if (empty($this->default_previewlen)) {
                     $this->default_previewlen = 200;
                 }
             }
             $this->snippet_length = $this->default_previewlen + $html_count;
         }
     }
     $noparse = false;
     $video = false;
     $in_page = false;
     foreach ($tokens as $tokenid => $token) {
         if (!empty($token['name']) and $token['name'] == 'noparse' and $do_html) {
             //can't parse this. We don't know what's inside.
             $new[] = $token;
             $noparse = !$noparse;
         } else {
             if (!empty($token['name']) and $token['name'] == 'video') {
                 $video = !$token['closing'];
                 continue;
             } else {
                 if (!empty($token['name']) and $token['name'] == 'page') {
                     $in_page = !$token['closing'];
                     continue;
                 } else {
                     if ($video or $in_page) {
                         continue;
                     } else {
                         if ($token['type'] == 'text') {
                             if ($over_threshold) {
                                 continue;
                             }
                             if (!$noparse) {
                                 //If this has [ATTACH] or [IMG] or VIDEO then we nuke it.
                                 $pagetext = preg_replace('#\\[ATTACH.*?\\[/ATTACH\\]#si', '', $token['data']);
                                 $pagetext = preg_replace('#\\[IMG.*?\\[/IMG\\]#si', '', $pagetext);
                                 $pagetext = preg_replace('#\\[video.*?\\[/video\\]#si', '', $pagetext);
                                 if ($pagetext == '') {
                                     continue;
                                 }
                                 if ($trim = stripos($pagetext, '[PRBREAK][/PRBREAK]')) {
                                     $pagetext = substr($pagetext, 0, $trim);
                                     $over_threshold = true;
                                 }
                                 $token['data'] = $pagetext;
                             }
                             $length = vB_String::vbStrlen($token['data']);
                             // uninterruptable means that we will always show until this tag is closed
                             $uninterruptable = (isset($stack[0]) and isset($this->uninterruptable["{$stack['0']}"]));
                             if ($counter + $length < $this->snippet_length or $uninterruptable or $noparse) {
                                 // this entry doesn't push us over the threshold
                                 $new[] = $token;
                                 $counter += $length;
                             } else {
                                 // a text entry that pushes us over the threshold
                                 $over_threshold = true;
                                 $last_char_pos = $this->snippet_length - $counter - 1;
                                 // this is the threshold char; -1 means look for a space at it
                                 if ($last_char_pos < 0) {
                                     $last_char_pos = 0;
                                 }
                                 if (preg_match('#\\s#s', $token['data'], $match, PREG_OFFSET_CAPTURE, $last_char_pos)) {
                                     if ($do_html) {
                                         $token['data'] = strip_tags($token['data']);
                                     }
                                     $token['data'] = substr($token['data'], 0, $match[0][1]);
                                     // chop to offset of whitespace
                                     if (substr($token['data'], -3) == '<br') {
                                         // we cut off a <br /> code, so just take this out
                                         $token['data'] = substr($token['data'], 0, -3);
                                     }
                                     $new[] = $token;
                                 } else {
                                     if ($do_html) {
                                         $token['data'] = strip_tags($token['data']);
                                     }
                                     $token['data'] = substr($token['data'], 0, $last_char_pos);
                                     if (substr($token['data'], -3) == '<br') {
                                         // we cut off a <br /> code, so just take this out
                                         $token['data'] = substr($token['data'], 0, -3);
                                     }
                                     $new[] = $token;
                                 }
                                 break;
                             }
                         } else {
                             // not a text entry
                             if ($token['type'] == 'tag') {
                                 //If we have a prbreak we are done.
                                 if ($token['name'] == 'prbreak' and isset($tokens[intval($tokenid) + 1]) and $tokens[intval($tokenid) + 1]['name'] == 'prbreak' and $tokens[intval($tokenid) + 1]['closing']) {
                                     $over_threshold == true;
                                     break;
                                 }
                                 // build a stack of open tags
                                 if ($token['closing'] == true) {
                                     // by now, we know the stack is sane, so just remove the first entry
                                     array_shift($stack);
                                 } else {
                                     array_unshift($stack, $token['name']);
                                 }
                             }
                             $new[] = $token;
                         }
                     }
                 }
             }
         }
     }
     // since we may have cut the text, close any tags that we left open
     foreach ($stack as $tag_name) {
         $new[] = array('type' => 'tag', 'name' => $tag_name, 'closing' => true);
     }
     $this->createdsnippet = (sizeof($new) != sizeof($tokens) or $over_threshold);
     // we did something, so we made a snippet
     $result = $this->parse_array($new, $do_smilies, true, $do_html);
     return $result;
 }
Exemplo n.º 17
0
 /**
  * Callback for preg_replace_callback in handle_bbcode_img
  */
 protected function attachReplaceCallback($matches)
 {
     $currentUserid = vb::getUserContext()->fetchUserId();
     $align = $matches[1];
     $showOldImage = false;
     $tempid = false;
     // used if this attachment hasn't been saved yet (ex. going back & forth between source mode & wysiwyg on a new content)
     $filedataid = false;
     $attachmentid = false;
     // Same as before: are we looking at a legacy attachment?
     if (preg_match('#^n(\\d+)$#', $matches[2], $matches2)) {
         // if the id has 'n' as prefix, it's a nodeid
         $attachmentid = intval($matches2[1]);
     } else {
         if (preg_match('#^temp_(\\d+)_(\\d+)_(\\d+)$#', $matches[2], $matches2)) {
             // if the id is in the form temp_##_###_###, it's a temporary id that links to hidden inputs that contain
             // the stored settings that will be saved when it becomes a new attachment @ post save.
             $tempid = $matches2[0];
             $filedataid = intval($matches2[1]);
         } else {
             // it's a legacy attachmentid, get the new id
             if (isset($this->oldAttachments[intval($matches[2])])) {
                 // key should be nodeid, not filedataid.
                 $attachmentid = $this->oldAttachments[intval($matches[2])]['nodeid'];
                 //$showOldImage = $this->oldAttachments[intval($matches[2])]['cangetattachment'];
             }
         }
     }
     if ($attachmentid === false and $tempid === false) {
         // No data match was found for the attachment, so just return nothing
         return '';
     } else {
         if ($attachmentid and !empty($this->attachments["{$attachmentid}"])) {
             // attachment specified by [attach] tag belongs to this post
             $attachment =& $this->attachments["{$attachmentid}"];
             $filedataid = $attachment['filedataid'];
             // TODO: This doesn't look right to me. I feel like htmlSpecialCharsUni should be outside of the
             // fetchCensoredText() call, but don't have time to verify this right now...
             $attachment['filename'] = $this->fetchCensoredText(vB5_String::htmlSpecialCharsUni($attachment['filename']));
             if (empty($attachment['extension'])) {
                 $attachment['extension'] = strtolower(file_extension($attachment['filename']));
             }
             $attachment['filesize_humanreadable'] = vb_number_format($attachment['filesize'], 1, true);
             $settings = array();
             if (!empty($attachment['settings']) and strtolower($align) == 'config') {
                 $settings = unserialize($attachment['settings']);
                 // TODO: REPLACE USE OF unserialize() above WITH json_decode
                 // ALSO UPDATE createcontent controller's handleAttachmentUploads() to use json_encode() instead of serialize()
             } elseif (!empty($matches['settings'])) {
                 // Currently strictly used by VBV-12051, replacing [IMG]...?filedataid=...[/IMG] with corresponding attachment image
                 // when &amp;type=[a-z]+ or &amp;thumb=1 is part of the image url, that size is passed into us as settings from handle_bbcode_img()
                 // Nothing else AFAIK should be able to pass in the settings, but if we do add this as a main feature,
                 // we should be sure to scrub this well (either via the regex pattern or actual cleaning) to prevent xss.
                 if (isset($matches['settings']['size'])) {
                     // This cleaning is not strictly necessary since the switch-case below that uses this restricts the string to a small set, so xss is not possible.
                     $size = Api_InterfaceAbstract::instance()->callApi('filedata', 'sanitizeFiletype', array($matches['settings']['size']));
                     $settings['size'] = $size;
                 }
             }
             $type = isset($settings['size']) ? $settings['size'] : '';
             // <IMG > OR <A > CHECK
             $params = array($attachment['extension'], $type);
             $isImage = Api_InterfaceAbstract::instance()->callApi('content_attach', 'isImage', $params);
             /*
             	The only reason we do permission checks here is to make the rendered result look nicer, NOT for
             	security.
             	If they have no permission to see an image, any image tags will just show a broken image,
             	so we show a link with the filename instead.
             */
             if (!isset($this->userImagePermissions[$currentUserid][$attachment['parentid']]['cangetimageattachment'])) {
                 $canDownloadImages = vb::getUserContext()->getChannelPermission('forumpermissions2', 'cangetimgattachment', $attachment['parentid']);
                 $this->userImagePermissions[$currentUserid][$attachment['parentid']] = $canDownloadImages;
             }
             if (!isset($this->userImagePermissions[$currentUserid][$attachment['parentid']]['canseethumbnails'])) {
                 $canDownloadImages = vb::getUserContext()->getChannelPermission('forumpermissions', 'canseethumbnails', $attachment['parentid']);
                 $this->userImagePermissions[$currentUserid][$attachment['parentid']] = $canDownloadImages;
             }
             $hasPermission = ($this->userImagePermissions[$currentUserid][$attachment['parentid']]['cangetimageattachment'] or $this->userImagePermissions[$currentUserid][$attachment['parentid']]['canseethumbnails']);
             $useImageTag = ($this->options['do_imgcode'] and $isImage and $hasPermission);
             // Special override for 'canseethumbnails'
             if ($useImageTag and !$this->userImagePermissions[$currentUserid][$attachment['parentid']]['cangetimageattachment']) {
                 $settings['size'] = 'thumb';
             }
             // OUTPUT LOGIC
             $link = vB5_Template_Options::instance()->get('options.frontendurl') . '/filedata/fetch?';
             if (!empty($attachment['nodeid'])) {
                 $link .= "id={$attachment['nodeid']}";
                 $id = 'attachment' . $attachment['nodeid'];
             } else {
                 $link .= "filedataid={$attachment['filedataid']}";
                 $id = 'filedata' . $attachment['filedataid'];
             }
             if (!empty($attachment['resize_dateline'])) {
                 $link .= "&d={$attachment['resize_dateline']}";
             } else {
                 $link .= "&d={$attachment['dateline']}";
             }
             // image_x_y_z isn't strictly for images ATM. If that changes, we can check $isImage here and select
             // a different phrase for the title.
             $title = vB5_Template_Phrase::instance()->register(array('image_x_y_z', $attachment['filename'], intval($attachment['counter']), $attachment['filesize_humanreadable']));
             $filename = $attachment['filename'];
             // html escaped above.
             if ($useImageTag) {
                 $fullsize = false;
                 // Set if $settings['size'] is 'full' or 'fullsize'
                 $customLink = false;
                 // If $settings['link'] is 1 and $settings['url'] isn't empty, it becomes an array of data-attributes to set in the img bits
                 $imgclass = array();
                 $imgbits = array('border' => 0, 'src' => vB_String::htmlSpecialCharsUni($link));
                 $title_text = !empty($settings['title']) ? vB_String::htmlSpecialCharsUni($settings['title']) : '';
                 $description_text = !empty($settings['description']) ? vB_String::htmlSpecialCharsUni($settings['description']) : '';
                 if ($title_text) {
                     $imgbits['title'] = $title_text;
                     $imgbits['data-title'] = $title_text;
                     // only set this if $setting['title'] is not empty
                 } else {
                     if ($description_text) {
                         $imgbits['title'] = $description_text;
                     }
                 }
                 if ($description_text) {
                     $imgbits['description'] = $description_text;
                     $imgbits['data-description'] = $description_text;
                 }
                 $alt_text = !empty($settings['description']) ? vB_String::htmlSpecialCharsUni($settings['description']) : $title_text;
                 // vB4 used to use description for alt text. vB5 seems to expect title for it, for some reason. Here's a compromise
                 if ($alt_text) {
                     $imgbits['alt'] = $alt_text;
                 } else {
                     $imgbits['alt'] = vB5_Template_Phrase::instance()->register(array('image_larger_version_x_y_z', $attachment['filename'], $attachment['counter'], $attachment['filesize_humanreadable'], $attachment['filedataid']));
                 }
                 // See VBV-14079 -- This requires the forumpermissions.canattachmentcss permission.
                 // @TODO Do we want to escape this in some fashion?
                 $styles = !empty($settings['styles']) ? $settings['styles'] : false;
                 if ($styles) {
                     $imgbits['style'] = $styles;
                     $imgbits['data-styles'] = vB_String::htmlSpecialCharsUni($styles);
                 } else {
                     if (!$settings and $align and $align != '=CONFIG') {
                         $imgbits['style'] = "float:{$align}";
                     }
                 }
                 // TODO: WHAT IS THIS CAPTION???
                 //						if ($settings['caption'])
                 //						{
                 //							$caption_tag = "<p class=\"caption $size_class\">$settings[caption]</p>";
                 //						}
                 if (!empty($attachment['nodeid'])) {
                     $imgbits['data-attachmentid'] = $attachment['nodeid'];
                     // used by ckeditor.js's dialogShow handler for Image Dialogs
                 }
                 // image size
                 if (isset($settings['size'])) {
                     // For all the supported sizes, refer to vB_Api_Filedata::SIZE_{} class constants
                     switch ($settings['size']) {
                         case 'icon':
                             // AFAIK vB4 didn't have this size, but vB5 does.
                             $type = $settings['size'];
                             break;
                         case 'thumb':
                             // I think 'thumbnail' was used mostly in vB4. We lean towards the usage of 'thumb' instead in vB5.
                         // I think 'thumbnail' was used mostly in vB4. We lean towards the usage of 'thumb' instead in vB5.
                         case 'thumbnail':
                             $type = 'thumb';
                             break;
                         case 'small':
                             // AFAIK vB4 didn't have this size, but vB5 does.
                         // AFAIK vB4 didn't have this size, but vB5 does.
                         case 'medium':
                         case 'large':
                             $type = $settings['size'];
                             break;
                         case 'full':
                             // I think 'fullsize' was used mostly in vB4. We lean towards the usage of 'full' instead in vB5.
                         // I think 'fullsize' was used mostly in vB4. We lean towards the usage of 'full' instead in vB5.
                         case 'fullsize':
                         default:
                             // @ VBV-5936 we're changing the default so that if settings are not specified, we're displaying the fullsize image.
                             $type = 'full';
                             $fullsize = true;
                             break;
                     }
                     if (!empty($type)) {
                         $imgbits['src'] .= '&amp;type=' . $type;
                         $imgbits['data-size'] = $type;
                     }
                 }
                 // alignment setting
                 if (isset($settings['alignment'])) {
                     switch ($settings['alignment']) {
                         case 'left':
                         case 'center':
                         case 'right':
                             $imgclass[] = 'align_' . $settings['alignment'];
                             $imgbits['data-alignment'] = $settings['alignment'];
                         default:
                             break;
                     }
                 }
                 if (!empty($imgclass)) {
                     $imgbits['class'] = "bbcode-attachment " . implode(' ', $imgclass);
                 } else {
                     $imgbits['class'] = "bbcode-attachment " . 'thumbnail';
                 }
                 /*
                 					We still need to check customURL stuff before we can build the <IMG > tag!
                 */
                 $hrefbits = array('id' => $id, 'class' => 'bbcode-attachment js-slideshow__gallery-node');
                 // if user specified link settings, we need to override the above slidesshow gallery stuff.
                 // link: 0 = default, 1 = url, 2 = none
                 if (!empty($settings['link'])) {
                     if ($settings['link'] == 1 and !empty($settings['linkurl'])) {
                         $settings['linkurl'] = vB_String::htmlSpecialCharsUni($settings['linkurl']);
                         // escape html-special-chars that might break the anchor or img tag
                         // custom URL
                         $linkinfo = $this->handle_bbcode_url('', $settings['linkurl'], true);
                         if ($linkinfo['link'] and $linkinfo['link'] != 'http://') {
                             $customLink = array('data-link' => $settings['link'], 'data-linkurl' => $settings['linkurl']);
                             $hrefbits['href'] = $linkinfo['link'];
                             // linktarget: 0 = self, 1 = new window
                             if (!empty($settings['linktarget'])) {
                                 $customLink['data-linktarget'] = $settings['linktarget'];
                                 $hrefbits['target'] = '_blank';
                             }
                             // below will always occur if it's an external link.
                             if ($linkinfo['nofollow']) {
                                 $hrefbits["rel"] = "nofollow";
                             }
                         }
                     } else {
                         if ($settings['link'] == 2) {
                             // DO NOT SURROUND BY ANCHOR TAG IF LINK TYPE IS "None"
                             $hrefbits = array();
                         }
                     }
                 } else {
                     if ($fullsize) {
                         // Do not link for a full sized image. There's no bigger image to view.
                         $hrefbits = array();
                     } else {
                         $hrefbits['href'] = vB_String::htmlSpecialCharsUni($link);
                         // Use lightbox only if it's not fullsize and one of these extensions
                         // Not sure why we have the extension list here. Maybe the plugin only supported
                         // certain file types in vB4?
                         $lightbox_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png', 'bmp');
                         $lightbox = in_array(strtolower($attachment['extension']), $lightbox_extensions);
                         if ($lightbox) {
                             /* Lightbox doesn't work in vB5 for non-gallery attachments yet.
                              */
                             $hrefbits["rel"] = 'Lightbox_' . $this->containerid;
                             //$imgbits["class"] .= ' js-lightbox group-by-parent-' . $attachment['parentid'];
                         } else {
                             $hrefbits["rel"] = "nofollow";
                         }
                     }
                 }
                 if (!empty($customLink)) {
                     foreach ($customLink as $name => $value) {
                         $imgbits[$name] = $value;
                     }
                 }
                 /*
                 					MAKE THE IMG & ANCHOR TAGS
                 */
                 $imgtag = '';
                 foreach ($imgbits as $tag => $value) {
                     $imgtag .= "{$tag}=\"{$value}\" ";
                 }
                 $atag = '';
                 foreach ($hrefbits as $tag => $value) {
                     $atag .= "{$tag}=\"{$value}\" ";
                 }
                 // If we're showing this in the editor, we don't want the surrounding anchor tags. quick work-around.
                 // Also handle the image setting link= "none"
                 if ($this->turnOffSurroundingAnchor or empty($hrefbits)) {
                     $insertHtml = "<img {$imgtag}/>";
                 } else {
                     $insertHtml = "<a {$atag}><img {$imgtag}/></a>";
                 }
                 if (isset($settings['alignment']) && $settings['alignment'] == 'center') {
                     return "<div class=\"img_align_center" . ($fullsize ? ' size_fullsize' : '') . "\">{$insertHtml}</div>";
                 } else {
                     return ($fullsize ? '<div class="size_fullsize">' : '') . $insertHtml . ($fullsize ? '</div>' : '');
                 }
             } else {
                 // Just display a link.
                 $link = vB5_String::htmlSpecialCharsUni($link);
                 return "<a href=\"" . $link . "\" title=\"" . $title . "\">{$filename}</a>";
             }
         } else {
             // if we have a temporaryid, then we're probably editing a post with a new attachment that doesn't have
             // a node created for the attachment yet. Let's return a basic image tag and let JS handle fixing it.
             if ($tempid and $filedataid) {
                 if (isset($this->filedatas[$filedataid]) and !$this->filedatas[$filedataid]['isImage']) {
                     return "<a class=\"bbcode-attachment\" href=\"" . vB5_Template_Options::instance()->get('options.frontendurl') . "/filedata/fetch?filedataid={$filedataid}\" data-tempid=\"" . $tempid . "\" >" . vB5_Template_Phrase::instance()->register(array('attachment')) . "</a>";
                 } else {
                     return "<img class=\"bbcode-attachment js-need-data-att-update\" src=\"" . vB5_Template_Options::instance()->get('options.frontendurl') . "/filedata/fetch?filedataid={$filedataid}\" data-tempid=\"" . $tempid . "\" />";
                 }
             } else {
                 // We don't know how to handle this. It'll just be replaced by a link via attachReplaceCallbackFinal later.
                 return $matches[0];
             }
         }
     }
 }
Exemplo n.º 18
0
 public static function vBVar($value)
 {
     return vB_String::htmlSpecialCharsUni($value);
 }
Exemplo n.º 19
0
 /**
  * Moves nodes to a new parent
  *
  * @param	array	Node ids
  * @param	int	New parent node id
  * @param	bool	Make topic
  * @param	bool	New title
  * @param	bool	Mod log
  * @param	array	Information to leave a thread redirect. If empty, no redirect is created.
  *			If not empty, should contain these items:
  *				redirect (string) - perm|expires	Permanent or expiring redirect
  *				frame (string) - h|d|w|m|y	Hours, days, weeks, months, years (valid only for expiring redirects)
  *				period (int) - 1-10	How many hours, days, weeks etc, for the expiring redirect
  *
  * @return
  */
 public function moveNodes($nodeids, $to_parent, $makeTopic = false, $newtitle = false, $modlog = true, array $leaveRedirectData = array())
 {
     $movedNodes = array();
     $oldnodeInfo = array();
     $to_parent = $this->assertNodeidStr($to_parent);
     $userContext = vB::getUserContext();
     $currentUserid = vB::getCurrentSession()->get('userid');
     $channelAPI = vB_Api::instanceInternal('content_channel');
     $newparent = $this->getNode($to_parent);
     // If all the nodes to be moved are content nodes and are currently in the same
     // channel, then we are only merging posts/topics and need to check different permissions.
     // To detemine this, we iterate through all the nodes to be moved and get all the "starter"
     // nodeids. We then iterate through all the starters and check if they all have the same
     // parentid, which is the channel they are in.
     $isTopicMerge = false;
     $checkNodes = $this->getNodes(array_merge((array) $nodeids, (array) $to_parent));
     $skipCheck = false;
     $checkStarterIds = array();
     foreach ($checkNodes as $checkNode) {
         if (empty($checkNode['starter'])) {
             // we can skip this check because one of the nodes is a channel
             $skipCheck = true;
             break;
         } else {
             $checkStarterIds[] = $checkNode['starter'];
         }
     }
     if (!$skipCheck) {
         $checkStarters = $this->getNodes($checkStarterIds);
         $starterParents = array();
         foreach ($checkStarters as $checkStarter) {
             $starterParents[$checkStarter['parentid']] = $checkStarter['parentid'];
         }
         if (count($starterParents) === 1) {
             // the parent node of all the starters is the same, so we are
             // only moving topics / posts around inside the same channel,
             // this is likely a topic merge request and we can check a separate
             // permission below
             $isTopicMerge = true;
         }
         unset($checkStarters, $checkStarter, $starterParents);
     }
     unset($checkNode, $checkStarterIds, $skipCheck);
     //If the current user has can moderator canmove on the current nodes, or if the user can create in
     //the new channel and is the owner of the moved nodes and has forum canmove, then they can move
     if (!$userContext->getChannelPermission('forumpermissions', 'canmove', $to_parent) and !$userContext->getChannelPermission('moderatorpermissions', 'canmassmove', $to_parent) and (!$isTopicMerge or !$userContext->getChannelPermission('moderatorpermissions', 'canmanagethreads', $to_parent))) {
         throw new vB_Exception_Api('no_permission');
     }
     $nodes = vB::getDbAssertor()->getRows('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'nodeid' => $nodeids), array('field' => array('publishdate'), 'direction' => array(vB_dB_Query::SORT_ASC)), 'nodeid');
     $needRebuild = false;
     $firstTitle = false;
     $loginfo = array();
     $parent = $this->getNodeFullContent($to_parent);
     $parent = $parent[$to_parent];
     $cacheEvents = array($to_parent);
     $oldparents = array();
     $channelTypeid = vB_Types::instance()->getContentTypeId('vBForum_Channel');
     $infractionTypeid = vB_Types::instance()->getContentTypeId('vBForum_Infraction');
     foreach ($nodes as $node) {
         if ($node['contenttypeid'] == $infractionTypeid) {
             throw new vB_Exception_Api('cannot_move_infraction_nodes');
         }
         if ($node['contenttypeid'] == $channelTypeid) {
             // If any of the moved nodes are channels, the target must be a channel.
             if ($newparent['contenttypeid'] != $channelTypeid) {
                 throw new vB_Exception_Api('invalid_request');
             }
             // We should not allow the moving of channels from one root channel to another.
             if ($channelAPI->getTopLevelChannel($newparent['nodeid']) != $channelAPI->getTopLevelChannel($node['nodeid'])) {
                 throw new vB_Exception_Api('cant_change_top_level');
             }
         }
         //Only channels can be moved to categories, UI shouldn't allow this
         if ($parent['contenttypeid'] == $channelTypeid) {
             $newrouteid = vB_Api::instanceInternal('route')->getChannelConversationRoute($to_parent);
             if ($node['contenttypeid'] != $channelTypeid and (empty($newrouteid) or !empty($parent['category']))) {
                 // The node we want to move is not a channel and the parent cannot have conversations
                 // (e.g. categories, the root blog channel, the root forum channel)
                 throw new vB_Exception_Api('invalid_request');
             }
         }
         if ($node['contenttypeid'] == vB_Types::instance()->getContentTypeID('vBForum_Channel')) {
             $needRebuild = true;
         }
         if ($userContext->getChannelPermission('moderatorpermissions', 'canmassmove', $node['nodeid']) or $currentUserid == $node['userid'] and $userContext->getChannelPermission('forumpermissions', 'canmove', $node['nodeid'], false, $node['parentid']) or $isTopicMerge and $userContext->getChannelPermission('moderatorpermissions', 'canmanagethreads', $to_parent)) {
             if (empty($movedNodes)) {
                 if (empty($node['title']) and !empty($node['starter'])) {
                     $starter = vB_Library::instance('node')->getNodeBare($node['starter']);
                     $firstTitle = $starter['title'];
                 } else {
                     $firstTitle = $node['title'];
                 }
             }
             $movedNodes[] = $node['nodeid'];
             $oldnodeInfo[$node['nodeid']] = $node;
             $oldparents[$node['nodeid']] = $node['parentid'];
             $this->contentLibs[$node['nodeid']] = vB_Library::instance('Content_' . vB_Types::instance()->getContentTypeClass($node['contenttypeid']));
             if ($modlog) {
                 $oldparent = $this->getNode($node['parentid']);
                 $extra = array('fromnodeid' => $oldparent['nodeid'], 'fromtitle' => $oldparent['title'], 'tonodeid' => $newparent['nodeid'], 'totitle' => $newparent['title']);
                 $loginfo[] = array('nodeid' => $node['nodeid'], 'nodetitle' => $node['title'], 'nodeusername' => $node['authorname'], 'nodeuserid' => $node['userid'], 'action' => $extra);
             }
             if (!in_array($node['parentid'], $cacheEvents)) {
                 $cacheEvents[] = $node['parentid'];
             }
             if (!in_array($node['starter'], $cacheEvents) and intval($node['starter'])) {
                 $cacheEvents[] = $node['starter'];
             }
         } else {
             throw new vB_Exception_Api('no_permission');
         }
     }
     if (empty($movedNodes)) {
         return false;
     }
     //can't move a node to its decendant, we like proper trees.
     $db = vB::getDbAssertor();
     $row = $db->getRow('vBForum:closure', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'parent' => $movedNodes, 'child' => $to_parent, vB_Db_Query::PARAM_LIMIT => 1));
     if (!empty($row)) {
         throw new vB_Exception_Api('move_node_to_child');
     }
     //back out counts for the nodes about to be moved.
     //keep track of the parentids to so we can update the last content after
     //we've moved things around.
     $lastContentParents = array();
     foreach ($movedNodes as $nodeid) {
         $node = $this->getNode($nodeid);
         $movedNodeParents = $this->getParents($nodeid);
         $parentids = array();
         foreach ($movedNodeParents as $movedNodeParent) {
             if ($movedNodeParent['nodeid'] != $nodeid) {
                 $parentids[] = $movedNodeParent['nodeid'];
                 $lastContentParents[] = $movedNodeParent['nodeid'];
             }
         }
         $this->updateAddRemovedNodeParentCounts($node, $node, $node['showpublished'], false, $parentids);
     }
     if ($parent['contenttypeid'] == $channelTypeid and $makeTopic) {
         if (empty($newtitle)) {
             if (!empty($firstTitle)) {
                 $newtitle = $firstTitle;
             } else {
                 throw new vB_Exception_Api('notitle');
             }
         }
         $newchildid = $movedNodes[0];
         $this->moveNodesInternal(array($newchildid), $newparent);
         // We need to promote give the new node the correct title
         vB::getDbAssertor()->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'routeid' => vB_Api::instanceInternal('route')->getChannelConversationRoute($to_parent), 'title' => $newtitle, 'htmltitle' => vB_String::htmlSpecialCharsUni(vB_String::stripTags($newtitle), false), 'urlident' => vB_String::getUrlIdent($newtitle), 'description' => $newtitle, vB_dB_Query::CONDITIONS_KEY => array('nodeid' => $movedNodes[0])));
         if (count($movedNodes) > 1) {
             $grandchildren = array_slice($movedNodes, 1);
             $this->moveNodesInternal($grandchildren, $checkNodes[$newchildid]);
         }
         //moving the grandchildren under the first node may have changed it's last child info
         $db->assertQuery('vBForum:updateLastData', array('parentid' => $newchildid, 'timenow' => vB::getRequest()->getTimeNow()));
         $node = $this->getNode($newchildid);
         $this->updateSubTreePublishStatus($node, $newparent['showpublished']);
     } else {
         $this->moveNodesInternal($movedNodes, $newparent);
         foreach ($movedNodes as $nodeid) {
             $node = $this->getNode($nodeid);
             $this->updateSubTreePublishStatus($node, $newparent['showpublished']);
         }
     }
     //dedup the array (so we don't update a node more than once) but we need to
     //do so in a particular way.  We always want to keep the *last* occurance
     //of any id in the array.  This ensures that a node is not updated before
     //any of its decendants (which could cause bad results).
     $seen = array();
     foreach ($lastContentParents as $key => $parentid) {
         if (isset($seen[$parentid])) {
             unset($lastContentParents[$seen[$parentid]]);
         }
         $seen[$parentid] = $key;
     }
     //we can't do this before we move the nodes because the parent/child relationships haven't
     //changed yet.
     foreach ($lastContentParents as $parentid) {
         $this->fixNodeLast($parentid);
     }
     $userid = vB::getCurrentSession()->get('userid');
     // afterMove requires some ancestors info which we just changed above, let's clear cache before updating
     $searchAPI = vB_Api::instanceInternal('search');
     foreach ($movedNodes as $nodeid) {
         vB_Cache::instance()->allCacheEvent('nodeChg_' . $nodeid);
         //some search information may have changed, let's check
         $searchAPI->attributeChanged($nodeid);
     }
     // Leave a thread redirect if required
     // Note: UI only allows leaving a redirect when moving a thread which is one node
     if (!empty($leaveRedirectData) and count($movedNodes) == 1 and count($nodes) == 1) {
         $node = reset($nodes);
         $redirectData = array('title' => $node['title'], 'urlident' => $node['urlident'], 'parentid' => $node['parentid'], 'tonodeid' => $node['nodeid'], 'userid' => $node['userid'], 'publishdate' => $node['publishdate'], 'created' => $node['created']);
         // handle expiring redirects
         if (isset($leaveRedirectData['redirect']) and $leaveRedirectData['redirect'] == 'expires') {
             $period = (int) isset($leaveRedirectData['period']) ? $leaveRedirectData['period'] : 1;
             $frame = (string) isset($leaveRedirectData['frame']) ? $leaveRedirectData['frame'] : 'm';
             $period = max(min($period, 10), 1);
             $frame = in_array($frame, array('h', 'd', 'w', 'm', 'y'), true) ? $frame : 'm';
             $frames = array('h' => 3600, 'd' => 86400, 'w' => 86400 * 7, 'm' => 86400 * 30, 'y' => 86400 * 365);
             $redirectData['unpublishdate'] = vB::getRequest()->getTimeNow() + $period * $frames[$frame];
         }
         // skip any text spam checks, because a redirect has no text to check.
         vB_Library::instance('content_redirect')->add($redirectData, array('skipSpamCheck' => true));
     }
     vB_Api::instance('Search')->purgeCacheForCurrentUser();
     vB_Library_Admin::logModeratorAction($loginfo, 'node_moved_by_x');
     $cacheEvents = array_unique(array_merge($movedNodes, $cacheEvents, array($to_parent)));
     $this->clearChildCache($cacheEvents);
     $this->clearCacheEvents($cacheEvents);
     if ($needRebuild) {
         vB::getUserContext()->rebuildGroupAccess();
         vB_Channel::rebuildChannelTypes();
     }
     return $movedNodes;
 }
Exemplo n.º 20
0
 public function actionLoadPreview()
 {
     $input = array('parentid' => isset($_POST['parentid']) ? intval($_POST['parentid']) : 0, 'channelid' => isset($_POST['channelid']) ? intval($_POST['channelid']) : 0, 'pagedata' => isset($_POST['pagedata']) ? (array) $_POST['pagedata'] : array(), 'conversationtype' => isset($_POST['conversationtype']) ? trim(strval($_POST['conversationtype'])) : '', 'posttags' => isset($_POST['posttags']) ? trim(strval($_POST['posttags'])) : '', 'rawtext' => isset($_POST['rawtext']) ? trim(strval($_POST['rawtext'])) : '', 'filedataid' => isset($_POST['filedataid']) ? (array) $_POST['filedataid'] : array(), 'link' => isset($_POST['link']) ? (array) $_POST['link'] : array(), 'poll' => isset($_POST['poll']) ? (array) $_POST['poll'] : array(), 'video' => isset($_POST['video']) ? (array) $_POST['video'] : array(), 'htmlstate' => isset($_POST['htmlstate']) ? trim(strval($_POST['htmlstate'])) : '', 'disable_bbcode' => isset($_POST['disable_bbcode']) ? intval($_POST['disable_bbcode']) : 0);
     $results = array();
     if ($input['parentid'] < 1) {
         $results['error'] = 'invalid_parentid';
         $this->sendAsJson($results);
         return;
     }
     if (!in_array($input['htmlstate'], array('off', 'on_nl2br', 'on'), true)) {
         $input['htmlstate'] = 'off';
     }
     // when creating a new content item, channelid == parentid
     $input['channelid'] = $input['channelid'] == 0 ? $input['parentid'] : $input['channelid'];
     $templateName = 'display_contenttype_conversationreply_';
     $templateName .= ucfirst($input['conversationtype']);
     $api = Api_InterfaceAbstract::instance();
     $channelBbcodes = $api->callApi('content_channel', 'getBbcodeOptions', array($input['channelid']));
     // The $node['starter'] and $node['nodeid'] values are just there to differentiate starters and replies
     $node = array('rawtext' => '', 'userid' => vB5_User::get('userid'), 'authorname' => vB5_User::get('username'), 'tags' => $input['posttags'], 'taglist' => $input['posttags'], 'approved' => true, 'created' => time(), 'avatar' => $api->callApi('user', 'fetchAvatar', array('userid' => vB5_User::get('userid'))), 'parentid' => $input['parentid'], 'starter' => $input['channelid'] == $input['parentid'] ? 0 : $input['parentid'], 'nodeid' => $input['channelid'] == $input['parentid'] ? 0 : 1);
     if ($input['conversationtype'] == 'gallery') {
         $node['photopreview'] = array();
         foreach ($input['filedataid'] as $filedataid) {
             $node['photopreview'][] = array('nodeid' => $filedataid, 'htmltitle' => isset($_POST['title_' . $filedataid]) ? vB_String::htmlSpecialCharsUni($_POST['title_' . $filedataid]) : '');
             //photo preview is up to 3 photos only
             if (count($node['photopreview']) == 3) {
                 break;
             }
         }
         $node['photocount'] = count($input['filedataid']);
     }
     if ($input['conversationtype'] == 'link') {
         $node['url_title'] = !empty($input['link']['title']) ? $input['link']['title'] : '';
         $node['url'] = !empty($input['link']['url']) ? $input['link']['url'] : '';
         $node['meta'] = !empty($input['link']['meta']) ? $input['link']['meta'] : '';
         $node['previewImage'] = !empty($input['link']['url_image']) ? $input['link']['url_image'] : '';
     }
     if ($input['conversationtype'] == 'poll') {
         $node['multiple'] = !empty($input['poll']['mutliple']);
         $node['options'] = array();
         if (!empty($input['poll']['options']) and is_array($input['poll']['options'])) {
             $optionIndex = 1;
             foreach ($input['poll']['options'] as $option) {
                 $node['options'][] = array('polloptionid' => $optionIndex, 'title' => $option);
                 $optionIndex++;
             }
         }
         $node['permissions']['canviewthreads'] = 1;
         //TODO: Fix this!!
     }
     if ($input['conversationtype'] == 'video') {
         $node['url_title'] = !empty($input['video']['title']) ? $input['video']['title'] : '';
         $node['url'] = !empty($input['video']['url']) ? $input['video']['url'] : '';
         $node['meta'] = !empty($input['video']['meta']) ? $input['video']['meta'] : '';
         $node['items'] = !empty($input['video']['items']) ? $input['video']['items'] : '';
     }
     try {
         $results = vB5_Template::staticRenderAjax($templateName, array('nodeid' => $node['nodeid'], 'conversation' => $node, 'currentConversation' => $node, 'bbcodeOptions' => $channelBbcodes, 'pagingInfo' => array(), 'postIndex' => 0, 'reportActivity' => false, 'showChannelInfo' => false, 'showInlineMod' => false, 'commentsPerPage' => 1, 'view' => 'stream', 'previewMode' => true));
     } catch (Exception $e) {
         if (vB5_Config::instance()->debug) {
             $results['error'] = 'error_rendering_preview_template ' . (string) $e;
         } else {
             $results['error'] = 'error_rendering_preview_template';
         }
         $this->sendAsJson($results);
         return;
     }
     $bbcodeoptions = array('allowhtml' => in_array($input['htmlstate'], array('on', 'on_nl2br'), true), 'allowbbcode' => !$input['disable_bbcode'], 'htmlstate' => $input['htmlstate']);
     $results = array_merge($results, $this->parseBbCodeForPreview(fetch_censored_text($input['rawtext']), $bbcodeoptions));
     $this->sendAsJson($results);
 }
Exemplo n.º 21
0
 public static function execUnstrikeUser($username)
 {
     $ipFields = vB_Ip::getIpFields(vB::getRequest()->getIpAddress());
     vB::getDbAssertor()->delete('vBForum:strikes', array('ip_4' => vB_dB_Type_UInt::instance($ipFields['ip_4']), 'ip_3' => vB_dB_Type_UInt::instance($ipFields['ip_3']), 'ip_2' => vB_dB_Type_UInt::instance($ipFields['ip_2']), 'ip_1' => vB_dB_Type_UInt::instance($ipFields['ip_1']), 'username' => vB_String::htmlSpecialCharsUni($username)));
 }
Exemplo n.º 22
0
/**
* Returns a list of <option> tags representing the list of channels
*
* @param	array	List of Channels to display
* @param	boolean	Whether or not to display the 'Select Channel' option
* @param	string	If specified, name for the optional top element - no name, no display
* @param	string	Text to be used in sprintf() to indicate a 'category' forum, eg: '%s (Category)'. Leave blank for no category indicator
*
* @return	string	List of <option> tags
*/
function construct_channel_chooser_options($channels, $displayselectchannel = false, $topname = null, $category_phrase = null)
{
    global $vbulletin, $vbphrase;
    $selectoptions = array();
    if ($displayselectchannel) {
        $selectoptions[0] = $vbphrase['select_channel'];
    }
    if ($topname) {
        $selectoptions['-1'] = $topname;
        $startdepth = '--';
    } else {
        $startdepth = '';
    }
    if (!$category_phrase) {
        $category_phrase = '%s';
    }
    foreach ($channels as $nodeid => $channel) {
        if (!($channel['options'] & $vbulletin->bf_misc_forumoptions['cancontainthreads'])) {
            $channel['htmltitle'] = sprintf($category_phrase, $channel['htmltitle']);
        }
        $selectoptions["{$nodeid}"] = $startdepth . str_repeat('--', $channel['depth']) . ' ' . vB_String::htmlSpecialCharsUni($channel['htmltitle']);
        if (!empty($channel['channels'])) {
            $selectoptions += construct_channel_chooser_options($channel['channels'], $displayselectchannel, $topname, $category_phrase);
        }
    }
    return $selectoptions;
}
Exemplo n.º 23
0
 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;
 }
Exemplo n.º 24
0
 /**
  * Returns appropriate user info for the owner of this session.
  *
  * @return	array	Array of user information.
  */
 public function &fetch_userinfo()
 {
     if ($this->userinfo) {
         // we already calculated this
         // If languageid is changed by set(), we need to reload language too. The language cached in session cache isn't correct
         if (empty($this->userinfo['lang_options']) or !empty($this->changes['languageid'])) {
             $this->loadLanguage();
         }
         return $this->userinfo;
     } else {
         if ($this->vars['userid'] and !defined('SKIP_USERINFO')) {
             $this->loadUserInfo();
             return $this->userinfo;
         } else {
             $options = $this->datastore->getValue('options');
             $bf_misc_useroptions = $this->datastore->getValue('bf_misc_useroptions');
             // guest setup
             $this->userinfo = array('userid' => 0, 'usergroupid' => 1, 'username' => !empty($_REQUEST['username']) ? vB_String::htmlSpecialCharsUni($_REQUEST['username']) : '', 'password' => '', 'email' => '', 'emailstamp' => 0, 'styleid' => $this->vars['styleid'], 'languageid' => $this->vars['languageid'], 'lastactivity' => $this->vars['lastactivity'], 'daysprune' => 0, 'timezoneoffset' => $options['timeoffset'], 'dstonoff' => $options['dstonoff'], 'showsignatures' => 1, 'showavatars' => 1, 'showimages' => 1, 'showusercss' => 1, 'dstauto' => 0, 'maxposts' => -1, 'startofweek' => 1, 'threadedmode' => 0, 'securitytoken' => 'guest', 'securitytoken_raw' => 'guest');
             $this->userinfo['options'] = $bf_misc_useroptions['showsignatures'] | $bf_misc_useroptions['showavatars'] | $bf_misc_useroptions['showimages'] | $bf_misc_useroptions['dstauto'] | $bf_misc_useroptions['showusercss'];
             if (empty($this->userinfo['lang_options'])) {
                 $this->loadLanguage();
             }
             if (!$this->userinfo['username']) {
                 if (empty($globalPhrases) and !empty($this->userinfo['phrasegroup_global'])) {
                     $globalPhrases = @unserialize($this->userinfo['phrasegroup_global']);
                 }
                 $this->userinfo['username'] = $globalPhrases['guest'];
             }
         }
     }
     return $this->userinfo;
 }
Exemplo n.º 25
0
    }
}
// ###################### Start view client #######################
if ($_REQUEST['do'] == 'viewclient') {
    $vbulletin->input->clean_array_gpc('r', array('apiclientid' => vB_Cleaner::TYPE_UINT));
    if (!$vbulletin->GPC['apiclientid'] or !($client = vB::getDbAssertor()->getRow('api_fetchclientbyid', array('apiclientid' => $vbulletin->GPC['apiclientid'])))) {
        print_stop_message2(array('invalidid', 'apiclientid'));
    }
    print_form_header('api', 'viewclient');
    print_table_header($vbphrase['apiclient']);
    print_label_row($vbphrase['apiclientid'], $client['apiclientid']);
    print_label_row($vbphrase['apiclientname'], vB_String::htmlSpecialCharsUni($client['clientname']));
    print_label_row($vbphrase['apiclientversion'], vB_String::htmlSpecialCharsUni($client['clientversion']));
    print_label_row($vbphrase['apiclient_platformname'], vB_String::htmlSpecialCharsUni($client['platformname']));
    print_label_row($vbphrase['apiclient_platformversion'], vB_String::htmlSpecialCharsUni($client['platformversion']));
    print_label_row($vbphrase['apiclient_uniqueid'], vB_String::htmlSpecialCharsUni($client['uniqueid']));
    print_label_row($vbphrase['apiclient_initialipaddress'], iif(!empty($client['initialipaddress']), "<a href=\"usertools.php?" . vB::getCurrentSession()->get('sessionurl') . "do=doips&amp;depth=2&amp;ipaddress={$client['initialipaddress']}&amp;hash=" . CP_SESSIONHASH . "\">{$client['initialipaddress']}</a>", "&nbsp;"));
    print_label_row($vbphrase['apiclient_initialtime'], vbdate($vbulletin->options['dateformat'] . ' ' . $vbulletin->options['timeformat'], $client['dateline']));
    print_label_row($vbphrase['apiclient_lastactivity'], vbdate($vbulletin->options['dateformat'] . ' ' . $vbulletin->options['timeformat'], $client['lastactivity']));
    print_label_row($vbphrase['apiclient_clienthash'], $client['clienthash']);
    print_label_row($vbphrase['apiclient_secret'], $client['secret']);
    print_label_row($vbphrase['apiclient_apiaccesstoken'], $client['apiaccesstoken']);
    print_label_row($vbphrase['apiclient_remembereduser'], iif(!empty($client['username']), "<a href=\"user.php?" . vB::getCurrentSession()->get('sessionurl') . "do=edit&amp;u={$client['userid']}\"><b>{$client['username']}</b></a>", $vbphrase['guest']));
    print_table_footer();
}
echo '<p class="smallfont" align="center"><a href="#" onclick="js_open_help(\'adminlog\', \'restrict\', \'\');">' . $vbphrase['want_to_access_grant_access_to_this_script'] . '</a></p>';
print_cp_footer();
/*=========================================================================*\
|| #######################################################################
|| # Downloaded: 15:45, Tue Sep 8th 2015
|| # CVS: $RCSfile$ - $Revision: 83435 $
Exemplo n.º 26
0
 /**
  * This adds a new message
  *
  * @param	mixed	must include 'sentto', 'contenttypeid', and the necessary data for that contenttype.
  * @param	array	Array of options for the content being created.
  * 						Understands skipTransaction, skipFloodCheck, floodchecktime, skipDupCheck, skipNotification, nl2br, autoparselinks, skipNonExistentRecipients.
  *							- nl2br: if TRUE, all \n will be converted to <br /> so that it's not removed by the html parser (e.g. comments).
  *						- skipNonExistentRecipients (bool) skips recipients that don't exist instead of throwing an exception.
  *
  * 	@return	mixed		array with errors, or nodeid.
  *
  * Notes: 		For Notifications, go through the notification library.
  **/
 public function add($data, array $options = array(), $convertWysiwygTextToBbcode = true)
 {
     //If we're installing, just abort.
     if (defined('VBINSTALL')) {
         return true;
     }
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     $sender = $data['sender'];
     if (isset($data['msgRecipients']) and empty($data['sentto'])) {
         $recipientNames = explode(',', $data['msgRecipients']);
         foreach ($recipientNames as $k => $name) {
             $recipientNames[$k] = vB_String::htmlSpecialCharsUni($name);
         }
         $recipQry = $this->assertor->getRows('fetchPmRecipients', array('usernames' => $recipientNames, 'userid' => $sender));
         if (!$recipQry or !empty($recipQry['errors'])) {
             throw new vB_Exception_Api('invalid_pm_recipients');
         }
         foreach ($recipQry as $recipient) {
             $this->checkCanReceivePM($recipient);
             $data['sentto'][] = $recipient['userid'];
         }
     }
     if (!isset($data['msgtype']) or $data['msgtype'] != 'request' and $data['msgtype'] != 'notification') {
         $data['msgtype'] = 'message';
     } else {
         if ($data['msgtype'] == 'notification') {
             if (empty($data['about']) or empty($data['aboutid']) or empty($data['sentto'])) {
                 throw new vB_Exception_Api('invalid_data');
             }
         }
     }
     //If we have a message we need text content
     if ($data['msgtype'] == 'message' and (empty($data['rawtext']) and empty($data['pagetext']))) {
         throw new vB_Exception_Api('need_privatemessage_text');
     }
     if ($data['msgtype'] == 'request' and (empty($data['rawtext']) and empty($data['pagetext'])) and !empty($data['sentto'])) {
         $recipient = vB_User::fetchUserinfo($data['sentto']);
         switch ($data['about']) {
             case vB_Api_Node::REQUEST_TAKE_OWNER:
                 $channel = vB_Library::instance('node')->getNodeBare($data['aboutid']);
                 $phrase = vB_Api::instanceInternal('phrase')->fetch(array('sent_ownership_transfer_request_for_x_to_y'));
                 $data['rawtext'] = $data['pagetext'] = vsprintf($phrase['sent_ownership_transfer_request_for_x_to_y'], array($channel['title'], $recipient['username']));
                 break;
             case vB_Api_Node::REQUEST_TAKE_MODERATOR:
                 $channel = vB_Library::instance('node')->getNodeBare($data['aboutid']);
                 $phrase = vB_Api::instanceInternal('phrase')->fetch(array('sent_moderation_request_for_x_to_y'));
                 $data['rawtext'] = $data['pagetext'] = vsprintf($phrase['sent_moderation_request_for_x_to_y'], array($channel['title'], $recipient['username']));
                 break;
             case vB_Api_Node::REQUEST_GRANT_MEMBER:
                 $channel = vB_Library::instance('node')->getNodeBare($data['aboutid']);
                 $phrase = vB_Api::instanceInternal('phrase')->fetch(array('sent_subscription_request_to_x'));
                 $data['rawtext'] = $data['pagetext'] = vsprintf($phrase['sent_subscription_request_to_x'], $channel['title']);
                 break;
             case vB_Api_Node::REQUEST_SG_GRANT_SUBSCRIBER:
                 $channel = vB_Library::instance('node')->getNodeBare($data['aboutid']);
                 $phrase = vB_Api::instanceInternal('phrase')->fetch(array('sent_subscription_request_to_x'));
                 $data['rawtext'] = $data['pagetext'] = vsprintf($phrase['sent_subscription_request_to_x'], $channel['title']);
                 break;
             default:
                 $phrase = vB_Api::instanceInternal('phrase')->fetch(array('sent_follow_request_to_x'));
                 $data['rawtext'] = $data['pagetext'] = vsprintf($phrase['sent_follow_request_to_x'], $recipient['username']);
                 break;
         }
     }
     // don't check the skipNonExistentRecipients option since
     // we're actually checking the *sender's* folders here.
     // I have added this option because of upgrade failure in specific circumstances described in VBV-13331
     $skipNonExistentRecipients = !empty($options['skipNonExistentRecipients']);
     $this->checkFolders($sender, $skipNonExistentRecipients);
     $sendto = array();
     if (isset($data['respondto'])) {
         //We have a forward/reply. We maintain the node hierarchy. If it's a reply
         // we also need to keep the list of recipients.
         $data['parentid'] = $data['respondto'];
         //Obviously we've read this, if we're forwarding it.
         $this->setRead($data['respondto'], 1, $sender);
         $recipients = $this->assertor->getRows('vBForum:getRecipientsForNode', array('nodeid' => $data['respondto']));
         $msgSender = 0;
         $senderIncluded = false;
         foreach ($recipients as $recipient) {
             if ($msgSender) {
                 continue;
             }
             if ($recipient['folder'] == self::SENT_FOLDER) {
                 $msgSender = $recipient['userid'];
             }
         }
         foreach ($recipients as $recipient) {
             $this->checkCanReceivePM($recipient);
             if ($recipient['userid'] == $msgSender and $recipient['folder'] != self::SENT_FOLDER) {
                 $senderIncluded = true;
             }
             $data['sentto'][] = intval($recipient['userid']);
         }
     } else {
         if (isset($data['forward'])) {
             if (empty($data['sentto'])) {
                 throw new vB_Exception_Api('invalid_request');
             }
             $data['parentid'] = $this->pmChannel;
             //Obviously we've read this, if we're forwarding it.
             $this->setRead($data['forward'], 1, $sender);
         } else {
             //We'll get the folders into which we need to insert this record. In the process we'll
             // validate that all the sentto id's are valid.
             $data['parentid'] = $this->pmChannel;
         }
     }
     if (empty($data['sentto'])) {
         throw new vB_Exception_Api('invalid_data');
     }
     if (!is_array($data['sentto'])) {
         $sendto = array($data['sentto']);
     } else {
         $sendto = array_unique($data['sentto']);
     }
     //We can't pass recipients to the parent add method.
     $data['userid'] = $sender;
     $fields = array('parentid', 'rawtext', 'pagetext', 'msgtype', 'title', 'userid', 'about', 'aboutid', 'folderid', 'deleted', 'msgread', 'publishdate', 'url', 'filedataid', 'url_title', 'url_meta', 'url_image', 'attachments');
     $contentData = array();
     foreach ($fields as $field) {
         if (isset($data[$field])) {
             $contentData[$field] = $data[$field];
         }
     }
     try {
         $options['skipTransaction'] = true;
         // create the node, unless it's a notification
         if (!($data['msgtype'] == 'notification')) {
             if (!$skipTransaction) {
                 $this->assertor->beginTransaction();
             }
             $result = parent::add($contentData, $options, $convertWysiwygTextToBbcode);
         } else {
             // USE THE NOTIFICATION LIBRARY
             throw new vB_Exception_Api('invalid_data');
         }
         if (!$result or !empty($result['errors']) or !intval($result['nodeid'])) {
             if (!$skipTransaction) {
                 $this->assertor->rollbackTransaction();
             }
             throw new vB_Exception_Api('invalid_data');
         }
         if (!$skipTransaction) {
             $this->assertor->commitTransaction();
         }
     } catch (exception $e) {
         if (!$skipTransaction) {
             $this->assertor->rollbackTransaction();
         }
         throw $e;
     }
     $nodeid = $result['nodeid'];
     //If we are passed 'request', then this is just inserted for the recipient. But the user must be an admin.
     $insertSent = false;
     if ($data['msgtype'] == 'notification') {
         // USE THE NOTIFICATION LIBRARY
         throw new vB_Exception_Api('invalid_request');
         //$folderKey = self::NOTIFICATION_FOLDER;
     } else {
         if ($data['msgtype'] == 'request') {
             $folderKey = self::REQUEST_FOLDER;
         } else {
             $folderKey = self::MESSAGE_FOLDER;
             $insertSent = true;
         }
     }
     $userOptions = vB::getDatastore()->getValue('bf_misc_useroptions');
     //Note that if this is a response, sendto is empty.
     foreach ($sendto as $recipient) {
         // verify recipient's folders, but instruct checkFolders to not throw
         // an exception if we have an invalid recipient
         $folderCheck = $this->checkFolders($recipient, $skipNonExistentRecipients);
         if ($skipNonExistentRecipients and isset($folderCheck['result']) and $folderCheck['result'] === 'user_skipped') {
             // bad recipient; skip this notification and continue
             continue;
         }
         $sendData = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'userid' => $recipient, 'nodeid' => $result['nodeid'], 'folderid' => $this->folders[$recipient]['systemfolders'][$folderKey]);
         // create a sentto record only if it's not an existing notification
         if (!($data['msgtype'] == 'notification' and ($existingNotification and !empty($existingNotification) and empty($existingNotification['errors'])))) {
             $this->assertor->assertQuery('vBForum:sentto', $sendData);
         }
         // Going through user LIB not API. The API will mask the email field unless current user
         // has canadminusers.
         $recipientInfo = vB_Library::instance('User')->fetchUserinfo($recipient);
         $emailOnPm = $recipientInfo['options'] & $userOptions['emailonpm'];
         if ($recipientInfo['emailnotification'] == 1) {
             if ($contentData['msgtype'] == 'request') {
                 $contentData['sentto'] = $data['sentto'];
                 $contentData['folderid'] = $this->folders[$recipient]['systemfolders'][$folderKey];
                 $contentData['email'] = $recipientInfo['email'];
                 $contentData['username'] = $recipientInfo['username'];
                 $this->sendEmailNotification($contentData);
             }
         }
         // only send email about PM if this is a message, recipient isn't the sender &  the recipient opted in.
         $sendPMEmail = ($data['msgtype'] == 'message' and $recipient != vB::getCurrentSession()->get('userid') and $emailOnPm);
         if ($sendPMEmail) {
             $data['folderid'] = $this->folders[$recipient]['systemfolders'][$folderKey];
             $data['recipient'] = $recipient;
             $data['contentid'] = $result['nodeid'];
             $data['email'] = $recipientInfo['email'];
             $data['username'] = $recipientInfo['username'];
             $this->sendEmailNotification($data);
         }
     }
     // insert message starter for sender if needed
     if (isset($data['respondto']) and $data['respondto'] and ($msgSender and !$senderIncluded)) {
         // don't check the skipNonExistentRecipients option since
         // we're actually checking the *sender's* folders here.
         // I added the flag bacause update failures described in VBV-13331
         $this->checkFolders($msgSender, $skipNonExistentRecipients);
         $sendData = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'userid' => $msgSender, 'nodeid' => $data['respondto'], 'folderid' => $this->folders[$msgSender]['systemfolders'][$folderKey], 'msgread' => 1);
         $this->assertor->assertQuery('vBForum:sentto', $sendData);
     }
     //If this is a new message, we also insert a "sentto" record for the sender, but we mark that "read".
     //That ensures we properly handle replies.
     if (!in_array($data['msgtype'], array('notification', 'request'))) {
         //If someone deleted their message we need to restore it. For that we need the starter.
         //This can only occur, of course, if this is a response.
         $existing = $this->nodeApi->getNode($data['parentid']);
         // only check the "trash" and "messages" folders for everyone. We don't want to accidentally change
         // something in the sent_items folder, for instance
         $includeFoldersQry = $this->assertor->getRows('vBForum:messagefolder', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'titlephrase' => array(self::TRASH_FOLDER, self::MESSAGE_FOLDER), vB_Db_Query::COLUMNS_KEY => array('folderid')));
         $includeFolders = array(-1);
         // -1 so that array is not empty. Other wise IN clause breaks
         foreach ($includeFoldersQry as $includeFolder) {
             $includeFolders[] = $includeFolder['folderid'];
         }
         $queryData = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'nodeid', 'value' => $existing['starter']), array('field' => 'userid', 'value' => $sender, 'operator' => vB_dB_Query::OPERATOR_NE), 'folderid' => $includeFolders), 'msgread' => 0, 'deleted' => 0);
         $this->assertor->assertQuery('vBForum:sentto', $queryData);
         // @TODO : Shouldn't we move the "restored" messages back to the inbox...?
         $this->setRead($nodeid, 1, $sender, 'sent_items');
     }
     if ($insertSent) {
         // don't check the skipNonExistentRecipients option since
         // we're actually checking the *sender's* folders here.
         $this->checkFolders($sender, $skipNonExistentRecipients);
         $queryData = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'userid' => $sender, 'nodeid' => $result['nodeid'], 'folderid' => $this->folders[$sender]['systemfolders'][self::SENT_FOLDER], 'msgread' => 1);
         $this->assertor->assertQuery('vBForum:sentto', $queryData);
     }
     $sendto[] = $sender;
     // duplicate ids is fine in this array
     $this->buildPmTotals($sendto);
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($result['nodeid'], $data, $options, $result['cacheEvents'], $result['nodeVals']);
     }
     vB_Api::instance('Search')->index($result['nodeid']);
     //update user cached info
     if ($folderKey == self::MESSAGE_FOLDER) {
         vB_Library::instance('user')->clearUserInfo($sendto);
     }
     return $result;
 }
Exemplo n.º 27
0
 protected function getProfileFieldConditions($profilefield, $profile)
 {
     $varname = "field{$profilefield['profilefieldid']}";
     $optionalvar = $varname . '_opt';
     if (isset($profile["{$varname}"])) {
         $value = $profile["{$varname}"];
     } else {
         $value = '';
     }
     if (isset($profile["{$optionalvar}"])) {
         $optvalue = $profile["{$optionalvar}"];
     } else {
         $optvalue = '';
     }
     if (empty($value) and $optvalue === '') {
         return array();
     }
     if (($profilefield['type'] == 'input' or $profilefield['type'] == 'textarea') and $value !== '') {
         $conditions[] = array('field' => $varname, 'value' => vB_String::htmlSpecialCharsUni(trim($value)), 'operator' => vB_dB_Query::OPERATOR_INCLUDES);
     }
     if ($profilefield['type'] == 'radio' or $profilefield['type'] == 'select') {
         if ($value == 0 and $optvalue === '') {
             // The select field was left blank!
             // and the optional field is also empty
             return array();
         }
         if ($profilefield['optional'] and !empty($optvalue)) {
             $conditions[] = array('field' => $varname, 'value' => htmlspecialchars_uni(trim($optvalue)), 'operator' => vB_dB_Query::OPERATOR_INCLUDES);
         } else {
             $data = unserialize($profilefield['data']);
             foreach ($data as $key => $val) {
                 if ($key + 1 == $value) {
                     $conditions[] = array('field' => $varname, 'value' => htmlspecialchars_uni(trim($val)), 'operator' => vB_dB_Query::OPERATOR_INCLUDES);
                     break;
                 }
             }
         }
     }
     if (($profilefield['type'] == 'checkbox' or $profilefield['type'] == 'select_multiple') and is_array($value)) {
         foreach ($value as $key => $val) {
             $conditions[] = array('field' => $varname, 'value' => pow(2, $val - 1), 'operator' => vB_dB_Query::OPERATOR_AND);
         }
     }
     return $conditions;
 }
Exemplo n.º 28
0
    print_label_row(construct_link_code($vbphrase['top_apimethods'], 'apistats.php?do=method'), '');
    print_label_row(construct_link_code($vbphrase['top_apiclients'], 'apistats.php?do=client'), '');
    print_label_row(construct_link_code($vbphrase['apiclient_activity_statistics'], 'apistats.php?do=activity'), '');
    print_table_footer();
}
// Find most popular things below
if ($_REQUEST['do'] == 'top') {
    // Top Client
    $maxclient = vB::getDbAssertor()->getRow('api_fetchmaxclient');
    // Top API Method
    $maxmethod = vB::getDbAssertor()->getRow('api_fetchmaxmethod');
    print_form_header('');
    print_table_header($vbphrase['top']);
    $linktext = construct_link_code(vB_String::htmlSpecialCharsUni($maxclient['clientname']) . " ({$vbphrase['id']}: " . $maxclient['apiclientid'] . ')', "apilog.php?do=viewclient&apiclientid=" . $maxclient['apiclientid']);
    print_label_row($vbphrase['top_apiclient'], $linktext . " (" . construct_phrase($vbphrase['api_x_calls'], $maxclient['c']) . ")");
    print_label_row($vbphrase['top_apimethod'], vB_String::htmlSpecialCharsUni($maxmethod['method']) . " (" . construct_phrase($vbphrase['api_x_calls'], $maxclient['c']) . ")");
    print_table_footer();
}
if ($_REQUEST['do'] == 'method') {
    $vbulletin->input->clean_array_gpc('r', array('pagenumber' => vB_Cleaner::TYPE_INT));
    if ($vbulletin->GPC['perpage'] < 1) {
        $vbulletin->GPC['perpage'] = 15;
    }
    if ($vbulletin->GPC['pagenumber'] < 1) {
        $vbulletin->GPC['pagenumber'] = 1;
    }
    $startat = ($vbulletin->GPC['pagenumber'] - 1) * $vbulletin->GPC['perpage'];
    $counter = vB::getDbAssertor()->getRow('api_methodcount');
    $totalpages = ceil($counter['total'] / $vbulletin->GPC['perpage']);
    $logs = vB::getDbAssertor()->getRows('api_methodlogs', array('startat' => $startat, 'limit' => $vbulletin->GPC['perpage']));
    if (count($logs) > 0) {
Exemplo n.º 29
0
 /**
  * Verifies that the provided username is valid, and attempts to correct it if it is not valid
  *
  * @param	string	Username
  *
  * @return	boolean	Returns true if the username is valid, or has been corrected to be valid
  */
 function verify_username(&$username)
 {
     // this is duplicated from the user manager
     // fix extra whitespace and invisible ascii stuff
     $username = trim(preg_replace('#[ \\r\\n\\t]+#si', ' ', strip_blank_ascii($username, ' ')));
     $username_raw = $username;
     $username = vB_String::cleanUserName($username);
     $username = str_replace(chr(0), '', $username);
     $username = trim($username);
     $length = vB_String::vbStrlen($username);
     if ($length < $this->registry->options['minuserlength']) {
         // name too short
         $this->error('usernametooshort', $this->registry->options['minuserlength']);
         return false;
     } else {
         if ($length > $this->registry->options['maxuserlength']) {
             // name too long
             $this->error('usernametoolong', $this->registry->options['maxuserlength']);
             return false;
         } else {
             if (preg_match('/(?<!&#[0-9]{3}|&#[0-9]{4}|&#[0-9]{5});/', $username)) {
                 // name contains semicolons
                 $this->error('username_contains_semi_colons');
                 return false;
             } else {
                 if ($username != fetch_censored_text($username)) {
                     // name contains censored words
                     $this->error('censorfield');
                     return false;
                 } else {
                     $result = $this->assertor->assertQuery('verifyUsername', array('userid' => intval($this->existing['userid']), 'username' => vB_String::htmlSpecialCharsUni($username), 'username_raw' => vB_String::htmlSpecialCharsUni($username_raw)));
                     if ($result->valid() and $result->current()) {
                         // name is already in use
                         $this->error('usernametaken', vB_String::htmlSpecialCharsUni($username), vB::getCurrentSession()->get('sessionurl'));
                         return false;
                     } else {
                         if (!empty($this->registry->options['illegalusernames'])) {
                             // check for illegal username
                             $usernames = preg_split('/[ \\r\\n\\t]+/', $this->registry->options['illegalusernames'], -1, PREG_SPLIT_NO_EMPTY);
                             foreach ($usernames as $val) {
                                 if (strpos(strtolower($username), strtolower($val)) !== false) {
                                     // wierd error to show, but hey...
                                     $this->error('usernametaken', vB_String::htmlSpecialCharsUni($username), vB::getCurrentSession()->get('sessionurl'));
                                     return false;
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     // if we got here, everything is okay
     $username = vB_String::htmlSpecialCharsUni($username);
     return true;
 }
Exemplo n.º 30
0
 /**
  * updates a record
  *
  *	@param	mixed		array of nodeid's
  *	@param	mixed		array of permissions that should be checked.
  *
  * 	@return	boolean
  */
 public function update($nodeid, $data)
 {
     $channelContentTypeId = vB_Types::instance()->getContentTypeId('vBForum_Channel');
     // Verify prefixid
     if ($this->contenttypeid != $channelContentTypeId and isset($data['prefixid'])) {
         $this->verifyPrefixid($data['prefixid']);
     } else {
         // Channel can't have a prefix
         unset($data['prefixid']);
     }
     // Verify post iconid
     if ($this->contenttypeid != $channelContentTypeId and isset($data['iconid'])) {
         $this->verifyPostIconid($data['iconid']);
     } else {
         // Channels can't have a post icon
         unset($data['iconid']);
     }
     $timeNow = vB::getRequest()->getTimeNow();
     $userContext = vB::getUserContext();
     //If this user doesn't have the featured permission and they are trying to set it,
     //Let's just quietly unset it.
     if (isset($data['featured'])) {
         if (!$userContext->getChannelPermission('moderatorpermissions', 'cansetfeatured', $data['parentid'])) {
             unset($data['featured']);
         }
     }
     //We can't allow directly setting parentid. That should only happen through the node api move function
     //And there are number of other fields that shouldn't be changed here. We have methods for the ones that can be changed at all.
     foreach (array('open', 'showopen', 'approved', 'showapproved', 'protected') as $field) {
         if (isset($data[$field])) {
             unset($data[$field]);
         }
     }
     if (isset($data['parentid'])) {
         //Only allow for articles.
         $content = $this->nodeApi->getNodeFullContent($nodeid);
         $content = array_pop($content);
         // you can't move it to the category it's already in
         if ($data['parentid'] != $content['parentid']) {
             // only allow this for articles (currently)
             if ($content['channeltype'] == 'article') {
                 if (!$userContext->getChannelPermission('forumpermissions', 'canmove', $data['parentid']) and !$userContext->getChannelPermission('moderatorpermissions', 'canmassmove', $data['parentid'])) {
                     throw new vB_Exception_Api('no_permission');
                 }
                 //If we got here, we're O.K. to move. let's do that now.
                 vB_Library::instance('node')->moveNodes($nodeid, $data['parentid']);
             }
         }
         unset($data['parentid']);
     }
     //We need to see if we need to update.
     $prior = vB_Library::instance('node')->getNodeBare($nodeid);
     if ($this->contenttypeid != $channelContentTypeId) {
         $content = $this->getFullContent($nodeid);
     }
     if (isset($data['publish_now']) and !empty($data['publish_now'])) {
         $data['publishdate'] = vB::getRequest()->getTimeNow();
     }
     if (empty($data['htmltitle']) and !empty($data['title'])) {
         $data['htmltitle'] = vB_String::htmlSpecialCharsUni(vB_String::stripTags($data['title']), false);
     }
     if (empty($data['urlident']) and !empty($data['title'])) {
         $data['urlident'] = vB_String::getUrlIdent($data['title']);
     }
     // Do not change publishdate or showpublished status unless it was explicitly set while calling update().
     if ((!isset($data['publishdate']) or empty($data['publishdate']) and $data['publishdate'] !== 0) and !empty($prior['publishdate'])) {
         $data['publishdate'] = $prior['publishdate'];
     }
     if ($this->isPublished($data)) {
         $published = 1;
     } else {
         $published = 0;
     }
     $nodevals = array();
     if ($published != $prior['showpublished']) {
         $nodevals['showpublished'] = $published;
     }
     // set default node options
     if ((empty($data['nodeoptions']) or !is_numeric($data['nodeoptions'])) and $prior['contenttypeid'] != $channelContentTypeId) {
         $parentFullContent = vB_Library::instance('node')->getNodeFullContent($prior['parentid']);
         if (!empty($parentFullContent[$prior['parentid']]['channeltype'])) {
             $data['nodeoptions'] = self::$defaultNodeOptions[$parentFullContent[$prior['parentid']]['channeltype']];
         } else {
             $data['nodeoptions'] = self::$defaultNodeOptions['default'];
         }
         // Add or remove any nodeoptions that have been explicitly passed in.
         // This would have otherwise happened in updateNodeOptions/setNodeOptions
         // (which is where it happens when adding a node as opposed to updating
         // a node), but since $data['nodeoptions'] is now defined, setNodeOptions
         // won't take care of setting these (it will just apply the int
         // nodeoptions value).
         $baseNodeOptions = vB_Api::instanceInternal('node')->getOptions();
         foreach ($baseNodeOptions as $baseOptionKey => $baseOptionVal) {
             if (isset($data[$baseOptionKey])) {
                 if (intval($data[$baseOptionKey])) {
                     $data['nodeoptions'] = $data['nodeoptions'] | intval($baseOptionVal);
                 } else {
                     $data['nodeoptions'] = $data['nodeoptions'] & ~intval($baseOptionVal);
                 }
             }
         }
     }
     //node table data.
     $data[vB_dB_Query::TYPE_KEY] = vB_dB_Query::QUERY_UPDATE;
     $data['nodeid'] = $nodeid;
     $data['lastupdate'] = $timeNow;
     //If the field passed is in the $nodeFields array then we update the node table.
     foreach ($data as $field => $value) {
         if (in_array($field, $this->nodeFields)) {
             $nodevals[$field] = $value;
         }
     }
     $index = empty($data['noIndex']);
     unset($data['noIndex']);
     // Update the content-type specific data
     if (!is_array($this->tablename)) {
         $tables = array($this->tablename);
     } else {
         $tables = $this->tablename;
     }
     $success = true;
     foreach ($tables as $table) {
         $structure = $this->assertor->fetchTableStructure('vBForum:' . $table);
         if (empty($structure) or empty($structure['structure'])) {
             throw new vB_Exception_Api('invalid_query_parameters');
         }
         $queryData = array();
         $queryData[vB_dB_Query::TYPE_KEY] = vB_dB_Query::QUERY_UPDATE;
         $queryData['nodeid'] = $nodeid;
         foreach ($structure['structure'] as $fieldname) {
             if (isset($data[$fieldname])) {
                 $queryData[$fieldname] = $data[$fieldname];
             }
         }
         //Now we have at least a query type and a nodeid. We put those in above. So if we don't
         //have at least one other value there's no reason to try an update.
         if (count($queryData) > 2) {
             $success = $success and $this->assertor->assertQuery('vBForum:' . $table, $queryData);
         }
     }
     if ($success) {
         // Handle Attachments
         // The text library (and most derivatives) can have attachments,
         // for the others, this is a no-op.
         $this->handleAttachments('update', $nodeid, $data);
         //Clear cached query info that would be significantly impacted
         $events = array('fUserContentChg_' . $prior['userid']);
         if ($prior['starter']) {
             $starterNodeInfo = vB_Library::instance('node')->getNodeBare($prior['starter']);
             $events[] = 'fUserContentChg_' . $starterNodeInfo['userid'];
         } else {
             if ($prior['parentid']) {
                 $starterNodeInfo = vB_Library::instance('node')->getNodeBare($prior['parentid']);
                 $events[] = 'fUserContentChg_' . $starterNodeInfo['userid'];
             }
         }
         $this->nodeApi->clearCacheEvents($nodeid);
         vB_Cache::instance()->allCacheEvent($events);
         if (isset($nodevals['publishdate']) and $nodevals['publishdate'] > $timeNow) {
             if (empty($nodevals['unpublishdate']) or $nodevals['unpublishdate'] > $nodevals['publishdate']) {
                 $nodevals['nextupdate'] = $nodevals['publishdate'];
             }
         } else {
             if (isset($nodevals['unpublishdate']) and $nodevals['unpublishdate'] > $timeNow) {
                 $nodevals['nextupdate'] = $nodevals['unpublishdate'];
             }
         }
         // handle approved
         if (isset($nodevals['approved'])) {
             if ($nodevals['approved']) {
                 $approved = 1;
                 $queryName = 'approveNode';
             } else {
                 $approved = 0;
                 $queryName = 'unapproveNode';
             }
             // set approved to parent...
             $this->assertor->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'nodeid' => $nodeid, 'approved' => $approved));
             // and handle showapproved
             $this->assertor->assertQuery('vBForum:' . $queryName, array('nodeid' => $nodeid));
             unset($nodevals['approved']);
         }
         if (isset($nodevals)) {
             $nodevals[vB_dB_Query::TYPE_KEY] = vB_dB_Query::QUERY_UPDATE;
             $nodevals['nodeid'] = $nodeid;
             $success = $this->assertor->assertQuery('vBForum:node', $nodevals);
         }
         //We need to compare the current publishdate and unpublishdate values against the
         // parent.
         //But we can skip this if neither publish or unpublishdate is set
         $updateParents = false;
         if ($published != $prior['showpublished']) {
             $updateParents = true;
             //We are concerned about two possibilities. It could have gone from published to unpublished.
             //In either case we change by totalcount +1 (for ourselves.
             //Remember that published is always unpublished.
             //From unpublished to published.
             if ($published) {
                 $nodeUpdates = $this->nodeLibrary->publishChildren($nodeid);
                 // if $nodeUpdates is empty, that means no change was made to this node or its descendants,
                 // and no parent count changes are necessary. If it's not empty but doesn't have totalcount set,
                 // that means it possibly failed with a DB error. In such a case, we will just not update the
                 // counts but continue updating the node.
                 if (!empty($nodeUpdates) and isset($nodeUpdates['totalcount'])) {
                     // text-counts only change by 1 (or 0 for non-text types), because it only affects the immediate parent
                     $textChange = $this->textCountChange;
                     $textUnPubChange = -1 * $textChange;
                     // Note, below assumes that a DB had been diligent about
                     // keeping track of the count fields correctly.
                     $totalPubChange = $nodeUpdates['totalcount'] - $prior['totalcount'] + $textChange;
                     // we add the text change because self counts for ancestors' total counts
                     $totalUnPubChange = -1 * $totalPubChange;
                 } else {
                     $updateParents = false;
                 }
             } else {
                 $nodeUpdates = $this->nodeLibrary->unpublishChildren($nodeid);
                 if (!empty($nodeUpdates) and isset($nodeUpdates['totalunpubcount'])) {
                     $textUnPubChange = $this->textCountChange;
                     $textChange = -1 * $textUnPubChange;
                     $totalUnPubChange = $nodeUpdates['totalunpubcount'] - $prior['totalunpubcount'] + $textUnPubChange;
                     $totalPubChange = -1 * $totalUnPubChange;
                 } else {
                     $updateParents = false;
                 }
             }
             vB_Library::instance('node')->clearChildCache($nodeid);
         }
         //update the parent count if necessary
         if ($updateParents) {
             vB_Library::instance('node')->updateParentCounts($nodeid, $textChange, $textUnPubChange, $totalPubChange, $totalUnPubChange, $published);
         }
         //update viewperms from childs if needed, do we want this channel specific?
         if (isset($nodevals['viewperms']) and isset($prior['viewperms']) and $nodevals['viewperms'] != $prior['viewperms']) {
             vB_Api::instanceInternal('node')->setNodePerms($nodeid, array('viewperms' => $nodevals['viewperms']));
         }
         if ($index) {
             vB_Api::instanceInternal('Search')->index($nodeid);
         }
         // update user tags
         $tags = !empty($data['tags']) ? explode(',', $data['tags']) : array();
         $tagRet = vB_Api::instanceInternal('tags')->updateUserTags($nodeid, $tags);
         $this->updateNodeOptions($nodeid, $data);
         // Update childs nodeoptions
         $this->assertor->assertQuery('vBForum:updateChildsNodeoptions', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'parentid' => $nodeid));
         $this->nodeApi->clearCacheEvents(array($nodeid, $prior['parentid']));
         $loginfo = array('nodeid' => $prior['nodeid'], 'nodetitle' => $prior['title'], 'nodeusername' => $prior['authorname'], 'nodeuserid' => $prior['userid']);
         $extra = array();
         if ($nodevals !== null && isset($nodevals['title'])) {
             if ($prior['title'] != $nodevals['title']) {
                 $extra = array('newtitle' => $nodevals['title']);
             }
         }
         vB_Library_Admin::logModeratorAction($loginfo, 'node_edited_by_x', $extra);
         $updateEditLog = true;
         if (!vB::getUserContext()->hasPermission('genericoptions', 'showeditedby') and (isset($content[$nodeid]['edit_reason']) and $data['reason'] == $content[$nodeid]['edit_reason'] or !isset($content[$nodeid]['edit_reason']) and empty($data['reason']))) {
             $updateEditLog = false;
         }
         // Clear autosave table of this items entry
         if (vB::getCurrentSession()->get('userid') and !empty($data['rawtext'])) {
             $this->assertor->delete('vBForum:autosavetext', array('userid' => vB::getCurrentSession()->get('userid'), 'nodeid' => $nodeid, 'parentid' => $content[$nodeid]['parentid']));
         }
         // Log edit by info
         if ($updateEditLog and $this->contenttypeid != $channelContentTypeId and isset($content[$nodeid]['rawtext']) and isset($data['rawtext']) and $content[$nodeid]['rawtext'] != $data['rawtext'] and !empty($data['publishdate']) and $prior['publishdate'] and (!empty($data['reason']) or $data['publishdate'] < vB::getRequest()->getTimeNow() - $this->options['noeditedbytime'] * 60)) {
             $userinfo = vB::getCurrentSession()->fetch_userinfo();
             // save the postedithistory
             if ($this->options['postedithistory']) {
                 $record = $this->assertor->getRow('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'original' => 1, 'nodeid' => $nodeid));
                 // insert original post on first edit
                 if (empty($record)) {
                     $this->assertor->assertQuery('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'nodeid' => $nodeid, 'userid' => $content[$nodeid]['userid'], 'username' => $content[$nodeid]['authorname'], 'dateline' => $data['publishdate'], 'pagetext' => $content[$nodeid]['rawtext'], 'original' => 1));
                 }
                 // insert the new version
                 $this->assertor->assertQuery('vBForum:postedithistory', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'nodeid' => $nodeid, 'userid' => $userinfo['userid'], 'username' => $userinfo['username'], 'dateline' => vB::getRequest()->getTimeNow(), 'reason' => isset($data['reason']) ? vB5_String::htmlSpecialCharsUni($data['reason']) : '', 'pagetext' => isset($data['rawtext']) ? $data['rawtext'] : ''));
             }
             $this->assertor->assertQuery('editlog_replacerecord', array('nodeid' => $nodeid, 'userid' => $userinfo['userid'], 'username' => $userinfo['username'], 'timenow' => vB::getRequest()->getTimeNow(), 'reason' => isset($data['reason']) ? vB5_String::htmlSpecialCharsUni($data['reason']) : '', 'hashistory' => intval($this->options['postedithistory'])));
         }
         return true;
     }
     $this->nodeApi->clearCacheEvents(array($nodeid, $prior['parentid']));
     return false;
 }