1<?php 2/** 3 * Loads various functions used in parsing XML (mostly for extensions). 4 * 5 * @copyright (C) 2008-2012 PunBB, partially based on code (C) 2008-2009 FluxBB.org 6 * @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher 7 * @package PunBB 8 */ 9 10 11// Make sure no one attempts to run this script "directly" 12if (!defined('FORUM')) 13 exit; 14 15 16// 17// Parse XML data into an array 18// 19function xml_to_array($raw_xml) 20{ 21 $multi_key = array(); 22 $multi_key2 = array(); 23 $xml_parser = xml_parser_create(); 24 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0); 25 xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0); 26 xml_parse_into_struct($xml_parser, $raw_xml, $vals); 27 xml_parser_free($xml_parser); 28 unset($xml_parser); 29 30 $_tmp = ''; 31 foreach ($vals as $xml_elem) 32 { 33 $x_tag = $xml_elem['tag']; 34 $x_level = $xml_elem['level']; 35 $x_type = $xml_elem['type']; 36 37 if ($x_level != 1 && $x_type == 'close') 38 { 39 if (isset($multi_key[$x_tag][$x_level])) 40 $multi_key[$x_tag][$x_level] = 1; 41 else 42 $multi_key[$x_tag][$x_level] = 0; 43 } 44 45 if ($x_level != 1 && $x_type == 'complete') 46 { 47 if ($_tmp == $x_tag) 48 $multi_key[$x_tag][$x_level] = 1; 49 50 $_tmp = $x_tag; 51 } 52 } 53 54 foreach ($vals as $xml_elem) 55 { 56 $x_tag = $xml_elem['tag']; 57 $x_level = $xml_elem['level']; 58 $x_type = $xml_elem['type']; 59 60 if ($x_type == 'open') 61 $level[$x_level] = $x_tag; 62 63 $start_level = 1; 64 $php_stmt = '$xml_array'; 65 if ($x_type == 'close' && $x_level != 1) 66 $multi_key[$x_tag][$x_level]++; 67 68 while ($start_level < $x_level) 69 { 70 $php_stmt .= '[$level['.$start_level.']]'; 71 if (isset($multi_key[$level[$start_level]][$start_level]) && $multi_key[$level[$start_level]][$start_level]) 72 $php_stmt .= '['.($multi_key[$level[$start_level]][$start_level]-1).']'; 73 74 ++$start_level; 75 } 76 77 $add = ''; 78 if (isset($multi_key[$x_tag][$x_level]) && $multi_key[$x_tag][$x_level] && ($x_type == 'open' || $x_type == 'complete')) 79 { 80 if (!isset($multi_key2[$x_tag][$x_level])) 81 $multi_key2[$x_tag][$x_level] = 0; 82 else 83 $multi_key2[$x_tag][$x_level]++; 84 85 $add = '['.$multi_key2[$x_tag][$x_level].']'; 86 } 87 88 if (isset($xml_elem['value']) && forum_trim($xml_elem['value']) != '' && !array_key_exists('attributes', $xml_elem)) 89 { 90 if ($x_type == 'open') 91 $php_stmt_main = $php_stmt.'[$x_type]'.$add.'[\'content\'] = $xml_elem[\'value\'];'; 92 else 93 $php_stmt_main = $php_stmt.'[$x_tag]'.$add.' = $xml_elem[\'value\'];'; 94 95 eval($php_stmt_main); 96 } 97 98 if (array_key_exists('attributes', $xml_elem)) 99 { 100 if (isset($xml_elem['value'])) 101 { 102 $php_stmt_main = $php_stmt.'[$x_tag]'.$add.'[\'content\'] = $xml_elem[\'value\'];'; 103 eval($php_stmt_main); 104 } 105 106 foreach ($xml_elem['attributes'] as $key=>$value) 107 { 108 $php_stmt_att=$php_stmt.'[$x_tag]'.$add.'[\'attributes\'][$key] = $value;'; 109 eval($php_stmt_att); 110 } 111 } 112 } 113 114 if (isset($xml_array)) 115 { 116 // Make sure there's an array of notes (even if there is only one) 117 if (isset($xml_array['extension']['note'])) 118 { 119 if (!is_array(current($xml_array['extension']['note']))) 120 $xml_array['extension']['note'] = array($xml_array['extension']['note']); 121 } 122 else 123 $xml_array['extension']['note'] = array(); 124 125 // Make sure there's an array of hooks (even if there is only one) 126 if (isset($xml_array['extension']['hooks']) && isset($xml_array['extension']['hooks']['hook'])) 127 { 128 if (!is_array(current($xml_array['extension']['hooks']['hook']))) 129 $xml_array['extension']['hooks']['hook'] = array($xml_array['extension']['hooks']['hook']); 130 } 131 } 132 133 return isset($xml_array) ? $xml_array : array(); 134} 135 136 137// 138// Validate the syntax of an extension manifest file 139// 140function validate_manifest($xml_array, $folder_name) 141{ 142 global $lang_admin_ext, $forum_config; 143 144 $errors = array(); 145 146 $return = ($hook = get_hook('xm_fn_validate_manifest_start')) ? eval($hook) : null; 147 if ($return !== null) 148 return; 149 150 if (!isset($xml_array['extension']) || !is_array($xml_array['extension'])) 151 $errors[] = $lang_admin_ext['extension root error']; 152 else 153 { 154 $ext = $xml_array['extension']; 155 if (!isset($ext['attributes']['engine'])) 156 $errors[] = $lang_admin_ext['extension/engine error']; 157 else if ($ext['attributes']['engine'] != '1.0') 158 $errors[] = $lang_admin_ext['extension/engine error2']; 159 160 if (!isset($ext['id']) || $ext['id'] == '') 161 $errors[] = $lang_admin_ext['extension/id error']; 162 else if ($ext['id'] != $folder_name) 163 $errors[] = $lang_admin_ext['extension/id error2']; 164 165 if (!isset($ext['title']) || $ext['title'] == '') 166 $errors[] = $lang_admin_ext['extension/title error']; 167 if (!isset($ext['version']) || $ext['version'] == '' || preg_match('/[^a-z0-9\- \.]+/i', $ext['version'])) 168 $errors[] = $lang_admin_ext['extension/version error']; 169 if (!isset($ext['description']) || $ext['description'] == '') 170 $errors[] = $lang_admin_ext['extension/description error']; 171 if (!isset($ext['author']) || $ext['author'] == '') 172 $errors[] = $lang_admin_ext['extension/author error']; 173 if (!isset($ext['minversion']) || $ext['minversion'] == '') 174 $errors[] = $lang_admin_ext['extension/minversion error']; 175 if (isset($ext['minversion']) && version_compare(clean_version($forum_config['o_cur_version']), clean_version($ext['minversion']), '<')) 176 $errors[] = sprintf($lang_admin_ext['extension/minversion error2'], $ext['minversion']); 177 if (!isset($ext['maxtestedon']) || $ext['maxtestedon'] == '') 178 $errors[] = $lang_admin_ext['extension/maxtestedon error']; 179 180 if (isset($ext['note'])) 181 { 182 foreach ($ext['note'] as $note) 183 { 184 if (!isset($note['content']) || $note['content'] == '') 185 $errors[] = $lang_admin_ext['extension/note error']; 186 if (!isset($note['attributes']['type']) || $note['attributes']['type'] == '') 187 $errors[] = $lang_admin_ext['extension/note error2']; 188 } 189 } 190 191 if (isset($ext['hooks']) && is_array($ext['hooks'])) 192 { 193 if (!isset($ext['hooks']['hook']) || !is_array($ext['hooks']['hook'])) 194 $errors[] = $lang_admin_ext['extension/hooks/hook error']; 195 else 196 { 197 foreach ($ext['hooks']['hook'] as $hook) 198 { 199 if (!isset($hook['content']) || $hook['content'] == '') 200 $errors[] = $lang_admin_ext['extension/hooks/hook error']; 201 if (!isset($hook['attributes']['id']) || $hook['attributes']['id'] == '') 202 $errors[] = $lang_admin_ext['extension/hooks/hook error2']; 203 if (isset($hook['attributes']['priority']) && (!ctype_digit($hook['attributes']['priority']) || $hook['attributes']['priority'] < 0 || $hook['attributes']['priority'] > 10)) 204 $errors[] = $lang_admin_ext['extension/hooks/hook error3']; 205 206 $tokenized_hook = token_get_all('<?php '.$hook['content']); 207 $last_element = array_pop($tokenized_hook); 208 if (is_array($last_element) && $last_element[0] == T_INLINE_HTML) 209 $errors[] = $lang_admin_ext['extension/hooks/hook error4']; 210 } 211 } 212 } 213 } 214 215 ($hook = get_hook('xm_fn_validate_manifest_end')) ? eval($hook) : null; 216 217 return $errors; 218} 219 220define('FORUM_XML_FUNCTIONS_LOADED', 1); 221