| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- <?php
- /* $Id: Wrapper.wget.php 3237 2007-10-26 21:17:22Z munk $ */
- /*******************************************************************************
- LICENSE
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License (GPL)
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- To read the license please visit http://www.gnu.org/copyleft/gpl.html
- *******************************************************************************/
- /**
- * class Wrapper for wget-client
- */
- class WrapperWget
- {
- // private fields
- // vars from args
- var $_transfer = "";
- var $_owner = "";
- var $_path = "";
- var $_drate = 0;
- var $_retries = 0;
- var $_pasv = 0;
- var $_commandFile = "";
- // runtime-vars
- var $_percent_done = 0;
- var $_time_left = "-";
- var $_down_speed = "0.00 kB/s";
- var $_downtotal = 0;
- var $_size = 0;
- // speed as number
- var $_speed = 0;
- // pid
- var $_pid = 0;
- // buffer
- var $_buffer = "";
- // done-flag
- var $_done = false;
- // statfile-object-instance
- var $_sf = null;
- // process-handle
- var $_wget = null;
- // =========================================================================
- // public static methods
- // =========================================================================
- /**
- * start
- *
- * @param $file
- * @param $owner
- * @param $path
- * @param $drate
- * @param $retries
- * @param $pasv
- */
- function start($file, $owner, $path, $drate, $retries, $pasv) {
- global $instanceWrapperWget;
- $instanceWrapperWget = new WrapperWget($file, $owner, $path, $drate, $retries, $pasv);
- $instanceWrapperWget->instance_start();
- }
- /**
- * stop
- */
- function stop() {
- global $instanceWrapperWget;
- if (isset($instanceWrapperWget))
- $instanceWrapperWget->instance_stop();
- }
- // =========================================================================
- // ctor
- // =========================================================================
- /**
- * ctor
- *
- * @param $file
- * @param $owner
- * @param $path
- * @param $drate
- * @param $retries
- * @param $pasv
- * @return WrapperWget
- */
- function WrapperWget($file, $owner, $path, $drate, $retries, $pasv) {
- global $cfg;
- // set fields from params
- $this->_transfer = str_replace($cfg['transfer_file_path'], '', $file);
- $this->_owner = $owner;
- $this->_path = $path;
- $this->_drate = $drate;
- $this->_retries = $retries;
- $this->_pasv = $pasv;
- $this->_commandFile = $file.".cmd";
- // set user-var
- $cfg["user"] = $this->_owner;
- // set admin-var
- $cfg['isAdmin'] = IsAdmin($this->_owner);
- // init sf-instance
- $this->_sf = new StatFile($this->_transfer, $this->_owner);
- }
- // =========================================================================
- // public methods
- // =========================================================================
- /**
- * instance_start
- *
- * @return boolean
- */
- function instance_start() {
- // wrapper start
- $this->_wrapperStart();
- // wrapper main
- $mainRet = $this->_wrapperMain();
- // wrapper stop
- $this->_wrapperStop(!$mainRet);
- }
- /**
- * instance_stop
- */
- function instance_stop() {
- // wrapper stop
- $this->_wrapperStop(false);
- }
- // =========================================================================
- // private methods
- // =========================================================================
- /**
- * start wrapper
- *
- * @return boolean
- */
- function _wrapperStart() {
- global $cfg;
- // print startup
- $this->_outputMessage("wget-wrapper starting up :\n");
- $this->_outputMessage(" - transfer : ".$this->_transfer."\n");
- $this->_outputMessage(" - owner : ".$this->_owner."\n");
- $this->_outputMessage(" - path : ".$this->_path."\n");
- $this->_outputMessage(" - drate : ".$this->_drate."\n");
- $this->_outputMessage(" - retries : ".$this->_retries."\n");
- $this->_outputMessage(" - pasv : ".$this->_pasv."\n");
- // write stat-file
- $this->_statStartup();
- // start client
- if (!$this->_clientStart()) {
- // stop
- $this->_wrapperStop(true);
- // return
- return false;
- }
- // signal-handler
- if (function_exists("pcntl_signal")) {
- $this->_outputMessage("setting up signal-handler...\n");
- pcntl_signal(SIGHUP, array($this, "_sigHandler"));
- pcntl_signal(SIGINT, array($this, "_sigHandler"));
- pcntl_signal(SIGTERM, array($this, "_sigHandler"));
- pcntl_signal(SIGQUIT, array($this, "_sigHandler"));
- }
- // remove command-file if exists
- if (@is_file($this->_commandFile)) {
- // print
- $this->_outputMessage("removing command-file ".$this->_commandFile."...\n");
- // delete command-file
- @unlink($this->_commandFile);
- }
- // return
- return true;
- }
- /**
- * wrapper main
- *
- * @return boolean
- */
- function _wrapperMain() {
- // print
- $this->_outputMessage("wget up and running\n");
- // write stat with "Connecting..."
- $this->_statRunning($this->_percent_done, "Connecting...", $this->_down_speed, $this->_downtotal);
- // process header
- if ($this->_processHeader() === false) {
- $this->_outputMessage("failed to start download, shutting down... (pid: ".$this->_pid.")\n");
- // print buffer
- $this->_outputMessage("buffer :\n".$this->_buffer);
- return false;
- }
- // check for client before entering main-loop
- if ($this->_clientIsRunning() === false) {
- $this->_outputMessage("wget-client not running, shutting down... (pid: ".$this->_pid.")\n");
- // print buffer
- $this->_outputMessage("buffer :\n".$this->_buffer);
- return false;
- }
- // write stat with "Downloading..."
- $this->_statRunning($this->_percent_done, "Downloading...", $this->_down_speed, $this->_downtotal);
- // flush buffer
- $this->_buffer = "";
- // main loop
- $this->_outputMessage("downloading...\n");
- $tick = 1;
- for (;;) {
- // read to buffer
- if (!@feof($this->_wget))
- $this->_buffer .= @fread($this->_wget, 8192);
- // process buffer
- $this->_done = $this->_processBuffer();
- // return if done
- if ($this->_done)
- return true;
- // process Command Stack, return if quit
- if ($this->_processCommandStack())
- return true;
- // write stat-file every 5 secs
- if (($tick % 5) == 0)
- $this->_statRunning($this->_percent_done, $this->_time_left, $this->_down_speed, $this->_downtotal);
- // check if client is still up once a minute
- if (($tick % 60) == 0) {
- if ($this->_clientIsRunning() === false) {
- $this->_outputMessage("wget-client not running, shutting down... (pid: ".$this->_pid.")\n");
- return false;
- }
- }
- // check buffer-size, truncate if needed
- if (strlen($this->_buffer) > 16384)
- $this->_buffer = substr($this->_buffer, -1024);
- // sleep 1 second and increment tick-count
- sleep(1);
- $tick++;
- if (($tick <= 0) || ($tick >= 2147483647)) $tick = 1;
- }
- // return
- return true;
- }
- /**
- * stop wrapper
- *
- * @param $error
- */
- function _wrapperStop($error = false) {
- // output
- $this->_outputMessage("wget-wrapper shutting down...\n");
- // stop client
- $this->_clientStop();
- // transfer settings
- stopTransferSettings($this->_transfer);
- // stat
- $this->_statShutdown($error);
- // pid
- $this->_pidFileDelete();
- // output
- $this->_outputMessage("wget-wrapper exit.\n");
- // exit
- exit();
- }
- /**
- * start client
- *
- * @return boolean
- */
- function _clientStart() {
- global $cfg;
- // print startup
- $this->_outputMessage("starting up wget-client...\n");
- // command-string
- $command = "cd ".tfb_shellencode($this->_path).";";
- $command .= " HOME=".tfb_shellencode($this->_path)."; export HOME;";
- if ($cfg["enable_umask"] != 0)
- $command .= " umask 0000;";
- if ($cfg["nice_adjust"] != 0)
- $command .= " nice -n ".$cfg["nice_adjust"];
- $command .= " ".$cfg['bin_wget'];
- $command .= " -c";
- if (($this->_drate != "") && ($this->_drate != "0"))
- $command .= " --limit-rate=" . $this->_drate;
- if ($this->_retries != "")
- $command .= " -t ".$this->_retries;
- if ($this->_pasv == 1)
- $command .= " --passive-ftp";
- $command .= " -i ".tfb_shellencode($cfg['transfer_file_path'].$this->_transfer);
- $command .= " 2>&1"; // direct STDERR to STDOUT
- $command .= " & echo $! > ".tfb_shellencode($cfg['transfer_file_path'].$this->_transfer.".pid"); // write pid-file
- // print startup
- $this->_outputMessage("executing command : \n".$command."\n", true);
- // start process
- $this->_wget = @popen($command, 'r');
- // wait for 0.5 seconds
- usleep(500000);
- // get + set pid
- $this->_pid = getTransferPid($this->_transfer);
- // check for error
- if (($this->_wget === false) || ($this->_clientIsRunning() === false)) {
- // error
- $this->_outputError("error starting up wget-client, shutting down...\n");
- // return
- return false;
- }
- // output
- $this->_outputMessage("wget-client started. (pid: ".$this->_pid.")\n");
- // return
- return true;
- }
- /**
- * stop client
- *
- * @return boolean
- */
- function _clientStop() {
- // close handle
- if ((!empty($this->_wget)) && (is_resource($this->_wget))) {
- $this->_outputMessage("closing process-handle...\n");
- @pclose($this->_wget);
- }
- // try to kill if running
- if ($this->_clientIsRunning()) {
- // send KILL ("nohup")
- $this->_outputMessage("sending KILL to wget-client... (pid: ".$this->_pid.")\n");
- posix_kill($this->_pid, SIGKILL);
- // wait for 0.25 seconds
- usleep(250000);
- // check if running
- if ($this->_clientIsRunning()) {
- // check if running
- if ($this->_clientIsRunning()) {
- $this->_outputMessage("wget-client still running 0.25 seconds after KILL. (pid: ".$this->_pid.")\n");
- return false;
- }
- }
- // output
- $this->_outputMessage("wget-client stopped. (pid: ".$this->_pid.")\n");
- } else {
- // client not running
- $this->_outputMessage("wget-client not running. (pid: ".$this->_pid.")\n");
- }
- // return
- return true;
- }
- /**
- * check if client-process is running
- *
- * @return boolean
- */
- function _clientIsRunning() {
- return (strpos(exec('ps -p '.tfb_shellencode($this->_pid)), $this->_pid) !== false);
- }
- /**
- * process header
- *
- * @return boolean
- */
- function _processHeader() {
- // output
- $this->_outputMessage("starting download...\n");
- // flush buffer
- $this->_buffer = "";
- // read until we find the Length-string which indicates dl-start
- $ctr = 0;
- while (($ctr < 64) && (!@feof($this->_wget))) {
- // read
- $this->_buffer .= @fread($this->_wget, 256);
- // check for error
- if (preg_match("/.*error.*/i", $this->_buffer)) {
- $this->_outputError("error in response.\n");
- // return
- return false;
- }
- // check for Length
- if (preg_match("/.*Length:\s(.+\d)\s(\[|\()/i", $this->_buffer, $matches)) {
- // set size
- $this->_size = str_replace(',','', $matches[1]);
- // set size in stat-file
- $this->_sf->size = $this->_size;
- // return
- return true;
- }
- // wait for 0.25 seconds
- usleep(250000);
- // increment counter
- $ctr++;
- }
- // there were problems
- $this->_outputMessage("problems when processing header...\n");
- // set size from sf
- $this->_outputMessage("try to set size from stat-file...\n");
- if (!empty($this->_sf->size)) {
- $this->_outputMessage("set size from stat-file :".formatBytesTokBMBGBTB($this->_sf->size)."\n");
- $this->_size = $this->_sf->size;
- // return
- return true;
- }
- // give up, then we got no size
- $this->_outputError("failed to get size for download.\n");
- // set size to 0
- $this->_size = 0;
- // set size in stat-file
- $this->_sf->size = $this->_size;
- // return
- return false;
- }
- /**
- * process buffer
- *
- * @return boolean
- */
- function _processBuffer() {
- // downtotal
- if (preg_match_all("/(\d*)K\s\./i", $this->_buffer, $matches, PREG_SET_ORDER))
- $this->_downtotal = $matches[count($matches) - 1][1] * 1024;
- // percent_done + down_speed + _speed
- if (preg_match_all("/(\d*)%(\s*)(.*)\/s/i", $this->_buffer, $matches, PREG_SET_ORDER)) {
- $matchIdx = count($matches) - 1;
- // percentage
- $this->_percent_done = $matches[$matchIdx][1];
- // speed
- $this->_down_speed = $matches[$matchIdx][3]."/s";
- // we dont want upper-case k
- $this->_down_speed = str_replace("KB/s", "kB/s", $this->_down_speed);
- // size as int + convert MB/s
- $sizeTemp = substr($this->_down_speed, 0, -5);
- if (is_numeric($sizeTemp)) {
- $this->_speed = intval($sizeTemp);
- if (substr($this->_down_speed, -4) == "MB/s") {
- $this->_speed = $this->_speed * 1024;
- $this->_down_speed = $this->_speed." kB/s";
- }
- } else {
- $this->_speed = 0;
- $this->_down_speed = "0.00 kB/s";
- }
- }
- // time left
- $this->_time_left = (($this->_size > 0) && ($this->_speed > 0))
- ? convertTime((($this->_size - $this->_downtotal) / 1024) / $this->_speed)
- : '-';
- // download done
- if (preg_match("/.*saved\s\[.*/", $this->_buffer)) {
- $this->_outputMessage("download complete. initializing shutdown...\n");
- // return
- return true;
- }
- // return
- return false;
- }
- /**
- * process command stack
- *
- * @return boolean
- */
- function _processCommandStack() {
- // check for command-file
- if (@is_file($this->_commandFile)) {
- // print
- $this->_outputMessage("processing command-file ".$this->_commandFile."...\n");
- // read command-file
- $data = @file_get_contents($this->_commandFile);
- // delete command-file
- @unlink($this->_commandFile);
- // process content
- $commands = @explode("\n", $data);
- if ((is_array($commands)) && (count($commands > 0))) {
- foreach ($commands as $command) {
- // exec, early out when reading a quit-command
- $command = str_replace("\n", "", $command);
- $command = trim($command);
- if ($this->_execCommand($command)) {
- // return
- return true;
- }
- }
- } else {
- // no commands found
- $this->_outputMessage("No commands found.\n");
- }
- }
- // return
- return false;
- }
- /**
- * exec a command
- *
- * @param $command
- * @return boolean
- */
- function _execCommand($command) {
- // parse command-string
- $len = strlen($command);
- if ($len < 1)
- return false;
- $opcode = $command{0};
- $workload = ($len > 1)
- ? substr($command, 1)
- : "";
- // opcode-switch
- switch ($opcode) {
- // q
- case 'q':
- $this->_outputMessage("command: stop-request, initializing shutdown...\n");
- return true;
- // default
- default:
- $this->_outputMessage("op-code unknown: ".$opcode."\n");
- return false;
- }
- }
- /**
- * stat-file at startup
- *
- * @return boolean
- */
- function _statStartup() {
- // set some values
- $this->_sf->running = 1;
- $this->_sf->percent_done = 0;
- $this->_sf->time_left = "Starting...";
- $this->_sf->down_speed = "0.00 kB/s";
- $this->_sf->up_speed = "0.00 kB/s";
- $this->_sf->transferowner = $this->_owner;
- $this->_sf->seeds = 1;
- $this->_sf->peers = 1;
- $this->_sf->sharing = "";
- $this->_sf->seedlimit = "";
- $this->_sf->uptotal = 0;
- $this->_sf->downtotal = 0;
- // write
- return $this->_sf->write();
- }
- /**
- * stat-file while running
- *
- * @param $percent_done
- * @param $time_left
- * @param $down_speed
- * @param $downtotal
- * @return boolean
- */
- function _statRunning($percent_done, $time_left, $down_speed, $downtotal) {
- // set some values
- $this->_sf->percent_done = $percent_done;
- $this->_sf->time_left = $time_left;
- $this->_sf->down_speed = $down_speed;
- $this->_sf->downtotal = $downtotal;
- // write
- return $this->_sf->write();
- }
- /**
- * stat-file at shutdown
- *
- * @param $error
- * @return boolean
- */
- function _statShutdown($error = false) {
- // set some values
- $this->_sf->running = 0;
- if ($this->_done) {
- $this->_sf->percent_done = 100;
- $this->_sf->time_left = "Download Succeeded!";
- } else {
- $this->_sf->percent_done = ($this->_size > 0)
- ? (((intval((100.0 * $this->_downtotal / $this->_size))) + 100) * (-1))
- : "-100";
- $this->_sf->time_left = "Transfer Stopped";
- }
- if ($error)
- $this->_sf->time_left = "Error";
- $this->_sf->down_speed = "";
- $this->_sf->up_speed = "";
- $this->_sf->transferowner = $this->_owner;
- $this->_sf->seeds = "";
- $this->_sf->peers = "";
- $this->_sf->sharing = "";
- $this->_sf->seedlimit = "";
- $this->_sf->uptotal = 0;
- $this->_sf->downtotal = $this->_downtotal;
- // write
- return $this->_sf->write();
- }
- /**
- * delete the pid-file
- */
- function _pidFileDelete() {
- global $cfg;
- if (@file_exists($cfg['transfer_file_path'].$this->_transfer.".pid")) {
- $this->_outputMessage("removing pid-file : ".$cfg['transfer_file_path'].$this->_transfer.".pid\n");
- @unlink($cfg['transfer_file_path'].$this->_transfer.".pid");
- }
- }
- /**
- * signal-handler
- *
- * @param $signal
- */
- function _sigHandler($signal) {
- switch ($signal) {
- // HUP
- case SIGHUP:
- $this->_outputMessage("got SIGHUP, ignoring...\n");
- break;
- // INT
- case SIGINT:
- $this->_outputMessage("got SIGINT, shutting down...\n");
- $this->_wrapperStop(false);
- break;
- // TERM
- case SIGTERM:
- $this->_outputMessage("got SIGTERM, shutting down...\n");
- $this->_wrapperStop(false);
- break;
- // QUIT
- case SIGQUIT:
- $this->_outputMessage("got SIGQUIT, shutting down...\n");
- $this->_wrapperStop(false);
- break;
- }
- }
- /**
- * output message
- *
- * @param $message
- */
- function _outputMessage($message) {
- @fwrite(STDOUT, @date("[Y/m/d - H:i:s]")." ".$message);
- }
- /**
- * output error
- *
- * @param $message
- */
- function _outputError($message) {
- @fwrite(STDERR, @date("[Y/m/d - H:i:s]")." ".$message);
- }
- }
- ?>
|