PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/modules/validate/controllers/validate.php

https://github.com/ochinedu/FUEL-CMS
PHP | 471 lines | 366 code | 78 blank | 27 comment | 52 complexity | 11bbebe3d9ebb1a0eb674a1716b5c2bb MD5 | raw file
  1. <?php
  2. require_once(FUEL_PATH.'libraries/Fuel_base_controller.php');
  3. class Validate extends Fuel_base_controller {
  4. public $nav_selected = 'tools/validate|tools/validate/:any';
  5. public $view_location = 'validate';
  6. function __construct()
  7. {
  8. parent::__construct();
  9. $this->load->config('validate');
  10. $this->load->language('validate');
  11. $this->js_controller_params['module'] = 'tools';
  12. $this->_validate_user('tools/validate');
  13. }
  14. function index()
  15. {
  16. if (!$this->_has_module('fuel')) show_error(lang('error_missing_module', 'validate'));
  17. $this->load->module_model(FUEL_FOLDER, 'pages_model');
  18. $pages = $this->pages_model->all_pages_including_views(TRUE);
  19. $validate_config = $this->config->item('validate');
  20. $vars['default_page_input'] = $validate_config['default_page_input'];
  21. $vars['error'] = (!extension_loaded('curl')) ? lang('error_no_curl_lib') : '';
  22. $vars['validation_type'] = 'HTML';
  23. $vars['pages_select'] = $pages;
  24. $this->js_controller_params['method'] = 'validate';
  25. $this->js_controller_params['pages_input'] = lang('pages_input');
  26. $this->_render('validate', $vars);
  27. }
  28. function html()
  29. {
  30. if (!$this->_has_module('fuel')) show_error(lang('error_missing_module'));
  31. if (!extension_loaded('curl')) show_error(lang('error_no_curl_lib'));
  32. $validate_config = $this->config->item('validate');
  33. if ($this->input->post('uri'))
  34. {
  35. $this->load->library('user_agent');
  36. $this->load->module_model(FUEL_FOLDER, 'pages_model');
  37. $page_data = $this->pages_model->find_by_location($this->input->post('uri'), FALSE);
  38. // if valid_internal_domains config match then read the file and post to validator
  39. // determine if server is local
  40. $results = '';
  41. $local = false;
  42. $servers = (array) $validate_config['valid_internal_server_names'];
  43. foreach($servers as $server)
  44. {
  45. $server = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $server));
  46. if (preg_match('#^'.$server.'$#', $_SERVER['SERVER_NAME'])) $local = TRUE;
  47. }
  48. if ($local)
  49. {
  50. $this->load->helper('file');
  51. // scrape html from page running on localhost
  52. $ch = curl_init();
  53. curl_setopt($ch, CURLOPT_URL, $this->input->post('uri'));
  54. curl_setopt($ch, CURLOPT_HEADER, 0);
  55. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  56. curl_setopt($ch, CURLOPT_USERAGENT, $this->agent->agent_string());
  57. $fragment = curl_exec($ch);
  58. curl_close($ch);
  59. // post data using fragment variable
  60. $tmp_filename = str_replace(array('/', ':'), '_', $this->input->post('uri'));
  61. $tmp_filename = substr($tmp_filename, 4);
  62. $tmp_file_for_validation_urls = BASEPATH.'cache/validation_url-'.$tmp_filename.'.html';
  63. write_file($tmp_file_for_validation_urls, $fragment);
  64. //$post['fragment'] = $fragment;
  65. $post['uploaded_file'] = '@'.$tmp_file_for_validation_urls.';type=text/html';
  66. $ch = curl_init();
  67. curl_setopt($ch, CURLOPT_URL, $validate_config['validator_url']);
  68. curl_setopt($ch, CURLOPT_HEADER, 0);
  69. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  70. curl_setopt($ch, CURLOPT_POST, 1);
  71. curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  72. $results = curl_exec($ch);
  73. curl_close($ch);
  74. if (file_exists($tmp_file_for_validation_urls)) unlink($tmp_file_for_validation_urls);
  75. }
  76. // else just pass it the uri value for it to read itself
  77. else
  78. {
  79. $ch = curl_init();
  80. curl_setopt($ch, CURLOPT_URL, $validate_config['validator_url'].'?uri='.$this->input->post('uri'));
  81. curl_setopt($ch, CURLOPT_HEADER, 0);
  82. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  83. // curl_setopt($ch, CURLOPT_POST, 1);
  84. // curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  85. $results = curl_exec($ch);
  86. curl_close($ch);
  87. }
  88. // do some html cleanup so that css and images pull
  89. $url_parts = parse_url($validate_config['validator_url']);
  90. $base_url = 'http://'.$url_parts['host'].'/';
  91. $results = str_replace('</head>', "<base href=\"".$base_url."\" />".PHP_EOL."</head>", $results);
  92. if (!empty($page_data['id'])) $results = str_replace('<body>', "<body><span style=\"display: none\" id=\"edit_url\">".fuel_url('pages/edit/'.$page_data['id'])."</span>", $results);
  93. $results = str_replace('"./style/base.css"', '"'.$base_url.'style/base.css"', $results);
  94. $results = str_replace('"./style/results.css"', '"'.$base_url.'style/results.css"', $results);
  95. $vars['results'] = $results;
  96. $this->output->set_output($results);
  97. return;
  98. }
  99. else if (!$this->input->post('pages') && !$this->input->post('pages_input') && !$this->input->post('pages_serialized'))
  100. {
  101. $this->session->set_flashdata('error', lang('error_no_pages_selected'));
  102. redirect(fuel_uri('tools/validate'));
  103. }
  104. if (!is_writable(BASEPATH.'cache/'))
  105. {
  106. $vars['error'] = lang('error_cache_folder_not_writable');
  107. }
  108. $this->js_controller_params['method'] = 'html';
  109. // $vars['js_method'] = 'html';
  110. $pages = $this->_get_pages();
  111. $this->js_controller_params['pages'] = $pages;
  112. $vars['pages_serialized'] = base64_encode(serialize($pages));
  113. $vars['validation_type'] = 'HTML';
  114. $vars['page_title'] = $this->_page_title(array('Tools', 'Validate', 'HTML'), FALSE);
  115. $this->_render('run', $vars);
  116. }
  117. function links()
  118. {
  119. if (!$this->_has_module('fuel')) show_error(lang('error_missing_module'));
  120. if (!extension_loaded('curl')) show_error(lang('error_no_curl_lib'));
  121. if ($this->input->post('uri'))
  122. {
  123. $this->load->library('user_agent');
  124. // first we grab links using the DomDocument object
  125. // turn off the warnings for bad html
  126. $oldSetting = libxml_use_internal_errors(TRUE);
  127. libxml_clear_errors();
  128. $url = $this->input->post('uri');
  129. $html = new DOMDocument();
  130. if (!@$html->loadHTMLFile($url))
  131. {
  132. $vars['error'] = lang('error_checking_page_links');
  133. }
  134. $xpath = new DOMXPath( $html );
  135. $links = $xpath->query("//a");
  136. $formatted_links = array();
  137. foreach($links as $link)
  138. {
  139. $href = $link->getAttribute('href');
  140. if (substr($href, 0, 7) != 'mailto:')
  141. {
  142. if (substr($href, 0, 1) == '/')
  143. {
  144. $href = "http://".$_SERVER['HTTP_HOST'].$href;
  145. }
  146. else if (substr($href, 0, 4) != 'http')
  147. {
  148. $href = $url.$href;
  149. }
  150. $formatted_links[] = $href;
  151. }
  152. }
  153. // change errors back to original settings
  154. libxml_clear_errors();
  155. libxml_use_internal_errors( $oldSetting );
  156. $results = '';
  157. // now loop through the links and check if they are valid
  158. $valid = array();
  159. $invalid = array();
  160. $ch = curl_init();
  161. foreach($formatted_links as $link)
  162. {
  163. curl_setopt($ch, CURLOPT_URL, $link);
  164. curl_setopt($ch, CURLOPT_HEADER, 1);
  165. curl_setopt($ch, CURLOPT_NOBODY, 1);
  166. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  167. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  168. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  169. curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 3600);
  170. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  171. curl_setopt($ch, CURLOPT_USERAGENT, $this->agent->agent_string());
  172. $ret = curl_exec($ch);
  173. $err_num = curl_errno($ch);
  174. $hcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  175. if ($hcode >= 400)
  176. {
  177. $invalid[] = $link;
  178. }
  179. else
  180. {
  181. $valid[] = $link;
  182. }
  183. }
  184. curl_close($ch);
  185. $this->load->module_model(FUEL_FOLDER, 'pages_model');
  186. $page_data = $this->pages_model->find_by_location($this->input->post('uri'), FALSE);
  187. $vars['invalid'] = $invalid;
  188. $vars['valid'] = $valid;
  189. $vars['total'] = count($formatted_links);
  190. $vars['link'] = $url;
  191. $vars['edit_url'] = (!empty($page_data['id'])) ? fuel_url('pages/edit/'.$page_data['id']) : '';
  192. $output = $this->load->view('links_output', $vars, TRUE);
  193. $this->output->set_output($output);
  194. return;
  195. }
  196. else if (!$this->input->post('pages') && !$this->input->post('pages_input') && !$this->input->post('pages_serialized'))
  197. {
  198. $this->session->set_flashdata('error', lang('error_no_pages_selected'));
  199. redirect(fuel_uri('tools/validate'));
  200. }
  201. $this->js_controller_params['method'] = 'links';
  202. $pages = $this->_get_pages();
  203. $this->js_controller_params['pages'] = $pages;
  204. $vars['pages_serialized'] = base64_encode(serialize($pages));
  205. $vars['js_method'] = 'links';
  206. $vars['validation_type'] = 'Links';
  207. $this->_render('run', $vars);
  208. }
  209. function size_report()
  210. {
  211. if (!$this->_has_module('fuel')) show_error(lang('error_missing_module'));
  212. if (!extension_loaded('curl')) show_error(lang('error_no_curl_lib'));
  213. $this->load->helper('number');
  214. $validate_config = $this->config->item('validate');
  215. if ($this->input->post('uri'))
  216. {
  217. $this->load->library('user_agent');
  218. // first we grab links using the DomDocument object
  219. // turn off the warnings for bad html
  220. $oldSetting = libxml_use_internal_errors(TRUE);
  221. libxml_clear_errors();
  222. $url = $this->input->post('uri');
  223. //$url = $uri;
  224. $html = new DOMDocument();
  225. $html->loadHTMLFile($url);
  226. $xpath = new DOMXPath( $html );
  227. $imgs = $xpath->query("//img[@src]");
  228. $css = $xpath->query("//link[@href]");
  229. $js = $xpath->query("//script[@src]");
  230. $ext_resources = array($imgs, $css, $js);
  231. $ext_resources_xpath_attr = array('src', 'href', 'src');
  232. $resources = array($url);
  233. $css_resources = array($url);
  234. $i = 0;
  235. foreach($ext_resources as $val)
  236. {
  237. foreach($val as $r)
  238. {
  239. $href = $r->getAttribute($ext_resources_xpath_attr[$i]);
  240. if (substr($href, 0, 1) == '/')
  241. {
  242. $href = "http://".$_SERVER['HTTP_HOST'].$href;
  243. }
  244. else if (substr($href, 0, 4) != 'http')
  245. {
  246. $href = $url.$href;
  247. }
  248. // check if css so we can put into a css_resource array to parse for bg images
  249. if ($ext_resources_xpath_attr[$i] == 'href')
  250. {
  251. $css_resources[] = $href;
  252. }
  253. $resources[] = $href;
  254. }
  255. $i++;
  256. }
  257. // change errors back to original settings
  258. libxml_clear_errors();
  259. libxml_use_internal_errors( $oldSetting );
  260. // now look through all css get background urls
  261. foreach($css_resources as $href)
  262. {
  263. $css_contents = file_get_contents($href);
  264. $file_base = explode('/', $href);
  265. array_pop($file_base);
  266. $file_base = implode('/', $file_base).'/';
  267. preg_match_all('|url\((.+)\)|Umis', $css_contents, $matches);
  268. if (isset($matches[1]))
  269. {
  270. foreach($matches[1] as $match)
  271. {
  272. if (substr($match, 0, 4) != 'http')
  273. {
  274. $resources[] = $file_base.$match;
  275. }
  276. else
  277. {
  278. $resources[] = $match;
  279. }
  280. }
  281. }
  282. }
  283. // remove duplicates
  284. $resources = array_unique($resources);
  285. $i++;
  286. $results = '';
  287. // now loop through the links and check if they are valid
  288. $valid = array();
  289. $invalid = array();
  290. $output_arr = array();
  291. $config_limit = $validate_config['size_report_warn_limit'];
  292. $filesize_range = array('warn' => array(), 'ok' => array());
  293. $total_kb = 0;
  294. $ch = curl_init();
  295. foreach($resources as $link)
  296. {
  297. curl_setopt($ch, CURLOPT_URL, $link);
  298. curl_setopt($ch, CURLOPT_HEADER, 0);
  299. curl_setopt($ch, CURLOPT_NOBODY, 1);
  300. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  301. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  302. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  303. curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 3600);
  304. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  305. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
  306. curl_setopt($ch, CURLOPT_USERAGENT, $this->agent->agent_string());
  307. $ret = curl_exec($ch);
  308. $err_num = curl_errno($ch);
  309. $info = curl_getinfo($ch);
  310. if ($info['http_code'] >= 400)
  311. {
  312. $invalid[] = $link;
  313. $output_arr[$link] = 'Invalid';
  314. }
  315. else
  316. {
  317. $valid[] = $link;
  318. $output_arr[$link] = $info['download_content_length'];
  319. // set filesize range
  320. $kb = $output_arr[$link]/1000;
  321. $total_kb += $output_arr[$link];
  322. switch($kb)
  323. {
  324. case ($kb < 0):
  325. $filesize_range['error'][$link] = $output_arr[$link];
  326. break;
  327. case ($kb >= $config_limit):
  328. $filesize_range['warn'][$link] = $output_arr[$link];
  329. break;
  330. default:
  331. $filesize_range['ok'][$link] = $output_arr[$link];
  332. }
  333. }
  334. }
  335. curl_close($ch);
  336. // sort array in reverse order of size
  337. arsort($output_arr);
  338. $vars['invalid'] = $invalid;
  339. $vars['valid'] = $valid;
  340. $vars['total'] = count($resources);
  341. $vars['total_kb'] = $total_kb;
  342. $vars['link'] = $url;
  343. $vars['output_arr'] = $output_arr;
  344. $vars['config_limit'] = $config_limit;
  345. $vars['filesize_range'] = $filesize_range;
  346. $output = $this->load->view('size_report_output', $vars, TRUE);
  347. $this->output->set_output($output);
  348. return;
  349. }
  350. else if (!$this->input->post('pages') && !$this->input->post('pages_input') && !$this->input->post('pages_serialized'))
  351. {
  352. $this->session->set_flashdata('error', lang('error_no_pages_selected'));
  353. redirect(fuel_uri('tools/validate'));
  354. }
  355. $this->js_controller_params['method'] = 'size';
  356. //$vars['js_method'] = 'size';
  357. $pages = $this->_get_pages();
  358. $this->js_controller_params['pages'] = $pages;
  359. $vars['pages_serialized'] = base64_encode(serialize($pages));
  360. $vars['validation_type'] = 'Size Report';
  361. $this->_render('run', $vars);
  362. }
  363. function _get_pages()
  364. {
  365. $pages_input = $this->input->post('pages_input');
  366. $extra_pages = array();
  367. if (!empty($pages_input) && $pages_input != lang('pages_input'))
  368. {
  369. $extra_pages = explode("\n", $pages_input);
  370. foreach($extra_pages as $key => $page)
  371. {
  372. $extra_pages[$key] = site_url(trim($page));
  373. }
  374. }
  375. $post_pages = $this->input->post('pages') ? $this->input->post('pages') : array();
  376. $pages = array_merge($post_pages, $extra_pages);
  377. if (empty($pages) )
  378. {
  379. $pages = $this->input->post('pages_serialized');
  380. if (empty($pages))
  381. {
  382. redirect(fuel_uri('tools/validate'));
  383. }
  384. else
  385. {
  386. $pages = unserialize(base64_decode($pages));
  387. }
  388. }
  389. return $pages;
  390. }
  391. }
  392. /* End of file tools.php */
  393. /* Location: ./codeigniter/application/modules/tools/controllers/validate.php */