Пример #1
0
/**
 * 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);
    }
}
Пример #2
0
 // 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();
         }
Пример #3
0
 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 = \' -&nbsp;\'.$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;
 }
Пример #4
0
 /**
  * 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'];
 }
Пример #5
0
 /**
  * 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);
     }
 }
Пример #6
0
Файл: safe.php Проект: rair/yacs
 /**
  * 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;
 }
Пример #7
0
 /**
  * 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);
         }
     }
 }
Пример #8
0
         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 = '';
Пример #9
0
         } 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>';
Пример #10
0
 /**
  * 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++;
 }
Пример #11
0
    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']))) {
Пример #12
0
 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;
 }
Пример #13
0
 } 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;
 }
Пример #14
0
 /**
  * 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);
 }
Пример #15
0
Файл: i18n.php Проект: rair/yacs
 /**
  * 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;
 }