Example #1
0
 /**
  * process one single HTTP request
  *
  * @return void
  */
 public static function check_request()
 {
     global $context;
     // ensure we know where we are
     if (!isset($context['script_url']) || !$context['script_url']) {
         return;
     }
     // don't bother with HEAD requests
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'HEAD') {
         return;
     }
     // ensure we have a valid database resource
     if (!isset($context['connection']) || !$context['connection']) {
         return;
     }
     // only on regular operation
     if (!file_exists($context['path_to_root'] . 'parameters/switch.on')) {
         return;
     }
     // script used for this request
     $url = $context['script_url'];
     // execution time up to now
     $execution_time = round(get_micro_time() - $context['start_time'], 4);
     // if a record exists for this url
     $query = "SELECT * FROM " . SQL::table_name('profiles') . " AS profiles WHERE profiles.url = '{$url}'";
     $item = SQL::query_first($query);
     // update figures
     if ($item['id']) {
         $query = "UPDATE " . SQL::table_name('profiles') . " SET " . "total_hits='" . ($item['total_hits'] + 1) . "', " . "total_time='" . ($item['total_time'] + $execution_time) . "', " . "minimum_time='" . min($item['minimum_time'], $execution_time) . "', " . "maximum_time='" . max($item['maximum_time'], $execution_time) . "' " . " WHERE id = " . $item['id'];
     } else {
         $query = "INSERT INTO " . SQL::table_name('profiles') . " SET " . "url='" . $url . "', " . "total_hits='1', " . "total_time='" . $execution_time . "', " . "minimum_time='" . $execution_time . "', " . "maximum_time='" . $execution_time . "'";
     }
     SQL::query($query);
 }
Example #2
0
File: new.php Project: rair/yacs
        $context['text'] .= i18n::s('One letter has been transmitted.') . BR . "\n";
    } else {
        $context['text'] .= sprintf(i18n::s('%d letters have been transmitted.'), $recipients_ok) . BR . "\n";
    }
    // transmission errors, if any
    if ($recipients_errors == 1) {
        $context['text'] .= i18n::s('One transmission error has been encountered.') . BR . "\n";
    } elseif ($recipients_errors > 1) {
        $context['text'] .= sprintf(i18n::s('%d transmission errors have been encountered.'), $recipients_errors) . BR . "\n";
    }
    // save digest stamp, if any
    if (isset($_REQUEST['digest_stamp']) && $_REQUEST['digest_stamp'] > NULL_DATE) {
        Values::set('letters.digest.stamp', $_REQUEST['digest_stamp']);
    }
    // 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>';
    // forward to the index page
    $menu = array('letters/' => i18n::s('Newsletters'));
    $context['text'] .= Skin::build_list($menu, 'menu_bar');
    // make the user select an option
} else {
    // the splash message
    $context['text'] .= '<p>' . i18n::s('This script will help you to prepare and to send a electronic message to community members. Please select below the action you would like to perform. Depending on your choice, the assistant may ask for additional parameters on successive panels.') . '</p>' . "\n";
    // the form
    $context['text'] .= '<form method="get" action="' . $context['script_url'] . '" id="main_form">' . "\n";
    // a digest of most recent articles
    $context['text'] .= '<p><input type="radio" name="action" value="digest" selected="selected" /> ' . i18n::s('Send a digest of articles published recently') . '</p>' . "\n";
    // list featured pages
    $context['text'] .= '<p><input type="radio" name="action" value="featured" /> ' . i18n::s('List featured pages') . '</p>' . "\n";
    // some announcement
Example #3
0
/**
 * 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();
}
Example #4
0
File: ping.php Project: rair/yacs
    Safe::redirect($context['url_to_home'] . $context['url_to_root'] . 'users/login.php?url=' . urlencode('servers/ping.php'));
} elseif (!Surfer::is_associate()) {
    Safe::header('Status: 401 Unauthorized', TRUE, 401);
    Logger::error(i18n::s('You are not allowed to perform this operation.'));
    // do the ping
} elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'ping') {
    // list servers to be advertised
    if ($servers = Servers::list_for_ping(0, 20, 'ping')) {
        $context['text'] .= '<p>' . i18n::s('Servers that have been notified') . '</p><ul>';
        // ping each server
        foreach ($servers as $server_url => $attributes) {
            list($server_ping, $server_label) = $attributes;
            $milestone = get_micro_time();
            $result = @Call::invoke($server_ping, 'weblogUpdates.ping', array(strip_tags($context['site_name']), $context['url_to_home'] . $context['url_to_root']), 'XML-RPC');
            if ($result[0]) {
                $label = round(get_micro_time() - $milestone, 2) . ' sec.';
            } else {
                $label = @$result[1];
            }
            $context['text'] .= '<li>' . $server_label . ' (' . $label . ')</li>';
        }
        $context['text'] .= '</ul>';
        // no server to ping
    } else {
        $context['text'] .= '<p>' . i18n::s('No server has been created yet.') . '</p>';
    }
    // back to the index of servers
    $menu = array('servers/' => i18n::s('Servers'));
    $context['text'] .= Skin::build_list($menu, 'menu_bar');
    // remember this in log as well
    Logger::remember('servers/ping.php: The cloud has been pinged');
Example #5
0
 /**
  * notify servers about a new page
  *
  * @param string page URL
  * @param string server name
  */
 public static function notify($link, $title = NULL)
 {
     global $context;
     if (!$title) {
         $title = $context['site_name'];
     }
     // the list of recipients contacted during overall script execution
     if (!isset($context['servers_endpoints'])) {
         $context['servers_endpoints'] = array();
     }
     // list servers to be advertised
     if ($servers = Servers::list_for_ping(0, COMPACT_LIST_SIZE, 'ping')) {
         // ping each server
         include_once $context['path_to_root'] . 'services/call.php';
         foreach ($servers as $server_url => $attributes) {
             list($server_ping, $server_label) = $attributes;
             $milestone = get_micro_time();
             $result = Call::invoke($server_ping, 'weblogUpdates.ping', array(strip_tags($title), $context['url_to_home'] . $context['url_to_root'] . $link), 'XML-RPC');
             if ($result[0]) {
                 $server_label .= ' (' . round(get_micro_time() - $milestone, 2) . ' sec.)';
             }
             $context['servers_endpoints'][] = $server_label;
         }
     }
 }
Example #6
0
File: page.php Project: rair/yacs
 /**
  * echo the standard footer
  *
  * Note that this one does not echo $context['page_footer'], and you have
  * to do it yourself.
  *
  * @param string footer prefix, if any
  * @param string footer suffix, if any
  */
 public static function footer($prefix = '', $suffix = '')
 {
     global $context;
     // the last paragraph
     echo '<p>';
     // add footer prefix
     echo $prefix;
     $details = array();
     // execution time and surfer name, for logged user only (not for indexing robots!)
     if (is_callable(array('Surfer', 'get_name')) && is_callable(array('i18n', 's'))) {
         $execution_time = round(get_micro_time() - $context['start_time'], 2);
         $details[] = sprintf(i18n::s('page prepared in %.2f seconds for %s'), $execution_time, ucwords(Surfer::get_name()));
     }
     // site copyright
     if (isset($context['site_copyright']) && $context['site_copyright']) {
         $details[] = '&copy; ' . $context['site_copyright'] . "\n";
     }
     // a command to authenticate
     if (is_callable(array('Surfer', 'is_logged')) && !Surfer::is_logged() && is_callable(array('i18n', 's'))) {
         $details[] = Skin::build_link('users/login.php', i18n::s('login'), 'basic');
     }
     // about this site
     if (is_callable(array('i18n', 's')) && is_callable(array('Articles', 'get_url'))) {
         $details[] = Skin::build_link(Articles::get_url('about'), i18n::s('about this site'), 'basic');
     }
     // privacy statement
     if (is_callable(array('i18n', 's')) && is_callable(array('Articles', 'get_url'))) {
         $details[] = Skin::build_link(Articles::get_url('privacy'), i18n::s('privacy statement'), 'basic');
     }
     // a reference to YACS
     if (is_callable(array('i18n', 's')) && $context['host_name'] != 'www.yacs.fr') {
         $details[] = sprintf(i18n::s('powered by %s'), Skin::build_link(i18n::s('http://www.yacs.fr/'), 'Yacs', 'external'));
     }
     // all our feeds
     if (is_callable(array('i18n', 's'))) {
         $details[] = Skin::build_link('feeds/', i18n::s('information channels'), 'basic');
     }
     echo join(' -&nbsp;', $details);
     // add footer suffix
     echo $suffix;
     // end of the last paragraph
     echo '</p>' . "\n";
 }
Example #7
0
File: purge.php Project: rair/yacs
    if (SQL::query($query) === FALSE) {
        $context['text'] .= Logger::error_pop() . BR . "\n";
    }
    // display the execution time
    $time_end = get_micro_time();
    $time = round($time_end - $context['start_time'], 2);
    $context['text'] .= '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>';
    // forward to the control panel
    $menu = array('control/' => i18n::s('Control Panel'), 'control/purge.php' => i18n::s('Purge again'));
    $context['text'] .= Skin::build_list($menu, 'menu_bar');
    // delete formatting code patterns, will be rebuild automaticaly
} elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'codeyacs') {
    $context['text'] .= '<p>' . i18n::s('Deleting formatting codes cache...') . "</p>\n";
    Safe::unlink($context['path_to_root'] . 'codes/patterns.auto.php');
    // display the execution time
    $time_end = get_micro_time();
    $time = round($time_end - $context['start_time'], 2);
    $context['text'] .= '<p>' . sprintf(i18n::s('Script terminated in %.2f seconds.'), $time) . '</p>';
    // forward to the control panel
    $menu = array('control/' => i18n::s('Control Panel'), 'control/purge.php' => i18n::s('Purge again'));
    $context['text'] .= Skin::build_list($menu, 'menu_bar');
    // which check?
} else {
    // the splash message
    $context['text'] .= '<p>' . i18n::s('Please select the action to perform.') . "</p>\n";
    // the form
    $context['text'] .= '<form method="post" action="' . $context['script_url'] . '" id="main_form">';
    // purge the cache
    $context['text'] .= '<p><input type="radio" name="action" value="cache" checked="checked" /> ' . i18n::s('Purge the server cache.') . '</p>';
    // purge .bak scripts
    $context['text'] .= '<p><input type="radio" name="action" value="bak" /> ' . i18n::s('Delete all files with the suffix .bak.') . '</p>';
Example #8
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);
    }
}
Example #9
0
?>
<tr>
  <td style="border: none bgcolor="555555">
<font size="1" face="verdana" color="#fcfcfc">
<br>
 <tr>
<tr>
  <td style="border: none bgcolor="555555">
<font size="1" face="verdana" color="#fcfcfc">
<br>
 </tr>
</table>
</div>
</td>
</tr>
</table>
<table width=950>
<tr>
  <td style="border: 1 solid #000000" bgcolor="677667" >
<font size="1" face="verdana" color="#000000">
<center>

<?php 
echo "-=[" . $cshver . " | Page generation time: <font color=#fcfcfc>[<b>" . round(get_micro_time() - start_time, 4) . "</b>]</font> seconds.]=-";
?>

 </td>
 </tr>
 </table>
</BODY>
</HTML>
Example #10
0
 /**
  * process new messages, if any
  *
  * This function checks inbound mailboxes, and process new messages on their arrival.
  *
  * This function is aiming to run silently, therefore errors are logged in a file.
  *
  * @return a string to be displayed in resulting page, if any
  */
 public static function tick_hook()
 {
     global $context;
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return;
     }
     // we need some queue definitions
     Safe::load('parameters/agents.include.php');
     if (!isset($context['mail_queues']) || !is_array($context['mail_queues']) || !count($context['mail_queues'])) {
         return 'agents/messages.php: no queue has been defined' . BR;
     }
     // remember start time
     $stamp = get_micro_time();
     // process each inbound queue
     include_once $context['path_to_root'] . 'shared/values.php';
     // messages.tick
     $count = 0;
     foreach ($context['mail_queues'] as $name => $queue) {
         // count messages retrieved
         $messages = Messages::process_queue($queue);
         $count += $messages;
         // remember tick date
         Values::set('messages.tick.' . $name, $messages);
     }
     // rebuild index pages
     if ($count) {
         Cache::clear();
     }
     // compute execution time
     $time = round(get_micro_time() - $stamp, 2);
     // report on work achieved
     if ($count > 1) {
         return 'agents/messages.php: ' . $count . ' messages have been processed (' . $time . ' seconds)' . BR;
     } elseif ($count == 1) {
         return 'agents/messages.php: 1 message has been processed (' . $time . ' seconds)' . BR;
     } else {
         return 'agents/messages.php: nothing to do (' . $time . ' seconds)' . BR;
     }
 }
Example #11
0
File: sql.php Project: 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;
 }
Example #12
0
 /**
  * process new uploads, if any
  *
  * This function checks the input queue, and process new files on their arrival.
  *
  * This function is aiming to run silently, therefore errors are logged in a file.
  *
  * @return a string to be displayed in resulting page, if any
  *
  */
 public static function tick_hook()
 {
     global $context;
     // useless if we don't have a valid database connection
     if (!$context['connection']) {
         return;
     }
     // remember start time
     $stamp = get_micro_time();
     // process handx weblog entries, if any
     $count = 0;
     if (($files = Uploads::list_files('inbox/entries')) && @count($files) > 0) {
         foreach ($files as $file) {
             // help the webmaster
             Logger::remember('agents/upload.php: processing ' . $file);
             // create articles
             Uploads::process_handx_weblog($file);
             // no more than 10 entries per tick
             $count += 1;
             if ($count >= 10) {
                 break;
             }
         }
         // remember tick date
         include_once $context['path_to_root'] . 'shared/values.php';
         Values::set('uploads.tick.entries', $count);
     }
     // rebuild index pages
     if ($count) {
         Cache::clear();
     }
     // compute execution time
     $time = round(get_micro_time() - $stamp, 2);
     // report on work achieved
     if ($count > 1) {
         return 'agents/uploads.php: ' . $count . ' files have been processed (' . $time . " seconds)" . BR;
     } elseif ($count == 1) {
         return 'agents/uploads.php: 1 file has been processed (' . $time . " seconds)" . BR;
     } else {
         return 'agents/uploads.php: nothing to do (' . $time . " seconds)" . BR;
     }
 }
Example #13
0
File: mailer.php Project: 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;
     }
 }
Example #14
0
File: feeds.php Project: rair/yacs
 /**
  * get news from remote servers
  *
  * This function queries remote sources and populate the table of links based on fetched news.
  *
  * On tick, the including hook calls [code]Feeds::tick_hook()[/code].
  * See [script]control/scan.php[/script] for a more complete description of hooks.
  *
  * The function browses the database to locate servers acting as feeders, and read the URLs to use.
  *
  * A round-robin algorithm is implemented, meaning that servers are polled in sequence throughout successive ticks.
  * At most 1 feed is parsed on each tick, to limit impact when the "poor-man" cron mechanism is used,
  * which is the default setting.
  *
  * XML feeds are fetched and parsed according to their type.
  * At the moment YACS is able to process RSS and slashdot feeds.
  * Link records are created or updated in the database saving as much of possible of provided data.
  * Item data is reflected in Link, Title, and Description fields.
  * Channel	data is used to populate the Source field.
  * Stamping information is based on feeding date, and channel title.
  * Also, the edit action 'link:feed' marks links that are collected from feeders.
  * The anchor field is set to the category assigned in the server profile.
  *
  * At the end of the feeding process, the database is purged from oldest links according to the limit
  * defined in parameters/feeds.include.php, set through feeds/configure.php.
  * See Links::purge_old_news().
  *
  * @param boolean if set to true, fetch news on each call; else use normal period of time
  * @return a string to be displayed in resulting page, if any
  *
  * @see control/scan.php
  * @see feeds/configure.php
  */
 public static function tick_hook($forced = FALSE)
 {
     global $context;
     // load librairies only once
     include_once $context['path_to_root'] . 'links/links.php';
     include_once $context['path_to_root'] . 'servers/servers.php';
     include_once $context['path_to_root'] . 'shared/values.php';
     // feeds.tick
     // get feeding parameters
     Safe::load('parameters/feeds.include.php');
     // delay between feeds - minimum is 5 minutes
     if (!isset($context['minutes_between_feeds']) || $context['minutes_between_feeds'] < 5) {
         $context['minutes_between_feeds'] = 5;
     }
     // do not wait for the end of a feeding cycle
     if ($forced) {
         $threshold = gmstrftime('%Y-%m-%d %H:%M:%S');
     } else {
         $threshold = gmstrftime('%Y-%m-%d %H:%M:%S', time() - $context['minutes_between_feeds'] * 60);
     }
     // get a batch of feeders
     if (!($feeders = Servers::list_for_feed(0, 1, 'feed'))) {
         return 'feeds/feeds.php: no feed has been defined' . BR;
     }
     // remember start time
     $start_time = get_micro_time();
     // list banned tokens
     $banned_pattern = Servers::get_banned_pattern();
     // browse each feed
     $count = 0;
     foreach ($feeders as $server_id => $attributes) {
         // get specific feed parameters
         list($feed_url, $feed_title, $anchor, $stamp) = $attributes;
         // skip servers processed recently
         if ($stamp > $threshold) {
             continue;
         }
         // flag this record to enable round-robin even on error
         Servers::stamp($server_id);
         // fetch news from the provided link
         if (!($news = Feeds::get_remote_news_from($feed_url)) || !is_array($news)) {
             continue;
         }
         // no anchor has been defined for this feed
         if (!$anchor) {
             // create a default section if necessary
             if (!($anchor = Sections::lookup('external_news'))) {
                 $fields = array();
                 $fields['nick_name'] = 'external_news';
                 $fields['create_date'] = gmstrftime('%Y-%m-%d %H:%M:%S', time());
                 $fields['edit_date'] = gmstrftime('%Y-%m-%d %H:%M:%S', time());
                 $fields['index_map'] = 'N';
                 $fields['locked'] = 'Y';
                 // no direct contributions
                 $fields['rank'] = 40000;
                 // at the end of the list
                 $fields['title'] = i18n::c('External News');
                 $fields['description'] = i18n::c('Received from feeding servers');
                 if (!($fields['id'] = Sections::post($fields))) {
                     Logger::remember('feeds/feeds.php: Impossible to add a section.');
                     return;
                 }
                 $anchor = 'section:' . $fields['id'];
             }
         }
         // process retrieved links
         $links = 0;
         foreach ($news as $item) {
             // link has to be valid
             if (!isset($item['link']) || !($item['title'] . $item['description'])) {
                 if (isset($context['debug_feeds']) && $context['debug_feeds'] == 'Y') {
                     Logger::remember('feeds/feeds.php: feed item is invalid', $item, 'debug');
                 }
                 continue;
             }
             // skip banned servers
             if ($banned_pattern && preg_match($banned_pattern, $item['link'])) {
                 if (isset($context['debug_feeds']) && $context['debug_feeds'] == 'Y') {
                     Logger::remember('feeds/feeds.php: feed host has been banned', $item['link'], 'debug');
                 }
                 continue;
             }
             // one link processed
             $links++;
             // link description
             $fields = array();
             $fields['anchor'] = $anchor;
             $fields['link_url'] = $item['link'];
             $fields['title'] = $item['title'];
             $fields['description'] = $item['description'];
             if ($item['category']) {
                 $fields['description'] .= ' (' . $item['category'] . ')';
             }
             $fields['edit_name'] = $feed_title;
             $fields['edit_address'] = $feed_url;
             $fields['edit_action'] = 'link:feed';
             if ($item['pubDate']) {
                 $fields['edit_date'] = gmstrftime('%Y-%m-%d %H:%M:%S', strtotime($item['pubDate']));
             }
             // update links that already exist in the database
             if (Links::have($item['link'], $anchor, $fields)) {
                 continue;
             }
             // save link in the database
             if (!Links::post($fields)) {
                 Logger::remember('feeds/feeds.php: Impossible to save feed link: ' . Logger::error_pop());
             }
         }
         // one feed has been processed
         $count += 1;
         // remember tick date
         Values::set('feeds.tick.' . $feed_url, $links);
     }
     // cap the number of links used for news
     if (!isset($context['maximum_news']) || !$context['maximum_news']) {
         $context['maximum_news'] = 1000;
     }
     if ($context['maximum_news'] > 10) {
         include_once $context['path_to_root'] . 'links/links.php';
         Links::purge_old_news($context['maximum_news']);
     }
     // compute execution time
     $time = round(get_micro_time() - $start_time, 2);
     // report on work achieved
     if ($count > 1) {
         return 'feeds/feeds.php: ' . $count . ' feeds have been processed (' . $time . ' seconds)' . BR;
     } elseif ($count == 1) {
         return 'feeds/feeds.php: 1 feed has been processed (' . $time . ' seconds)' . BR;
     } else {
         return 'feeds/feeds.php: nothing to do (' . $time . ' seconds)' . BR;
     }
 }
Example #15
0
 /**
  * compare two sets of lines by finding the longest common sequence
  *
  * @param string or array the left set
  * @param string or array the right set
  * @param int maximm number of lines to consider
  * @return an array of ('=', $left, $right) or ('-', $left, '-') or ('+', '-', $right)
  */
 public static function &compare($old_stream, $new_stream, $maximum = 500)
 {
     $start_time = get_micro_time();
     // the resulting sequence
     $sequence = array();
     // make lists of nodes
     if (is_array($old_stream)) {
         $old_lines = $old_stream;
     } else {
         $old_lines = explode("\n", $old_stream);
     }
     if (is_array($new_stream)) {
         $new_lines = $new_stream;
     } else {
         $new_lines = explode("\n", $new_stream);
     }
     // don't count things too many times
     $old_lines_count = count($old_lines);
     $new_lines_count = count($new_lines);
     // hash nodes
     for ($i = $old_lines_count - 1; $i >= 0; $i--) {
         $old_lines[$i] = rtrim($old_lines[$i]);
         $old_hash[$i] = md5(strtolower(trim($old_lines[$i])));
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     for ($j = $new_lines_count - 1; $j >= 0; $j--) {
         $new_lines[$j] = rtrim($new_lines[$j]);
         $new_hash[$j] = md5(strtolower(trim($new_lines[$j])));
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // skip the head of common nodes
     $head = 0;
     while ($head < $old_lines_count && $head < $new_lines_count) {
         if ($old_hash[$head] == $new_hash[$head]) {
             $head++;
         } else {
             break;
         }
     }
     // skip the tail of common nodes
     $tail = 0;
     $oindex = $old_lines_count;
     $nindex = $new_lines_count;
     while (--$oindex > $head && --$nindex > $head) {
         if ($old_hash[$oindex] == $new_hash[$nindex]) {
             $tail++;
         } else {
             break;
         }
     }
     // compute lengths
     $lengths = array();
     $lengths[0][0] = 0;
     $lengths[0][1] = 0;
     $i_count = min($maximum, $old_lines_count - $head - $tail);
     $j_count = min($maximum, $new_lines_count - $head - $tail);
     for ($i = $i_count; $i >= 0; $i--) {
         $lengths[$i + 1][$j_count + 1] = 0;
         $lengths[$i + 1][$j_count] = 0;
         $lengths[$i][$j_count + 1] = 0;
         for ($j = $j_count; $j >= 0; $j--) {
             if ($i == $i_count || $j == $j_count) {
                 $lengths[$i][$j] = 0;
             } elseif ($old_hash[$i + $head] == $new_hash[$j + $head]) {
                 $lengths[$i][$j] = 1 + $lengths[$i + 1][$j + 1];
             } else {
                 $lengths[$i][$j] = max($lengths[$i + 1][$j], $lengths[$i][$j + 1]);
             }
         }
     }
     // ensure enough execution time
     Safe::set_time_limit(30);
     // parse the resulting matrix
     $i = $j = 0;
     while ($i < $old_lines_count && $j < $new_lines_count) {
         // same nodes
         if ($old_hash[$i] == $new_hash[$j]) {
             $sequence[] = array('=', $old_lines[$i], $new_lines[$j]);
             $i++;
             $j++;
             // one node has been deleted
         } elseif (isset($lengths[$i - $head + 1][$j - $head]) && $lengths[$i - $head + 1][$j - $head] >= $lengths[$i - $head][$j - $head + 1]) {
             $sequence[] = array('-', $old_lines[$i], '-');
             $i++;
             // one node has been inserted
         } else {
             $sequence[] = array('+', '-', $new_lines[$j]);
             $j++;
         }
     }
     // other nodes that have been removed
     while ($i < $old_lines_count) {
         $sequence[] = array('-', $old_lines[$i++], '-');
     }
     // nodes that have been appended
     while ($j < $new_lines_count) {
         $sequence[] = array('+', '-', $new_lines[$j++]);
     }
     // return the whole diff sequence
     return $sequence;
 }