[ Index ] |
PHP Cross Reference of MyBB 1.8.38 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11 /** 12 * Import an entire theme (stylesheets, properties & templates) from an XML file. 13 * 14 * @param string $xml The contents of the XML file 15 * @param array $options Optional array of options or overrides 16 * @return boolean True on success, false on failure 17 */ 18 function import_theme_xml($xml, $options=array()) 19 { 20 global $mybb, $db; 21 22 $parser = create_xml_parser($xml); 23 $tree = $parser->get_tree(); 24 25 if(!is_array($tree) || !is_array($tree['theme'])) 26 { 27 return -1; 28 } 29 30 $theme = $tree['theme']; 31 32 // Do we have MyBB 1.2 template's we're importing? 33 $css_120 = ""; 34 35 if(isset($theme['cssbits']) && is_array($theme['cssbits'])) 36 { 37 $cssbits = kill_tags($theme['cssbits']); 38 39 foreach($cssbits as $name => $values) 40 { 41 $css_120 .= "{$name} {\n"; 42 foreach($values as $property => $value) 43 { 44 if(is_array($value)) 45 { 46 $property = str_replace('_', ':', $property); 47 48 $css_120 .= "}\n{$name} {$property} {\n"; 49 foreach($value as $property2 => $value2) 50 { 51 $css_120 .= "\t{$property2}: {$value2}\n"; 52 } 53 } 54 else 55 { 56 $css_120 .= "\t{$property}: {$value}\n"; 57 } 58 } 59 $css_120 .= "}\n"; 60 } 61 } 62 63 if(isset($theme['themebits']) && is_array($theme['themebits'])) 64 { 65 $themebits = kill_tags($theme['themebits']); 66 67 $theme['properties']['tag'] = 'properties'; 68 69 foreach($themebits as $name => $value) 70 { 71 if($name == "extracss") 72 { 73 $css_120 .= $value; 74 continue; 75 } 76 77 $theme['properties'][$name] = $value; 78 } 79 } 80 81 if($css_120) 82 { 83 $css_120 = upgrade_css_120_to_140($css_120); 84 $theme['stylesheets']['tag'] = 'stylesheets'; 85 $theme['stylesheets']['stylesheet'][0]['tag'] = 'stylesheet'; 86 $theme['stylesheets']['stylesheet'][0]['attributes'] = array('name' => 'global.css', 'version' => $mybb->version_code); 87 $theme['stylesheets']['stylesheet'][0]['value'] = $css_120; 88 89 unset($theme['cssbits']); 90 unset($theme['themebits']); 91 } 92 93 if(is_array($theme['properties'])) 94 { 95 foreach($theme['properties'] as $property => $value) 96 { 97 if($property == "tag" || $property == "value") 98 { 99 continue; 100 } 101 102 if($property == 'colors' || $property == 'disporder') 103 { 104 $data = my_unserialize($value['value']); 105 106 if(!is_array($data)) 107 { 108 // Bad data? 109 continue; 110 } 111 112 $value['value'] = $data; 113 } 114 115 $properties[$property] = $value['value']; 116 } 117 } 118 119 if(empty($mybb->input['name'])) 120 { 121 $name = $theme['attributes']['name']; 122 } 123 else 124 { 125 $name = $mybb->input['name']; 126 } 127 $version = $theme['attributes']['version']; 128 129 $query = $db->simple_select("themes", "tid", "name='".$db->escape_string($name)."'", array("limit" => 1)); 130 $existingtheme = $db->fetch_array($query); 131 if(!empty($options['force_name_check']) && $existingtheme) 132 { 133 return -3; 134 } 135 else if($existingtheme) 136 { 137 $options['tid'] = $existingtheme['tid']; 138 } 139 140 if($mybb->version_code != $version && $options['version_compat'] != 1) 141 { 142 return -2; 143 } 144 145 // Do we have any templates to insert? 146 if(!empty($theme['templates']['template']) && empty($options['no_templates'])) 147 { 148 $templates = $theme['templates']['template']; 149 if(is_array($templates)) 150 { 151 // Theme only has one custom template 152 if(array_key_exists("attributes", $templates)) 153 { 154 $templates = array($templates); 155 } 156 } 157 158 // Security check 159 $security_check = false; 160 foreach($templates as $template) 161 { 162 if(check_template($template['value'])) 163 { 164 $security_check = true; 165 break; 166 } 167 } 168 169 if($security_check == true) 170 { 171 return -4; 172 } 173 174 if(!empty($options['templateset'])) 175 { 176 $sid = (int)$options['templateset']; 177 } 178 else 179 { 180 $sid = $db->insert_query("templatesets", array('title' => $db->escape_string($name)." Templates")); 181 } 182 183 $templatecache = array(); 184 foreach($templates as $template) 185 { 186 $templatecache[] = array( 187 "title" => $db->escape_string($template['attributes']['name']), 188 "template" => $db->escape_string($template['value']), 189 "sid" => $db->escape_string($sid), 190 "version" => $db->escape_string($template['attributes']['version']), 191 "dateline" => TIME_NOW 192 ); 193 } 194 195 foreach($templatecache as $template) 196 { 197 // PostgreSQL causes apache to stop sending content sometimes and 198 // causes the page to stop loading during many queries all at one time 199 if($db->engine == "pgsql") 200 { 201 echo " "; 202 flush(); 203 } 204 205 $db->insert_query("templates", $template); 206 } 207 208 $properties['templateset'] = $sid; 209 } 210 211 // Not overriding an existing theme 212 if(empty($options['tid'])) 213 { 214 // Insert the theme 215 if(!isset($options['parent'])) 216 { 217 $options['parent'] = 0; 218 } 219 $theme_id = build_new_theme($name, $properties, $options['parent']); 220 } 221 // Overriding an existing - delete refs. 222 else 223 { 224 $db->delete_query("themestylesheets", "tid='{$options['tid']}'"); 225 $db->update_query("themes", array("properties" => $db->escape_string(my_serialize($properties))), "tid='{$options['tid']}'"); 226 $theme_id = $options['tid']; 227 } 228 229 // If we have any stylesheets, process them 230 if(!empty($theme['stylesheets']['stylesheet']) && empty($options['no_stylesheets'])) 231 { 232 // Are we dealing with a single stylesheet? 233 if(isset($theme['stylesheets']['stylesheet']['tag'])) 234 { 235 // Trick the system into thinking we have a good array =P 236 $theme['stylesheets']['stylesheet'] = array($theme['stylesheets']['stylesheet']); 237 } 238 239 // Retrieve a list of inherited stylesheets 240 $query = $db->simple_select("themes", "stylesheets", "tid = '{$theme_id}'"); 241 if($db->num_rows($query)) 242 { 243 $inherited_stylesheets = my_unserialize($db->fetch_field($query, "stylesheets")); 244 245 if(isset($inherited_stylesheets['inherited']) && is_array($inherited_stylesheets['inherited'])) 246 { 247 $loop = 1; 248 foreach($inherited_stylesheets['inherited'] as $action => $stylesheets) 249 { 250 foreach($stylesheets as $filename => $stylesheet) 251 { 252 if($properties['disporder'][basename($filename)]) 253 { 254 continue; 255 } 256 257 $properties['disporder'][basename($filename)] = $loop; 258 ++$loop; 259 } 260 } 261 } 262 } 263 264 $loop = 1; 265 foreach($theme['stylesheets']['stylesheet'] as $stylesheet) 266 { 267 $stylesheet['attributes']['name'] = my_substr($stylesheet['attributes']['name'], 0, 30); 268 269 if(substr($stylesheet['attributes']['name'], -4) != ".css") 270 { 271 continue; 272 } 273 274 if(empty($stylesheet['attributes']['lastmodified'])) 275 { 276 $stylesheet['attributes']['lastmodified'] = TIME_NOW; 277 } 278 279 if(empty($stylesheet['attributes']['disporder'])) 280 { 281 $stylesheet['attributes']['disporder'] = $loop; 282 } 283 284 if(empty($stylesheet['attributes']['attachedto'])) 285 { 286 $stylesheet['attributes']['attachedto'] = ''; 287 } 288 289 $properties['disporder'][$stylesheet['attributes']['name']] = $stylesheet['attributes']['disporder']; 290 291 $new_stylesheet = array( 292 "name" => $db->escape_string($stylesheet['attributes']['name']), 293 "tid" => $theme_id, 294 "attachedto" => $db->escape_string($stylesheet['attributes']['attachedto']), 295 "stylesheet" => $db->escape_string($stylesheet['value']), 296 "lastmodified" => (int)$stylesheet['attributes']['lastmodified'], 297 "cachefile" => $db->escape_string($stylesheet['attributes']['name']) 298 ); 299 $sid = $db->insert_query("themestylesheets", $new_stylesheet); 300 $css_url = "css.php?stylesheet={$sid}"; 301 $cached = cache_stylesheet($theme_id, $stylesheet['attributes']['name'], $stylesheet['value']); 302 if($cached) 303 { 304 $css_url = $cached; 305 } 306 307 $attachedto = $stylesheet['attributes']['attachedto']; 308 if(!$attachedto) 309 { 310 $attachedto = "global"; 311 } 312 313 // private.php?compose,folders|usercp.php,global|global 314 $attachedto = explode("|", $attachedto); 315 foreach($attachedto as $attached_file) 316 { 317 $attached_actions = explode(",", $attached_file); 318 $attached_file = array_shift($attached_actions); 319 if(count($attached_actions) == 0) 320 { 321 $attached_actions = array("global"); 322 } 323 324 foreach($attached_actions as $action) 325 { 326 $theme_stylesheets[$attached_file][$action][] = $css_url; 327 } 328 } 329 330 ++$loop; 331 } 332 // Now we have our list of built stylesheets, save them 333 $updated_theme = array( 334 "stylesheets" => $db->escape_string(my_serialize($theme_stylesheets)) 335 ); 336 337 $db->update_query("themes", $updated_theme, "tid='{$theme_id}'"); 338 } 339 340 update_theme_stylesheet_list($theme_id); 341 342 // And done? 343 return $theme_id; 344 } 345 346 /** 347 * Parse theme variables in a specific string. 348 * 349 * @param string $string The string to parse variables for 350 * @param array $variables Array of variables 351 * @return string Parsed string with variables replaced 352 */ 353 function parse_theme_variables($string, $variables=array()) 354 { 355 $find = array(); 356 $replace = array(); 357 foreach(array_keys($variables) as $variable) 358 { 359 $find[] = "{{$variable}}"; 360 $replace[] = $variables[$variable]; 361 } 362 return str_replace($find, $replace, $string); 363 } 364 365 /** 366 * Caches a stylesheet to the file system. 367 * 368 * @param string $tid The theme ID this stylesheet belongs to. 369 * @param string $filename The name of the stylesheet. 370 * @param string $stylesheet The contents of the stylesheet. 371 * 372 * @return string The cache file path. 373 */ 374 function cache_stylesheet($tid, $filename, $stylesheet) 375 { 376 global $mybb; 377 378 $filename = basename($filename); 379 $tid = (int) $tid; 380 $theme_directory = "cache/themes/theme{$tid}"; 381 382 if(substr($filename, -4) != ".css") 383 { 384 return false; 385 } 386 387 // If we're in safe mode save to the main theme folder by default 388 if($mybb->safemode) 389 { 390 $theme_directory = "cache/themes"; 391 $filename = $tid."_".$filename; 392 } 393 // Does our theme directory exist? Try and create it. 394 elseif(!is_dir(MYBB_ROOT . $theme_directory)) 395 { 396 if(!@mkdir(MYBB_ROOT . $theme_directory)) 397 { 398 $theme_directory = "cache/themes"; 399 $filename = $tid."_".$filename; 400 } 401 else 402 { 403 // Add in empty index.html! 404 $fp = @fopen(MYBB_ROOT . $theme_directory."/index.html", "w"); 405 @fwrite($fp, ""); 406 @fclose($fp); 407 408 } 409 } 410 411 $theme_vars = array( 412 "theme" => $theme_directory 413 ); 414 $stylesheet = parse_theme_variables($stylesheet, $theme_vars); 415 $stylesheet = preg_replace_callback("#url\((\"|'|)([^\"'\s]*?)\\1\)#", 'fix_css_urls_callback', $stylesheet); 416 417 $fp = @fopen(MYBB_ROOT . "{$theme_directory}/{$filename}", "wb"); 418 if(!$fp) 419 { 420 return false; 421 } 422 423 @fwrite($fp, $stylesheet); 424 @fclose($fp); 425 426 $stylesheet_min = minify_stylesheet($stylesheet); 427 $filename_min = str_replace('.css', '.min.css', $filename); 428 $fp_min = @fopen(MYBB_ROOT . "{$theme_directory}/{$filename_min}", "wb"); 429 if(!$fp_min) 430 { 431 return false; 432 } 433 @fwrite($fp_min, $stylesheet_min); 434 @fclose($fp_min); 435 436 copy_file_to_cdn(MYBB_ROOT . "{$theme_directory}/{$filename}"); 437 copy_file_to_cdn(MYBB_ROOT . "{$theme_directory}/{$filename_min}"); 438 439 return "{$theme_directory}/{$filename}"; 440 } 441 442 /** 443 * Minify a stylesheet to remove comments, linebreaks, whitespace, 444 * unnecessary semicolons, and prefers #rgb over #rrggbb. 445 * 446 * @param $stylesheet string The stylesheet in it's untouched form. 447 * @return string The minified stylesheet 448 */ 449 function minify_stylesheet($stylesheet) 450 { 451 // Remove comments. 452 $stylesheet = preg_replace('@/\*.*?\*/@s', '', $stylesheet); 453 // Remove whitespace around symbols. 454 $stylesheet = preg_replace('@\s*([{}:;,])\s*@', '\1', $stylesheet); 455 // Remove unnecessary semicolons. 456 $stylesheet = preg_replace('@;}@', '}', $stylesheet); 457 // Replace #rrggbb with #rgb when possible. 458 $stylesheet = preg_replace('@#([a-f0-9])\1([a-f0-9])\2([a-f0-9])\3@i','#\1\2\3',$stylesheet); 459 $stylesheet = trim($stylesheet); 460 return $stylesheet; 461 } 462 463 /** 464 * @param array $stylesheet 465 * 466 * @return bool 467 */ 468 function resync_stylesheet($stylesheet) 469 { 470 global $db; 471 472 // Try and fix any missing cache file names 473 if(!$stylesheet['cachefile'] && $stylesheet['name']) 474 { 475 $stylesheet['cachefile'] = $stylesheet['name']; 476 $db->update_query("themestylesheets", array('cachefile' => $db->escape_string($stylesheet['name'])), "sid='{$stylesheet['sid']}'"); 477 } 478 479 // Still don't have the cache file name or is it not a flat file? Return false 480 if(!$stylesheet['cachefile'] || strpos($stylesheet['cachefile'], 'css.php') !== false) 481 { 482 return false; 483 } 484 485 if(!file_exists(MYBB_ROOT."cache/themes/theme{$stylesheet['tid']}/{$stylesheet['name']}") && !file_exists(MYBB_ROOT."cache/themes/{$stylesheet['tid']}_{$stylesheet['name']}")) 486 { 487 if(cache_stylesheet($stylesheet['tid'], $stylesheet['cachefile'], $stylesheet['stylesheet']) !== false) 488 { 489 $db->update_query("themestylesheets", array('cachefile' => $db->escape_string($stylesheet['name'])), "sid='{$stylesheet['sid']}'"); 490 491 update_theme_stylesheet_list($stylesheet['tid']); 492 493 if($stylesheet['sid'] != 1) 494 { 495 $db->update_query("themestylesheets", array('lastmodified' => TIME_NOW), "sid='{$stylesheet['sid']}'"); 496 } 497 } 498 499 return true; 500 } 501 502 return false; 503 } 504 505 /** 506 * @deprecated 507 * @param string $url 508 * 509 * @return string 510 */ 511 function fix_css_urls($url) 512 { 513 if(!preg_match("#^([a-z0-9]+\:|/)#i", $url) && strpos($url, "../../../") === false) 514 { 515 return "url(../../../{$url})"; 516 } 517 else 518 { 519 return "url({$url})"; 520 } 521 } 522 523 /** 524 * @param array $matches Matches. 525 * 526 * @return string 527 */ 528 function fix_css_urls_callback($matches) 529 { 530 return fix_css_urls($matches[2]); 531 } 532 533 /** 534 * @deprecated 535 * @param string $url 536 * 537 * @return string 538 */ 539 function unfix_css_urls($url) 540 { 541 return str_replace("../../../", "", $url); 542 } 543 544 /** 545 * Build a theme based on the specified parameters. 546 * 547 * @param string $name The name of the theme 548 * @param array $properties Array of theme properties (if blank, inherits from parent) 549 * @param int $parent The parent ID for this theme (defaults to Master) 550 * @return int The new theme ID 551 */ 552 function build_new_theme($name, $properties=null, $parent=1) 553 { 554 global $db; 555 556 $new_theme = array( 557 "name" => $db->escape_string($name), 558 "pid" => (int)$parent, 559 "def" => 0, 560 "allowedgroups" => "all", 561 "properties" => "", 562 "stylesheets" => "" 563 ); 564 $tid = $db->insert_query("themes", $new_theme); 565 566 $inherited_properties = false; 567 $stylesheets = array(); 568 if($parent > 0) 569 { 570 $query = $db->simple_select("themes", "*", "tid='".(int)$parent."'"); 571 $parent_theme = $db->fetch_array($query); 572 if(!is_array($properties) || count($properties) == 0) 573 { 574 $parent_properties = my_unserialize($parent_theme['properties']); 575 if(!empty($parent_properties)) 576 { 577 foreach($parent_properties as $property => $value) 578 { 579 if($property == "inherited") 580 { 581 continue; 582 } 583 584 $properties[$property] = $value; 585 if(!empty($parent_properties['inherited'][$property])) 586 { 587 $properties['inherited'][$property] = $parent_properties['inherited'][$property]; 588 } 589 else 590 { 591 $properties['inherited'][$property] = $parent; 592 } 593 } 594 $inherited_properties = true; 595 } 596 } 597 598 $parent_stylesheets = my_unserialize($parent_theme['stylesheets']); 599 if(!empty($parent_stylesheets)) 600 { 601 foreach($parent_stylesheets as $location => $value) 602 { 603 if($location == "inherited") 604 { 605 continue; 606 } 607 608 foreach($value as $action => $sheets) 609 { 610 foreach($sheets as $stylesheet) 611 { 612 $stylesheets[$location][$action][] = $stylesheet; 613 $inherited_check = "{$location}_{$action}"; 614 if(!empty($parent_stylesheets['inherited'][$inherited_check][$stylesheet])) 615 { 616 $stylesheets['inherited'][$inherited_check][$stylesheet] = $parent_stylesheets['inherited'][$inherited_check][$stylesheet]; 617 } 618 else 619 { 620 $stylesheets['inherited'][$inherited_check][$stylesheet] = $parent; 621 } 622 } 623 } 624 } 625 } 626 } 627 628 if(!$inherited_properties) 629 { 630 $theme_vars = array( 631 "theme" => "cache/themes/theme{$tid}" 632 ); 633 $properties['logo'] = parse_theme_variables($properties['logo'], $theme_vars); 634 } 635 636 $updated_theme = array(); 637 if(!empty($stylesheets)) 638 { 639 $updated_theme['stylesheets'] = $db->escape_string(my_serialize($stylesheets)); 640 } 641 $updated_theme['properties'] = $db->escape_string(my_serialize($properties)); 642 643 if(count($updated_theme) > 0) 644 { 645 $db->update_query("themes", $updated_theme, "tid='{$tid}'"); 646 } 647 648 return $tid; 649 } 650 651 /** 652 * Generates an array from an incoming CSS file. 653 * 654 * @param string $css The incoming CSS 655 * @return array Parsed CSS file as array, false on failure 656 */ 657 function css_to_array($css) 658 { 659 // Normalise line breaks 660 $css = str_replace(array("\r\n", "\n", "\r"), "\n", $css); 661 662 /** 663 * Play with the css a little - just to ensure we can parse it 664 * 665 * This essentially adds line breaks before and after each } not inside a string 666 * so it's parsed correctly below 667 */ 668 $stripped_css = preg_replace('#(?<!\\")\}#', "\n}\n", $css); 669 670 // Fetch out classes and comments 671 preg_match_all('#(\/\*(.|[\r\n])*?\*\/)?([a-z0-9a+\\\[\]\-\"=_:>\*\.\#\,\s\(\)\|~|@\^]+)(\s*)\{(.*?)\}\n#msi', $stripped_css, $matches, PREG_PATTERN_ORDER); 672 $total = count($matches[1]); 673 674 $parsed_css = array(); 675 676 for($i=0; $i < $total; $i++) 677 { 678 $name = $description = ''; 679 $class_name = $matches[3][$i]; 680 $class_name = trim($class_name); 681 $comments = $matches[1][$i]; 682 preg_match_all("#Name:(.*)#i", $comments, $name_match); 683 if(isset($name_match[count($name_match)-1][0])) 684 { 685 $name = trim($name_match[count($name_match)-1][0]); 686 } 687 preg_match_all("#Description:(.*)#i", $comments, $description_match); 688 if(isset($description_match[count($description_match)-1][0])) 689 { 690 $description = trim($description_match[count($description_match)-1][0]); 691 } 692 $class_id = md5($class_name); 693 if(isset($already_parsed[$class_id])) 694 { 695 $already_parsed[$class_id]++; 696 $class_id .= "_".$already_parsed[$class_id]; 697 } 698 else 699 { 700 $already_parsed[$class_id] = 1; 701 } 702 $values = trim($matches[5][$i]); 703 $values = preg_replace("#/\*(.*?)\*/#s", "", $values); 704 $parsed_css[$class_id] = array("class_name" => $class_name, "name" => $name, "description" => $description, "values" => $values); 705 } 706 707 return $parsed_css; 708 } 709 710 /** 711 * @param array|string $css 712 * @param int $selected_item 713 * 714 * @return string 715 */ 716 function get_selectors_as_options($css, $selected_item=null) 717 { 718 $select = ""; 719 720 if(!is_array($css)) 721 { 722 $css = css_to_array($css); 723 } 724 725 $selected = false; 726 727 if(is_array($css)) 728 { 729 uasort($css, "css_selectors_sort_cmp"); 730 731 foreach($css as $id => $css_array) 732 { 733 if(!$css_array['name']) 734 { 735 $css_array['name'] = $css_array['class_name']; 736 } 737 738 if($selected_item == $id || (!$selected_item && !$selected)) 739 { 740 $select .= "<option value=\"{$id}\" selected=\"selected\">{$css_array['name']}</option>\n"; 741 $selected = true; 742 } 743 else 744 { 745 $select .= "<option value=\"{$id}\">{$css_array['name']}</option>\n"; 746 } 747 } 748 } 749 return $select; 750 } 751 752 /** 753 * @param array $a 754 * @param array $b 755 * 756 * @return int 757 */ 758 function css_selectors_sort_cmp($a, $b) 759 { 760 if(!$a['name']) 761 { 762 $a['name'] = $a['class_name']; 763 } 764 765 if(!$b['name']) 766 { 767 $b['name'] = $b['class_name']; 768 } 769 return strcmp($a['name'], $b['name']); 770 } 771 772 /** 773 * @param array|string $css 774 * @param string $id 775 * 776 * @return array|bool 777 */ 778 function get_css_properties($css, $id) 779 { 780 if(!is_array($css)) 781 { 782 $css = css_to_array($css); 783 } 784 785 if(!isset($css[$id])) 786 { 787 return false; 788 } 789 return parse_css_properties($css[$id]['values']); 790 } 791 792 /** 793 * Parses CSS supported properties and returns them as an array. 794 * 795 * @param string $values Value of CSS properties from within class or selector 796 * @return array Array of CSS properties 797 */ 798 function parse_css_properties($values) 799 { 800 $css_bits = array( 801 'extra' => null, 802 ); 803 804 if(!$values) 805 { 806 return null; 807 } 808 809 $values = explode(";", $values); 810 foreach($values as $value) 811 { 812 $value = trim($value); 813 if(!$value) continue; 814 list($property, $css_value) = explode(":", $value, 2); 815 $property = trim($property); 816 switch(strtolower($property)) 817 { 818 case "background": 819 case "color": 820 case "width": 821 case "font-family": 822 case "font-size": 823 case "font-weight": 824 case "font-style": 825 case "text-decoration": 826 $css_bits[$property] = trim($css_value); 827 break; 828 default: 829 $css_bits['extra'] .= "{$property}: ".trim($css_value).";\n"; 830 831 } 832 } 833 return $css_bits; 834 } 835 836 /** 837 * Inserts an incoming string of CSS in to an already defined document. If the class ID is not found, the CSS is appended to the file. 838 * 839 * @param string $new_css CSS we wish to insert at this location. 840 * @param string $selector The selector for this piece of CSS. 841 * @param string $css The existing CSS if we have any. 842 * @param string $class_id (Optional) The optional friendly class id value just incase the CSS is not found in the file. 843 * 844 * @return string The altered CSS. 845 */ 846 function insert_into_css($new_css, $selector="", $css="", $class_id="") 847 { 848 $new_css = str_replace(array("\r\n", "\n", "\r"), "\n", $new_css); 849 850 $generated_css = ''; 851 852 // Build the new CSS properties list 853 $new_css = explode("\n", $new_css); 854 foreach($new_css as $css_line) 855 { 856 $generated_css .= "\t".trim($css_line)."\n"; 857 } 858 859 $parsed_css = array(); 860 861 // Parse out the CSS 862 if($css) 863 { 864 $parsed_css = css_to_array($css); 865 } 866 867 if(!$class_id) 868 { 869 $class_id = $parsed_css[$selector]['class_name']; 870 } 871 872 // The specified class ID cannot be found, add CSS to end of file 873 if(!$css || !$parsed_css[$selector]) 874 { 875 return $css."{$class_id}\n{\n{$generated_css}\n}\n\n"; 876 } 877 // Valid CSS, swap out old, swap in new 878 else 879 { 880 $css = str_replace(array("\r\n", "\n", "\r"), "\n", $css); 881 $css = preg_replace('#(?<!\\")\}#', "}\n", $css); 882 $css = preg_replace("#^(?!@)\s*([a-z0-9a+\\\[\]\-\"=_:>\*\.\#\,\s\(\)\|~\^]+)(\s*)\{(\n*)#isu", "\n$1 {\n", $css); 883 $css = preg_replace("#\s{1,}\{#", " {", $css); 884 $existing_block = $parsed_css[$selector]; 885 886 $break = strrpos($selector, "_"); 887 $actual_occurance = 0; 888 if($break !== false) 889 { 890 $actual_occurance = (int)substr($selector, ($break+1)); 891 } 892 893 if(!$actual_occurance) 894 { 895 $actual_occurance = 1; 896 } 897 898 $occurance = 1; 899 $pos = 0; 900 do 901 { 902 $pos = strpos($css, "\n".$existing_block['class_name']." {", $pos); 903 if($pos === false) 904 { 905 break; 906 } 907 if($occurance == $actual_occurance) 908 { 909 // This is the part we want to replace, now we need to fetch the opening & closing braces 910 $opening = strpos($css, "{", $pos); 911 $closing = strpos($css, "}", $pos); 912 $css = substr_replace($css, "\n".$generated_css."\n", $opening+1, $closing-$opening-1); 913 break; 914 } 915 ++$occurance; 916 ++$pos; 917 } while($occurance <= $actual_occurance); 918 } 919 $css = preg_replace("#{\n*#s", "{\n", $css); 920 $css = preg_replace("#\s*\}\s*#", "\n}\n\n", $css); 921 return $css; 922 } 923 924 /** 925 * @param array $stylesheet 926 * @param int $tid 927 * 928 * @return bool|int 929 */ 930 function copy_stylesheet_to_theme($stylesheet, $tid) 931 { 932 global $db; 933 934 $stylesheet['tid'] = $tid; 935 unset($stylesheet['sid']); 936 937 $new_stylesheet = array(); 938 foreach($stylesheet as $key => $value) 939 { 940 if(!is_numeric($key)) 941 { 942 $new_stylesheet[$db->escape_string($key)] = $db->escape_string($value); 943 } 944 } 945 946 $sid = $db->insert_query("themestylesheets", $new_stylesheet); 947 948 return $sid; 949 } 950 951 /** 952 * @param int $tid 953 * @param bool|array $theme 954 * @param bool $update_disporders 955 * 956 * @return bool 957 */ 958 function update_theme_stylesheet_list($tid, $theme = false, $update_disporders = true) 959 { 960 global $mybb, $db, $cache, $plugins; 961 962 $stylesheets = array(); 963 964 $child_list = make_child_theme_list($tid); 965 $parent_list = make_parent_theme_list($tid); 966 967 if(!is_array($parent_list)) 968 { 969 return false; 970 } 971 972 $tid_list = implode(',', $parent_list); 973 974 // Get our list of stylesheets 975 $query = $db->simple_select("themestylesheets", "*", "tid IN ({$tid_list})", array('order_by' => 'tid', 'order_dir' => 'desc')); 976 while($stylesheet = $db->fetch_array($query)) 977 { 978 if(empty($stylesheets[$stylesheet['name']])) 979 { 980 if($stylesheet['tid'] != $tid) 981 { 982 $stylesheet['inherited'] = $stylesheet['tid']; 983 } 984 985 $stylesheets[$stylesheet['name']] = $stylesheet; 986 } 987 } 988 989 $theme_stylesheets = array(); 990 991 foreach($stylesheets as $name => $stylesheet) 992 { 993 $sid = $stylesheet['sid']; 994 $css_url = "css.php?stylesheet={$sid}"; 995 996 foreach($parent_list as $theme_id) 997 { 998 if(!empty($mybb->settings['usecdn']) && !empty($mybb->settings['cdnpath'])) 999 { 1000 $cdnpath = rtrim($mybb->settings['cdnpath'], '/\\').'/'; 1001 if(file_exists($cdnpath."cache/themes/theme{$theme_id}/{$stylesheet['name']}") && filemtime( 1002 $cdnpath."cache/themes/theme{$theme_id}/{$stylesheet['name']}" 1003 ) >= $stylesheet['lastmodified'] 1004 ) 1005 { 1006 $css_url = "cache/themes/theme{$theme_id}/{$stylesheet['name']}"; 1007 break; 1008 } 1009 } 1010 else 1011 { 1012 if(file_exists(MYBB_ROOT."cache/themes/theme{$theme_id}/{$stylesheet['name']}") && filemtime( 1013 MYBB_ROOT."cache/themes/theme{$theme_id}/{$stylesheet['name']}" 1014 ) >= $stylesheet['lastmodified'] 1015 ) 1016 { 1017 $css_url = "cache/themes/theme{$theme_id}/{$stylesheet['name']}"; 1018 break; 1019 } 1020 } 1021 } 1022 1023 if(is_object($plugins)) 1024 { 1025 $plugins->run_hooks('update_theme_stylesheet_list_set_css_url', $css_url); 1026 } 1027 1028 $attachedto = $stylesheet['attachedto']; 1029 if(!$attachedto) 1030 { 1031 $attachedto = "global"; 1032 } 1033 // private.php?compose,folders|usercp.php,global|global 1034 $attachedto = explode("|", $attachedto); 1035 foreach($attachedto as $attached_file) 1036 { 1037 $attached_actions = array(); 1038 if(strpos($attached_file, '?') !== false) 1039 { 1040 $attached_file = explode('?', $attached_file); 1041 $attached_actions = explode(",", $attached_file[1]); 1042 $attached_file = $attached_file[0]; 1043 } 1044 1045 if(count($attached_actions) == 0) 1046 { 1047 $attached_actions = array("global"); 1048 } 1049 1050 foreach($attached_actions as $action) 1051 { 1052 $theme_stylesheets[$attached_file][$action][] = $css_url; 1053 1054 if(!empty($stylesheet['inherited'])) 1055 { 1056 $theme_stylesheets['inherited']["{$attached_file}_{$action}"][$css_url] = $stylesheet['inherited']; 1057 } 1058 } 1059 } 1060 } 1061 1062 // Now we have our list of built stylesheets, save them 1063 $updated_theme = array( 1064 "stylesheets" => $db->escape_string(my_serialize($theme_stylesheets)) 1065 ); 1066 1067 // Do we have a theme present? If so, update the stylesheet display orders 1068 if($update_disporders) 1069 { 1070 if(!is_array($theme) || !$theme) 1071 { 1072 $theme_cache = cache_themes(); 1073 $theme = $theme_cache[$tid]; 1074 } 1075 1076 $orders = $orphaned_stylesheets = array(); 1077 $properties = $theme['properties']; 1078 1079 if(!is_array($properties)) 1080 { 1081 $properties = my_unserialize($theme['properties']); 1082 } 1083 1084 $max_disporder = 0; 1085 1086 foreach($stylesheets as $stylesheet) 1087 { 1088 if(!isset($properties['disporder'][$stylesheet['name']])) 1089 { 1090 $orphaned_stylesheets[] = $stylesheet['name']; 1091 continue; 1092 } 1093 1094 if($properties['disporder'][$stylesheet['name']] > $max_disporder) 1095 { 1096 $max_disporder = $properties['disporder'][$stylesheet['name']]; 1097 } 1098 1099 $orders[$stylesheet['name']] = $properties['disporder'][$stylesheet['name']]; 1100 } 1101 1102 if(!empty($orphaned_stylesheets)) 1103 { 1104 $loop = $max_disporder + 1; 1105 $max_disporder = $loop; 1106 foreach($orphaned_stylesheets as $stylesheet) 1107 { 1108 $orders[$stylesheet] = $loop; 1109 ++$loop; 1110 } 1111 } 1112 1113 asort($orders); 1114 $properties['disporder'] = $orders; 1115 $updated_theme['properties'] = $db->escape_string(my_serialize($properties)); 1116 } 1117 1118 $db->update_query("themes", $updated_theme, "tid = '{$tid}'"); 1119 1120 // Do we have any children themes that need updating too? 1121 if(is_array($child_list) && count($child_list) > 0) 1122 { 1123 foreach($child_list as $id) 1124 { 1125 update_theme_stylesheet_list($id, false, $update_disporders); 1126 } 1127 } 1128 1129 $cache->update_default_theme(); 1130 1131 return true; 1132 } 1133 1134 /** 1135 * @param int $tid 1136 * 1137 * @return array|bool 1138 */ 1139 function make_parent_theme_list($tid) 1140 { 1141 static $themes_by_parent; 1142 1143 $themes = array(); 1144 if(!is_array($themes_by_parent)) 1145 { 1146 $theme_cache = cache_themes(); 1147 foreach($theme_cache as $key => $theme) 1148 { 1149 if($key == "default") 1150 { 1151 continue; 1152 } 1153 1154 $themes_by_parent[$theme['tid']][$theme['pid']] = $theme; 1155 } 1156 } 1157 1158 if(!isset($themes_by_parent[$tid]) || !is_array($themes_by_parent[$tid])) 1159 { 1160 return false; 1161 } 1162 1163 reset($themes_by_parent); 1164 reset($themes_by_parent[$tid]); 1165 1166 $themes = array(); 1167 1168 foreach($themes_by_parent[$tid] as $key => $theme) 1169 { 1170 $themes[] = $theme['tid']; 1171 $parents = make_parent_theme_list($theme['pid']); 1172 1173 if(is_array($parents)) 1174 { 1175 $themes = array_merge($themes, $parents); 1176 } 1177 } 1178 1179 return $themes; 1180 } 1181 1182 /** 1183 * @param int $tid 1184 * 1185 * @return array|null 1186 */ 1187 function make_child_theme_list($tid) 1188 { 1189 static $themes_by_child; 1190 1191 $themes = array(); 1192 if(!is_array($themes_by_child)) 1193 { 1194 $theme_cache = cache_themes(); 1195 foreach($theme_cache as $key => $theme) 1196 { 1197 if($key == "default") 1198 { 1199 continue; 1200 } 1201 1202 $themes_by_child[$theme['pid']][$theme['tid']] = $theme; 1203 } 1204 } 1205 1206 if(!isset($themes_by_child[$tid]) || !is_array($themes_by_child[$tid])) 1207 { 1208 return null; 1209 } 1210 1211 $themes = array(); 1212 1213 foreach($themes_by_child[$tid] as $theme) 1214 { 1215 $themes[] = $theme['tid']; 1216 $children = make_child_theme_list($theme['tid']); 1217 1218 if(is_array($children)) 1219 { 1220 $themes = array_merge($themes, $children); 1221 } 1222 } 1223 1224 return $themes; 1225 } 1226 1227 /** 1228 * @return array 1229 */ 1230 function cache_themes() 1231 { 1232 global $db, $theme_cache; 1233 1234 if(empty($theme_cache) || !is_array($theme_cache)) 1235 { 1236 $query = $db->simple_select("themes", "*", "", array('order_by' => "pid, name")); 1237 while($theme = $db->fetch_array($query)) 1238 { 1239 $theme['users'] = 0; 1240 $theme['properties'] = my_unserialize($theme['properties']); 1241 $theme['stylesheets'] = my_unserialize($theme['stylesheets']); 1242 $theme_cache[$theme['tid']] = $theme; 1243 1244 if($theme['def'] == 1) 1245 { 1246 $theme_cache['default'] = $theme['tid']; 1247 } 1248 } 1249 } 1250 1251 // Do we have no themes assigned as default? 1252 if(empty($theme_cache['default'])) 1253 { 1254 $theme_cache['default'] = 1; 1255 } 1256 1257 return $theme_cache; 1258 } 1259 1260 /** 1261 * @param int $parent 1262 * @param int $depth 1263 */ 1264 function build_theme_list($parent=0, $depth=0) 1265 { 1266 global $mybb, $db, $table, $lang, $page; // Global $table is bad, but it will have to do for now 1267 static $theme_cache; 1268 1269 $padding = $depth*20; // Padding 1270 1271 if(!is_array($theme_cache)) 1272 { 1273 $themes = cache_themes(); 1274 $query = $db->simple_select("users", "style, COUNT(uid) AS users", "", array('group_by' => 'style')); 1275 while($user_themes = $db->fetch_array($query)) 1276 { 1277 if($user_themes['style'] == 0) 1278 { 1279 $user_themes['style'] = $themes['default']; 1280 } 1281 1282 if(isset($themes[$user_themes['style']]['users']) && $themes[$user_themes['style']]['users'] > 0) 1283 { 1284 $themes[$user_themes['style']]['users'] += (int)$user_themes['users']; 1285 } 1286 else 1287 { 1288 $themes[$user_themes['style']]['users'] = (int)$user_themes['users']; 1289 } 1290 } 1291 1292 // Restrucure the theme array to something we can "loop-de-loop" with 1293 foreach($themes as $key => $theme) 1294 { 1295 if($key == "default") 1296 { 1297 continue; 1298 } 1299 1300 $theme_cache[$theme['pid']][$theme['tid']] = $theme; 1301 } 1302 $theme_cache['num_themes'] = count($themes); 1303 unset($themes); 1304 } 1305 1306 if(!isset($theme_cache[$parent]) || !is_array($theme_cache[$parent])) 1307 { 1308 return; 1309 } 1310 1311 foreach($theme_cache[$parent] as $theme) 1312 { 1313 $popup = new PopupMenu("theme_{$theme['tid']}", $lang->options); 1314 $set_default = ''; 1315 if($theme['tid'] > 1) 1316 { 1317 $popup->add_item($lang->edit_theme, "index.php?module=style-themes&action=edit&tid={$theme['tid']}"); 1318 $theme['name'] = "<a href=\"index.php?module=style-themes&action=edit&tid={$theme['tid']}\">".htmlspecialchars_uni($theme['name'])."</a>"; 1319 1320 // We must have at least the master and 1 other active theme 1321 if($theme_cache['num_themes'] > 2) 1322 { 1323 $popup->add_item($lang->delete_theme, "index.php?module=style-themes&action=delete&tid={$theme['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_theme_deletion}')"); 1324 } 1325 1326 if($theme['def'] != 1) 1327 { 1328 $popup->add_item($lang->set_as_default, "index.php?module=style-themes&action=set_default&tid={$theme['tid']}&my_post_key={$mybb->post_code}"); 1329 $set_default = "<a href=\"index.php?module=style-themes&action=set_default&tid={$theme['tid']}&my_post_key={$mybb->post_code}\"><img src=\"styles/{$page->style}/images/icons/make_default.png\" alt=\"{$lang->set_as_default}\" style=\"vertical-align: middle;\" title=\"{$lang->set_as_default}\" /></a>"; 1330 } 1331 else 1332 { 1333 $set_default = "<img src=\"styles/{$page->style}/images/icons/default.png\" alt=\"{$lang->default_theme}\" style=\"vertical-align: middle;\" title=\"{$lang->default_theme}\" />"; 1334 } 1335 $popup->add_item($lang->force_on_users, "index.php?module=style-themes&action=force&tid={$theme['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_theme_forced}')"); 1336 $set_default = "<div class=\"float_right\">{$set_default}</div>"; 1337 } 1338 $popup->add_item($lang->export_theme, "index.php?module=style-themes&action=export&tid={$theme['tid']}"); 1339 $popup->add_item($lang->duplicate_theme, "index.php?module=style-themes&action=duplicate&tid={$theme['tid']}"); 1340 $table->construct_cell("{$set_default}<div style=\"margin-left: {$padding}px;\"><strong>{$theme['name']}</strong></div>"); 1341 $table->construct_cell(my_number_format($theme['users']), array("class" => "align_center")); 1342 $table->construct_cell($popup->fetch(), array("class" => "align_center")); 1343 $table->construct_row(); 1344 1345 // Fetch & build any child themes 1346 build_theme_list($theme['tid'], ++$depth); 1347 } 1348 } 1349 1350 /** 1351 * returns an array which can be sent to generate_select_box() 1352 * 1353 * @param int $ignoretid 1354 * @param int $parent 1355 * @param int $depth 1356 * 1357 * @return null|string 1358 */ 1359 function build_theme_array($ignoretid = null, $parent=0, $depth=0) 1360 { 1361 global $list; 1362 static $theme_cache; 1363 1364 if(!is_array($theme_cache)) 1365 { 1366 $themes = cache_themes(); 1367 // Restrucure the theme array to something we can "loop-de-loop" with 1368 foreach($themes as $key => $theme) 1369 { 1370 if($key == "default") 1371 { 1372 continue; 1373 } 1374 1375 $theme_cache[$theme['pid']][$theme['tid']] = $theme; 1376 } 1377 unset($theme); 1378 } 1379 1380 if(!isset($theme_cache[$parent]) || !is_array($theme_cache[$parent]) || $ignoretid === $parent) 1381 { 1382 return null; 1383 } 1384 1385 foreach($theme_cache[$parent] as $theme) 1386 { 1387 if($ignoretid === $theme['tid']) 1388 { 1389 continue; 1390 } 1391 1392 $list[$theme['tid']] = str_repeat("--", $depth).$theme['name']; 1393 // Fetch & build any child themes 1394 build_theme_array($ignoretid, $theme['tid'], $depth+1); 1395 } 1396 1397 if(!$parent) 1398 { 1399 return $list; 1400 } 1401 } 1402 1403 /** 1404 * @param array $theme 1405 * 1406 * @return array|bool 1407 */ 1408 function fetch_theme_stylesheets($theme) 1409 { 1410 // Fetch list of all of the stylesheets for this theme 1411 $file_stylesheets = my_unserialize($theme['stylesheets']); 1412 1413 if(!is_array($file_stylesheets)) 1414 { 1415 return false; 1416 } 1417 1418 $stylesheets = array(); 1419 $inherited_load = array(); 1420 1421 // Now we loop through the list of stylesheets for each file 1422 foreach($file_stylesheets as $file => $action_stylesheet) 1423 { 1424 if($file == 'inherited') 1425 { 1426 continue; 1427 } 1428 1429 foreach($action_stylesheet as $action => $style) 1430 { 1431 foreach($style as $stylesheet2) 1432 { 1433 $stylesheets[$stylesheet2]['applied_to'][$file][] = $action; 1434 if(isset($file_stylesheets['inherited'][$file."_".$action]) && is_array($file_stylesheets['inherited'][$file."_".$action]) && in_array($stylesheet2, array_keys($file_stylesheets['inherited'][$file."_".$action]))) 1435 { 1436 $stylesheets[$stylesheet2]['inherited'] = $file_stylesheets['inherited'][$file."_".$action]; 1437 foreach($file_stylesheets['inherited'][$file."_".$action] as $value) 1438 { 1439 $inherited_load[] = $value; 1440 } 1441 } 1442 } 1443 } 1444 } 1445 1446 foreach($stylesheets as $file => $stylesheet2) 1447 { 1448 if(isset($stylesheet2['inherited']) && is_array($stylesheet2['inherited'])) 1449 { 1450 foreach($stylesheet2['inherited'] as $inherited_file => $tid) 1451 { 1452 $stylesheet2['inherited'][basename($inherited_file)] = $tid; 1453 unset($stylesheet2['inherited'][$inherited_file]); 1454 } 1455 } 1456 1457 $stylesheets[basename($file)] = $stylesheet2; 1458 unset($stylesheets[$file]); 1459 } 1460 1461 return $stylesheets; 1462 } 1463 1464 /** 1465 * @param string $css 1466 * 1467 * @return string 1468 */ 1469 function upgrade_css_120_to_140($css) 1470 { 1471 global $mybb; 1472 // Update our CSS to the new stuff in 1.4 1473 $parsed_css = css_to_array($css); 1474 1475 if(!is_array($parsed_css)) 1476 { 1477 return ""; 1478 } 1479 1480 foreach($parsed_css as $class_id => $array) 1481 { 1482 $parsed_css[$class_id]['values'] = str_replace('#eea8a1', '#ffdde0', $array['values']); 1483 $parsed_css[$class_id]['values'] = str_replace('font-family: Verdana;', 'font-family: Verdana, Arial, Sans-Serif;', $array['values']); 1484 1485 switch($array['class_name']) 1486 { 1487 case '.bottommenu': 1488 $parsed_css[$class_id]['values'] = str_replace('padding: 6px;', 'padding: 10px;', $array['values']); 1489 break; 1490 case '.expcolimage': 1491 $parsed_css[$class_id]['values'] .= "\n\tmargin-top: 2px;"; 1492 break; 1493 case '.toolbar_normal': 1494 case '.toolbar_hover': 1495 case '.toolbar_clicked': 1496 case '.pagenav': 1497 case '.pagenavbit': 1498 case '.pagenavbit a': 1499 case '.pagenavcurrent': 1500 case '.quote_header': 1501 case '.quote_body': 1502 case '.code_header': 1503 case '.code_body': 1504 case '.usercpnav': 1505 case '.usercpnav li': 1506 case '.usercpnav .pmfolders': 1507 unset($parsed_css[$class_id]); 1508 break; 1509 default: 1510 } 1511 } 1512 1513 $to_add = array( 1514 md5('.trow_selected td') => array("class_name" => '.trow_selected td', "values" => 'background: #FFFBD9;'), 1515 md5('blockquote') => array("class_name" => 'blockquote', "values" => "border: 1px solid #ccc;\n\tmargin: 0;\n\tbackground: #fff;\n\tpadding: 4px;"), 1516 md5('blockquote cite') => array("class_name" => 'blockquote cite', "values" => "font-weight: bold;\n\tborder-bottom: 1px solid #ccc;\n\tfont-style: normal;\n\tdisplay: block;\n\tmargin: 4px 0;"), 1517 md5('blockquote cite span') => array("class_name" => 'blockquote cite span', "values" => "float: right;\n\tfont-weight: normal;"), 1518 md5('.codeblock') => array("class_name" => '.codeblock', "values" => "background: #fff;\n\tborder: 1px solid #ccc;\n\tpadding: 4px;"), 1519 md5('.codeblock .title') => array("class_name" => '.codeblock .title', "values" => "border-bottom: 1px solid #ccc;\n\tfont-weight: bold;\n\tmargin: 4px 0;"), 1520 md5('.codeblock code') => array("class_name" => '.codeblock code', "values" => "overflow: auto;\n\theight: auto;\n\tmax-height: 200px;\n\tdisplay: block;\n\tfont-family: Monaco, Consolas, Courier, monospace;\n\tfont-size: 13px;"), 1521 md5('.subject_new') => array("class_name" => '.subject_new', "values" => "font-weight: bold;"), 1522 md5('.highlight') => array("class_name" => '.highlight', "values" => "background: #FFFFCC;\n\tpadding: 3px;"), 1523 md5('.pm_alert') => array("class_name" => '.pm_alert', "values" => "background: #FFF6BF;\n\tborder: 1px solid #FFD324;\n\ttext-align: center;\n\tpadding: 5px 20px;\n\tfont-size: 11px;"), 1524 md5('.red_alert') => array("class_name" => '.red_alert', "values" => "background: #FBE3E4;\n\tborder: 1px solid #A5161A;\n\tcolor: #A5161A;\n\ttext-align: center;\n\tpadding: 5px 20px;\n\tfont-size: 11px;"), 1525 md5('.high_warning') => array("class_name" => '.high_warning', "values" => "color: #CC0000;"), 1526 md5('.moderate_warning') => array("class_name" => '.moderate_warning', "values" => "color: #F3611B;"), 1527 md5('.low_warning') => array("class_name" => '.low_warning', "values" => "color: #AE5700;"), 1528 md5('div.error') => array("class_name" => 'div.error', "values" => "padding: 5px 10px;\n\tborder-top: 2px solid #FFD324;\n\tborder-bottom: 2px solid #FFD324;\n\tbackground: #FFF6BF\n\tfont-size: 12px;"), 1529 md5('.high_warning') => array("class_name" => '.high_warning', "values" => "color: #CC0000;"), 1530 md5('.moderate_warning') => array("class_name" => '.moderate_warning', "values" => "color: #F3611B;"), 1531 md5('.low_warning') => array("class_name" => '.low_warning', "values" => "color: #AE5700;"), 1532 md5('div.error') => array("class_name" => 'div.error', "values" => "padding: 5px 10px;\n\tborder-top: 2px solid #FFD324;\n\tborder-bottom: 2px solid #FFD324;\n\tbackground: #FFF6BF;\n\tfont-size: 12px;"), 1533 md5('div.error p') => array("class_name" => 'div.error p', "values" => "margin: 0;\n\tcolor: #000;\n\tfont-weight: normal;"), 1534 md5('div.error p em') => array("class_name" => 'div.error p em', "values" => "font-style: normal;\n\tfont-weight: bold;\n\tpadding-left: 24px;\n\tdisplay: block;\n\tcolor: #C00;\n\tbackground: url({$mybb->settings['bburl']}/images/error.png) no-repeat 0;"), 1535 md5('div.error.ul') => array("class_name" => 'div.error.ul', "values" => "margin-left: 24px;"), 1536 md5('.online') => array("class_name" => '.online', "values" => "color: #15A018;"), 1537 md5('.offline') => array("class_name" => '.offline', "values" => "color: #C7C7C7;"), 1538 md5('.pagination') => array("class_name" => '.pagination', "values" => "font-size: 11px;\n\tpadding-top: 10px;\n\tmargin-bottom: 5px;"), 1539 md5('.tfoot .pagination, .tcat .pagination') => array("class_name" => '.tfoot .pagination, .tcat .pagination', "values" => "padding-top: 0;"), 1540 md5('.pagination .pages') => array("class_name" => '.pagination .pages', "values" => "font-weight: bold;"), 1541 md5('.pagination .pagination_current, .pagination a') => array("class_name" => '.pagination .pagination_current, .pagination a', "values" => "padding: 2px 6px;\n\tmargin-bottom: 3px;"), 1542 md5('.pagination a') => array("class_name" => '.pagination a', "values" => "border: 1px solid #81A2C4;"), 1543 md5('.pagination .pagination_current') => array("class_name" => '.pagination .pagination_current', "values" => "background: #F5F5F5;\n\tborder: 1px solid #81A2C4;\n\tfont-weight: bold;"), 1544 md5('.pagination a:hover') => array("class_name" => '.pagination a:hover', "values" => "background: #F5F5F5;\n\ttext-decoration: none;"), 1545 md5('.thread_legend, .thread_legend dd') => array("class_name" => '.thread_legend, .thread_legend dd', "values" => "margin: 0;\n\tpadding: 0;"), 1546 md5('.thread_legend dd') => array("class_name" => '.thread_legend dd', "values" => "padding-bottom: 4px;\n\tmargin-right: 15px;"), 1547 md5('.thread_legend img') => array("class_name" => '.thread_legend img', "values" => "margin-right: 4px;\n\tvertical-align: bottom;"), 1548 md5('.forum_legend, .forum_legend dt, .forum_legend dd') => array("class_name" => '.forum_legend, .forum_legend dt, .forum_legend dd', "values" => "margin: 0;\n\tpadding: 0;"), 1549 md5('.forum_legend dd') => array("class_name" => '.forum_legend dd', "values" => "float: left;\n\tmargin-right: 10px;"), 1550 md5('.forum_legend dt') => array("class_name" => '.forum_legend dt', "values" => "margin-right: 10px;\n\tfloat: left;"), 1551 md5('.success_message') => array("class_name" => '.success_message', "values" => "color: #00b200;\n\tfont-weight: bold;\n\tfont-size: 10px;\n\tmargin-bottom: 10px;"), 1552 md5('.error_message') => array("class_name" => '.error_message', "values" => "color: #C00;\n\tfont-weight: bold;\n\tfont-size: 10px;\n\tmargin-bottom: 10px;"), 1553 md5('.post_body') => array("class_name" => '.post_body', "values" => "padding: 5px;"), 1554 md5('.post_content') => array("class_name" => '.post_content', "values" => "padding: 5px 10px;"), 1555 md5('.invalid_field') => array("class_name" => '.invalid_field', "values" => "border: 1px solid #f30;\n\tcolor: #f30;"), 1556 md5('.valid_field') => array("class_name" => '.valid_field', "values" => "border: 1px solid #0c0;"), 1557 md5('.validation_error') => array("class_name" => '.validation_error', "values" => "background: url(images/invalid.png) no-repeat center left;\n\tcolor: #f30;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), 1558 md5('.validation_success') => array("class_name" => '.validation_success', "values" => "background: url(images/valid.png) no-repeat center left;\n\tcolor: #00b200;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), 1559 md5('.validation_loading') => array("class_name" => '.validation_loading', "values" => "background: url(images/spinner.gif) no-repeat center left;\n\tcolor: #555;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), 1560 ); 1561 1562 $already_parsed = array(); 1563 1564 foreach($to_add as $class_id => $array) 1565 { 1566 if(isset($already_parsed[$class_id])) 1567 { 1568 $already_parsed[$class_id]++; 1569 $class_id .= "_".$already_parsed[$class_id]; 1570 } 1571 else 1572 { 1573 $already_parsed[$class_id] = 1; 1574 } 1575 1576 $array['name'] = ""; 1577 $array['description'] = ""; 1578 1579 $parsed_css[$class_id] = $array; 1580 } 1581 1582 $theme = array( 1583 'css' => '', 1584 ); 1585 1586 $css = ""; 1587 foreach($parsed_css as $class_id => $array) 1588 { 1589 if($array['name'] || $array['description']) 1590 { 1591 $theme['css'] .= "/* "; 1592 if($array['name']) 1593 { 1594 $array['css'] .= "Name: {$array['name']}"; 1595 1596 if($array['description']) 1597 { 1598 $array['css'] .= "\n"; 1599 } 1600 } 1601 1602 if($array['description']) 1603 { 1604 $array['css'] .= "Description: {$array['description']}"; 1605 } 1606 1607 $array['css'] .= " */\n"; 1608 } 1609 1610 $css .= "{$array['class_name']} {\n\t{$array['values']}\n}\n"; 1611 } 1612 1613 return $css; 1614 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |