示例#1
0
文件: logger.php 项目: rair/yacs
 /**
  * remember a string during software debug
  *
  * This script appends information to temporary/debug.txt
  *
  * @param mixed something to be printed
  * @param string an optional label string
  * @return void
  */
 public static function debug($value = '', $label = NULL)
 {
     global $context;
     // ensure we have a string --preserve native string
     $value = Logger::to_string($value, FALSE);
     // stamp the line
     $line = gmdate('Y-m-d H:i:s') . "\t";
     if (isset($label)) {
         $line .= $label . ' ';
     }
     $line .= $value;
     $line .= "\n";
     // ensure enough execution time
     Safe::set_time_limit(30);
     // apend to the debug file
     if ($handle = Safe::fopen($context['path_to_root'] . 'temporary/debug.txt', 'a')) {
         fwrite($handle, $line);
         fclose($handle);
     } else {
         echo $line;
     }
 }
示例#2
0
文件: validate.php 项目: rair/yacs
/**
 * 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);
    }
}
示例#3
0
文件: scan.php 项目: rair/yacs
function include_hook($path)
{
    global $context, $hooks;
    // animate user screen and take care of time
    global $scanned_directories;
    $scanned_directories++;
    // ensure enough execution time
    Safe::set_time_limit(30);
    // open the directory
    if (!($dir = Safe::opendir($path))) {
        $context['text'] .= sprintf(i18n::s('Impossible to read %s.'), $path) . BR . "\n";
        return;
    }
    // browse the directory
    while (($item = Safe::readdir($dir)) !== FALSE) {
        // skip some files
        if ($item[0] == '.') {
            continue;
        }
        // load any 'hook.php', or any file which names ends with 'hook.php'
        $actual_item = str_replace('//', '/', $path . '/' . $item);
        if (preg_match('/hook\\.php$/i', $item)) {
            include_once $actual_item;
            $context['text'] .= sprintf(i18n::s('Hook %s has been included'), $actual_item) . BR . "\n";
            // scan any sub dir except at server root
        } elseif (is_dir($actual_item) && $path != $context['path_to_root'] && !strpos($path, '/files/') && !strpos($path, '/images/')) {
            include_hook($actual_item);
        }
    }
    // close the directory
    Safe::closedir($dir);
}
示例#4
0
文件: messages.php 项目: rair/yacs
 /**
  * process all messages from one mailbox
  *
  * This is original code compliant to RFC 1939 for the authentication,
  * fetching and processing of messages queued in a POP3 mailbox.
  *
  * @param array of mailbox attributes ($server, $account, $password)
  * @return the number of processed messages
  */
 public static function process_queue($queue)
 {
     global $context;
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return 0;
     }
     // make queue parameters available
     $context['mail_queue'] = $queue;
     // use queue parameters to connect to the server
     list($server, $account, $password, $allowed, $match, $section, $options, $hooks, $prefix, $suffix) = $queue;
     // no host, assume it's us
     if (!$server) {
         $server = $context['host_name'];
     }
     // assume the standard pop3 socket
     $port = 110;
     // use alternate port if required to do so
     if (preg_match('/^(.+):([0-9]+)$/', $server, $matches)) {
         $server = $matches[1];
         $port = intval($matches[2]);
     }
     // ensure that we can support tls communications
     if (isset($server) && !strncmp($server, 'ssl://', 6) && is_callable('extension_loaded') && !extension_loaded('openssl')) {
         Logger::remember('agents/messages.php: Load the OpenSSL extension to support secured transmissions to mail server ' . $server);
         return 0;
     }
     // open a network connection
     if (!($handle = Safe::fsockopen($server, $port, $errno, $errstr, 10))) {
         Logger::remember('agents/messages.php: ' . sprintf('Impossible to connect to %s', $server));
         return 0;
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // get server banner
     if (($reply = fgets($handle)) === FALSE) {
         Logger::remember('agents/messages.php: Impossible to get banner of ' . $server);
         fclose($handle);
         return 0;
     }
     if ($context['debug_messages'] == 'Y') {
         Logger::remember('agents/messages.php: POP <-', rtrim($reply), 'debug');
     }
     // expecting an OK
     if (strncmp($reply, '+OK', 3)) {
         Logger::remember('agents/messages.php: Mail service is closed at ' . $server, rtrim($reply));
         fclose($handle);
         return 0;
     }
     // maybe the server accepts APOP
     $stamp = '';
     if (preg_match('/<.+@.+>/U', $reply, $matches)) {
         $stamp = $matches[0];
     }
     // we will go with APOP, only if explicitly allowed
     $authenticated = FALSE;
     if ($stamp && preg_match('/\\bwith_apop\\b/i', $options)) {
         // the digest
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP stamp', $stamp . $password, 'debug');
         }
         $hash = md5($stamp . $password);
         // send user name and hash
         $request = 'APOP ' . $account . ' ' . $hash;
         fputs($handle, $request . CRLF);
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP ->', $request, 'debug');
         }
         // expecting an OK
         if (($reply = fgets($handle)) === FALSE) {
             Logger::remember('agents/messages.php: No reply to APOP command at ' . $server);
             fclose($handle);
             return 0;
         }
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP <-', rtrim($reply), 'debug');
         }
         if (strncmp($reply, '+OK', 3)) {
             Logger::remember('agents/messages.php: Impossible to authenticate account ' . $account . ' at ' . $server, rtrim($reply));
         } else {
             $authenticated = TRUE;
         }
     }
     // we will transmit the password in clear
     if (!$authenticated) {
         // send user name
         $request = 'USER ' . $account;
         fputs($handle, $request . CRLF);
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP ->', $request, 'debug');
         }
         // expecting an OK
         if (($reply = fgets($handle)) === FALSE) {
             Logger::remember('agents/messages.php: No reply to USER command at ' . $server);
             fclose($handle);
             return 0;
         }
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP <-', rtrim($reply), 'debug');
         }
         if (strncmp($reply, '+OK', 3)) {
             Logger::remember('agents/messages.php: Unknown account ' . $account . ' at ' . $server, rtrim($reply));
             fclose($handle);
             return 0;
         }
         // send password
         $request = 'PASS ' . $password;
         fputs($handle, $request . CRLF);
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP ->', $request, 'debug');
         }
         // expecting an OK
         if (($reply = fgets($handle)) === FALSE) {
             Logger::remember('agents/messages.php: No reply to PASS command at ' . $server);
             fclose($handle);
             return 0;
         }
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP <-', rtrim($reply), 'debug');
         }
         if (strncmp($reply, '+OK', 3)) {
             Logger::remember('agents/messages.php: Invalid password for account ' . $account . ' at ' . $server, rtrim($reply));
             fclose($handle);
             return 0;
         }
     }
     // ask for information
     $request = 'STAT';
     fputs($handle, $request . CRLF);
     if ($context['debug_messages'] == 'Y') {
         Logger::remember('agents/messages.php: POP ->', $request, 'debug');
     }
     // expecting an OK
     if (($reply = fgets($handle)) === FALSE) {
         Logger::remember('agents/messages.php: No reply to STAT command at ' . $server);
         fclose($handle);
         return 0;
     }
     if (strncmp($reply, '+OK', 3)) {
         Logger::remember('agents/messages.php: Rejected command STAT at ' . $server, 'reply="' . rtrim($reply) . '"');
         fclose($handle);
         return 0;
     }
     // evaluate queue size
     $tokens = explode(' ', $reply);
     if ($context['debug_messages'] == 'Y') {
         Logger::remember('agents/messages.php: POP <-', rtrim($reply), 'debug');
     }
     $queue_size = @$tokens[1];
     // nothing to do
     if (!$queue_size) {
         fclose($handle);
         return 0;
     }
     // limit the number of messages processed on each tick
     if ($queue_size > 10) {
         $queue_size = 10;
     }
     // process messages one by one
     for ($index = 1; $index <= $queue_size; $index++) {
         // ask for the message
         $request = 'RETR ' . $index;
         fputs($handle, $request . CRLF);
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP ->', $request, 'debug');
         }
         // expecting an OK
         if (($reply = fgets($handle)) === FALSE) {
             Logger::remember('agents/messages.php: No reply to RETR command at ' . $server);
             fclose($handle);
             return $index - 1;
         }
         if (strncmp($reply, '+OK', 3)) {
             Logger::remember('agents/messages.php: Rejected command RETR at ' . $server, rtrim($reply));
             fclose($handle);
             return $index - 1;
         }
         // fetch one message at a time
         $message = '';
         while (!feof($handle)) {
             // ensure enough execution time
             Safe::set_time_limit(30);
             // get a chunk (up to ten 1500-byte Ethernet packets)
             $chunk = fread($handle, 16384);
             // look for message end
             if (preg_match("/(.*)\\.\r\n\$/s", $chunk, $matches)) {
                 $message .= $matches[1];
                 break;
             }
             // not yet at the end
             $message .= $chunk;
         }
         // suppress the message from the mailbox before entering into the database
         $request = 'DELE ' . $index;
         fputs($handle, $request . CRLF);
         if ($context['debug_messages'] == 'Y') {
             Logger::remember('agents/messages.php: POP ->', $request, 'debug');
         }
         // expecting an OK
         if (($reply = fgets($handle)) === FALSE) {
             Logger::remember('agents/messages.php: No reply to DELE command at ' . $server);
         } elseif (strncmp($reply, '+OK', 3)) {
             Logger::remember('agents/messages.php: Rejected command DELE at ' . $server, rtrim($reply));
         }
         // file the message if in debug mode
         if ($context['debug_messages'] == 'Y' && Safe::make_path('temporary/agents')) {
             Safe::file_put_contents('temporary/agents/' . uniqid('message_'), $message);
         }
         // process the message
         Messages::process_message($message);
     }
     // close the session to actually purge the queue
     $request = 'QUIT';
     fputs($handle, $request . CRLF);
     if ($context['debug_messages'] == 'Y') {
         Logger::remember('agents/messages.php: POP ->', $request, 'debug');
     }
     // expecting an OK
     if (($reply = fgets($handle)) === FALSE) {
         Logger::remember('agents/messages.php: No reply to QUIT command at ' . $server);
     } elseif (strncmp($reply, '+OK', 3)) {
         Logger::remember('agents/messages.php: Rejected command QUIT at ' . $server, rtrim($reply));
     }
     if ($queue_size > 0) {
         Logger::remember('agents/messages.php: ' . $queue_size . ' message(s) have been processed from ' . $server);
     }
     fclose($handle);
     return $queue_size;
 }
示例#5
0
文件: smileys.php 项目: rair/yacs
 /**
  * transform some text to load related images
  *
  * @param string the input text
  * @return the tansformed text
  */
 public static function render_smileys($text)
 {
     global $context;
     // no content on HEAD request --see scripts/validate.php
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'HEAD') {
         return $text;
     }
     // sanity check
     $text = trim($text);
     if (!$text) {
         return $text;
     }
     // the list of codes to be interpreted --initialize only once
     static $pattern, $replace;
     if (!isset($pattern)) {
         $pattern = array();
         $replace = array();
         $prefix = ' <img src="' . $context['url_to_root'] . 'skins/_reference/smileys/';
         $suffix = '" alt="" /> ';
         $pattern[] = '>:(';
         $replace[] = $prefix . 'angry.gif' . $suffix;
         $pattern[] = ':-D';
         $replace[] = $prefix . 'cheesy.gif' . $suffix;
         $pattern[] = " :'(";
         $replace[] = $prefix . 'cry.gif' . $suffix;
         $pattern[] = ":'-(";
         $replace[] = $prefix . 'cry.gif' . $suffix;
         $pattern[] = '8-)';
         $replace[] = $prefix . 'cool.gif' . $suffix;
         $pattern[] = ':-(';
         $replace[] = $prefix . 'frown.gif' . $suffix;
         $pattern[] = '???';
         $replace[] = $prefix . 'confused.gif' . $suffix;
         $pattern[] = ':-[';
         $replace[] = $prefix . 'embarassed.gif' . $suffix;
         $pattern[] = ':blush:';
         $replace[] = $prefix . 'blushing.gif' . $suffix;
         $pattern[] = ':-X';
         $replace[] = $prefix . 'sealed.gif' . $suffix;
         $pattern[] = ':-P';
         $replace[] = $prefix . 'tongue.gif' . $suffix;
         $pattern[] = ':medal:';
         $replace[] = $prefix . 'medal_full.gif' . $suffix;
         $pattern[] = ':half_medal:';
         $replace[] = $prefix . 'medal_half.gif' . $suffix;
         $pattern[] = '::-)';
         $replace[] = $prefix . 'rolleyes.gif' . $suffix;
         $pattern[] = ' :)';
         $replace[] = $prefix . 'smile.gif' . $suffix;
         $pattern[] = ':-)';
         $replace[] = $prefix . 'smile.gif' . $suffix;
         $pattern[] = ':-o';
         $replace[] = $prefix . 'shocked.gif' . $suffix;
         $pattern[] = ' :/';
         $replace[] = $prefix . 'undecided.gif' . $suffix;
         $pattern[] = ':-/';
         $replace[] = $prefix . 'undecided.gif' . $suffix;
         $pattern[] = ' ;)';
         $replace[] = $prefix . 'winkgrin.gif' . $suffix;
         $pattern[] = ';-)';
         $replace[] = $prefix . 'winkgrin.gif' . $suffix;
         $pattern[] = ':party:';
         $replace[] = $prefix . 'partygirl.gif' . $suffix;
         $pattern[] = ':*:';
         $replace[] = $prefix . 'star.gif' . $suffix;
         $pattern[] = ' :*';
         $replace[] = $prefix . 'kiss.gif' . $suffix;
         $pattern[] = ':-*';
         $replace[] = $prefix . 'kiss.gif' . $suffix;
         $pattern[] = ' :+';
         $replace[] = $prefix . 'thumbsup.gif' . $suffix;
         $pattern[] = ':up:';
         $replace[] = $prefix . 'thumbsup.gif' . $suffix;
         $pattern[] = ' :-';
         $replace[] = $prefix . 'thumbsdown.gif' . $suffix;
         $pattern[] = ':down:';
         $replace[] = $prefix . 'thumbsdown.gif' . $suffix;
         $pattern[] = ':?!';
         $replace[] = $prefix . 'idea.gif' . $suffix;
         $pattern[] = ' :?2';
         $replace[] = $prefix . 'question2.gif' . $suffix;
         $pattern[] = ' :?';
         $replace[] = $prefix . 'question.gif' . $suffix;
         $pattern[] = ' :!2';
         $replace[] = $prefix . 'exclamation2.gif' . $suffix;
         $pattern[] = ' :!';
         $replace[] = $prefix . 'exclamation.gif' . $suffix;
     }
     // ensure we have enough processing time
     Safe::set_time_limit(30);
     // process dotted smileys --insert a space for smileys at the very beginning of the string
     $text = str_replace($pattern, $replace, ' ' . $text);
     // process any image file
     $text = preg_replace_callback('/:([\\w_]+):/', array('smileys', 'parse_match'), $text);
     return $text;
 }
示例#6
0
文件: check.php 项目: rair/yacs
 $context['text'] .= Skin::build_block(sprintf(i18n::s('Analyzing table %s...'), SQL::table_name('comments')), 'title');
 // scan up to 20000 items
 $count = 0;
 $query = "SELECT id, anchor FROM " . SQL::table_name('comments') . " ORDER BY anchor LIMIT 0, 100000";
 if (!($result = SQL::query($query))) {
     return;
 } else {
     // fetch one anchor and the linked member
     $errors_count = 0;
     while ($row = SQL::fetch($result)) {
         // animate user screen and take care of time
         $count++;
         if (!($count % 500)) {
             $context['text'] .= sprintf(i18n::s('%d records have been processed'), $count) . BR . "\n";
             // ensure enough execution time
             Safe::set_time_limit(30);
         }
         // check that the anchor exists, if any
         if ($row['anchor'] && !Anchors::get($row['anchor'])) {
             $context['text'] .= sprintf(i18n::s('Orphan: %s'), 'comment ' . Skin::build_link(Comments::get_url($row['id']), $row['id'])) . BR . "\n";
             if (++$errors_count >= 5) {
                 $context['text'] .= i18n::s('Too many successive errors. Aborted') . BR . "\n";
                 break;
             }
         } else {
             $errors_count = 0;
         }
     }
 }
 // ending message
 $context['text'] .= sprintf(i18n::s('%d records have been processed'), $count) . BR . "\n";
示例#7
0
文件: link.php 项目: rair/yacs
 /**
  * validate a link
  *
  * This function submits a HTTP request to the target server to check that the page actually exists
  *
  * @param the link to validate
  * @return A date if Last-Modified has been provided, or TRUE if the link is reachable, FALSE otherwise
  */
 function validate($url)
 {
     global $context;
     // parse this url
     $items = @parse_url($url);
     // assume the link is correct if not http
     if ($items['scheme'] && $items['scheme'] != 'http') {
         return TRUE;
     }
     // no host, assume it's us
     if (!($host = $items['host'])) {
         $host = $context['host_name'];
     }
     // sometime parse_url() adds a '_'
     $host = rtrim($host, '_');
     // no port, assume the standard
     if (!($port = $items['port'])) {
         $port = 80;
     }
     // assume the link is correct when outbound web is not authorized
     if (isset($context['without_outbound_http']) && $context['without_outbound_http'] == 'Y') {
         return TRUE;
     }
     // open a network connection -- wait for up to 10 seconds for the TCP connection
     if (!($handle = Safe::fsockopen($host, $port, $errno, $errstr, 10))) {
         if ($context['with_debug'] == 'Y') {
             logger::remember('links/link.php: ' . $host . ':' . $port . ' is not reachable', $url, 'debug');
         }
         return FALSE;
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // build the path
     $path = $items['path'];
     if (!$path) {
         $path = '/';
     }
     // sometime parse_url() adds a '_'
     $path = rtrim($path, '_');
     // include any query
     if ($items['query']) {
         $path .= '?' . $items['query'];
     }
     // send an HTTP request
     fputs($handle, 'HEAD ' . $path . " HTTP/1.0" . CRLF . 'Host: ' . $host . CRLF . "User-Agent: YACS (www.yacs.fr)" . CRLF . "Connection: close" . CRLF . CRLF);
     // we are interested into the header only
     $response = '';
     while (!feof($handle) && strlen($response) < 5242880) {
         // ask for Ethernet-sized chunks
         $chunk = fread($handle, 1500);
         // split on headers boundary
         $here = strpos($chunk, CRLF . CRLF);
         if ($here !== FALSE) {
             $chunk = substr($chunk, 0, $here);
             $response .= $chunk;
             break;
         }
         // gather header information
         $response .= $chunk;
     }
     fclose($handle);
     // split headers into lines
     $lines = explode(CRLF, $response);
     // ensure we have a valid HTTP status line
     if (!preg_match('/^HTTP\\/[0-9\\.]+ 20\\d /', $lines[0])) {
         if ($context['with_debug'] == 'Y') {
             logger::remember('links/link.php: bad status: ' . $lines[0], $url, 'debug');
         }
         return FALSE;
     }
     // scan lines for "Last-Modified" header
     foreach ($lines as $line) {
         if (preg_match('/^Last-Modified: (.*?)/', $line, $matches)) {
             // return the stamp for this link
             return date("Y-m-d H:i:s", strtotime($matches[1]));
         }
     }
     // no date, but the link has been validated anyway
     return TRUE;
 }
示例#8
0
文件: utf8.php 项目: rair/yacs
 /**
  * transcode multi-byte characters to HTML representations for Unicode
  *
  * This function is aiming to preserve Unicode characters through storage in a ISO-8859-1 compliant system.
  *
  * Every multi-byte UTF-8 character is transformed to its equivalent HTML numerical entity (eg, &amp;#4568;)
  * that may be handled safely by PHP and by MySQL.
  *
  * Of course, this solution does not allow for full-text search in the database and therefore, is not a
  * definitive solution to internationalization issues.
  * It does enable, however, practical use of Unicode to build pages in foreign languages.
  *
  * Also, this function transforms HTML entities into their equivalent Unicode entities.
  * For example, w.bloggar posts pages using HTML entities.
  * If you have to modify these pages using web forms, you would like to get UTF-8 instead.
  *
  * @link http://www.evolt.org/article/A_Simple_Character_Entity_Chart/17/21234/ A Simple Character Entity Chart
  *
  * @param mixed the original UTF-8 string, or an array
  * @return a string acceptable in an ISO-8859-1 storage system (ie., PHP4 + MySQL 3)
  */
 public static function &to_unicode($input)
 {
     global $context;
     // transcode arrays as well
     if (is_array($input)) {
         utf8::to_unicode_recursively($input);
         $output = $input;
         return $output;
     }
     // scan the whole string
     $output = '';
     $index = 0;
     $tick = 0;
     while ($index < strlen($input)) {
         // for jumbo pages --observed 167 seconds processing time for 414kbyte input
         $tick++;
         if (!($tick % 25000)) {
             Safe::set_time_limit(30);
         }
         // look at one char
         $char = ord($input[$index]);
         // one byte (0xxxxxxx)
         if ($char < 0x80) {
             // some chars may be undefined
             $output .= chr($char);
             $index += 1;
             // two bytes (110xxxxx 10xxxxxx)
         } elseif ($char < 0xe0) {
             // strip weird sequences (eg, C0 80 -> NUL)
             if ($value = $char % 0x20 * 0x40 + ord($input[$index + 1]) % 0x40) {
                 $output .= '&#' . $value . ';';
             }
             $index += 2;
             // three bytes (1110xxxx 10xxxxxx 10xxxxxx) example: euro sign = \xE2\x82\xAC -> &#8364;
         } elseif ($char < 0xf0) {
             // strip weird sequences
             if ($value = $char % 0x10 * 0x1000 + ord($input[$index + 1]) % 0x40 * 0x40 + ord($input[$index + 2]) % 0x40) {
                 $output .= '&#' . $value . ';';
             }
             $index += 3;
             // four bytes (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
         } elseif ($char < 0xf8) {
             // strip weird sequences
             if ($value = $char % 0x8 * 0x40000 + ord($input[$index + 1]) % 0x40 * 0x1000 + ord($input[$index + 2]) % 0x40 * 0x40 + ord($input[$index + 3]) % 0x40) {
                 $output .= '&#' . $value . ';';
             }
             $index += 4;
             // five bytes (111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
         } elseif ($char < 0xfc) {
             // strip weird sequences
             if ($value = $char % 0x4 * 0x1000000 + ord($input[$index + 1]) % 0x40 * 0x40000 + ord($input[$index + 2]) % 0x40 * 0x1000 + ord($input[$index + 3]) % 0x40 * 0x40 + ord($input[$index + 4]) % 0x40) {
                 $output .= '&#' . $value . ';';
             }
             $index += 5;
             // six bytes (1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
         } else {
             // strip weird sequences
             if ($value = $char % 0x2 * 0x40000000 + ord($input[$index + 1]) % 0x40 * 0x1000000 + ord($input[$index + 2]) % 0x40 * 0x40000 + ord($input[$index + 3]) % 0x40 * 0x1000 + ord($input[$index + 4]) % 0x40 * 0x40 + ord($input[$index + 4]) % 0x40) {
                 $output .= '&#' . $value . ';';
             }
             $index += 6;
         }
     }
     // transcode explicit unicode entities %u2019 -> &#8217;
     $output = preg_replace_callback('/%u([0-9a-z]{4})/is', function ($matches) {
         return '&#' . hexdec($matches[1]);
     }, $output);
     // transcode HTML entities to Unicode entities
     $output =& utf8::transcode($output);
     // translate extended ISO8859-1 chars, if any, to utf-8
     $output = utf8_encode($output);
     // return the translated string
     return $output;
 }
示例#9
0
文件: phpdoc.php 项目: rair/yacs
 /**
  * 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++;
 }
示例#10
0
文件: tar.php 项目: rair/yacs
 function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path)
 {
     $v_result = true;
     $v_nb = 0;
     $v_extract_all = true;
     $v_listing = false;
     $p_path = $this->_translateWinPath($p_path, false);
     if ($p_path == '' || substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) {
         $p_path = "./" . $p_path;
     }
     $p_remove_path = $this->_translateWinPath($p_remove_path);
     // ----- Look for path to remove format (should end by /)
     if ($p_remove_path != '' && substr($p_remove_path, -1) != '/') {
         $p_remove_path .= '/';
     }
     $p_remove_path_size = strlen($p_remove_path);
     switch ($p_mode) {
         case "complete":
             $v_extract_all = TRUE;
             $v_listing = FALSE;
             break;
         case "partial":
             $v_extract_all = FALSE;
             $v_listing = FALSE;
             break;
         case "list":
             $v_extract_all = FALSE;
             $v_listing = TRUE;
             break;
         default:
             $this->_error('Invalid extract mode (' . $p_mode . ')');
             return false;
     }
     clearstatcache();
     while (strlen($v_binary_data = $this->_readBlock()) != 0) {
         $v_extract_file = FALSE;
         $v_extraction_stopped = 0;
         if (!$this->_readHeader($v_binary_data, $v_header)) {
             return false;
         }
         if ($v_header['filename'] == '') {
             continue;
         }
         // ----- Look for long filename
         if ($v_header['typeflag'] == 'L') {
             if (!$this->_readLongHeader($v_header)) {
                 return false;
             }
         }
         if (!$v_extract_all && is_array($p_file_list)) {
             // ----- By default no unzip if the file is not found
             $v_extract_file = false;
             for ($i = 0; $i < sizeof($p_file_list); $i++) {
                 // ----- Look if it is a directory
                 if (substr($p_file_list[$i], -1) == '/') {
                     // ----- Look if the directory is in the filename path
                     if (strlen($v_header['filename']) > strlen($p_file_list[$i]) && substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]) {
                         $v_extract_file = TRUE;
                         break;
                     }
                 } elseif ($p_file_list[$i] == $v_header['filename']) {
                     $v_extract_file = TRUE;
                     break;
                 }
             }
         } else {
             $v_extract_file = TRUE;
         }
         // ----- Look if this file need to be extracted
         if ($v_extract_file && !$v_listing) {
             if ($p_remove_path != '' && substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path) {
                 $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
             }
             if ($p_path != './' && $p_path != '/') {
                 while (substr($p_path, -1) == '/') {
                     $p_path = substr($p_path, 0, strlen($p_path) - 1);
                 }
                 if (substr($v_header['filename'], 0, 1) == '/') {
                     $v_header['filename'] = $p_path . $v_header['filename'];
                 } else {
                     $v_header['filename'] = $p_path . '/' . $v_header['filename'];
                 }
             }
             if (file_exists($v_header['filename'])) {
                 if (@is_dir($v_header['filename']) && $v_header['typeflag'] == '') {
                     $this->_error('File ' . $v_header['filename'] . ' already exists as a directory');
                     return false;
                 }
                 if ($this->_isArchive($v_header['filename']) && $v_header['typeflag'] == "5") {
                     $this->_error('Directory ' . $v_header['filename'] . ' already exists as a file');
                     return false;
                 }
                 if (!is_writeable($v_header['filename'])) {
                     $this->_error('File ' . $v_header['filename'] . ' already exists and is write protected');
                     return false;
                 }
                 if (filemtime($v_header['filename']) > $v_header['mtime']) {
                     // To be completed : An error or silent no replace ?
                 }
             } elseif (($v_result = $this->_dirCheck($v_header['typeflag'] == "5" ? $v_header['filename'] : dirname($v_header['filename']))) != 1) {
                 $this->_error('Unable to create path for ' . $v_header['filename']);
                 return false;
             }
             if ($v_extract_file) {
                 if ($v_header['typeflag'] == "5") {
                     if (!@file_exists($v_header['filename'])) {
                         global $context;
                         if (!@mkdir($v_header['filename'], $context['directory_mask'])) {
                             $this->_error('Unable to create directory {' . $v_header['filename'] . '}');
                             return false;
                         }
                     }
                 } else {
                     if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                         $this->_error('Error while opening {' . $v_header['filename'] . '} in write binary mode');
                         return false;
                     } else {
                         $n = floor($v_header['size'] / 512);
                         for ($i = 0; $i < $n; $i++) {
                             $v_content = $this->_readBlock();
                             fwrite($v_dest_file, $v_content, 512);
                         }
                         if ($v_header['size'] % 512 != 0) {
                             $v_content = $this->_readBlock();
                             fwrite($v_dest_file, $v_content, $v_header['size'] % 512);
                         }
                         @fclose($v_dest_file);
                         // ----- Change the file mode, mtime
                         @touch($v_header['filename'], $v_header['mtime']);
                         // To be completed
                         Safe::chmod($v_header['filename']);
                     }
                     // ----- Check the file size
                     clearstatcache();
                     if (filesize($v_header['filename']) != $v_header['size']) {
                         $this->_error('Extracted file ' . $v_header['filename'] . ' does not have the correct file size \'' . filesize($v_header['filename']) . '\' (' . $v_header['size'] . ' expected). Archive may be corrupted.');
                         return false;
                     }
                 }
             } else {
                 $this->_jumpBlock(ceil($v_header['size'] / 512));
             }
         } else {
             $this->_jumpBlock(ceil($v_header['size'] / 512));
         }
         /* TBC : Seems to be unused ...
         	  if ($this->_compress)
         		$v_end_of_file = @gzeof($this->_file);
         	  else
         		$v_end_of_file = @feof($this->_file);
         		*/
         if ($v_listing || $v_extract_file || $v_extraction_stopped) {
             // ----- Log extracted files
             if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
                 $v_file_dir = '';
             }
             if (substr($v_header['filename'], 0, 1) == '/' && $v_file_dir == '') {
                 $v_file_dir = '/';
             }
             $p_list_detail[$v_nb++] = $v_header;
         }
         Safe::set_time_limit(30);
     }
     return true;
 }
示例#11
0
文件: mailer.php 项目: rair/yacs
 /**
  * process deferred messages
  *
  * Most often, the server has to stay below a given rate of messages,
  * for example 50 messages per hour.
  *
  * Of course, any lively community will feature bursts of activity and of
  * messages, therefore the need for a shaping mechanism.
  *
  * YACS implements a leaking bucket algorithm to take care of messages sent
  * previously:
  *
  * 1. Initially, the bucket is empty.
  *
  * 2. New messages are queued in the database, to be processed asynchronously.
  *
  * 3. On background ticks, the bucket is decremented. If the bucket becomes
  * empty, and if some messages have been queued, a couple of them are sent, and
  * the bucket is incremented accordingly.
  *
  * Bucket content is managed as value 'bucket.content' saved in the database.
  *
  * The bucket size is given by parameter $context['mail_hourly_maximum'], set
  * in the configuration panel for system parameters.
  *
  * This parameter has a default value of 50, meaning YACS will not send more
  * than 50 messages per hour.
  *
  * Background processing is either added to regular page generation or delegated
  * to an external sub-system (e.g., cron). In case of a large site, we recommend
  * to use the second solution, even if this adds additional setup steps. Your
  * choice will be recorded in the configuration panel for system parameters.
  *
  * @see control/configure.php
  *
  * The number of messages sent on each tick can go up to the bucket size if
  * background processing is external. Else it is one fourth of bucket size, to
  * minimize impact on watching surfer.
  *
  * @see cron.php
  */
 public static function tick_hook()
 {
     global $context;
     // email services have to be activated
     if (!isset($context['with_email']) || $context['with_email'] != 'Y') {
         return;
     }
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return;
     }
     // remember start time
     $start = get_micro_time();
     // get bucket size --force it if set to 0
     if (!isset($context['mail_hourly_maximum']) || $context['mail_hourly_maximum'] < 5) {
         $context['mail_hourly_maximum'] = 50;
     }
     // get record related to last tick
     include_once $context['path_to_root'] . 'shared/values.php';
     $bucket = Values::get_record('mailer.bucket.content', 0);
     $bucket['value'] = intval($bucket['value']);
     // some content to leak
     if ($bucket['value'] > 0) {
         // date of last stamp
         if (isset($bucket['edit_date'])) {
             $stamp = SQL::strtotime($bucket['edit_date']);
         } else {
             $stamp = time() - 3600;
         }
         // leak is maximum after one hour
         $leak = intval($context['mail_hourly_maximum'] * (time() - $stamp) / 3600);
         // preserve previous value until actual leak
         if ($leak < 1) {
             return;
         }
         // actual leak
         $bucket['value'] = max(0, $bucket['value'] - $leak);
     }
     // process some messages only when bucket is empty
     $count = 0;
     if ($bucket['value'] < 1) {
         // reduced speed if on-line processing
         if (isset($_SERVER['REMOTE_ADDR'])) {
             $slice = intval($context['mail_hourly_maximum'] / 4);
         } else {
             $slice = intval($context['mail_hourly_maximum']);
         }
         // get some messages, if any
         $query = "SELECT * FROM " . SQL::table_name('messages') . " ORDER BY edit_date LIMIT 0, " . $slice;
         if ($result = SQL::query($query)) {
             // process every message
             while ($item = SQL::fetch($result)) {
                 Mailer::process($item['recipient'], $item['subject'], $item['message'], $item['headers']);
                 // purge the queue
                 $query = 'DELETE FROM ' . SQL::table_name('messages') . ' WHERE id = ' . $item['id'];
                 SQL::query($query);
                 // fill the bucket
                 $bucket['value'] += 1;
                 $count++;
                 // take care of time
                 if (!($count % 50)) {
                     // ensure enough execution time
                     Safe::set_time_limit(30);
                 }
             }
             // close connection
             Mailer::close();
         }
     }
     // remember new state of the bucket
     Values::set('mailer.bucket.content', $bucket['value']);
     // compute execution time
     $time = round(get_micro_time() - $start, 2);
     // report on work achieved
     if ($count > 1) {
         return 'shared/mailer.php: ' . $count . ' messages have been processed (' . $time . ' seconds)' . BR;
     } elseif ($count == 1) {
         return 'shared/mailer.php: 1 message has been processed (' . $time . ' seconds)' . BR;
     } elseif ($bucket['value']) {
         return 'shared/mailer.php: delaying messages (' . $time . ' seconds)' . BR;
     } else {
         return 'shared/mailer.php: nothing to do (' . $time . ' seconds)' . BR;
     }
 }
示例#12
0
文件: import.php 项目: rair/yacs
 function parse_tag_close($parser, $tag)
 {
     global $context;
     global $in_overlay, $overlay_class, $overlay_parameters;
     global $parsed_cdata, $parsed_item, $parsed_overlay, $parsing_report;
     // save gathered data if necessary
     switch ($tag) {
         case 'article':
             // end of article
             // transcode owner id
             $parsed_item['owner_id'] = Surfer::get_id();
             if (isset($parsed_item['owner_nick_name']) && ($user = Users::get($parsed_item['owner_nick_name']))) {
                 $parsed_item['owner_id'] = $user['id'];
             }
             // transcode creator id
             $parsed_item['create_id'] = Surfer::get_id();
             if (isset($parsed_item['create_nick_name']) && ($user = Users::get($parsed_item['create_nick_name']))) {
                 $parsed_item['create_id'] = $user['id'];
             }
             // transcode editor id
             $parsed_item['edit_id'] = Surfer::get_id();
             if (isset($parsed_item['edit_nick_name']) && ($user = Users::get($parsed_item['edit_nick_name']))) {
                 $parsed_item['edit_id'] = $user['id'];
             }
             // transcode publisher id
             $parsed_item['publish_id'] = Surfer::get_id();
             if (isset($parsed_item['publish_nick_name']) && ($user = Users::get($parsed_item['publish_nick_name']))) {
                 $parsed_item['publish_id'] = $user['id'];
             }
             // bind to given overlay
             $overlay = NULL;
             if ($overlay_class) {
                 $overlay = Overlay::bind($overlay_class . ' ' . $overlay_parameters);
             }
             // when the page has been overlaid
             if (is_object($overlay)) {
                 // update the overlay from content
                 foreach ($parsed_overlay as $label => $value) {
                     $overlay->attributes[$label] = $value;
                 }
                 // save content of the overlay in this item
                 $parsed_item['overlay'] = $overlay->save();
                 $parsed_item['overlay_id'] = $overlay->get_id();
             }
             // find anchor from handle
             if (isset($parsed_item['anchor_handle']) && ($reference = Sections::lookup($parsed_item['anchor_handle']))) {
                 $parsed_item['anchor'] = $reference;
             }
             // update an existing page
             if (isset($parsed_item['handle']) && ($item = Articles::get($parsed_item['handle']))) {
                 // transcode page id
                 $parsed_item['id'] = $item['id'];
                 // stop on error
                 if (!Articles::put($parsed_item) || is_object($overlay) && !$overlay->remember('update', $parsed_item, 'article:' . $item['id'])) {
                     Logger::error(sprintf('Unable to save article %s', $parsed_item['title'] . ' (' . $parsed_item['id'] . ')'));
                 }
                 // create a new page
             } else {
                 unset($parsed_item['id']);
                 // stop on error
                 if (!($parsed_item['id'] = Articles::post($parsed_item))) {
                     Logger::error(sprintf('Unable to save article %s', $parsed_item['title']));
                 } else {
                     // save overlay content
                     if (is_object($overlay)) {
                         $overlay->remember('insert', $parsed_item, 'article:' . $parsed_item['id']);
                     }
                 }
             }
             // report to surfer
             $parsing_report .= '<li>' . Skin::build_link(Articles::get_permalink($parsed_item), $parsed_item['title']) . "</li>\n";
             // ready for next item
             $overlay_class = NULL;
             $overlay_parameters = '';
             $parsed_overlay = array();
             $parsed_item = array();
             Safe::set_time_limit(30);
             break;
         case 'overlay':
             // end of overlay data
             $in_overlay = FALSE;
             break;
         case 'section':
             // end of section
             // transcode owner id
             $parsed_item['owner_id'] = Surfer::get_id();
             if (isset($parsed_item['owner_nick_name']) && ($user = Users::get($parsed_item['owner_nick_name']))) {
                 $parsed_item['owner_id'] = $user['id'];
             }
             // transcode creator id
             $parsed_item['create_id'] = Surfer::get_id();
             if (isset($parsed_item['create_nick_name']) && ($user = Users::get($parsed_item['create_nick_name']))) {
                 $parsed_item['create_id'] = $user['id'];
             }
             // transcode editor id
             $parsed_item['edit_id'] = Surfer::get_id();
             if (isset($parsed_item['edit_nick_name']) && ($user = Users::get($parsed_item['edit_nick_name']))) {
                 $parsed_item['edit_id'] = $user['id'];
             }
             // bind to given overlay
             $overlay = NULL;
             if ($overlay_class) {
                 $overlay = Overlay::bind($overlay_class . ' ' . $overlay_parameters);
             }
             // when the page has been overlaid
             if (is_object($overlay)) {
                 // update the overlay from content
                 foreach ($parsed_overlay as $label => $value) {
                     $overlay->attributes[$label] = $value;
                 }
                 // save content of the overlay in this item
                 $parsed_item['overlay'] = $overlay->save();
                 $parsed_item['overlay_id'] = $overlay->get_id();
             }
             // find anchor from handle
             if (isset($parsed_item['anchor_handle']) && ($reference = Sections::lookup($parsed_item['anchor_handle']))) {
                 $parsed_item['anchor'] = $reference;
             }
             // update an existing section
             if (isset($parsed_item['handle']) && ($item = Sections::get($parsed_item['handle']))) {
                 // transcode section id
                 $parsed_item['id'] = $item['id'];
                 // stop on error
                 if (!Sections::put($parsed_item) || is_object($overlay) && !$overlay->remember('update', $parsed_item, 'section:' . $item['id'])) {
                     Logger::error(sprintf('Unable to save section %s', $parsed_item['title'] . ' (' . $parsed_item['id'] . ')'));
                 }
                 // create a new page
             } else {
                 unset($parsed_item['id']);
                 // stop on error
                 if (!($parsed_item['id'] = Sections::post($parsed_item))) {
                     Logger::error(sprintf('Unable to save section %s', $parsed_item['title']));
                 } else {
                     // save overlay content
                     if (is_object($overlay)) {
                         $overlay->remember('insert', $parsed_item, 'section:' . $parsed_item['id']);
                     }
                 }
             }
             // report to surfer
             $parsing_report .= '<li>' . Skin::build_link(Sections::get_permalink($parsed_item), $parsed_item['title']) . "</li>\n";
             // ready for next item
             $overlay_class = NULL;
             $overlay_parameters = '';
             $parsed_overlay = array();
             $parsed_item = array();
             Safe::set_time_limit(30);
             break;
         default:
             // just another attribute
             // decode cdata
             $parsed_cdata = trim(preg_replace(array('/&lt;/', '/&gt;/'), array('<', '>'), $parsed_cdata));
             // feeding the overlay or the item itself
             if ($in_overlay) {
                 $parsed_overlay[$tag] = $parsed_cdata;
             } else {
                 $parsed_item[$tag] = $parsed_cdata;
             }
             // ready for next attribute
             $parsed_cdata = '';
             break;
     }
 }
示例#13
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;
 }
示例#14
0
文件: codes.php 项目: rair/yacs
 /**
  * Internal function to process text replacement according
  * to codes' patterns.
  * uses preg_replace_callback and do the following treatment with priority :
  * 1. try to find a function among loaded script ( could be this class, or Skin class)
  * 2. try to find a class within codes extensions (in /codes/code_*.php) to perform the rendering
  * 3. perform a regular preg_replace
  * 4. let the text as is 
  * 
  * @global array $context
  * @param string $text to transform
  * @param array $patterns_map all the patterns to check and action to do with them
  * @return string transformed text.
  */
 private static function process($text, $patterns_map)
 {
     global $context;
     // ensure we have enough time to execute
     Safe::set_time_limit(30);
     foreach ($patterns_map as $pattern => $action) {
         // use lowercase, we may look for a file with this
         $action = strtolower($action);
         // use of preg_replace_callback with an anonymous function
         $text = preg_replace_callback($pattern, function ($matches) use($pattern, $action, $context) {
             // returned text
             $replace = '';
             // function to call
             $func = '';
             // array of captured element
             $capture = array_slice($matches, 1);
             // test if mapped action is a callable function (case 1)
             if (is_callable($action)) {
                 $func = $action;
                 // test if map is a class
             } elseif (Safe::filesize('codes/' . $action . '.php')) {
                 // delegate rendering to an extension (case 2)
                 include_once $context['path_to_root'] . 'codes/' . $action . '.php';
                 $code = new $action();
                 $replace = $code->render($capture);
                 unset($code);
                 return $replace;
             }
             if ($func) {
                 // call of class Codes method, with or without parameters (case 1)
                 if (count($capture)) {
                     $replace .= call_user_func_array($func, $capture);
                 } else {
                     $replace .= call_user_func($func);
                 }
             } else {
                 // regular preg_replace (case 3 and 4)
                 $replace .= preg_replace($pattern, $action, $matches[0]);
             }
             return $replace;
         }, $text);
     }
     return $text;
 }
示例#15
0
文件: purge.php 项目: rair/yacs
/**
 * delete staging files
 *
 * @param string the directory to start with
 * @see scripts/update.php
 */
function delete_staging($path)
{
    global $context;
    $path_translated = str_replace('//', '/', $context['path_to_root'] . '/scripts/staging' . $path);
    if ($handle = Safe::opendir($path_translated)) {
        while (($node = Safe::readdir($handle)) !== FALSE) {
            if ($node == '.' || $node == '..') {
                continue;
            }
            // make a real name
            $target = str_replace('//', '/', $path . '/' . $node);
            $target_translated = str_replace('//', '/', $path_translated . '/' . $node);
            // delete sub directory content
            if (is_dir($target_translated)) {
                delete_staging($target);
                Safe::rmdir($target_translated);
                // delete all files
            } else {
                $context['text'] .= sprintf(i18n::s('Deleting %s'), '/scripts/staging' . $target) . BR . "\n";
                Safe::unlink($target_translated);
                global $deleted_nodes;
                $deleted_nodes++;
            }
            // ensure we have enough time
            Safe::set_time_limit(30);
        }
        Safe::closedir($handle);
    }
}
示例#16
0
文件: sql.php 项目: rair/yacs
 /**
  * query the database
  *
  * This function populates the error context, where applicable.
  *
  * @param string the SQL query
  * @param boolean optional TRUE to not report on any error
  * @param resource connection to be considered, if any
  * @return the resource returned by the database server, or the number of affected rows, or FALSE on error
  */
 public static function query(&$query, $silent = FALSE, $connection = NULL)
 {
     global $context;
     // allow for reference
     $output = FALSE;
     // use the default connection
     if (!$connection) {
         // we do need a connection to the database
         if (!isset($context['connection']) || !$context['connection']) {
             return $output;
         }
         $connection = $context['connection'];
     }
     // reopen a connection if database is not reachable anymore
     if (get_micro_time() - $context['start_time'] > 1.0 && !SQL::ping($connection)) {
         // remember the error, if any -- we may not have a skin yet
         if (!$silent) {
             if (is_callable(array('Skin', 'error'))) {
                 Logger::error(i18n::s('Connection to the database has been lost'));
             } else {
                 die(i18n::s('Connection to the database has been lost'));
             }
         }
         // query cannot be processed
         return $output;
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // profile database requests
     $query_stamp = get_micro_time();
     // do the job
     if (is_callable('mysqli_query')) {
         $result = mysqli_query($connection, $query);
     } else {
         $result = mysql_query($query, $connection);
     }
     // finalize result
     if ($result) {
         // provide more than a boolean result
         if ($result === TRUE) {
             if (is_callable('mysqli_affected_rows')) {
                 $result = mysqli_affected_rows($connection);
             } else {
                 $result = mysql_affected_rows($connection);
             }
         }
         // flag slow requests
         $duration = get_micro_time() - $query_stamp;
         if ($duration >= 0.5 && $context['with_debug'] == 'Y') {
             Logger::remember('shared/sql.php: SQL::query() slow request', $duration . "\n\n" . $query, 'debug');
         }
         // return the set of selected rows
         return $result;
     }
     // remember the error, if any
     if (SQL::errno($connection)) {
         // display some error message
         if (!$silent) {
             if (is_callable(array('Skin', 'error'))) {
                 Logger::error($query . '<br />' . SQL::error($connection));
             } else {
                 die($query . '<br />' . SQL::error($connection));
             }
         }
         // log the error at development host
         if ($context['with_debug'] == 'Y') {
             Logger::remember('shared/sql.php: SQL::query()', SQL::error($connection) . "\n\n" . $query, 'debug');
         }
     }
     // no valid result
     return $output;
 }
示例#17
0
文件: article.php 项目: rair/yacs
 /**
  * called from within a preg_replace_callback() in Article::parse()
  *
  */
 function parse_match($matches)
 {
     global $context;
     // useful if they are a lot of tags to process
     Safe::set_time_limit(30);
     switch ($matches[1]) {
         case 'anchor':
             $this->item['anchor'] = $matches[2];
             break;
         case 'author':
             if ($user = Users::get($matches[2])) {
                 $this->item['create_name'] = $user['nick_name'];
                 $this->item['create_id'] = $user['id'];
                 $this->item['create_address'] = $user['email'];
                 $this->item['publish_name'] = $user['nick_name'];
                 $this->item['publish_id'] = $user['id'];
                 $this->item['publish_address'] = $user['email'];
                 $this->item['edit_name'] = $user['nick_name'];
                 $this->item['edit_id'] = $user['id'];
                 $this->item['edit_address'] = $user['email'];
             }
             break;
         case 'blogid':
         case 'section':
             if ($section = Sections::get($matches[2])) {
                 $this->item['anchor'] = 'section:' . $section['id'];
             }
             break;
         case 'introduction':
             if (isset($this->item['introduction'])) {
                 $this->item['introduction'] .= $matches[2] . ' ';
             } else {
                 $this->item['introduction'] = $matches[2] . ' ';
             }
             break;
         case 'source':
             $this->item['source'] = $matches[2];
             break;
         case 'tags':
             // web form
         // web form
         case 'category':
             // xml-rpc
         // xml-rpc
         case 'categories':
             // legacy
             if (isset($this->item['tags'])) {
                 $this->item['tags'] .= $matches[2] . ' ';
             } else {
                 $this->item['tags'] = $matches[2] . ' ';
             }
             break;
         case 'title':
             if (isset($this->item['title'])) {
                 $this->item['title'] .= $matches[2] . ' ';
             } else {
                 $this->item['title'] = $matches[2] . ' ';
             }
             break;
         default:
             return $matches[0];
     }
     return '';
 }
示例#18
0
文件: http.php 项目: rair/yacs
 /**
  * login
  *
  * The script checks provided name and password against remote server.
  *
  * This is done by posting the user name and the password
  * to the web server.
  *
  * @param string the nickname of the user
  * @param string the submitted password
  * @return TRUE on succesful authentication, FALSE othewise
  */
 function login($name, $password)
 {
     global $context;
     // we need some parameters
     if (!isset($this->attributes['authenticator_parameters']) || !$this->attributes['authenticator_parameters']) {
         Logger::error(i18n::s('Please provide parameters to the authenticator.'));
         return FALSE;
     }
     // extract parameters
     $parameters = explode(" ", $this->attributes['authenticator_parameters']);
     // ensure a minimum number of parameters
     if (count($parameters) != 3) {
         Logger::error(i18n::s('Provide expected parameters to the REST POST authenticator.'));
         return FALSE;
     }
     // parse URL format
     if (!($url = $parameters[0])) {
         Logger::error(i18n::s('Wrong format of the URL target for the HTTP authenticator.'));
         return FALSE;
     }
     // prepare raw POST payload
     $payload = urlencode($parameters[1]) . "=" . urlencode($name) . "&" . urlencode($parameters[2]) . "=" . urlencode($password);
     // submit credentials to the authenticating server
     include_once $context['path_to_root'] . 'services/call.php';
     // build an HTTP request
     $request = "POST " . $url . " HTTP/1.0" . CRLF . 'Host: ' . $host . CRLF . "Accept-Encoding: gzip" . CRLF . "User-Agent: YACS (www.yacs.fr)" . CRLF . "Connection: close" . CRLF . "Content-Type: application/x-www-form-urlencoded" . CRLF . "Content-Length: " . strlen($payload) . CRLF . CRLF . $payload;
     // parse the target URL
     $items = @parse_url($url);
     // no host, assume it's us
     if (!isset($items['host']) || !($host = $items['host'])) {
         $host = $context['host_name'];
     }
     // no port, assume the standard
     if (!isset($items['port']) || !($port = $items['port'])) {
         $port = 80;
     }
     // outbound web is not authorized
     if (isset($context['without_outbound_http']) && $context['without_outbound_http'] == 'Y') {
         Logger::error(i18n::s('Outbound HTTP is not authorized.'));
         return FALSE;
     }
     // connect to the server
     if (!($handle = Safe::fsockopen($host, $port, $errno, $errstr, 30))) {
         Logger::error(sprintf(i18n::s('Impossible to connect to %.'), $items['host'] . ':' . $items['port']));
         return FALSE;
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // build the path, including any query
     $path = $items['path'];
     if (!$path) {
         $path = '/';
     }
     if (isset($items['query']) && $items['query']) {
         $path .= '?' . $items['query'];
     }
     // submit the request
     fputs($handle, $request);
     // get everything by Ethernet-sized chunks
     $response = '';
     while (!feof($handle) && strlen($response) < 5242880) {
         $response .= fread($handle, 1500);
     }
     fclose($handle);
     // ensure we have a valid HTTP status line
     if (preg_match('/^HTTP\\/[0-9\\.]+ 200 /', $response)) {
         return TRUE;
     }
     // failed authentication
     return FALSE;
 }
示例#19
0
文件: call.php 项目: rair/yacs
 /**
  * get a list of remote resources
  *
  * This function performs a REST call against a web services that provides a RSS-encoded response.
  *
  * Minimum example:
  * [php]
  * $result = Call::list_resources($url);
  * if(!$result[0])
  *	echo $result[1]; // error message
  * else
  *	... // use call result from $result[1]
  * [/php]
  *
  * @param string the url to use
  * @param array the parameters to transmit
  * @return an array of which the first value indicates call success or failure
  *
  * @see search.php
  */
 public static function list_resources($url, $parameters = NULL)
 {
     global $context;
     // encode the request
     $data = '';
     foreach ($parameters as $label => $value) {
         if ($data) {
             $data .= '&';
         }
         $data .= urlencode($label) . '=' . urlencode($value);
     }
     $headers = '';
     $headers .= 'Content-Type: application/x-www-form-urlencoded' . CRLF;
     $headers .= 'Content-Length: ' . strlen($data) . CRLF;
     // parse the target URL
     $items = @parse_url($url);
     // no host, assume it's us
     if (!($host = $items['host'])) {
         $host = $context['host_name'];
     }
     // no port, assume the standard
     if (!isset($items['port']) || !($port = $items['port'])) {
         $port = 80;
     }
     // outbound web is not authorized
     if (isset($context['without_outbound_http']) && $context['without_outbound_http'] == 'Y') {
         return array(FALSE, 'Outbound HTTP is not authorized.');
     }
     // connect to the server
     if (!($handle = Safe::fsockopen($host, $port, $errno, $errstr, 30))) {
         return array(FALSE, sprintf('Impossible to connect to %s.', $host . ':' . $port));
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // build the path, including any query
     $path = $items['path'];
     if ($items['query']) {
         $path .= '?' . $items['query'];
     }
     // build an HTTP request
     $request = "POST " . $path . " HTTP/1.0" . CRLF . 'Host: ' . $host . CRLF . "Accept-Encoding: gzip" . CRLF . "User-Agent: YACS (www.yacs.fr)" . CRLF . "Connection: close" . CRLF . $headers . CRLF . $data;
     // save the request if debug mode
     if ($context['debug_call'] == 'Y') {
         Logger::remember('services/call.php: Call::list_resources() request', str_replace("\r\n", "\n", $request), 'debug');
     }
     // submit the request
     fputs($handle, $request);
     // get everything by Ethernet-sized chunks
     $response = '';
     while (!feof($handle) && strlen($response) < 5242880) {
         $response .= fread($handle, 1500);
     }
     fclose($handle);
     // ensure we have a valid HTTP status line
     if (preg_match('/^HTTP/', $response) && !preg_match('/^HTTP\\/[0-9\\.]+ 200 /', $response)) {
         $lines = explode("\n", $response, 2);
         return array(FALSE, 'Unexpected HTTP status "' . $lines[0] . '"');
     }
     // separate headers from body
     list($headers, $content) = explode(CRLF . CRLF, $response, 2);
     // uncompress payload if necessary
     if (preg_match('/Content-Encoding: \\s*gzip/i', $headers)) {
         $content = gzinflate(substr($content, 10));
     }
     // save the response if debug mode
     if ($context['debug_call'] == 'Y') {
         Logger::remember('services/call.php: Call::list_resources() response', str_replace("\r\n", "\n", $headers . "\n\n" . $content), 'debug');
     }
     // we understand only text responses
     if (!preg_match('/^Content-Type: text/m', $headers)) {
         return array(FALSE, 'Impossible to process not-textual response');
     }
     // passthrough if not xml
     if (!preg_match('/^Content-Type: text\\/xml/m', $headers)) {
         return $content;
     }
     // select a codec handler
     include_once $context['path_to_root'] . 'services/codec.php';
     include_once $context['path_to_root'] . 'services/rss_codec.php';
     $codec = new RSS_Codec();
     if (!is_object($codec)) {
         return array(FALSE, 'Impossible to load codec RSS_Codec');
     }
     // decode the result
     return $codec->import_response($content, $headers, $parameters);
 }
示例#20
0
文件: files.php 项目: rair/yacs
 /**
  * scan a file for viruses
  *
  * This function connects to ClamAV daemon, if possible, to scan the referred file.
  *
  * @param string absolute path of the file to scan
  * @return string 'Y' if the file has been infected, '?' if clamav is not available, or 'N' if no virus has been found
  */
 public static function has_virus($file)
 {
     global $context;
     // file scanning must be configured
     if (!isset($context['clamav_check']) || $context['clamav_check'] === 'N') {
         return 'N';
     }
     // we can't connect to clamav daemon
     $server = 'localhost';
     if (!($handle = Safe::fsockopen($server, 3310, $errno, $errstr, 1))) {
         if ($context['with_debug'] == 'Y') {
             Logger::remember('files/files.php: Unable to connect to CLAMAV daemon', '', 'debug');
         }
         return '?';
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // scan uploaded file
     $request = 'SCAN ' . $file;
     fputs($handle, $request . CRLF);
     if ($context['with_debug'] == 'Y') {
         Logger::remember('files/files.php: CLAMAV ->', $request, 'debug');
     }
     // expecting an OK
     if (($reply = fgets($handle)) === FALSE) {
         Logger::remember('files/files.php: No reply to SCAN command at ' . $server);
         fclose($handle);
         return '?';
     }
     if ($context['with_debug'] == 'Y') {
         Logger::remember('files/files.php: CLAMAV <-', $reply, 'debug');
     }
     // file has been infected!
     if (!stripos($reply, ': ok')) {
         Logger::remember('files/files.php: Infected upload by ' . Surfer::get_name());
         fclose($handle);
         return 'Y';
     }
     // everything is ok
     fclose($handle);
     return 'N';
 }
示例#21
0
文件: run_once.php 项目: rair/yacs
/**
 * dynamically generate the page
 *
 * @see skins/index.php
 */
function send_body()
{
    global $context, $local;
    // $local is required to localize included scripts
    // include every script that has to be run once
    global $scripts, $scripts_count;
    if (@count($scripts)) {
        // the alphabetical order may be used to control script execution order
        sort($scripts);
        reset($scripts);
        // process each script one by one
        foreach ($scripts as $item) {
            // do not execute on first installation
            if (file_exists('../parameters/switch.on') || file_exists('../parameters/switch.off')) {
                // ensure we have a valid database resource
                if (!$context['connection']) {
                    break;
                }
                // remember this as an event
                Logger::remember('scripts/run_once.php: ' . sprintf(i18n::c('script %s has been executed'), $item));
                // where scripts actually are
                $actual_item = str_replace('//', '/', $context['path_to_root'] . 'scripts/run_once/' . $item);
                // include the script to execute it
                $scripts_count++;
                echo Skin::build_block($item, 'subtitle');
                include $actual_item;
                echo "\n";
            }
            // ensure enough overall execution time
            Safe::set_time_limit(30);
            // stamp the file to remember execution time
            Safe::touch($actual_item);
            // rename the script to avoid further execution
            Safe::unlink($actual_item . '.done');
            Safe::rename($actual_item, $actual_item . '.done');
        }
        // refresh javascript libraries
        Cache::purge('js');
    }
    // report on actual execution
    if ($scripts_count) {
        echo '<p>&nbsp;</p><p>' . sprintf(i18n::ns('%d script has been executed', '%d scripts have been executed', $scripts_count), $scripts_count) . "</p>\n";
    } else {
        echo '<p>' . i18n::s('No script has been executed') . "</p>\n";
    }
    // display the total execution time
    $time = round(get_micro_time() - $context['start_time'], 2);
    if ($time > 30) {
        echo '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>';
    }
    // if the server has been switched off, go back to the control panel
    if (file_exists('../parameters/switch.off')) {
        echo '<form method="get" action="' . $context['url_to_root'] . 'control/">' . "\n" . '<p class="assistant_bar">' . Skin::build_submit_button(i18n::s('Control Panel')) . '</p>' . "\n" . '</form>' . "\n";
        // else back to the control panel as well, but without a button
    } else {
        $menu = array('control/' => i18n::s('Control Panel'));
        echo Skin::build_list($menu, 'menu_bar');
    }
    // purge the cache, since it is likely that we have modified some data
    Cache::clear();
}
示例#22
0
文件: comments.php 项目: rair/yacs
 /**
  * wait for updates
  *
  * This script will wait for new updates before providing them to caller.
  * Because of potential time-outs, you have to care of retries.
  *
  * @param string reference to thread (e.g., 'article:123')
  * @param string timestamp of previous update
  * @return array attributes including new comments and a timestamp
  *
  * @see articles/view_as_chat.php
  * @see comments/thread.php
  */
 public static function &pull($anchor, $stamp, $count = 100)
 {
     global $context;
     $timer = 1;
     // some implementations will kill network connections earlier anyway
     Safe::set_time_limit(max(30, $timer));
     // we return formatted text
     $text = '';
     // sanity check
     if (!$anchor) {
         return $text;
     }
     // the query to get time of last update
     $query = "SELECT edit_date, edit_name FROM " . SQL::table_name('comments') . " AS comments " . " WHERE comments.anchor LIKE '" . SQL::escape($anchor) . "'" . " ORDER BY comments.edit_date DESC" . " LIMIT 1";
     // we may timeout ourself, to be safe with network resources
     while (!($stat = SQL::query_first($query)) || isset($stat['edit_date']) && $stat['edit_date'] <= $stamp) {
         // kill the request to avoid repeated transmissions when nothing has changed
         if (--$timer < 1) {
             http::no_content();
             die;
         }
         // preserve server resources
         sleep(1);
     }
     // return an array of variables
     $response = array();
     $response['items'] =& Comments::list_by_thread_for_anchor($anchor, 0, $count, 'thread');
     $response['name'] = strip_tags($stat['edit_name']);
     $response['timestamp'] = SQL::strtotime($stat['edit_date']);
     // return by reference
     return $response;
 }
示例#23
0
文件: links.php 项目: rair/yacs
 /**
  * attempt to use the trackback interface
  *
  * @param string some text, extracted from the target site, to extract the broker URL, if any
  * @param string the source address
  * @param string the target address from which the text has been extracted
  * @param string title of the source page
  * @param string excerpt of the source page
  * @param string blog name of the source page
  * @return TRUE if the target site has been pinged back, FALSE otherwise
  *
  * @link http://www.movabletype.org/docs/mttrackback.html TrackBack Technical Specification
  */
 public static function ping_as_trackback($text, $source, $target, $title = '', $excerpt = '', $blog_name = '')
 {
     global $context;
     // extract all rdf blocks
     preg_match_all('/<rdf:RDF(.*)<\\/rdf:RDF>/iUs', $text, $blocks);
     // nothing to do
     if (!@count($blocks[1])) {
         return FALSE;
     }
     // look for the broker
     $broker = array();
     foreach ($blocks[1] as $block) {
         // seek the trackback interface
         if (!preg_match('/(dc:identifier|about)="' . preg_quote($target, '/') . '/mi', $block)) {
             continue;
         }
         // extract the broker link
         if (preg_match('/trackback:ping="([^"]+)"/mi', $block, $broker)) {
             break;
         }
     }
     // trackback interface not supported at this page
     if (!isset($broker[1])) {
         return FALSE;
     }
     // parse the broker URL
     $items = @parse_url($broker[1]);
     // no host, assume it's us
     if (!($host = $items['host'])) {
         $host = $context['host_name'];
     }
     // no port, assume the standard
     if (!isset($items['port']) || !($port = $items['port'])) {
         $port = 80;
     }
     // outbound web is not authorized
     if (isset($context['without_outbound_http']) && $context['without_outbound_http'] == 'Y') {
         if (isset($context['debug_trackback']) && $context['debug_trackback'] == 'Y') {
             Logger::remember('links/links.php: Links::ping_as_trackback()', 'Outbound HTTP is not authorized.', 'debug');
         }
         return FALSE;
     }
     // connect to the server
     if (!($handle = Safe::fsockopen($host, $port, $errno, $errstr, 30))) {
         if (isset($context['debug_trackback']) && $context['debug_trackback'] == 'Y') {
             Logger::remember('links/links.php: Links::ping_as_trackback()', sprintf('Impossible to connect to %s.', $host . ':' . $port), 'debug');
         }
         return FALSE;
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // build the path, including any query
     $path = $items['path'];
     if (isset($items['query']) && $items['query']) {
         $path .= '?' . $items['query'];
     }
     // encode the content
     $data = 'title=' . urlencode($title) . '&url=' . urlencode($source) . '&excerpt=' . urlencode($excerpt) . '&blog_name=' . urlencode($blog_name);
     $headers = 'Content-Type: application/x-www-form-urlencoded' . CRLF . 'Content-Length: ' . strlen($data) . CRLF;
     // actual trackback, through HTTP POST
     $request = "POST " . $path . " HTTP/1.0" . CRLF . 'Host: ' . $host . CRLF . "User-Agent: YACS (www.yacs.fr)" . CRLF . "Connection: close" . CRLF . $headers . CRLF . $data;
     // save the request if debug mode
     if (isset($context['debug_trackback']) && $context['debug_trackback'] == 'Y') {
         Logger::remember('links/links.php: Links::ping_as_trackback() request', str_replace("\r\n", "\n", $request), 'debug');
     }
     // submit the request
     fputs($handle, $request);
     // we are interested only in the very first bytes of the response
     $code = fread($handle, 15);
     fclose($handle);
     // save the response if debug mode
     if (isset($context['debug_trackback']) && $context['debug_trackback'] == 'Y') {
         Logger::remember('links/links.php: Links::ping_as_trackback() response', $code . '...', 'debug');
     }
     // check HTTP status
     if (!preg_match('/^HTTP\\/[0-9\\.]+ 200/', $code)) {
         return FALSE;
     }
     // successful trackback
     if (isset($context['debug_trackback']) && $context['debug_trackback'] == 'Y') {
         Logger::remember('links/links.php: Links::ping_as_trackback() success', $broker[1], 'debug');
     }
     return TRUE;
 }
示例#24
0
文件: scripts.php 项目: rair/yacs
 /**
  * list running scripts below a certain path
  *
  * This script is used to list scripts below the YACS installation path.
  * Special directories 'scripts/reference' and 'scripts/staging' are skipped.
  * Also directory entries named either 'files' or 'images' are not recursively scanned,
  * because of the potential high number of uninteresting files they can contain.
  *
  * Also echo '.' (one per file) and '!' (one per directory) during the scan,
  * if the verbose parameter is set to TRUE.
  *
  * @param string the path to scan
  * @param boolean TRUE to animate the screen, FALSE to stay silent
  * @return an array of file names
  *
  * @see scripts/build.php
  */
 public static function list_scripts_at($path, $verbose = TRUE)
 {
     global $context, $script_count;
     // we want a list of files
     $files = array();
     $path_translated = $context['path_to_root'];
     if ($path) {
         $path_translated .= '/' . $path;
     }
     if ($handle = Safe::opendir($path_translated)) {
         while (($node = Safe::readdir($handle)) !== FALSE) {
             if ($node[0] == '.') {
                 continue;
             }
             // avoid listing of special directories
             if ($node == 'reference' || $node == 'staging') {
                 continue;
             }
             // make a real name
             if ($path) {
                 $target = $path . '/' . $node;
             } else {
                 $target = $node;
             }
             $target_translated = $path_translated . '/' . $node;
             // scan a sub directory
             if (is_dir($target_translated)) {
                 // skip files and images, because of so many sub directories
                 if (strpos($path, 'files/') !== FALSE || strpos($path, 'images/') !== FALSE) {
                     continue;
                 }
                 // already included
                 if (strpos($path, 'included/') !== FALSE) {
                     continue;
                 }
                 // extend the list recursively
                 $files = array_merge($files, Scripts::list_scripts_at($target));
                 // animate the screen
                 if ($verbose) {
                     $context['text'] .= '!';
                 }
                 if ($script_count++ > 50) {
                     $script_count = 0;
                     if ($verbose) {
                         $context['text'] .= BR . "\n";
                     }
                 }
                 // scan a file
             } elseif (preg_match('/\\.php$/i', $node) && is_readable($target_translated)) {
                 // append the script to the list
                 if ($path) {
                     $files[] = $path . '/' . $node;
                 } else {
                     $files[] = $node;
                 }
                 // animate the screen
                 if ($verbose) {
                     $context['text'] .= '.';
                 }
                 if ($script_count++ > 50) {
                     $script_count = 0;
                     if ($verbose) {
                         $context['text'] .= BR . "\n";
                     }
                     Safe::set_time_limit(30);
                 }
             }
         }
         Safe::closedir($handle);
     }
     return $files;
 }