'group' => TYPE_STR, )); // check to see if we are deleting the last style $check = $db->query_first("SELECT COUNT(*) AS numstyles FROM " . TABLE_PREFIX . "style"); // Delete css file if ($vbulletin->options['storecssasfile'] AND $fetchstyle = $db->query_first("SELECT css FROM " . TABLE_PREFIX . "style WHERE styleid = " . $vbulletin->GPC['dostyleid'])) { $fetchstyle['css'] .= "\n"; $css = substr($fetchstyle['css'], 0, strpos($fetchstyle['css'], "\n")); // attempt to delete the old css file if it exists delete_css_file($vbulletin->GPC['dostyleid'], $css); delete_style_css_directory($vbulletin->GPC['dostyleid'], 'ltr'); delete_style_css_directory($vbulletin->GPC['dostyleid'], 'rtl'); } if ($check['numstyles'] <= 1) { // there is only one style remaining. we will completely empty the style table and start again $db->query_write("TRUNCATE TABLE " . TABLE_PREFIX . "style"); $db->query_write("TRUNCATE TABLE " . TABLE_PREFIX . "templatehistory"); $db->query_write("TRUNCATE TABLE " . TABLE_PREFIX . "templatemerge"); $db->query_write("DELETE FROM " . TABLE_PREFIX . "template WHERE styleid <> -1"); $db->query_write("DELETE FROM " . TABLE_PREFIX . "stylevar WHERE styleid <> -1"); // insert a new default style /*insert query*/ $db->query_write("
/** * Delete style * * @param integer $dostyleid Style ID to be deleted. */ public function deleteStyle($dostyleid) { if (!vB::getUserContext()->hasAdminPermission('canadminstyles')) { throw new vB_Exception_Api('no_permission'); } $vboptions = vB::getDatastore()->get_value('options'); if ($dostyleid == $vboptions['styleid']) { throw new vB_Exception_Api('cant_delete_default_style'); } // look at how many styles are being deleted $count = vB::getDbAssertor()->getField('style_count', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED)); // check that this isn't the last one that we're about to delete $last = vB::getDbAssertor()->getField('style_checklast', array('styleid' => $dostyleid, vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED)); if ($count == 1 and $last == 1) { throw new vB_Exception_Api('cant_delete_last_style'); } $style = $this->library->fetchStyleByID($dostyleid); // Delete css file if ($vboptions['storecssasfile'] and $style) { $style['css'] .= "\n"; $css = substr($style['css'], 0, strpos($style['css'], "\n")); // attempt to delete the old css file if it exists delete_css_file($dostyleid, $css); delete_style_css_directory($dostyleid, 'ltr'); delete_style_css_directory($dostyleid, 'rtl'); } vB::getDbAssertor()->assertQuery('template_deletefrom_templatemerge2', array('styleid' => $dostyleid)); vB::getDbAssertor()->assertQuery('style_delete', array('styleid' => $dostyleid)); vB::getDbAssertor()->assertQuery('template_deletehistory2', array('styleid' => $dostyleid)); vB::getDbAssertor()->assertQuery('template_delete2', array('styleid' => $dostyleid)); vB::getDbAssertor()->assertQuery('style_deletestylevar', array('styleid' => $dostyleid)); // If style/theme has an icon or preview image, remove it (decrement refcount and let the cron job clean it up) // we don't modify publicview here, since this file may be used somewhere else that needs // publicview=1, for example as the site header image. if ($style['filedataid'] > 0) { vB::getDbAssertor()->assertQuery('decrementFiledataRefcount', array('filedataid' => $style['filedataid'])); } if ($style['previewfiledataid'] > 0) { vB::getDbAssertor()->assertQuery('decrementFiledataRefcount', array('filedataid' => $style['previewfiledataid'])); } // update parent info for child styles vB::getDbAssertor()->assertQuery('style_updateparent', array('styleid' => $dostyleid, 'parentid' => $style['parentid'], 'parentlist' => $style['parentlist'])); $this->library->buildAllStyles(0, 0); return true; }
function write_style_css_directory($styleid, $parentlist, $dir = 'ltr') { global $vbulletin; //verify that we have or can create a style directory $styledir = 'clientscript/vbulletin_css/style' . str_pad($styleid, 5, '0', STR_PAD_LEFT) . ($dir == 'ltr' ? 'l' : 'r'); //if we have a file that's not a directory or not writable something is wrong. if (file_exists($styledir) AND (!is_dir($styledir) OR !is_writable($styledir))) { return false; } //clear any old files. if (file_exists($styledir)) { delete_style_css_directory($styleid, $dir); } //create the directory -- if it still exists try to continue with the existing dir if (!file_exists($styledir)) { if (!mkdir($styledir)) { return false; } } //check for success. if (!is_dir($styledir) OR !is_writable($styledir)) { return false; } //write out the files for this style. $set = $vbulletin->db->query_read($sql = " SELECT DISTINCT title FROM " . TABLE_PREFIX . "template WHERE styleid IN (" . $parentlist . ") AND title LIKE '%.css' "); //collapse the list. $css_templates = array(); while($row = $vbulletin->db->fetch_array($set)) { $css_templates[] = $row['title']; } switch_css_style($styleid, $css_templates); if ($dir == 'ltr') { vB_Template_Runtime::addStyleVar('left', 'left'); vB_Template_Runtime::addStyleVar('right', 'right'); vB_Template_Runtime::addStyleVar('textdirection', 'ltr'); } else { vB_Template_Runtime::addStyleVar('left', 'right'); vB_Template_Runtime::addStyleVar('right', 'left'); vB_Template_Runtime::addStyleVar('textdirection', 'rtl'); } $templates = array(); foreach ($css_templates AS $title) { //I'd call this a hack but there probably isn't a cleaner way to do this. //The css is published to a different directory than the css.php file //which means that relative urls that works for css.php won't work for the //published directory. Unfortunately urls from the webroot don't work //because the forum often isn't located at the webroot and we can only //specify urls from the forum root. And css doens't provide any way //of setting a base url like html does. So we are left to "fixing" //any relative urls in the published css. // //We leave alone any urls starting with '/', 'http', and 'https:' //there are other valid urls, but nothing that people should be //using in our css files. $text = vB_Template::create($title)->render(true); $re = '#url\(\s*["\']?(?!/|http:|https:)#'; $base = $vbulletin->options['bburl']; if ($base[-1] != '/') { $base .= '/'; } $text = preg_replace ($re, "$0$base", $text); $templates[$title] = $text; if (!write_css_file("$styledir/$title", $text)) { return false; } } static $vbdefaultcss, $cssfiles, $csstemplates; if (empty($vbdefaultcss)) { $vbdefaultcss = array(); // Now write the rollup templates require_once(DIR . '/includes/class_xml.php'); $cssfiles = array(); if ($handle = @opendir(DIR . '/includes/xml/')) { while (($file = readdir($handle)) !== false) { if (!preg_match('#^cssrollup_(.*).xml$#i', $file, $matches)) { continue; } $css_key = preg_replace('#[^a-z0-9]#i', '', $matches[1]); $cssfiles["$css_key"]['name'] = $file; } closedir($handle); } if (empty($cssfiles['vbulletin'])) // opendir failed or cpnav_vbulletin.xml is missing { if (is_readable(DIR . '/includes/xml/cssrollup_vbulletin.xml')) { $cssfiles['vbulletin']['name'] = 'cssrollup_vbulletin.xml'; } else { echo construct_phrase($vbphrase['could_not_open_x'], DIR . '/includes/xml/cssrollup_vbulletin.xml'); exit; } } unset($cssfiles['vbulletin']); $xmlobj = new vB_XML_Parser(false, DIR . "/includes/xml/cssrollup_vbulletin.xml"); $data = $xmlobj->parse(); if (!is_array($data['rollup'][0])) { $data['rollup'] = array($data['rollup']); } foreach ($data['rollup'] AS $file) { foreach ($file['template'] AS $name) { $vbdefaultcss["$file[name]"] = $file['template']; } } foreach ($cssfiles AS $css_file => $file) { $xmlobj = new vB_XML_Parser(false, DIR . "/includes/xml/$file[name]"); $data = $xmlobj->parse(); if ($data['product'] AND empty($vbulletin->products["$data[product]"])) { // attached to a specific product and that product isn't enabled continue; } if (!is_array($data['rollup'][0])) { $data['rollup'] = array($data['rollup']); } $cssfiles["$css_file"]['css'] = $data['rollup']; } } foreach ($cssfiles AS $css_file => $files) { if (is_array($files['css'])) { foreach ($files['css'] AS $file) { if (process_css_rollup_file($file['name'], $file['template'], $templates, $styledir, $vbdefaultcss) === false) { return false; } } } } foreach ($vbdefaultcss AS $xmlfile => $files) { if (process_css_rollup_file($xmlfile, $files, $templates, $styledir) === false) { return false; } } return true; }
/** * Writes style css directory on disk * * @param int $styleid * @param string $parentlist -- csv list of ancestors for this style * @param string $dir -- the "direction" of the css to write. Either 'ltr' or 'rtl' (there are actually two directories per style) */ function write_style_css_directory($styleid, $parentlist, $dir = 'ltr') { //verify that we have or can create a style directory $styledir = DIR . vB_Api::instanceInternal('style')->fetchCssLocation() . '/style' . str_pad($styleid, 5, '0', STR_PAD_LEFT) . ($dir == 'ltr' ? 'l' : 'r'); //if we have a file that's not a directory or not writable something is wrong. if (file_exists($styledir) and (!is_dir($styledir) or !is_writable($styledir))) { return false; } //clear any old files. if (file_exists($styledir)) { delete_style_css_directory($styleid, $dir, true); } //create the directory -- if it still exists try to continue with the existing dir if (!file_exists($styledir)) { if (!@mkdir($styledir)) { return false; } } //check for success. if (!is_dir($styledir) or !is_writable($styledir)) { return false; } //write out the files for this style. $parentlistarr = explode(',', $parentlist); $set = vB::getDbAssertor()->assertQuery('vBForum:fetchParentTemplates', array('parentlist' => $parentlistarr)); //collapse the list. $css_templates = array(); foreach ($set as $row) { $css_templates[] = $row['title']; } $stylelib = vB_Library::instance('Style'); $stylelib->switchCssStyle($styleid, $css_templates); if ($dir == 'ltr') { vB_Template_Runtime::addStyleVar('left', 'left'); vB_Template_Runtime::addStyleVar('right', 'right'); vB_Template_Runtime::addStyleVar('textdirection', 'ltr'); } else { vB_Template_Runtime::addStyleVar('left', 'right'); vB_Template_Runtime::addStyleVar('right', 'left'); vB_Template_Runtime::addStyleVar('textdirection', 'rtl'); } // Get new css cache bust $stylelib->setCssFileDate($styleid); $cssfiledate = $stylelib->getCssFileDate($styleid); $base = get_base_url_for_css(); if ($base === false) { return false; } $templates = array(); foreach ($css_templates as $title) { //I'd call this a hack but there probably isn't a cleaner way to do this. //The css is published to a different directory than the css.php file //which means that relative urls that works for css.php won't work for the //published directory. Unfortunately urls from the webroot don't work //because the forum often isn't located at the webroot and we can only //specify urls from the forum root. And css doens't provide any way //of setting a base url like html does. So we are left to "fixing" //any relative urls in the published css. // //We leave alone any urls starting with '/', 'http', and 'https:' //there are other valid urls, but nothing that people should be //using in our css files. $text = vB_Template::create($title)->render(true); //update image urls to be fully qualified. $re = '#url\\(\\s*["\']?(?!/|http:|https:|"/|\'/)#'; $text = preg_replace($re, "\$0{$base}", $text); $text = vB_String::getCssMinifiedText($text); $templates[$title] = $text; if (!write_css_file("{$styledir}/{$cssfiledate}-{$title}", $text)) { return false; } } static $vbdefaultcss = array(), $cssfiles = array(); if (empty($vbdefaultcss)) { require_once DIR . '/includes/class_xml.php'; $cssfilelist = vB_Api_Product::loadProductXmlList('cssrollup', true); if (empty($cssfilelist['vbulletin'])) { $vbphrase = vB_Api::instanceInternal('phrase')->fetch(array('could_not_open_x')); echo construct_phrase($vbphrase['could_not_open_x'], DIR . '/includes/xml/cssrollup_vbulletin.xml'); exit; } else { $mainfile = array_shift($cssfilelist); } $xmlobj = new vB_XML_Parser(false, $mainfile); $data = $xmlobj->parse(); if (!is_array($data['rollup'][0])) { $data['rollup'] = array($data['rollup']); } foreach ($data['rollup'] as $file) { foreach ($file['template'] as $name) { $vbdefaultcss["{$file['name']}"] = $file['template']; } } foreach ($cssfilelist as $css_file => $file) { $xmlobj = new vB_XML_Parser(false, $file); $data = $xmlobj->parse(); $products = vB::getDatastore()->getValue('products'); if ($data['product'] and empty($products["{$data['product']}"])) { // attached to a specific product and that product isn't enabled continue; } if (!is_array($data['rollup'][0])) { $data['rollup'] = array($data['rollup']); } $cssfiles[$css_file]['css'] = $data['rollup']; } } foreach ($cssfiles as $css_file => $files) { if (is_array($files['css'])) { foreach ($files['css'] as $file) { if (process_css_rollup_file($file['name'], $file['template'], $templates, $styleid, $styledir, $vbdefaultcss) === false) { return false; } } } } foreach ($vbdefaultcss as $xmlfile => $files) { if (process_css_rollup_file($xmlfile, $files, $templates, $styleid, $styledir) === false) { return false; } } return true; }