/** * 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); } }
// record surfer activity Activities::post('file:' . $item['id'], 'fetch'); $anchor->touch('file:fetch', 'file:' . $item['id'], true); // if we have an external reference, use it if (isset($item['file_href']) && $item['file_href']) { $target_href = $item['file_href']; // we have direct access to the file } else { // ensure a valid file name $file_name = utf8::to_ascii($item['file_name']); // where the file is located $path = Files::get_path($item['anchor']) . '/' . $item['file_name']; // file attributes $attributes = array(); // transmit file content if (!headers_sent() && ($handle = Safe::fopen($context['path_to_root'] . $path, "rb")) && ($stat = Safe::fstat($handle))) { // stream FLV files if required to do so if (substr($item['file_name'], -4) == '.flv' && isset($_REQUEST['position']) && $_REQUEST['position'] > 0 && $_REQUEST['position'] < $stat['size']) { Safe::header('Content-Length: ' . ($stat['size'] - $_REQUEST['position'] + 13)); echo 'FLV' . pack('C', 1) . pack('C', 1) . pack('N', 9) . pack('N', 9); fseek($handle, $_REQUEST['position']); echo fread($handle, $stat['size'] - $_REQUEST['position']); fclose($handle); return; } // load some file parser if one is available $analyzer = NULL; if (is_readable($context['path_to_root'] . 'included/getid3/getid3.php')) { include_once $context['path_to_root'] . 'included/getid3/getid3.php'; $analyzer = new getid3(); }
function process($template, $directory = 'blogger_import') { global $context; // we also have to prepare a skin -- the skin split is for scripts/validate.php $skin = '<?php' . "\n" . 'class Sk' . 'in extends Skin_skeleton {' . "\n"; // fix images relative path $template = preg_replace('/src="(.+?)"/ie', "'src=\"'.fix_relative('\$1', '{$directory}').'\"'", $template); $template = preg_replace('/background="(.+?)"/ie', "'background=\"'.fix_relative('\$1', '{$directory}').'\"'", $template); $template = preg_replace('/url\\((.+?)\\)/ie', "'url('.fix_relative('\$1', '{$directory}').')'", $template); // <$BlogArchiveFileName$> $from = '/<\\$BlogArchiveFileName\\$>/i'; $to = '<?php echo $context[\'url_to_root\'].\'categories/view.php?id=monthly\'; ?>'; $template = preg_replace($from, $to, $template); // <$BlogArchiveName$> $from = '/<\\$BlogArchiveName\\$>/i'; $to = '<?php echo \'Monthly Archives\'; ?>'; $template = preg_replace($from, $to, $template); // <$BlogArchiveLink$> $from = '/<\\$BlogArchiveLink\\$>/i'; $to = '<?php echo $context[\'url_to_root\'].\'categories/view.php?id=monthly\'; ?>'; $template = preg_replace($from, $to, $template); // <$BlogArchiveURL$> $from = '/<\\$BlogArchiveURL\\$>/i'; $to = '<?php echo $context[\'url_to_root\'].\'categories/view.php?id=monthly\'; ?>'; $template = preg_replace($from, $to, $template); // <$BlogDescription$> $from = '/<\\$BlogDescription\\$>/i'; $to = '<?php' . "\n" . 'if(is_object($anchor))' . "\n" . ' echo $anchor->get_teaser();' . "\n" . '?>'; $template = preg_replace($from, $to, $template); // <$BlogMemberProfile$> $from = '/<\\$BlogMemberProfile\\$>/i'; $to = '<?php echo $context[\'creator_profile\']; ?>'; $template = preg_replace($from, $to, $template); // <$BlogMetaData$> $from = '/<\\$BlogMetaData\\$>/i'; $to = '<?php echo $context[\'page_header\']; ?>'; $template = preg_replace($from, $to, $template); // <$BlogPageTitle$> $from = '/<\\$BlogPageTitle\\$>/i'; $to = '<?php echo ucfirst(strip_tags($context[\'page_title\'])); ?>'; $template = preg_replace($from, $to, $template); // <$BlogTitle$> $from = '/<\\$BlogTitle\\$>/i'; $to = '<?php echo ucfirst(strip_tags($context[\'page_title\'])); ?>'; $template = preg_replace($from, $to, $template); // <$BlogURL$> $from = '/<\\$BlogURL\\$>/i'; $to = '<?php echo $context[\'url_to_home\'].$context[\'url_to_root\']; ?>'; $template = preg_replace($from, $to, $template); // only one type of new lines $template = str_replace("\r\n", "\n", $template); $template = str_replace("\r", "\n", $template); // <MainOrArchivePage> $from = '/<MainOrArchivePage>(.*?)<\\/MainOrArchivePage>/is'; $to = ''; $template = preg_replace($from, $to, $template); // the <BlogItemComments>...</BlogItemComments> block $areas = preg_split('/<BlogItemComments>(.*?)<\\/BlogItemComments>/is', trim($template), -1, PREG_SPLIT_DELIM_CAPTURE); $template = ''; $index = 0; foreach ($areas as $area) { switch ($index % 3) { case 0: // prefix block $template .= $area; break; case 1: // commenting area // <$BlogCommentDateTime$> $from = '/<\\$BlogCommentDateTime\\$>/i'; $to = '\'.Skin::build_date($item[\'create_date\']).\''; $area = preg_replace($from, $to, $area); // <$BlogCommentNumber$> $from = '/<\\$BlogCommentNumber\\$>/i'; $to = '\'.$item[\'id\'].\''; $area = preg_replace($from, $to, $area); // <$BlogCommentAuthor$> $from = '/<\\$BlogCommentAuthor\\$>/i'; $to = '\'.$item[\'create_name\'].\''; $area = preg_replace($from, $to, $area); // <$BlogCommentAuthorNickname$> $from = '/<\\$BlogCommentAuthorNickname\\$>/i'; $to = '\'.$item[\'create_name\'].\''; $area = preg_replace($from, $to, $area); // <$BlogCommentBody$> $comment_prefix .= 'unset($BlogCommentBody);' . "\n" . '$BlogCommentBody .= Codes::beautify(trim($item[\'description\']));' . "\n" . "\n"; $from = '/<\\$BlogCommentBody\\$>/i'; $to = '\'.$BlogCommentBody.\''; $area = preg_replace($from, $to, $area); // make a skin $skin .= "\n" . ' function layout_comment($item, $variant = \'compact\') {' . "\n" . ' global $context;' . "\n" . ' ' . str_replace("\n", "\n\t\t", $comment_prefix) . "\n" . ' // array($prefix, $title, $suffix, $type, $icon)' . "\n" . ' $prefix = \'' . trim($item_prefix) . '\';' . "\n" . ' $title = \'_\';' . "\n" . ' $suffix = \'' . trim($area) . '\';' . "\n" . ' return array($prefix, $title, $suffix, \'comment\', NULL);' . "\n" . "\t}\n"; break; case 2: // suffix block $template .= $area; break; } $index++; } // the <Blogger>...</Blogger> block $areas = preg_split('/<Blogger>(.*?)<\\/Blogger>/is', trim($template), -1, PREG_SPLIT_DELIM_CAPTURE); $template = ''; $index = 0; foreach ($areas as $area) { // blogging area if ($index == 1) { $template .= '<?php ' . "\n" . '// display the menu bar, if any' . "\n" . 'if(@count($context[\'page_menu\']) > 0)' . "\n" . ' echo Skin::build_list($context[\'page_menu\'], \'page_menu\');' . "\n" . "\n" . '// display the prefix, if any' . "\n" . 'if($context[\'prefix\'])' . "\n" . ' echo $context[\'prefix\'];' . "\n" . "\n" . '// display the error message, if any' . "\n" . 'if($context[\'error\'])' . "\n" . ' echo Skin::build_block($context[\'error\'], \'error\');' . "\n" . "\n" . '// display the page image, if any' . "\n" . 'if($context[\'page_image\'])' . "\n" . ' echo \'<img src="\'.$context[\'page_image\'].\'" class="icon" alt="" />\';' . "\n" . "\n" . '// the main part of the page' . "\n" . 'echo $context[\'text\'];' . "\n" . "\n" . '// display the suffix, if any' . "\n" . 'if($context[\'suffix\'])' . "\n" . ' echo \'<p>\'.$context[\'suffix\'].\'</p>\';' . "\n" . '?>'; // make a skin for each item of the blogging area // break lines to not interfere with regular code $area = str_replace("\n", "'\n\t\t\t.'", addcslashes(trim($area), "'")); // <$BlogDateHeaderDate$> $from = '/<\\$BlogDateHeaderDate\\$>/i'; $to = '\'.Skin::build_date($item[\'create_date\']).\''; $area = preg_replace($from, $to, $area); // <$BlogItemArchiveFileName$> $from = '/<\\$BlogItemArchiveFileName\\$>/i'; $to = '\'.$context[\'url_to_root\'].Articles::get_permalink($item).\''; $area = preg_replace($from, $to, $area); // <$BlogItemAuthor$> $from = '/<\\$BlogItemAuthor\\$>/i'; $to = '\'.$item[\'create_name\'].\''; $area = preg_replace($from, $to, $area); // <$BlogItemAuthorNickname$> $from = '/<\\$BlogItemAuthorNickname\\$>/i'; $to = '\'.$item[\'create_name\'].\''; $area = preg_replace($from, $to, $area); // <$BlogItemBody$> $article_prefix .= 'unset($BlogItemBody);' . "\n" . '// the introduction' . "\n" . 'if($item[\'introduction\'])' . "\n" . ' $BlogItemBody .= Codes::beautify(trim($item[\'introduction\']));' . "\n" . 'elseif(!is_object($overlay)) {' . "\n" . ' // extract up to markup, if any' . "\n" . ' $raw = preg_split(\'/(\\[|<)/\', $item[\'description\']);' . "\n" . ' $BlogItemBody .= Skin::strip(trim($raw[0]), 30);' . "\n" . '}' . "\n" . 'if($suffix)' . "\n" . ' $BlogItemBody = \' - \'.$suffix;' . "\n" . "\n" . '// insert overlay data, if any' . "\n" . 'if(is_object($overlay))' . "\n" . ' $BlogItemBody .= $overlay->get_text(\'list\', $item);' . "\n" . "\n"; $from = '/<\\$BlogItemBody\\$>/i'; $to = '\'.$BlogItemBody.\''; $area = preg_replace($from, $to, $area); // <$BlogItemCommentCount$> $article_prefix .= 'unset($BlogItemCommentCount);' . "\n" . '// info on related comments' . "\n" . 'include_once $context[\'path_to_root\'].\'comments/comments.php\';' . "\n" . '$BlogItemCommentCount = Comments::count_for_anchor(\'article:\'.$item[\'id\']);' . "\n" . "\n"; $from = '/<\\$BlogItemCommentCount\\$>/i'; $to = '\'.$BlogItemCommentCount.\''; $area = preg_replace($from, $to, $area); // <$BlogItemControl$> -- the menu bar for associates and poster $article_prefix .= 'unset($BlogItemControl);' . "\n" . 'if(Surfer::is_associate() || Surfer::is($item[\'create_id\']) || Surfer::is($item[\'edit_id\'])) {' . "\n" . ' $menu = array( Articles::get_url($item[\'id\'], \'edit\') => i18n::s(\'edit\'),' . "\n" . ' Articles::get_url($item[\'id\'], \'delete\') => i18n::s(\'delete\') );' . "\n" . ' $BlogItemControl = \' \'.Skin::build_list($menu, \'menu\');' . "\n" . '}' . "\n" . "\n"; $from = '/<\\$BlogItemControl\\$>/i'; $to = '\'.$BlogItemControl.\''; $area = preg_replace($from, $to, $area); // <$BlogItemDateTime$> $from = '/<\\$BlogItemDateTime\\$>/i'; $to = '\'.Skin::build_date($item[\'create_date\']).\''; $area = preg_replace($from, $to, $area); // <$BlogItemNumber$> $from = '/<\\$BlogItemNumber\\$>/i'; $to = '\'.$item[\'id\'].\''; $area = preg_replace($from, $to, $area); // <$BlogItemPermalinkURL$> $from = '/<\\$BlogItemPermalinkURL\\$>/i'; $to = '\'.$context[\'url_to_root\'].Articles::get_permalink($item).\''; $area = preg_replace($from, $to, $area); // <$BlogItemTitle$> -- it has to be the last one for this item $from = '/<\\$BlogItemTitle\\$>/i'; list($item_prefix, $item_suffix) = preg_split($from, $area); // make a skin $skin .= "\n" . ' function layout_article($item, $variant = \'compact\') {' . "\n" . ' global $context;' . "\n" . ' ' . str_replace("\n", "\n\t\t", $article_prefix) . "\n" . ' // array($prefix, $title, $suffix, $type, $icon)' . "\n" . ' $prefix = \'' . trim($item_prefix) . '\';' . "\n" . ' $title = trim($item[\'title\']);' . "\n" . ' $suffix = \'' . trim($item_suffix) . '\';' . "\n" . ' return array($prefix, $title, $suffix, \'article\', NULL);' . "\n" . "\t}\n"; } else { // suffix block $template .= $area; } $index++; } // skin end $skin .= "}\n" . '?>' . "\n"; // backup the old skin, if any Safe::unlink($context['path_to_root'] . 'skins/' . $directory . '/skin.php.bak'); Safe::rename($context['path_to_root'] . 'skins/' . $directory . '/skin.php', $context['path_to_root'] . 'skins/' . $directory . '/skin.php.bak'); // create a new skin file if (!$skin) { Logger::error(i18n::s('No blogging block has been found.')); } elseif (!Safe::make_path('skins/' . $directory)) { Logger::error(sprintf(i18n::s('Impossible to create path %s.'), 'skins/' . $directory)); } elseif (!($handle = Safe::fopen($context['path_to_root'] . 'skins/' . $directory . '/skin.php', 'wb'))) { Logger::error(sprintf(i18n::s('Impossible to write to %s.'), $context['path_to_root'] . 'skins/' . $directory . '/skin.php')); } else { fwrite($handle, $skin); fclose($handle); } // backup the old template, if any Safe::unlink($context['path_to_root'] . 'skins/' . $directory . '/template.php.bak'); if (!$template) { Logger::error(i18n::s('Empty template file')); } else { Safe::rename($context['path_to_root'] . 'skins/' . $directory . '/template.php', $context['path_to_root'] . 'skins/' . $directory . '/template.php.bak'); } // create a new template file if (!Safe::make_path('skins/' . $directory)) { Logger::error(sprintf(i18n::s('Impossible to create path %s.'), 'skins/' . $directory)); } elseif (!($handle = Safe::fopen($context['path_to_root'] . 'skins/' . $directory . '/template.php', 'wb'))) { Logger::error(sprintf(i18n::s('Impossible to write to %s.'), $context['path_to_root'] . 'skins/' . $directory . '/template.php')); } else { fwrite($handle, $template); fclose($handle); $context['text'] .= '<p>' . sprintf(i18n::s('Template has been imported. Check skin %s'), Skin::build_link('skins/test.php?skin=' . $directory, $directory, 'shortcut')) . "</p>\n"; } return NULL; }
/** * create a referenced image * * @param array of entity attributes (e.g., 'Content-Disposition') * @param string image actual content * @param array poster attributes * @param string the target anchor (e.g., 'article:123') * @param string reference of the object to be extended, if any * @return string reference to the created object, or NULL */ public static function submit_image($entity_headers, $content, $user, $anchor, $target = NULL) { global $context; // retrieve queue parameters list($server, $account, $password, $allowed, $match, $section, $options, $hooks, $prefix, $suffix) = $context['mail_queue']; // locate content-disposition foreach ($entity_headers as $header) { if (preg_match('/Content-Disposition/i', $header['name'])) { $content_disposition = $header['value']; break; } } // find file name in content-disposition $file_name = ''; if ($content_disposition && preg_match('/filename="*([a-zA-Z0-9\'\\(\\)\\+_,-\\.\\/:=\\? ]+)"*\\s*/i', $content_disposition, $matches)) { $file_name = $matches[1]; } // as an alternative, look in content-type if (!$file_name) { // locate content-type foreach ($entity_headers as $header) { if (preg_match('/Content-Type/i', $header['name'])) { $content_type = $header['value']; break; } } // find file name in content-type if ($content_type && preg_match('/name="*([a-zA-Z0-9\'\\(\\)\\+_,-\\.\\/:=\\? ]+)"*\\s*/i', $content_type, $matches)) { $file_name = $matches[1]; } } // as an alternative, look in content-description if (!$file_name) { // locate content-description foreach ($entity_headers as $header) { if (preg_match('/Content-Description/i', $header['name'])) { $content_description = $header['value']; break; } } // find file name in content-description $file_name = $content_description; } // sanity check if (!$file_name) { Logger::remember('agents/messages.php: No file name to use for submitted image'); return NULL; } // file size $file_size = strlen($content); // sanity check if ($file_size < 7) { Logger::remember('agents/messages.php: Short image skipped', $file_name); return NULL; } // sanity check if (!$anchor) { Logger::remember('agents/messages.php: No anchor to use for submitted image', $file_name); return NULL; } // get anchor data -- this is a mutable object $host = Anchors::get($anchor, TRUE); if (!is_object($host)) { Logger::remember('agents/messages.php: Unknown anchor ' . $anchor, $file_name); return NULL; } // create target folders $file_path = Files::get_path($anchor, 'images'); if (!Safe::make_path($file_path)) { Logger::remember('agents/messages.php: Impossible to create ' . $file_path); return NULL; } if (!Safe::make_path($file_path . '/thumbs')) { Logger::remember('agents/messages.php: Impossible to create ' . $file_path . '/thumbs'); return NULL; } $file_path = $context['path_to_root'] . $file_path . '/'; // save the entity in the file system if (!($file = Safe::fopen($file_path . $file_name, 'wb'))) { Logger::remember('agents/messages.php: Impossible to open ' . $file_path . $file_name); return NULL; } if (fwrite($file, $content) === FALSE) { Logger::remember('agents/messages.php: Impossible to write to ' . $file_path . $file_name); return NULL; } fclose($file); // get image information if (!($image_information = Safe::GetImageSize($file_path . $file_name))) { Safe::unlink($file_path . $file_name); Logger::remember('agents/messages.php: No image information in ' . $file_path . $file_name); return NULL; } // we accept only gif, jpeg and png if ($image_information[2] != 1 && $image_information[2] != 2 && $image_information[2] != 3) { Safe::unlink($file_path . $file_name); Logger::remember('agents/messages.php: Rejected image type for ' . $file_path . $file_name); return NULL; } // build a thumbnail $thumbnail_name = 'thumbs/' . $file_name; // do not stop on error include_once $context['path_to_root'] . 'images/image.php'; if (!Image::shrink($file_path . $file_name, $file_path . $thumbnail_name, FALSE, FALSE)) { Logger::remember('agents/messages.php: No thumbnail has been created for ' . $file_path . $file_name); } // resize the image where applicable if (Image::adjust($file_path . $file_name, FALSE)) { $file_size = Safe::filesize($file_path . $file_name); } // all details $details = array(); // image size if ($image_information = Safe::GetImageSize($file_path . $file_name)) { $details[] = i18n::c('Size') . ': ' . $image_information[0] . ' x ' . $image_information[1]; } // update image description $item = array(); $item['anchor'] = $anchor; $item['image_name'] = $file_name; $item['thumbnail_name'] = $thumbnail_name; $item['image_size'] = $file_size; $item['description'] = ''; if (isset($content_description) && $content_description != $file_name) { $item['description'] .= $content_description; } if (@count($details)) { $item['description'] .= "\n\n" . '<p class="details">' . implode("<br />\n", $details) . "</p>\n"; } $item['edit_date'] = gmstrftime('%Y-%m-%d %H:%M:%S', time()); $item['edit_name'] = $user['nick_name']; $item['edit_id'] = $user['id']; $item['edit_address'] = $user['email']; // create an image record in the database include_once $context['path_to_root'] . 'images/images.php'; if (!($item['id'] = Images::post($item))) { Logger::remember('agents/messages.php: Impossible to save image ' . $item['image_name']); return NULL; } if ($context['debug_messages'] == 'Y') { Logger::remember('agents/messages.php: Messages::submit_image()', $item, 'debug'); } // insert the image in the anchor page $host->touch('image:create', $item['id'], TRUE); return 'image:' . $item['id']; }
/** * remember an event * * This script adds a line to temporary/log.txt, or to temporary/debug.txt. * * It the selected store is 'log', the function also submits a message to [code]syslog()[/code], to enable * distributed logging. * * Each line of the log store is made of fields separated by tabulations: * - time stamp (year-month-day hour:minutes:seconds) * - surfer name, if any, or '-' * - the label * - the description, if any * * Each line of the debug store is made of fields separated by tabulations: * - time stamp (year-month-day hour:minutes:seconds) * - the label * - the description, if any * * The description is truncated after 4 kbytes. * * @param string a one-line label that can be used as a mail title (e.g. 'creation of a new article') * @param mixed a more comprehensive description, if any * @param string either 'log' or 'debug' * @return void */ public static function remember($label, $description = '', $store = 'log') { global $context; // ensure we have a string $description = Logger::to_string($description, $store != 'debug'); // cap the description, just in case... $description = substr($description, 0, 8192); // event saved for debugging purpose if ($store == 'debug') { $store = 'temporary/debug.txt'; // stamp the line $line = gmdate('Y-m-d H:i:s') . "\t" . $label . ' ' . $description; // event saved for later review } else { $store = 'temporary/log.txt'; // surfer name -- surfer.php may not be loaded yet if (isset($_SESSION['surfer_name'])) { $name = preg_replace('/(@.+)$/', '', $_SESSION['surfer_name']); } else { $name = '-'; } // cap the description, just in case... $description = substr($description, 0, 2048); // strip control chars, encode new lines, single space $from = array('/\\r/', '/\\n/', '/\\s+/'); $to = array('', '\\n', ' '); // make a line $line = gmdate('Y-m-d H:i:s') . "\t" . $name . "\t" . preg_replace($from, $to, strip_tags($label)) . "\t" . preg_replace($from, $to, $description); // save it through syslog Safe::syslog(LOG_INFO, $line); } // save it in a local file if ($handle = Safe::fopen($context['path_to_root'] . $store, 'a')) { fwrite($handle, $line . "\n"); fclose($handle); } }
/** * write one string in a file * * This function also creates the path, if necessary. * * Warning: this function expects path information relative to the YACS * installation directory. This behavior differs from the original PHP function. * * @param string file to write, with a path relative to the installation directory * @param string new content * @return int the number of bytes written to the file, or 0 on failure */ public static function file_put_contents($file, $content) { global $context; // sanity check if (!$file) { return 0; } // ensure that target folder exists if (!Safe::make_path(dirname($file))) { return 0; } // use the library if (is_callable('file_put_contents')) { return file_put_contents(Safe::realpath($file), $content); } // access has been disallowed if (function_exists('file_put_contents')) { return 0; } // attempt a direct access if (!($handle = Safe::fopen(Safe::realpath($file), 'wb'))) { return 0; } $count = fwrite($handle, $content); fclose($handle); return $count; }
/** * process one file uploaded by handx weblog * * @param string the file to process */ public static function process_handx_weblog($file) { global $context; // load parameters for uploads Safe::load('parameters/agents.include.php'); if (!$context['uploads_nick_name']) { Logger::remember('agents/upload.php: no parameters, skipping ' . $file); return; } // read the input queue if (!($content = trim(Safe::file_get_contents($context['path_to_root'] . $file)))) { return; } // save in the output queue if ($handle = Safe::fopen($context['path_to_root'] . $file . '.bak', 'ab')) { fwrite($handle, $content); fclose($handle); // delete the input queue Safe::unlink($context['path_to_root'] . $file); } // date is derived from file name $name = basename($file); $year = substr($name, 0, 4); $month = substr($name, 4, 2); $day = substr($name, 6, 2); // split entries using the default separator value $separator = "/<table width=100%><tr><td class='time'>(.+?)<\\/td><\\/tr><\\/table>/"; $entries = preg_split($separator, $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); // no time information if (@count($entries) == 1) { // make a stamp $stamp = gmstrftime('%Y-%m-%d %H:%M:%S', mktime(0, 0, 0, $month, $day, $year)); // process this entry Uploads::process_handx_entry(trim($entries[0]), $stamp); // pairs of time and content strings } elseif (@count($entries) > 1) { // process all pairs for ($index = 0; $index < count($entries); $index++) { // the time as extracted by preg_split() $stamp = ''; if (preg_match('/(\\d{1,2}):(\\d{1,2}) (am|pm)/', $entries[$index], $matches)) { $index++; // make a stamp $hour = $matches[1]; $minutes = $matches[2]; if ($matches[3] == 'pm') { $hour += 12; } $stamp = gmstrftime('%Y-%m-%d %H:%M:%S', mktime($hour, $minutes, 0, $month, $day, $year)); } // the entry itself $entry = $entries[$index]; // process this entry Uploads::process_handx_entry(trim($entry), $stamp); } } }
case 'single': $enclosure = "'"; break; } } // no table name has been provided if (!$_REQUEST['table_name']) { $context['text'] .= '<p>' . i18n::s('No table name has been provided.') . "</p>\n"; } elseif (!$_FILES['upload']['name'] || $_FILES['upload']['name'] == 'none') { $context['text'] .= '<p>' . i18n::s('Nothing has been received.') . "</p>\n"; } elseif (!$_FILES['upload']['size']) { $context['text'] .= '<p>' . i18n::s('Nothing has been received.') . "</p>\n"; // check provided upload name } elseif (!Safe::is_uploaded_file($_FILES['upload']['tmp_name'])) { $context['text'] .= '<p>' . i18n::s('Possible file attack.') . "</p>\n"; } elseif (!($handle = Safe::fopen($_FILES['upload']['tmp_name'], 'rb'))) { $context['text'] .= '<p>' . sprintf(i18n::s('Impossible to read %s.'), $_FILES['upload']['tmp_name']) . "</p>\n"; } elseif (!($tokens = fgetcsv($handle, 2048, $delimiter, $enclosure))) { $context['text'] .= '<p>' . sprintf(i18n::s('No headers to read from %s.'), $_FILES['upload']['name']) . "</p>\n"; } else { // importing data $context['text'] .= '<p>' . sprintf(i18n::s('Importing data into %s from %s...'), $_REQUEST['table_name'], $_FILES['upload']['name']) . "</p>\n"; // ensure enough execution time Safe::set_time_limit(30); // drop the table, if it already exists $query = "DROP TABLE IF EXISTS " . SQL::escape($_REQUEST['table_name']); SQL::query($query); // create a table $query = "CREATE TABLE " . SQL::escape($_REQUEST['table_name']) . " (\n"; // use provided headers $headers = '';
} else { $zipfile->store('yacs/' . $file, Safe::filemtime($file_path . $file), $content); } // to be included in tar file as well $all_files[] = $file_path . $file; } else { $context['text'] .= BR . 'cannot read ' . $file_path . $file; } // avoid timeouts if (!($index++ % 50)) { Safe::set_time_limit(30); SQL::ping(); } } // save the zipfile if ($handle = Safe::fopen($context['path_to_root'] . $file_name . '.zip', 'wb')) { fwrite($handle, $zipfile->get()); fclose($handle); $context['text'] .= BR . Skin::build_link($file_name . '.zip', $file_name . '.zip', 'basic'); } // start the tar file include_once '../included/tar.php'; $tarfile = new Archive_Tar($context['path_to_root'] . $file_name . '.tgz'); // extend the tar file as well if ($tarfile->createModify($all_files, '', $file_path)) { $context['text'] .= BR . Skin::build_link($file_name . '.tgz', $file_name . '.tgz', 'basic'); } $context['text'] .= "</p>\n"; // display the execution time $time = round(get_micro_time() - $context['start_time'], 2); $context['text'] .= '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>';
/** * parse one script to build the php documentation * * @param string one script * @param the path to access the script * @return either NULL or an error message */ function parse($script, $path = 'scripts/reference/') { global $context, $page_count; // at least put the script name as a title $this->titles[$script] = $script; // read the file if (!($handle = Safe::fopen($path . $script, 'rb'))) { $this->comments[$script] = sprintf(i18n::s('Impossible to read %s.'), $script); return sprintf(i18n::s('Impossible to read %s.'), $context['path_to_root'] . $path . $script); } // locate php comments $comment = array(); global $first_comment; $first_comment = TRUE; $in_comment = FALSE; $count = 0; while (!feof($handle)) { // up to 4k per line $line = fgets($handle, 4096); // ensure we have enough execution time $count++; if (!($count % 1000)) { Safe::set_time_limit(30); } // a comment ends if ($in_comment && preg_match('/\\s*\\*+\\//', $line)) { $in_comment = FALSE; // a comment continues } elseif ($in_comment) { // strip the '*' at the beginning of the line $comment[] = preg_replace('/^\\s*\\*\\s{0,1}/', '', $line); // comment begins } elseif (preg_match('/\\s*\\/\\*{2,}/', $line)) { $in_comment = TRUE; // class extension } elseif (preg_match('/^\\s*class\\s+(\\w+)\\s+extends\\s+(\\w+)/i', $line, $matches)) { $name = $matches[0]; $this->comment_block($script, $name, $comment); $comment = array(); // class definition } elseif (preg_match('/^\\s*class\\s+(\\w+)/i', $line, $matches)) { $name = $matches[0]; $this->comment_block($script, $name, isset($comment) ? $comment : ''); $comment = array(); // function definition } elseif (preg_match('/^\\s*function\\s+(&{0,1}\\w+)\\s*\\((.*)\\)/i', $line, $matches)) { $name = $matches[0]; $this->comment_block($script, $name, isset($comment) ? $comment : ''); $comment = array(); // only a comment } elseif (preg_match('/^\\s*\\/\\//', $line)) { // a blank line } elseif (preg_match('/^\\s*$/', $line)) { // not a declaration } elseif (@count($comment)) { $this->comment_block($script, '', $comment); $comment = array(); } } // ensure enough execution time Safe::set_time_limit(30); // generate the documentation page for this file $fields['name'] = $script; $fields['anchor'] = dirname($script); $fields['label'] = isset($this->index[$script]) ? $this->index[$script] : '*** you should add a phpDoc label line to this file'; $fields['content'] = isset($this->comments[$script]) ? "[toc]" . $this->comments[$script] : '*** you should expand phpDoc comments for this file'; $query = "INSERT INTO " . SQL::table_name('phpdoc') . " SET " . " name='" . SQL::escape($fields['name']) . "'," . " anchor='" . SQL::escape($fields['anchor']) . "'," . " label='" . SQL::escape($fields['label']) . "'," . " content='" . SQL::escape($fields['content']) . "'," . " edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; if (SQL::query($query, TRUE) === FALSE) { echo $query . BR . SQL::error() . BR . "\n"; } $page_count++; }
Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation.')); // forward to the control panel $menu = array('control/' => i18n::s('Control Panel')); $context['text'] .= Skin::build_list($menu, 'menu_bar'); // backup the database } elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'backup') { // save in a temporary file $statements = 'statements.sql'; if (isset($context['host_name']) && isset($context['database'])) { $statements = $context['host_name'] . '_' . $context['database'] . '.sql'; } // put all statements in a file if (is_callable('gzopen') && ($handle = gzopen($context['path_to_root'] . 'temporary/' . $statements . '.gz', 'wb9'))) { $compressed = TRUE; } elseif ($handle = Safe::fopen('temporary/' . $statements, 'wb')) { $compressed = FALSE; } else { Safe::header('Status: 500 Internal Error', TRUE, 500); die('Impossible to write to temporary file.'); } // file header $sql = '#' . "\n" . '# This file has been created by the configuration script control/backup.php' . "\n" . '# on ' . gmdate("F j, Y, g:i a") . ' GMT, for ' . Surfer::get_name() . '.' . "\n" . '# Please avoid to modify it manually.' . "\n" . (isset($_REQUEST['backup_prefix']) ? '#' . "\n" . '# Only tables with the prefix "' . $_REQUEST['backup_prefix'] . '" have been considered' . "\n" : '') . '#' . "\n\n"; if ($compressed) { gzwrite($handle, $sql); } else { fwrite($handle, $sql); } // skip some tables $to_avoid = array(); if (isset($_REQUEST['backup_avoid']) && ($tokens = explode(' ', $_REQUEST['backup_avoid']))) {
function index_keywords($file_name) { // parse keywords in some files if (preg_match('/(\\.txt|\\.doc|\\.xls)$/i', $file_name) && ($handle = Safe::fopen($file_name, 'rb')) !== FALSE) { // load noise words Safe::load('files/noise_words.php'); // use chunks of 50 kbytes $filtered_words = array(); while (count($noise_words) && ($buffer = fread($handle, 51200))) { // strip binary stuff $buffer = preg_replace("/[вда]/m", 'a', $buffer); $buffer = preg_replace("/[йкли]/m", 'e', $buffer); $buffer = preg_replace("/[оп]/m", 'i', $buffer); $buffer = preg_replace("/[фц]/m", 'o', $buffer); $buffer = preg_replace("/[ыь]/m", 'u', $buffer); $buffer = str_replace('з', 'c', $buffer); $buffer = preg_replace('/[^a-zA-Z_0-9]+/m', ' ', $buffer); // ensure enough execution time Safe::set_time_limit(30); // strip html-like things $buffer = strip_tags($buffer); $buffer = preg_replace('/&\\w;/m', '', $buffer); // ensure enough execution time Safe::set_time_limit(30); // extract all readable words // $context['debug'][] = 'buffer=<pre>'.$buffer.'</pre>'; $words = preg_split("/[\\s]+/", $buffer); // $context['debug'][] = count($words).' words extracted'; // ensure enough execution time Safe::set_time_limit(30); // filter words foreach ($words as $word) { // mysql does not index words of less than 3 chars $length = strlen($word); if ($length <= 3 || $length > 25) { continue; } if (preg_match('/[0-9]/', $word)) { continue; } if (preg_match('/^[_0-9]/', $word)) { continue; } // filter words against the list of noise words $word = strtolower($word); if (!in_array($word, $noise_words)) { $filtered_words[$word] += 1; } } // ensure enough execution time Safe::set_time_limit(30); } // the complete file has been read fclose($handle); // ensure enough execution time Safe::set_time_limit(30); // memorize up to 1000 keywords if (is_array($filtered_words)) { ksort($filtered_words); reset($filtered_words); $keywords = ''; if (is_array($filtered_words)) { foreach ($filtered_words as $word => $count) { $keywords .= $word . ' '; if ($keywords_count++ > 1000) { break; } } } } // ensure enough execution time Safe::set_time_limit(30); } return $keywords; }
} elseif (!($xml = @simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA))) { Logger::error(sprintf('OpenTok: %s', 'response is not valid XML')); } elseif ($errors = $xml->xpath("//error")) { if ($message = $errors[0]->xpath("//@message")) { $message = (string) $message[0]['message']; } else { $message = 'unknown error'; } Logger::error(sprintf('OpenTok: %s', $xml->error['code'] . ' ' . $xml->error->children()->getName() . ': ' . $message)); // no session id in the response } elseif (!isset($xml->Session->session_id)) { Logger::error(sprintf('OpenTok: %s', 'no session id has been provided')); } else { // save the pair meeting id - OpenTok id in a text file $line = $id . '|' . (string) $xml->Session->session_id; if ($handle = Safe::fopen($context['path_to_root'] . 'temporary/faceme.txt', 'a')) { fwrite($handle, $line . "\n"); fclose($handle); } // return the id to caller $result = array('id' => $id); // handle the output correctly render_raw('application/json; charset=' . $context['charset']); // actual transmission except on a HEAD request if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') { echo Safe::json_encode($result); } // the post-processing hook finalize_page(); return; }
/** * hash the content of one file * * @param string the path of the target file * @return an array of ($lines, $hash), or NULL if not part of the reference set */ public static function hash($file) { global $context; // only process php scripts if (!strpos(basename($file), '.php')) { return NULL; } // check file content if (!($handle = Safe::fopen($file, 'rb'))) { return NULL; } // count lines $reference = FALSE; $count = 0; while ($line = fgets($handle)) { $count++; if (strpos($line, '@reference')) { $reference = TRUE; } } fclose($handle); // only accept reference scripts if (!$reference) { return NULL; } // compute md5 signature if (!($hash = md5_file(Safe::realpath($file)))) { return NULL; } // return the result return array($count, $hash); }
/** * load one .mo file * * This function attempts to include a cached version (actually, a .mo.php * file), then, if it is not available, it parses the .mo file. * * Expected data locations for language 'foo' and module 'bar' are: * - i18n/locale/foo/bar.mo.php (for the PHP equivalent to the .mo file) and * - i18n/locale/foo/bar.mo (for the original .mo file) * * The function also attempts to create a cached PHP version of the file * if one does not exists, to speed up subsequent calls. * * Loaded strings are all placed into the global array $context['l10n'] for later use. * * The function does not actually use the gettext PHP extension because of potential weak implementations. * Instead, it parses directly binary content of the .mo file. * * @link http://www.gnu.org/software/gettext/manual/html_chapter/gettext_8.html#SEC136 The Format of GNU MO Files * * @param string target language * @param string target module * @return TRUE on success, FALSE otherwise */ private static function load($language, $module) { global $context; // sanity check if (!$language) { return FALSE; } // expected location $path = 'i18n/locale/' . $language . '/' . $module . '.mo'; // translations have a global scope if (!isset($context['l10n'])) { $context['l10n'] = array(); } if (!isset($context['l10n'][$language])) { $context['l10n'][$language] = array(); } // load PHP version, if it exists, and if it is fresher than the original $hash = $context['path_to_root'] . $path . '.php'; if (is_readable($hash) && is_readable($context['path_to_root'] . $path) && filemtime($hash) > filemtime($context['path_to_root'] . $path)) { include_once $hash; return TRUE; } // also load the PHP version if there is no .mo file if (is_readable($hash) && !file_exists($context['path_to_root'] . $path)) { include_once $hash; return TRUE; } // access file content if (!($handle = Safe::fopen($context['path_to_root'] . $path, 'rb'))) { // log information on development platform if ($context['with_debug'] == 'Y') { logger::remember('i18n/i18n.php: Impossible to load ' . $path, '', 'debug'); } // we've got a problem return FALSE; } // read magic number $values = unpack('V', fread($handle, 4)); $magic = array_shift($values); // byte ordering if ($magic == (int) 0x950412de) { $order = 'V'; } elseif (dechex($magic) == 'ffffffff950412de') { $order = 'V'; } elseif ($magic == (int) 0xde120495) { $order = 'N'; } else { // log information on development platform if ($context['with_debug'] == 'Y') { logger::remember('i18n/i18n.php: bad magic number in ' . $path, '', 'debug'); } // we've got a problem return FALSE; } // read revision number $values = unpack($order, fread($handle, 4)); $revision = array_shift($values); // read number of strings $values = unpack($order, fread($handle, 4)); $number_of_strings = array_shift($values); // read offset for table of original strings $values = unpack($order, fread($handle, 4)); $original_table_offset = array_shift($values); // read offset for table of translated strings $values = unpack($order, fread($handle, 4)); $translated_table_offset = array_shift($values); // two integers per string (offset and size) $count = $number_of_strings * 2; // read the index of original strings fseek($handle, $original_table_offset); $original_table = unpack($order . $count, fread($handle, $count * 4)); // read the index of translated strings fseek($handle, $translated_table_offset); $translated_table = unpack($order . $count, fread($handle, $count * 4)); // no cache if we are not allowed to write files if ($cache = Safe::fopen($hash, 'w')) { // start the cache file --make it a reference file to ensure it is integrated into yacs built $cache_content = '<?php' . "\n" . '/**' . "\n" . ' * cache localized strings' . "\n" . ' *' . "\n" . ' * This file has been created by the script i18n/i18n.php. Please do not modify it manually.' . "\n" . ' */' . "\n"; } // read all pairs of string for ($index = 0; $index < $number_of_strings; $index++) { // read original string fseek($handle, $original_table[$index * 2 + 2]); if (!($length = $original_table[$index * 2 + 1])) { $original = '_headers'; } else { $original = fread($handle, $length); } // read translated string fseek($handle, $translated_table[$index * 2 + 2]); if (!($length = $translated_table[$index * 2 + 1])) { $translated = ''; } else { $translated = fread($handle, $length); } // save in memory $hash =& i18n::hash($original); $context['l10n'][$language][$hash] = $translated; // escape original string $hash = str_replace('\\000', "'.chr(0).'", addcslashes($hash, "\\'")); // escape translated string $translated = str_replace('\\000', "'.chr(0).'", addcslashes($translated, "\\'")); // update cache file, if any if ($cache && $hash != '_headers') { $cache_content .= '$context[\'l10n\'][\'' . $language . '\'][\'' . $hash . '\']=\'' . $translated . "';\n"; } } // clean out fclose($handle); // look for plural string if (preg_match('/plural-forms: ([^\\n]*)\\n/i', $context['l10n'][$language]['_headers'], $matches) && strcmp($matches[1], 'nplurals=INTEGER; plural=EXPRESSION;')) { $plural = $matches[1]; } else { $plural = 'nplurals=2; plural=(n != 1)'; } // save it in cache as well $context['l10n'][$language]['_plural'] = $plural; // finalize cache file, if any if ($cache) { $cache_content .= '$context[\'l10n\'][\'' . $language . '\'][\'_plural\']=\'' . addcslashes($plural, "\\'") . "';\n" . '?>'; fwrite($cache, $cache_content); fclose($cache); } // everything went fine return TRUE; }