function check_file($node) { global $context; global $footprints; $key = substr($node, strlen($context['path_to_root'])); // no extension to check if (strpos($key, '.') === FALSE) { } elseif (!strncmp($node, 'scripts/staging', 16)) { } elseif (!strcmp($key, 'footprints.php')) { } elseif (!strncmp(substr($key, -9), 'index.php', 9) && ($content = Safe::file_get_contents($node)) && !strcmp($content, Safe::mkdir_index_content())) { } elseif (!strncmp($key, 'temporary/cache_i18n_locale_', 28)) { } elseif (!strncmp(substr($key, -4), '.php', 4)) { // one of the parameter files created by yacs if (preg_match('/parameters\\/(agents|control|feeds|files|hooks|letters|root|scripts|services|skins|users|virtual_.+)\\.include\\.php$/i', $key)) { } elseif (isset($footprints[$key])) { $expected = $footprints[$key]; $actual = Scripts::hash($node); if ($expected[0] != $actual[0] || $expected[1] != $actual[1]) { $context['text'] .= sprintf(i18n::s('ERROR: File %s is missing or corrupted.'), $key) . BR . "\n"; } } else { $context['text'] .= sprintf(i18n::s('File %s is not part of Yacs.'), $key) . BR . "\n"; } // not a safe file } elseif (!preg_match('/\\.(bak|bat|css|done|dtd|fdb|flv|gif|ico|jpeg|jpg|js|jsmin|htc|htm|html|mo|off|on|pdf|png|po|pot|reg|sh|sql|swf|tgz|txt|xml|zip)$/i', $key)) { $context['text'] .= sprintf(i18n::s('File %s is not part of Yacs.'), $key) . BR . "\n"; } }
$url = 'http://' . $context['reference_server'] . '/scripts/fetch.php?script=' . $file; if (!($content = http::proceed($url))) { $context['text'] .= sprintf(i18n::s('Impossible to read %s.'), $url) . BR . "\n"; $errors++; continue; } // ensure enough execution time Safe::set_time_limit(30); // save it in the staging store if (!Safe::file_put_contents('scripts/staging/' . $file, $content)) { $context['text'] .= '<p>' . sprintf(i18n::s('Impossible to write to %s.'), 'scripts/staging/' . $file) . "</p>\n"; $errors++; continue; } // ensure we have an exact copy by comparing hashes $staging_hash = Scripts::hash('scripts/staging/' . $file); if ($attributes[1] != $staging_hash[1]) { $context['text'] .= i18n::s('File has been corrupted!') . BR . "\n"; $errors++; continue; } // update statistics $staging_files++; } // errors have been encountered if ($errors) { $context['text'] .= i18n::s('Errors have been encountered, and you cannot proceed with the network update.') . "</p>\n"; // forward to the index page $menu = array('scripts/' => i18n::s('Server software')); $context['text'] .= Skin::build_list($menu, 'menu_bar'); // server is up to date
/** * delete reference files * * @param string the directory to start with * @see scripts/build.php */ function delete_reference($path) { global $context; $path_translated = str_replace('//', '/', $context['path_to_reference'] . $path); if ($handle = Safe::opendir($path_translated)) { while (($node = Safe::readdir($handle)) !== FALSE) { if ($node[0] == '.') { continue; } // make a real name $target = str_replace('//', '/', $path . '/' . $node); $target_translated = str_replace('//', '/', $path_translated . '/' . $node); // delete sub directory content if (is_dir($target_translated)) { delete_reference($target); } elseif (Scripts::hash($context['path_to_reference'] . $target)) { $context['text'] .= sprintf(i18n::s('Deleting %s'), substr($target, 1)) . BR . "\n"; Safe::unlink($target_translated); global $deleted_nodes; $deleted_nodes++; } // ensure we have enough time Safe::set_time_limit(30); } Safe::closedir($handle); } }
/** * dynamically generate the page * * @see skins/index.php */ function send_body() { global $context; // only associates can proceed if (!Surfer::is_associate()) { Safe::header('Status: 401 Unauthorized', TRUE, 401); echo '<p>' . i18n::s('You are not allowed to perform this operation.') . "</p>\n"; // forward to the index page $menu = array('scripts/' => i18n::s('Server software')); echo Skin::build_list($menu, 'menu_bar'); // ask for confirmation } elseif (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'GET') { // the splash message echo '<p>' . i18n::s('This tool will include most of the running reference PHP scripts. Any syntax error should be spotted easily.') . '</p>'; // the submit button echo '<form method="post" action="' . $context['script_url'] . '" id="main_form"><p>' . Skin::build_submit_button(i18n::s('Yes, I want to validate scripts'), NULL, NULL, 'confirmed') . '</p></form>'; // set the focus on the button Page::insert_script('$("#confirmed").focus();'); // this may take some time echo '<p>' . i18n::s('When you will click on the button the server will be immediately requested to proceed. However, because of the so many things to do on the back-end, you may have to wait for minutes before getting a response displayed. Thank you for your patience.') . '</p>'; // just do it } else { // the splash message echo '<p>' . i18n::s('All reference scripts are included, to show evidence of possible syntax errors.') . "</p>\n"; // list running scripts echo '<p>' . i18n::s('Listing files...') . BR . "\n"; // locate script files starting at root $scripts = Scripts::list_scripts_at(NULL); if (is_array($scripts) && count($scripts)) { echo BR . sprintf(i18n::s('%d scripts have been found.'), count($scripts)) . "\n"; natsort($scripts); } echo "</p>\n"; // including scripts echo '<p>' . i18n::s('Including reference scripts...') . BR . "\n"; // strip as much output as possible $_SERVER['REQUEST_METHOD'] = 'HEAD'; // we will finalize this page later on global $finalizing_fuse; $finalizing_fuse = FALSE; // take care of dependancies include_once '../behaviors/behavior.php'; include_once '../services/codec.php'; include_once '../users/authenticator.php'; // analyse each script $included_files = 0; $links_to_be_checked_manually = array(); foreach ($scripts as $file) { // ensure we have enough time to process this script Safe::set_time_limit(30); // skip run once scripts if (strpos($file, 'run_once/')) { continue; } // don't include ourself if ($file == 'scripts/validate.php') { continue; } // process only reference scripts if (!Scripts::hash($file)) { continue; } // check file content if (!($handle = Safe::fopen($file, 'rb'))) { echo sprintf(i18n::s('%s has no readable content.'), $file) . BR . "\n"; continue; } // look at the beginning of the file if (!($header = fread($handle, 16384))) { echo sprintf(i18n::s('%s has no readable content.'), $file) . BR . "\n"; fclose($handle); continue; } fclose($handle); // skip scripts that generate content asynchronously if (stripos($header, 'send_body') || stripos($header, 'page::content')) { $links_to_be_checked_manually[$file] = '(asynchronous)'; continue; } // skip scripts that would redefine our skin if (stripos($header, 'extends skin_skeleton')) { $links_to_be_checked_manually[$file] = '(skin)'; continue; } // log script inclusion on development host if ($context['with_debug'] == 'Y') { logger::remember('scripts/validate.php: inclusion of ' . $file, '', 'debug'); } // include the script and display any error $included_files += 1; $validate_stamp = time(); echo sprintf(i18n::s('inclusion of %s'), $file) . "\n"; Safe::chdir($context['path_to_root'] . dirname($file)); include_once $context['path_to_root'] . $file; $duration = time() - $validate_stamp; if ($duration) { echo ' (' . $duration . 's.)'; } echo BR; } // memory status $used_memory = ''; if (is_callable('memory_get_usage')) { $used_memory = ' (' . memory_get_usage() . ' bytes)'; } // report of included files if ($included_files > 1) { echo '<p>' . sprintf(i18n::s('%d files have been included.'), $included_files) . $used_memory . '</p>'; } // list files to be checked manually if (count($links_to_be_checked_manually)) { echo '<p>' . i18n::s('Following scripts have to be included separately:') . BR . "\n"; ksort($links_to_be_checked_manually); foreach ($links_to_be_checked_manually as $file => $label) { echo Skin::build_link($file, $file, 'basic') . ' ' . $label . BR . "\n"; } echo sprintf(i18n::s('%d files to be checked manually.'), count($links_to_be_checked_manually)) . '</p>' . "\n"; } // display the execution time $time = round(get_micro_time() - $context['start_time'], 2); echo '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>'; // forward to the referential building echo '<form method="get" action="' . $context['url_to_root'] . 'scripts/build.php"><p>' . "\n" . Skin::build_submit_button(i18n::s('If no error has popped up, build the reference set >>')) . "\n" . '</p></form>' . "\n"; // this may take some time echo '<p>' . i18n::s('When you will click on the button the server will be immediately requested to proceed. However, because of the so many things to do on the back-end, you may have to wait for minutes before getting a response displayed. Thank you for your patience.') . '</p>'; // clear text some scripts could have added $context['debug'] = ''; $context['extra'] = ''; $context['navigation'] = ''; $context['suffix'] = ''; $context['text'] = ''; $context['page_details'] = ''; $context['page_footer'] = ''; $context['page_menu'] = array(); $context['page_tags'] = ''; $context['page_tools'] = ''; // now we will finalize this page global $finalizing_fuse; unset($finalizing_fuse); } }
$file = $name; } // look only into php script if (!preg_match('/\\.php$/i', $name)) { continue; } // look at phpDoc blocks if ($text = $documentation->parse($file, $context['path_to_reference'])) { $context['text'] .= $text . BR . "\n"; } elseif (isset($documentation->index[$file]) && $documentation->index[$file]) { $context['text'] .= $documentation->index[$file] . BR . "\n"; } else { $context['text'] .= sprintf(i18n::s('*** %s has no documentation block'), $file) . BR . "\n"; } // update footprints if (!isset($footprints[$file]) && ($footprint = Scripts::hash($context['path_to_reference'] . $file))) { $footprints[$file] = $footprint; } // ensure we have enough time to process next script Safe::set_time_limit(30); // avoid timeouts if (!($index++ % 50)) { Safe::set_time_limit(30); SQL::ping(); } } // report to surfer if (is_array($footprints)) { $context['text'] .= sprintf(i18n::s('%d scripts have been parsed.'), count($footprints)) . "\n"; } $context['text'] .= "</p>\n";
} } // we should have an updated file in the staging directory if (!is_readable($context['path_to_root'] . 'scripts/staging/' . $file)) { $box .= sprintf(i18n::s('ERROR: File %s is missing or corrupted.'), $file) . BR . "\n"; $missing_files++; continue; } // file should have some content --useful when space quota is full if (!Safe::filesize($context['path_to_root'] . 'scripts/staging/' . $file)) { $box .= sprintf(i18n::s('ERROR: File %s is missing or corrupted.'), $file) . BR . "\n"; $missing_files++; continue; } // ensure we have an exact copy $result = Scripts::hash('scripts/staging/' . $file); if ($attributes[1] != $result[1]) { $box .= sprintf(i18n::s('ERROR: File %s is missing or corrupted.'), $file) . BR . "\n"; $missing_files++; continue; } // report on the updated script $context['file_bar'] = array('scripts/browse.php?script=' . $file . '&store=staging' => i18n::s('Review'), 'scripts/compare.php?original=' . $file . '&updated=scripts/staging/' . $file . '&format=gdiff' => i18n::s('Diff')); $box .= $file . ' (' . $attributes[0] . ' ' . i18n::s('lines') . ') ' . Skin::build_list($context['file_bar'], 'menu') . BR . "\n"; $staging_files++; // ensure enough execution time Safe::set_time_limit(30); } // make a folded box if ($box) { $context['text'] .= Skin::build_box(i18n::s('Staging scripts'), $box, 'folded');