_action : ""; } /** * getArgs * * @return array */ function getArgs() { global $instanceFluxCLI; return (isset($instanceFluxCLI)) ? $instanceFluxCLI->_args : array(); } /** * process a request * * @param $args * @return mixed */ function processRequest($args) { global $instanceFluxCLI; // create new instance $instanceFluxCLI = new FluxCLI($args); // call instance-method return (!$instanceFluxCLI) ? false : $instanceFluxCLI->instance_processRequest(); } // ========================================================================= // ctor // ========================================================================= /** * do not use direct, use the public static methods ! * * @param $args * @return FluxCLI */ function FluxCLI($args) { global $cfg; // set user-var $cfg["user"] = GetSuperAdmin(); // set admin-var $cfg['isAdmin'] = true; // set user-agent $cfg['user_agent'] = $this->name."/" . _REVISION_FLUXCLI; $_SERVER['HTTP_USER_AGENT'] = $this->name."/" . _REVISION_FLUXCLI; // parse args and set fields $argCount = count($args); if ($argCount < 1) { // invalid args $this->_outputError("invalid args.\n"); return false; } $this->_script = basename($args[0]); $this->_action = (isset($args[1])) ? $args[1] : ""; if ($argCount > 2) { $prm = array_splice($args, 2); $this->_args = array_map('trim', $prm); $this->_argc = count($this->_args); } else { $this->_args = array(); $this->_argc = 0; } } // ========================================================================= // public methods // ========================================================================= /** * process a request * * @return mixed */ function instance_processRequest() { global $cfg; // action-switch switch ($this->_action) { /* netstat */ case "netstat": return $this->_netstat(); /* transfers */ case "transfers": return $this->_transfers(); /* start */ case "start": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferStart( $this->_args[0], (isset($this->_args[1])) ? $this->_args[1] : "", ($this->_argc > 2) ? array_slice($this->_args, 2) : array() ); } /* stop */ case "stop": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferStop($this->_args[0]); } /* enqueue */ case "enqueue": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferEnqueue($this->_args[0]); } /* dequeue */ case "dequeue": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferDequeue($this->_args[0]); } /* reset */ case "reset": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferReset($this->_args[0]); } /* delete */ case "delete": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferDelete($this->_args[0]); } /* wipe */ case "wipe": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: name of transfer. (extra-arg 1)"); break; } else { return $this->_transferWipe($this->_args[0]); } /* start-all */ case "start-all": return $this->_transfersStart( (isset($this->_args[0])) ? $this->_args[0] : "", ($this->_argc > 1) ? array_slice($this->_args, 1) : array() ); /* resume-all */ case "resume-all": return $this->_transfersResume( (isset($this->_args[0])) ? $this->_args[0] : "", ($this->_argc > 1) ? array_slice($this->_args, 1) : array() ); /* stop-all */ case "stop-all": return $this->_transfersStop(); /* tset */ case "tset": if ($this->_argc < 3) { array_push($this->_argErrors, "missing argument(s) for tset."); break; } else { return $this->_tset( $this->_args[0], $this->_args[1], $this->_args[2], (isset($this->_args[3])) ? $this->_args[3] : "s" ); } /* inject */ case "inject": if ($this->_argc < 2) { array_push($this->_argErrors, "missing argument(s) for inject."); break; } else { return $this->_inject( $this->_args[0], $this->_args[1], (isset($this->_args[2])) ? $this->_args[2] : "", ($this->_argc > 3) ? array_slice($this->_args, 3) : array() ); } /* watch */ case "watch": if ($this->_argc < 2) { array_push($this->_argErrors, "missing argument(s) for watch."); break; } else { return $this->_watch( $this->_args[0], $this->_args[1], (isset($this->_args[2])) ? $this->_args[2] : "ds", ($this->_argc > 3) ? array_slice($this->_args, 3) : array() ); } /* rss */ case "rss": if ($this->_argc < 4) { array_push($this->_argErrors, "missing argument(s) for rss."); break; } else { return $this->_rss( $this->_args[0], $this->_args[1], $this->_args[2], $this->_args[3], (isset($this->_args[4])) ? $this->_args[4] : "" ); } /* xfer */ case "xfer": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: time-delta of xfer to use : (all/total/month/week/day) (extra-arg 1)"); break; } else { return $this->_xfer($this->_args[0]); } /* repair */ case "repair": return $this->_repair(); /* maintenance */ case "maintenance": return $this->_maintenance(((isset($this->_args[0])) && (strtolower($this->_args[0]) == "true")) ? true : false); /* dump */ case "dump": if (empty($this->_args[0])) { array_push($this->_argErrors, "missing argument: type. (settings/users) (extra-arg 1)"); break; } else { return $this->_dump($this->_args[0]); } /* filelist */ case "filelist": printFileList((empty($this->_args[0])) ? $cfg['docroot'] : $this->_args[0], 1, 1); return true; /* checksums */ case "checksums": printFileList((empty($this->_args[0])) ? $cfg['docroot'] : $this->_args[0], 2, 1); return true; /* version */ case "version": case "-version": case "--version": case "-v": return $this->_printVersion(); /* help */ case "help": case "-help": case "--help": case "-h": default: return $this->_printUsage(); } // help return $this->_printUsage(); } // ========================================================================= // private methods -- options parsing helpers // ========================================================================= /** * Parse a list of options, with optional extra-args. * Returns false in case of error, e.g. missing extra-arg * (error already reported via $this->_outputError). * * Example: * _parseOptions( * array( // $desc: array of possible options with number of extra-args. * 'd' => 0, // Options 'd' and 's' take no extra-arg. * 's' => 0, * 'p' => 1, // Option 'p' takes one extra-arg. * 'x' => 2 // Option 'x' takes two extra-args. * ), * 'spx', // $options * array('profname', 'x1', 'x2') // $extra * ) === array( * 's' => array(), // Option 's' was found, no extra-arg. * 'p' => array('profname'), // Option 'p' was found, its extra-arg's value was 'profname'. * 'x' => array('x1', 'x2') // Option 'x' was found, its extra-args' values were 'x1' and 'x2'. * ) * * @param array $desc * @param string $options * @param array $extra * @return array */ function _parseOptions($desc, $options = '', $extra = array()) { $return = array(); // This preg_split merely does a str_split, but works on PHP4. foreach (preg_split('/(?<=.)(?=.)/s', $options) as $option) { // Unknown option, ignore it. if (!array_key_exists($option, $desc)) continue; $needed = $desc[$option]; $found = array(); // Option needs at least one extra-arg, ensure there are enough and load it/them. if ($needed > 0) { if (!is_array($extra) || count($extra) < $needed) { $this->_outputError("missing extra argument(s) for option '".$option."'.\n"); return false; } for ($i = 0; $i < $needed; $i++) array_push($found, array_shift($extra)); } $return[$option] = $found; } return $return; } /** * Build a list of options for a new function call, by passing * thru some options from the current call (works on an options * set, returned previously by $this->_parseOptions). * * Example: * _buildOptions( * 'spx', // $options: list of options to pass-thru * array( // $optionsSet: options of current call * 'd' => array(), * 's' => array(), * 'x' => array('x1', 'x2'), * 'p' => array('profname') * ) * ) === array( * 'sxp', // $options for new call // The three options 's', 'p' and 'x' are * array('x1', 'x2', 'profname') // $extra for new call // forwarded, with their extra-args. * ) * * @param string $options * @param array $optionsSet * @return array */ function _buildOptions($options, $optionsSet) { $returnOptions = ''; $returnExtra = array(); // Iterate on current call's options. foreach ($optionsSet as $option => $extra) { // If this option should be passed thru to next call, add it. if (strpos($options, $option) !== false) { $returnOptions .= $option; $returnExtra = array_merge($returnExtra, $extra); } } return array($returnOptions, $returnExtra); } // ========================================================================= // private methods // ========================================================================= /** * Print Net Stat * * @return mixed */ function _netstat() { global $cfg; echo $cfg['_ID_CONNECTIONS'].":\n"; echo netstatConnectionsSum()."\n"; echo $cfg['_ID_PORTS'].":\n"; echo netstatPortList(); echo $cfg['_ID_HOSTS'].":\n"; echo netstatHostList(); return true; } /** * Show Transfers * * @return mixed */ function _transfers() { global $cfg; // print out transfers echo "Transfers:\n"; $transferHeads = getTransferListHeadArray(); echo "* Name * ".implode(" * ", $transferHeads)."\n"; $transferList = getTransferListArray(); foreach ($transferList as $transferAry) echo "- ".implode(" - ", $transferAry)."\n"; // print out stats echo "Server:\n"; if (! array_key_exists("total_download", $cfg)) $cfg["total_download"] = 0; if (! array_key_exists("total_upload", $cfg)) $cfg["total_upload"] = 0; echo $cfg['_UPLOADSPEED']."\t".': '.number_format($cfg["total_upload"], 2).' kB/s'."\n"; echo $cfg['_DOWNLOADSPEED']."\t".': '.number_format($cfg["total_download"], 2).' kB/s'."\n"; echo $cfg['_TOTALSPEED']."\t".': '.number_format($cfg["total_download"]+$cfg["total_upload"], 2).' kB/s'."\n"; echo $cfg['_ID_CONNECTIONS']."\t".': '.netstatConnectionsSum()."\n"; return true; } /** * Start Transfer * * @param $transfer * @param $options * @param array $extra * @return mixed */ function _transferStart($transfer, $options = '', $extra = array()) { global $cfg; // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } // check running if (isTransferRunning($transfer)) { $this->_outputError("transfer already running.\n"); return false; } // parse options $optionsSet = $this->_parseOptions( array( 'p' => 1 ), // Only recognized option is 'p'. $options, $extra ); if ($optionsSet === false) return false; $profile = isset($optionsSet['p']) ? $optionsSet['p'][0] : null; // set user $cfg["user"] = getOwner($transfer); // output $this->_outputMessage( "Starting ".$transfer." for user ".$cfg["user"]. (!empty($profile) ? " using profile ".$profile : ''). " ...\n" ); $ch = ClientHandler::getInstance(getTransferClient($transfer)); // load and apply profile, if specified (just ignore // it if profiles are disabled, no error) if ($cfg['transfer_profiles'] >= 1 && !empty($profile)) { $ch->settingsDefault($transfer); $settings = GetProfileSettings($profile); if (empty($settings) || $settings === false) { $this->_outputError("profilename ".$profile." is no valid profile.\n"); return false; } $ch->rate = $settings['rate']; $ch->drate = $settings['drate']; $ch->maxuploads = $settings['maxuploads']; $ch->superseeder = $settings['superseeder']; $ch->runtime = $settings['runtime']; $ch->sharekill = $settings['sharekill']; $ch->minport = $settings['minport']; $ch->maxport = $settings['maxport']; $ch->maxcons = $settings['maxcons']; $ch->rerequest = $settings['rerequest']; $ch->settingsSave(); } // force start, don't queue $ch->start($transfer, false, false); if ($ch->state == CLIENTHANDLER_STATE_OK) { /* hooray */ $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("failed: ".implode("\n", $ch->messages)."\n"); return false; } } /** * Stop Transfer * * @param $transfer * @return mixed */ function _transferStop($transfer) { global $cfg; // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } // check running if (!isTransferRunning($transfer)) { $this->_outputError("transfer not running.\n"); return false; } // set user $cfg["user"] = getOwner($transfer); // output $this->_outputMessage("Stopping ".$transfer." for user ".$cfg["user"]."...\n"); // stop $ch = ClientHandler::getInstance(getTransferClient($transfer)); $ch->stop($transfer); $this->_outputMessage("done.\n"); return true; } /** * Enqueue Transfer * * @param $transfer * @return mixed */ function _transferEnqueue($transfer) { global $cfg; // initialize service-mod (why here ? see "fluxd-single-thread-problem") FluxdServiceMod::initializeServiceMod('Qmgr'); // check queue if (!FluxdQmgr::isRunning()) { $this->_outputError("Qmgr is not running.\n"); return false; } // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } // check running if (isTransferRunning($transfer)) { $this->_outputError("transfer already running.\n"); return false; } // set user $cfg["user"] = getOwner($transfer); // output $this->_outputMessage("Enqueue ".$transfer." for user ".$cfg["user"]."...\n"); // force start, don't queue $ch = ClientHandler::getInstance(getTransferClient($transfer)); $ch->start($transfer, false, true); if ($ch->state == CLIENTHANDLER_STATE_OK) { /* hooray */ $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("failed: ".implode("\n", $ch->messages)."\n"); return false; } } /** * Dequeue Transfer * * @param $transfer * @return mixed */ function _transferDequeue($transfer) { global $cfg; // initialize service-mod (why here ? see "fluxd-single-thread-problem") FluxdServiceMod::initializeServiceMod('Qmgr'); // check queue if (!FluxdQmgr::isRunning()) { $this->_outputError("Qmgr is not running.\n"); return false; } // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } // set user $cfg["user"] = getOwner($transfer); // output $this->_outputMessage("Dequeue ".$transfer." for user ".$cfg["user"]."...\n"); // dequeue FluxdQmgr::dequeueTransfer($transfer, $cfg["user"]); $this->_outputMessage("done.\n"); return true; } /** * Reset Transfer * * @param $transfer * @return mixed */ function _transferReset($transfer) { $this->_outputMessage("Resetting totals of ".$transfer." ...\n"); $msgs = resetTransferTotals($transfer, false); if (count($msgs) == 0) { $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("failed: ".implode("\n", $msgs)."\n"); return false; } } /** * Delete Transfer * * @param $transfer * @return mixed */ function _transferDelete($transfer) { global $cfg; // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } $this->_outputMessage("Delete ".$transfer." ...\n"); // set user $cfg["user"] = getOwner($transfer); // delete $ch = ClientHandler::getInstance(getTransferClient($transfer)); $tRunningFlag = isTransferRunning($transfer); if ($tRunningFlag) { // stop transfer first $this->_outputMessage("transfer is running, stopping first...\n"); $ch->stop($transfer); $tRunningFlag = isTransferRunning($transfer); } if (!$tRunningFlag) { $this->_outputMessage("Deleting...\n"); $ch->delete($transfer); $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("transfer still up... cannot delete\n"); return false; } } /** * Wipe Transfer * * @param $transfer * @return mixed */ function _transferWipe($transfer) { global $cfg; // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } $this->_outputMessage("Wipe ".$transfer." ...\n"); // set user $cfg["user"] = getOwner($transfer); // wipe $ch = ClientHandler::getInstance(getTransferClient($transfer)); $tRunningFlag = isTransferRunning($transfer); if ($tRunningFlag) { // stop transfer first $this->_outputMessage("transfer is running, stopping first...\n"); $ch->stop($transfer); $tRunningFlag = isTransferRunning($transfer); } if (!$tRunningFlag) { $this->_outputMessage("Deleting...\n"); $msgsDelete = deleteTransferData($transfer); $countDelete = count($msgsDelete); $msgsReset = resetTransferTotals($transfer, true); $countReset = count($msgsReset); if (($countDelete + $countReset) == 0) { $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("there were problems: " .(($countDelete > 0) ? implode("\n", $msgsDelete)."\n" : "") .(($countReset > 0) ? implode("\n", $msgsReset) : "") ."\n" ); return false; } } else { $this->_outputError("transfer still up... cannot delete\n"); return false; } } /** * Start Transfers * * @param $options * @param array $extra * @return mixed */ function _transfersStart($options = '', $extra = array()) { // parse options $optionsSet = $this->_parseOptions( array( 'p' => 1 ), // Only recognized option is 'p'. $options, $extra ); if ($optionsSet === false) return false; $profile = isset($optionsSet['p']) ? $optionsSet['p'][0] : null; $this->_outputMessage( "Starting all transfers". (!empty($profile) ? " using profile ".$profile : ''). " ...\n" ); // build args for _transferStart $newOptions = $this->_buildOptions('p', $optionsSet); // Pass-thru option 'p'. $transferList = getTransferArray(); foreach ($transferList as $transfer) { if (!isTransferRunning($transfer)) $this->_transferStart($transfer, $newOptions[0], $newOptions[1]); } } /** * Resume Transfers * * @param $options * @param array $extra * @return mixed */ function _transfersResume($options = '', $extra = array()) { // parse options $optionsSet = $this->_parseOptions( array( 'p' => 1 ), // Only recognized option is 'p'. $options, $extra ); if ($optionsSet === false) return false; $profile = isset($optionsSet['p']) ? $optionsSet['p'][0] : null; $this->_outputMessage( "Resuming all transfers". (!empty($profile) ? " using profile ".$profile : ''). " ...\n" ); // build args for _transferStart $newOptions = $this->_buildOptions('p', $optionsSet); // Pass-thru option 'p'. $transferList = getTransferArray(); $sf = new StatFile(""); foreach ($transferList as $transfer) { $sf->init($transfer); if (trim($sf->running) == 0) $this->_transferStart($transfer, $newOptions[0], $newOptions[1]); } } /** * Stop Transfers * * @return mixed */ function _transfersStop() { $this->_outputMessage("Stopping all transfers ...\n"); $transferList = getTransferArray(); foreach ($transferList as $transfer) { if (isTransferRunning($transfer)) $this->_transferStop($transfer); } } /** * set transfer setting * * @param $transfer * @param $key * @param $val * @param $options * @return mixed */ function _tset($transfer, $key, $val, $options) { global $cfg; // check transfer if (!transferExists($transfer)) { $this->_outputError("transfer does not exist.\n"); return false; } // check params $settingsKeys = array( 'uprate' => 'NUMBER', 'downrate' => 'NUMBER', 'completion' => 'BOOL', 'sharekill' => 'NUMBER' ); if (!array_key_exists($key, $settingsKeys)) { $this->_outputError("invalid settings-key: ".$key."\n"); return false; } if (strlen($val) < 1) { $this->_outputError("value for ".$key." invalid.\n"); return false; } switch ($settingsKeys[$key]) { case 'NUMBER': if (!preg_match('/^[0-9\-]+$/D', $val)) { $this->_outputError("value for ".$key." must be a number: ".$val."\n"); return false; } break; case 'BOOL': $val = strtolower($val); if (($val != 'true') && ($val != 'false')) { $this->_outputError("value for ".$key." must be true or false: ".$val."\n"); return false; } break; } // set user $cfg["user"] = getOwner($transfer); // output $this->_outputMessage("Setting ".$key." to ".$val." for ".$transfer." for user ".$cfg["user"]."...\n"); // init ch-instance $ch = ClientHandler::getInstance(getTransferClient($transfer)); // load settings, default if settings could not be loaded (fresh transfer) if ($ch->settingsLoad($transfer) !== true) $ch->settingsDefault(); // autosend $send = ((strpos($options, 's') !== false) && (isTransferRunning($transfer))); // set setting switch ($key) { case 'uprate': if ($ch->rate != $val) { $ch->setRateUpload($transfer, $val, $send); break; } else { $this->_outputMessage("no changes.\n"); return false; } case 'downrate': if ($ch->drate != $val) { $ch->setRateDownload($transfer, $val, $send); break; } else { $this->_outputMessage("no changes.\n"); return false; } case 'completion': if (strtolower($ch->runtime) != $val) { $ch->setRuntime($transfer, ($val == 'true') ? 'True' : 'False', $send); break; } else { $this->_outputMessage("no changes.\n"); return false; } case 'sharekill': if ($ch->sharekill != $val) { $ch->setSharekill($transfer, $val, $send); break; } else { $this->_outputMessage("no changes.\n"); return false; } } // save $ch->settingsSave(); // output + return if ($send) $this->_outputMessage("settings saved + changes sent to client.\n"); else $this->_outputMessage("settings saved.\n"); return true; } /** * Inject Transfer * * @param $transferFile * @param $username * @param $options * @param array $extra * @return mixed */ function _inject($transferFile, $username, $options = '', $extra = array()) { global $cfg; // check file if (!@is_file($transferFile)) { $this->_outputError("transfer-file ".$transferFile." is no file.\n"); return false; } // check username if (!IsUser($username)) { $this->_outputError("username ".$username." is no valid user.\n"); return false; } // parse options $optionsSet = $this->_parseOptions( array( 'd' => 0, 's' => 0, 'p' => 1 ), // Recognized options are 'd', 's' and 'p'. $options, $extra ); if ($optionsSet === false) return false; $profile = isset($optionsSet['p']) ? $optionsSet['p'][0] : null; $this->_outputMessage( "Inject ".$transferFile." for user ".$username. (!empty($profile) ? " using profile ".$profile : ''). " ...\n" ); // set user $cfg["user"] = $username; // set filename $transfer = basename($transferFile); $transfer = tfb_cleanFileName($transfer); // only inject valid transfers $msgs = array(); if ($transfer !== false) { $targetFile = $cfg["transfer_file_path"].$transfer; if (@is_file($targetFile)) { array_push($msgs, "transfer ".$transfer.", already exists."); } else { $this->_outputMessage("copy ".$transferFile." to ".$targetFile." ...\n"); if (@copy($transferFile, $targetFile)) { // chmod @chmod($cfg["transfer_file_path"].$transfer, 0644); // make owner entry AuditAction($cfg["constants"]["file_upload"], $transfer); // inject $this->_outputMessage("injecting ".$transfer." ...\n"); injectTransfer($transfer); // delete source-file if (isset($optionsSet['d'])) { $this->_outputMessage("deleting source-file ".$transferFile." ...\n"); @unlink($transferFile); } // start if (isset($optionsSet['s'])) { // build args for _transferStart $newOptions = $this->_buildOptions('p', $optionsSet); // Pass-thru option 'p'. return $this->_transferStart($transfer, $newOptions[0], $newOptions[1]); } // return else return true; } else { array_push($msgs, "File could not be copied: ".$transferFile); } } } else { array_push($msgs, "The type of file you are injecting is not allowed."); array_push($msgs, "valid file-extensions: "); array_push($msgs, $cfg["file_types_label"]); } if (count($msgs) == 0) { $this->_outputMessage("done.\n"); return true; } else { $this->_outputError("failed: ".implode("\n", $msgs)."\n"); return false; } } /** * Watch Dir * * @param $watchDir * @param $username * @param $options * @param array $extra * @return mixed */ function _watch($watchDir, $username, $options = '', $extra = array()) { global $cfg; // check dir if (!@is_dir($watchDir)) { $this->_outputError("watch-dir ".$watchDir." is no dir.\n"); return false; } // check username if (!IsUser($username)) { $this->_outputError("username ".$username." is no valid user.\n"); return false; } // parse options $optionsSet = $this->_parseOptions( array( 'd' => 0, 's' => 0, 'p' => 1 ), // Recognized options are 'd', 's' and 'p'. $options, $extra ); if ($optionsSet === false) return false; $profile = isset($optionsSet['p']) ? $optionsSet['p'][0] : null; $this->_outputMessage( "Processing watch-dir ".$watchDir." for user ".$username. (!empty($profile) ? " using profile ".$profile : ''). " ...\n" ); // process dir if ($dirHandle = @opendir($watchDir)) { // get input-files $input = array(); while (false !== ($file = @readdir($dirHandle))) if (@is_file($watchDir.$file)) array_push($input, $file); @closedir($dirHandle); if (empty($input)) { $this->_outputMessage("done. no files found.\n"); return true; } // trailing slash $watchDir = checkDirPathString($watchDir); // build args for _inject $newOptions = $this->_buildOptions('dsp', $optionsSet); // Pass-thru options 'd', 's' and 'p'. // process input-files $ctr = array('files' => count($input), 'ok' => 0); foreach ($input as $transfer) { // inject, increment if ok if ($this->_inject($watchDir.$transfer, $username, $newOptions[0], $newOptions[1]) !== false) $ctr['ok']++; } if ($ctr['files'] == $ctr['ok']) { $this->_outputMessage("done. files: ".$ctr['files']."; ok: ".$ctr['ok']."\n"); return true; } else { $this->_outputError("done with errors. files: ".$ctr['files']."; ok: ".$ctr['ok']."\n"); return false; } } else { $this->_outputError("failed to open watch-dir ".$watchDir.".\n"); return false; } } /** * Xfer Shutdown * * @param $delta * @return mixed */ function _xfer($delta) { global $cfg, $db; // check xfer if ($cfg['enable_xfer'] != 1) { $this->_outputError("xfer must be enabled.\n"); return false; } // check arg if (($delta != "all") && ($delta != "total") && ($delta != "month") && ($delta != "week") && ($delta != "day")) { $this->_outputMessage('invalid delta : "'.$delta.'"'."\n"); return false; } $this->_outputMessage('checking xfer-limit(s) for "'.$delta.'" ...'."\n"); // set xfer-realtime $cfg['xfer_realtime'] = 1; // set xfer-newday Xfer::setNewday(); // getTransferListArray to update xfer-stats $transferList = @getTransferListArray(); // get xfer-totals $xfer_total = Xfer::getStatsTotal(); // check if break needed // total if (($delta == "total") || ($delta == "all")) { // only do if a limit is set if ($cfg["xfer_total"] > 0) { if ($xfer_total['total']['total'] >= $cfg["xfer_total"] * 1048576) { // limit met, stop all Transfers now. $this->_outputMessage('Limit met for "total" : '.formatFreeSpace($xfer_total['total']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_total"])."\n"); return $this->_transfersStop(); } else { $this->_outputMessage('Limit not met for "total" : '.formatFreeSpace($xfer_total['total']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_total"])."\n"); } } else { $this->_outputMessage('no limit set for "total"'."\n"); } } // month if (($delta == "month") || ($delta == "all")) { // only do if a limit is set if ($cfg["xfer_month"] > 0) { if ($xfer_total['month']['total'] >= $cfg["xfer_month"] * 1048576) { // limit met, stop all Transfers now. $this->_outputMessage('Limit met for "month" : '.formatFreeSpace($xfer_total['month']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_month"])."\n"); return $this->_transfersStop(); } else { $this->_outputMessage('Limit not met for "month" : '.formatFreeSpace($xfer_total['month']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_month"])."\n"); } } else { $this->_outputMessage('no limit set for "month"'."\n"); } } // week if (($delta == "week") || ($delta == "all")) { // only do if a limit is set if ($cfg["xfer_week"] > 0) { if ($xfer_total['week']['total'] >= $cfg["xfer_week"] * 1048576) { // limit met, stop all Transfers now. $this->_outputMessage('Limit met for "week" : '.formatFreeSpace($xfer_total['week']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_week"])."\n"); return $this->_transfersStop(); } else { $this->_outputMessage('Limit not met for "week" : '.formatFreeSpace($xfer_total['week']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_week"])."\n"); } } else { $this->_outputMessage('no limit set for "week"'."\n"); } } // day if (($delta == "day") || ($delta == "all")) { // only do if a limit is set if ($cfg["xfer_day"] > 0) { if ($xfer_total['day']['total'] >= $cfg["xfer_day"] * 1048576) { // limit met, stop all Transfers now. $this->_outputMessage('Limit met for "day" : '.formatFreeSpace($xfer_total['day']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_day"])."\n"); return $this->_transfersStop(); } else { $this->_outputMessage('Limit not met for "day" : '.formatFreeSpace($xfer_total['day']['total'] / (1048576))." / ".formatFreeSpace($cfg["xfer_day"])."\n"); } } else { $this->_outputMessage('no limit set for "day"'."\n"); } } // done $this->_outputMessage("done.\n"); return true; } /** * rss download * * @param $saveDir * @param $filterFile * @param $historyFile * @param $url * @param $username * @return mixed */ function _rss($saveDir, $filterFile, $historyFile, $url, $username = "") { global $cfg; // set user if (!empty($username)) { // check first if (IsUser($username)) { $cfg["user"] = $username; } else { $this->_outputError("username ".$username." is no valid user.\n"); return false; } } // process Feed require_once("inc/classes/Rssd.php"); return Rssd::processFeed($saveDir, $filterFile, $historyFile, $url); } /** * Repair * * @return mixed */ function _repair() { require_once("inc/classes/MaintenanceAndRepair.php"); MaintenanceAndRepair::repair(); return true; } /** * Maintenance * * @param $trestart * @return mixed */ function _maintenance($trestart) { // initialize service-mod (why here ? see "fluxd-single-thread-problem") FluxdServiceMod::initializeServiceMod('Qmgr'); require_once("inc/classes/MaintenanceAndRepair.php"); MaintenanceAndRepair::maintenance( $trestart ? MAINTENANCEANDREPAIR_TYPE_EXT : MAINTENANCEANDREPAIR_TYPE_STD); return true; } /** * Dump Database * * @param $type * @return mixed */ function _dump($type) { global $cfg, $db; switch ($type) { case "settings": $sql = "SELECT tf_key, tf_value FROM tf_settings"; break; case "users": $sql = "SELECT uid, user_id FROM tf_users"; break; default: $this->_outputError("invalid type : ".$type."\n"); return false; } $recordset = $db->Execute($sql); if ($db->ErrorNo() != 0) dbError($sql); $content = ""; while (list($a, $b) = $recordset->FetchRow()) $content .= $a._DUMP_DELIM.$b."\n"; echo $content; return ($content != ""); } /** * output message * * @param $message */ function _outputMessage($message) { printMessage($this->name, $message); } /** * output error * * @param $message */ function _outputError($message) { printError($this->name, $message); } /** * prints version * * @return mixed */ function _printVersion() { echo $this->name." Revision "._REVISION_FLUXCLI."\n"; return (_REVISION_FLUXCLI > 0); } /** * prints usage * * @return mixed */ function _printUsage() { $this->_printVersion(); echo "\n" . "Usage: ".$this->_script." action [extra-args]\n" . "\n" . "action: \n" . " transfers : show transfers.\n" . " netstat : show netstat.\n" . " start : start a transfer.\n" . " extra-arg 1 : name of transfer as known inside webapp\n" . " extra-arg 2 : options (p) (optional, default: none)\n" . " options-arg contains 'p' : use transfer-profile\n" . " extra-arg 3 : transfer-profile name (optional, default: none)\n" . " stop : stop a transfer.\n" . " extra-arg : name of transfer as known inside webapp\n" . " reset : reset totals of a transfer.\n" . " extra-arg : name of transfer as known inside webapp\n" . " delete : delete a transfer.\n" . " extra-arg : name of transfer as known inside webapp\n" . " wipe : reset totals, delete metafile, delete data.\n" . " extra-arg : name of transfer as known inside webapp\n" . " enqueue : enqueue a transfer.\n" . " extra-arg : name of transfer as known inside webapp\n" . " dequeue : dequeue a transfer.\n" . " extra-arg : name of transfer as known inside webapp\n" . " start-all : start all transfers.\n" . " extra-arg 1 : options (p) (optional, default: none)\n" . " options-arg contains 'p' : use transfer-profile\n" . " extra-arg 2 : transfer-profile name (optional, default: none)\n" . " resume-all : resume all transfers.\n" . " extra-arg 1 : options (p) (optional, default: none)\n" . " options-arg contains 'p' : use transfer-profile\n" . " extra-arg 2 : transfer-profile name (optional, default: none)\n" . " stop-all : stop all running transfers.\n" . " tset : set a transfer-setting.\n" . " extra-arg 1 : name of transfer as known inside webapp\n" . " extra-arg 2 : settings-key\n" . " extra-arg 3 : settings-value\n" . " extra-arg 4 : options (optional, default: s)\n" . " options-arg contains 's' : send changes to running client\n" . " valid settings :\n" . " uprate ; value: uprate in kB/s ; options: s\n" . " downrate ; value: downrate in kB/s ; options: s\n" . " completion ; value: true/false ; options: s\n" . " sharekill ; value: seed-percentage ; options: s\n" . " inject : injects (+ starts) a transfer.\n" . " extra-arg 1 : path to transfer-meta-file\n" . " extra-arg 2 : username of fluxuser\n" . " extra-arg 3 : options (d/s/p) (optional, default: none)\n" . " options-arg contains 'd' : delete source-file after inject\n" . " options-arg contains 's' : start transfer after inject\n" . " options-arg contains 'p' : use transfer-profile\n" . " extra-arg 4 : transfer-profile name (optional, default: none)\n" . " watch : watch a dir and inject (+ start) transfers.\n" . " extra-arg 1 : watch-dir\n" . " extra-arg 2 : username of fluxuser\n" . " extra-arg 3 : options (d/s/p) (optional, default: ds)\n" . " options-arg contains 'd' : delete source-file(s) after inject\n" . " options-arg contains 's' : start transfer(s) after inject\n" . " options-arg contains 'p' : use transfer-profile\n" . " extra-arg 4 : transfer-profile name (optional, default: none)\n" . " rss : download torrents matching filter-rules from a rss-feed.\n" . " extra-arg 1 : save-dir\n" . " extra-arg 2 : filter-file\n" . " extra-arg 3 : history-file\n" . " extra-arg 4 : rss-feed-url\n" . " extra-arg 5 : use cookies from this torrentflux user (optional, default: superadmin)\n" . " xfer : xfer-Limit-Shutdown. stop all transfers if xfer-limit is met.\n" . " extra-arg 1 : time-delta of xfer to use : (all/total/month/week/day)\n" . " repair : repair of torrentflux. DON'T do this unless you have to.\n" . " Doing this on a running ok flux _will_ screw up things.\n" . " maintenance : call maintenance and repair all died transfers.\n" . " extra-arg 1 : restart died transfers (true/false. optional, default: false)\n" . " dump : dump database.\n" . " extra-arg 1 : type. (settings/users)\n" . " filelist : print file-list.\n" . " extra-arg 1 : dir (optional, default: docroot)\n" . " checksums : print checksum-list.\n" . " extra-arg 1 : dir (optional, default: docroot)\n" . "\n" . "examples:\n" . $this->_script." transfers\n" . $this->_script." netstat\n" . $this->_script." start foo.torrent\n" . $this->_script." start foo.torrent p profilename\n" . $this->_script." stop foo.torrent\n" . $this->_script." enqueue foo.torrent\n" . $this->_script." dequeue foo.torrent\n" . $this->_script." start-all\n" . $this->_script." start-all p profilename\n" . $this->_script." resume-all\n" . $this->_script." stop-all\n" . $this->_script." tset foo.torrent uprate 100\n" . $this->_script." tset foo.torrent downrate 100\n" . $this->_script." tset foo.torrent completion false\n" . $this->_script." tset foo.torrent sharekill 200\n" . $this->_script." reset foo.torrent\n" . $this->_script." delete foo.torrent\n" . $this->_script." wipe foo.torrent\n" . $this->_script." inject /path/to/foo.torrent fluxuser\n" . $this->_script." inject /path/to/foo.torrent fluxuser ds\n" . $this->_script." inject /path/to/foo.torrent fluxuser sp profilename\n" . $this->_script." watch /path/to/watch-dir/ fluxuser\n" . $this->_script." watch /path/to/watch-dir/ fluxuser d\n" . $this->_script." watch /path/to/watch-dir/ fluxuser dsp profilename\n" . $this->_script." rss /path/to/rss-torrents/ /path/to/filter.dat /path/to/filter.hist http://www.example.com/rss.xml\n" . $this->_script." rss /path/to/rss-torrents/ /path/to/filter.dat /path/to/filter.hist http://www.example.com/rss.xml fluxuser\n" . $this->_script." xfer month\n" . $this->_script." repair\n" . $this->_script." maintenance true\n" . $this->_script." dump settings\n" . $this->_script." dump users\n" . $this->_script." filelist /var/www\n" . $this->_script." checksums /var/www\n" . "\n"; if (count($this->_argErrors) > 0) { echo "arg-error(s) :\n" . implode("\n", $this->_argErrors) . "\n\n"; return false; } return true; } } ?>