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; }