function DownloadByRange($URI, $EXPECTED_SIZE = 0, $LocalFile = null)
{
    $HTTP_CODE = 0;
    $Time = null;
    if (!isset($GLOBALS["WindowsUpdateCachingDir"])) {
        $GLOBALS["WindowsUpdateCachingDir"] = @file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateCachingDir");
        if ($GLOBALS["WindowsUpdateCachingDir"] == null) {
            $GLOBALS["WindowsUpdateCachingDir"] = "/home/squid/WindowsUpdate";
        }
    }
    $WindowsUpdateBandwidthPartial = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateBandwidthPartial"));
    $WindowsUpdateUseLocalProxy = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateUseLocalProxy"));
    $WindowsUpdateInterface = @file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateInterface");
    if ($WindowsUpdateBandwidthPartial == 0) {
        $WindowsUpdateBandwidthPartial = 512;
    }
    if ($EXPECTED_SIZE == 0) {
        $EXPECTED_SIZE = GetTargetedSize($URI);
    }
    $EXPECTED_SIZE_TEXT = xFormatBytes($EXPECTED_SIZE / 1024);
    $BaseNameOfFile = basename($URI);
    $unix = new unix();
    $curl = $unix->find_program("curl");
    $rm = $unix->find_program("rm");
    $mv = $unix->find_program("mv");
    $TempDir = "{$GLOBALS["WindowsUpdateCachingDir"]}/Partials/" . md5($URI);
    $TempFile = "{$TempDir}/FILE";
    if (is_file($TempFile)) {
        $size = @filesize($TempFile);
    }
    @mkdir($TempDir, 0755, true);
    $WorkingPort = $SquidMgrListenPort = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/SquidMgrListenPort"));
    @unlink("{$TempDir}/stderr.txt");
    $f[] = "{$curl} --location";
    if ($WindowsUpdateUseLocalProxy == 1) {
        events("Downloading {$BaseNameOfFile} Proxy:127.0.0.1:{$WorkingPort}", __LINE__);
        $f[] = "--proxy 127.0.0.1:{$WorkingPort} --url \"{$URI}\"";
    }
    if ($WindowsUpdateInterface != null) {
        $INTERFACES = $unix->NETWORK_ALL_INTERFACES();
        $ipaddr = $INTERFACES[$WindowsUpdateInterface]["IPADDR"];
        if ($ipaddr == "0.0.0.0") {
            $ipaddr = null;
        }
        if ($ipaddr != null) {
            events("Downloading {$BaseNameOfFile} Interface:{$ipaddr}", __LINE__);
            $f[] = "--interface {$ipaddr}";
        }
    }
    $f[] = "--show-error --write-out \"RRRR:%{http_code} TTT:%{time_total}\"";
    $f[] = "--stderr {$TempDir}/stderr.txt";
    $f[] = "--output \"{$TempFile}\"";
    $f[] = "--continue-at -";
    $f[] = "--limit-rate {$WindowsUpdateBandwidthPartial}K";
    $f[] = "--url \"{$URI}\"";
    $f[] = "2>&1";
    $cmd = @implode(" ", $f);
    if ($GLOBALS["VERBOSE"]) {
        echo "{$cmd}\n";
    }
    $T1 = time();
    events("Downloading {$BaseNameOfFile} {$EXPECTED_SIZE_TEXT} limit:{$WindowsUpdateBandwidthPartial}Kb/s", __LINE__);
    exec($cmd, $results);
    $stderr = trim(@file_get_contents("{$TempDir}/stderr.txt"));
    if ($stderr != null) {
        while (list($num, $val) = each($results)) {
            if (preg_match("#RRRR:(.+?)\\s+TTT:(.+)#", $val, $re)) {
                $HTTP_CODE = $re[1];
                $Time = $re[2];
                continue;
            }
            events("INFO: {$val}", __LINE__);
        }
        if (intval($HTTP_CODE) != 200) {
            if (preg_match("#Resuming transfer from byte position\\s+([0-9]+)#", $stderr, $re)) {
                events("Downloading {$BaseNameOfFile} stopped duration:{$Time} HTTP Code:{$HTTP_CODE} and resuming position at : {$re[1]} (" . xFormatBytes($re[1] / 1024) . ")", __LINE__);
                return false;
            }
            events("Failed: duration:{$Time} {$BaseNameOfFile} with error {$HTTP_CODE} «{$stderr}»", __LINE__);
            return false;
        }
    }
    $size = @filesize($TempFile);
    $size_text = xFormatBytes($size);
    events("INFO: {$BaseNameOfFile} ({$size_text}) HTTP Code:{$HTTP_CODE} Duration:{$Time}", __LINE__);
    if ($size < $EXPECTED_SIZE) {
        events("Warning: {$BaseNameOfFile} {$size} is not {$EXPECTED_SIZE} (broken download) retry next time", __LINE__);
        return false;
    }
    events("INFO: {$BaseNameOfFile} move to {$LocalFile}", __LINE__);
    @mkdir(dirname($LocalFile));
    $cmd = "{$mv} \"{$TempFile}\" \"{$LocalFile}\"";
    exec($cmd, $output, $return_val);
    if ($return_val == 0) {
        events("Success: Retranslate {$BaseNameOfFile} to target directory", __LINE__);
        if (is_dir($TempDir)) {
            shell_exec("{$rm} -rf {$TempDir}");
        }
        return true;
    } else {
        events("Failed: {$BaseNameOfFile}, unable to move to target directory!", __LINE__);
        return false;
    }
}
Ejemplo n.º 2
0
function xstart()
{
    $T1 = time();
    $curl = new ccurl();
    $unix = new unix();
    $GLOBALS["MYPID"] = getmypid();
    $pidfile = "/etc/artica-postfix/pids/windowupdate.processor.pid";
    $pid = $unix->get_pid_from_file($pidfile);
    if ($unix->process_exists($pid, basename(__FILE__))) {
        die;
    }
    $pids = $unix->PIDOF_PATTERN_ALL(basename(__FILE__), true);
    if (count($pids) > 0) {
        while (list($i, $line) = each($pids)) {
            events("Already executed PID:{$i}... aborting ", __LINE__);
        }
        die;
    }
    $TEMPDIR = $unix->TEMP_DIR() . "/WindowsUpdates";
    $rm = $unix->find_program("rm");
    @file_put_contents($pidfile, $GLOBALS["MYPID"]);
    if (is_dir($TEMPDIR)) {
        shell_exec("{$rm} -rf {$TEMPDIR}");
    }
    @mkdir($TEMPDIR, 0755, true);
    $WindowsUpdateMaxPartition = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateMaxPartition"));
    if ($WindowsUpdateMaxPartition == 0) {
        $WindowsUpdateMaxPartition = 80;
    }
    $CheckPartitionPercentage = CheckPartitionPercentage();
    if ($CheckPartitionPercentage > $WindowsUpdateMaxPartition) {
        $time = $unix->file_time_min("/etc/squid3/WindowsUpdatePartitionExceed");
        if ($time > 10) {
            @unlink("/etc/squid3/WindowsUpdatePartitionExceed");
            events("Failed: Storage Partition exceed {$WindowsUpdateMaxPartition}%, Stopping retreivals", __LINE__);
            @touch("/etc/squid3/WindowsUpdatePartitionExceed");
            DirectorySize();
        }
        return;
    }
    $WindowsUpdateInProduction = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateInProduction"));
    if ($WindowsUpdateInProduction == 0) {
        if ($unix->IsProductionTime()) {
            $time = $unix->file_time_min("/etc/artica-postfix/pids/WindowsUpdateInProduction");
            if ($time > 15) {
                @unlink("/etc/artica-postfix/pids/WindowsUpdateInProduction");
                @touch("/etc/artica-postfix/pids/WindowsUpdateInProduction");
                events("INFO: Aborting, No download during production time", __LINE__);
                DirectorySize();
            }
            return;
        }
    }
    if (is_file("/etc/squid3/WindowsUpdatePartitionExceed")) {
        @unlink("/etc/squid3/WindowsUpdatePartitionExceed");
    }
    $q = new mysql_squid_builder();
    $sql = "CREATE TABLE IF NOT EXISTS `windowsupdate` (\n\t\t\t`filemd5` VARCHAR( 90 ) NOT NULL ,\n\t\t\t`zDate` DATETIME NOT NULL ,\n\t\t\t`zUri` VARCHAR( 255 ) NOT NULL ,\n\t\t\t`localpath` VARCHAR( 255 ) NOT NULL ,\n\t\t\t`filesize` BIGINT UNSIGNED DEFAULT '0',\n\t\t\t INDEX ( `filesize` ,`zDate`) ,\n\t\t\t KEY `localpath`(`localpath`),\n\t\t\t KEY `zUri`(`zUri`),\n\t\t\t PRIMARY KEY (`filemd5`)) ENGINE=MYISAM;";
    $q->QUERY_SQL($sql);
    if (!$q->ok) {
        events("MySQL Failed {$q->mysql_error}", __LINE__);
        die;
    }
    $GLOBALS["WindowsUpdateMaxToPartialQueue"] = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateMaxToPartialQueue"));
    if ($GLOBALS["WindowsUpdateMaxToPartialQueue"] == 0) {
        $GLOBALS["WindowsUpdateMaxToPartialQueue"] = 350;
    }
    $GLOBALS["WindowsUpdateCachingDir"] = @file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateCachingDir");
    if ($GLOBALS["WindowsUpdateCachingDir"] == null) {
        $GLOBALS["WindowsUpdateCachingDir"] = "/home/squid/WindowsUpdate";
    }
    $filepath = "{$GLOBALS["WindowsUpdateCachingDir"]}/Queue.log";
    $WindowsUpdateDownTimeout = intval(@file_get_contents("/etc/artica-postfix/settings/Daemons/WindowsUpdateDownTimeout"));
    if ($WindowsUpdateDownTimeout == 0) {
        $WindowsUpdateDownTimeout = 600;
    }
    $WindowsUpdateMaxToPartialQueue = $GLOBALS["WindowsUpdateMaxToPartialQueue"] * 1000;
    $WindowsUpdateMaxToPartialQueue = $WindowsUpdateMaxToPartialQueue * 1000;
    $LinesCount = $unix->COUNT_LINES_OF_FILE($filepath);
    if (!is_file($filepath)) {
        return;
    }
    $md5start = md5_file($filepath);
    $handle = @fopen($filepath, "r");
    if (!$handle) {
        events("Fopen failed on {$filepath}", __LINE__);
        return false;
    }
    $NEWBUFFER = array();
    $URLALREADY = array();
    $FinalSize = 0;
    $FF = 0;
    $c = 0;
    while (!feof($handle)) {
        $buffer = trim(fgets($handle));
        $c++;
        if ($buffer == null) {
            continue;
        }
        $TR = explode("|||", $buffer);
        $prc = $c / $LinesCount;
        $prc = round($prc * 100);
        $LocalFile = $TR[0];
        $URI = $TR[1];
        $ExpectedSize = 0;
        if (strpos($URI, $GLOBALS["WindowsUpdateCachingDir"]) > 0) {
            events("FOUND! directory in  URI", __LINE__);
            $TTR = explode($GLOBALS["WindowsUpdateCachingDir"], $URI);
            $URI = $TTR[0];
            $LocalFile = "{$GLOBALS["WindowsUpdateCachingDir"]}{$TTR[1]}";
            events("FOUND! URI:{$URI}", __LINE__);
            events("FOUND! NEXT:{$LocalFile}", __LINE__);
        }
        $BASENAMELL = basename($LocalFile);
        if (strlen($BASENAMELL) > 20) {
            $BASENAMELL = substr($BASENAMELL, 0, 17) . "...";
        }
        build_progressG("{$BASENAMELL} {$c}/{$LinesCount} {files}", $prc);
        if (isset($URLALREADY[$URI])) {
            continue;
        }
        $URLALREADY[$URI] = true;
        if (isBlacklisted($URI)) {
            events(basename($URI) . " blacklisted...");
            continue;
        }
        if (is_file($LocalFile)) {
            $size = @filesize($LocalFile);
            if ($size > 5) {
                events("SKIP " . basename($LocalFile) . " " . xFormatBytes($size / 1024), __LINE__);
                update_mysql($LocalFile, $URI);
                continue;
            } else {
                @unlink($LocalFile);
            }
        }
        $dirname = dirname($LocalFile);
        if (!is_dir($dirname)) {
            @mkdir($dirname, true, 0755);
        }
        $curl = new ccurl($URI);
        $Headers = $curl->getHeaders();
        $TIMEDOWN = time();
        $TMPFILE = "{$TEMPDIR}/" . basename($LocalFile);
        $GLOBALS["previousProgress"] = 0;
        $GLOBALS["DOWNLOADED_FILE"] = basename($LocalFile);
        $GLOBALS["TMPFILE"] = $TMPFILE;
        $ExpectedSize = GetTargetedSize($URI);
        if ($ExpectedSize == 0) {
            events("Failed to download {$URI} ( unable to get expected size)", __LINE__);
            continue;
        }
        if ($ExpectedSize > $WindowsUpdateMaxToPartialQueue) {
            $ExpectedSizeText = xFormatBytes($ExpectedSize / 1024, true);
            events(basename($URI) . " ({$ExpectedSizeText} {$ExpectedSize}/{$WindowsUpdateMaxToPartialQueue}) Limit {$WindowsUpdateMaxToPartialQueue} to BigFiles queue", __LINE__);
            AddToPartialQueue($URI, $ExpectedSize, $LocalFile);
            continue;
        }
        $curl = new ccurl($URI);
        $curl->WriteProgress = true;
        $curl->Timeout = $WindowsUpdateDownTimeout * 60;
        $curl->ProgressFunction = "xdownload_progress";
        events("Downloading " . basename($URI) . " to {$TMPFILE} (" . xFormatBytes($ExpectedSize / 1024, true) . " max:{$WindowsUpdateDownTimeout} Minutes)", __LINE__);
        if (!$curl->GetFile($TMPFILE)) {
            events("Failed: TMP: &laquo;{$TMPFILE}&raquo;", __LINE__);
            events("Failed: URL: &laquo;{$URI}&raquo;", __LINE__);
            events("Failed: After: " . $unix->distanceOfTimeInWords($TIMEDOWN, time(), true), __LINE__);
            events("Failed: With error: {$curl->error} http code: {$curl->CURLINFO_HTTP_CODE} (" . count($curl->CURL_ALL_INFOS) . ") infos", __LINE__);
            reset($curl->CURL_ALL_INFOS);
            while (list($index, $value) = each($curl->CURL_ALL_INFOS)) {
                events("Failed: &laquo;{$index}&raquo; [{$value}]", __LINE__);
            }
            if ($curl->CURLINFO_HTTP_CODE == 404) {
                continue;
            }
            @unlink($TMPFILE);
            $NEWBUFFER[] = "{$buffer}";
            continue;
        }
        if (!is_file($TMPFILE)) {
            events("Fatal {$TMPFILE}: no such file", __LINE__);
            continue;
        }
        $size = filesize($TMPFILE);
        $sizeT = xFormatBytes($size / 1024);
        if ($size < 5) {
            @unlink($TMPFILE);
            events("Failed: File less than 5 Bytes ({$size}), aborting", __LINE__);
            continue;
        }
        if ($ExpectedSize > 0) {
            if ($size != $ExpectedSize) {
                $ExpectedSizeT = xFormatBytes($ExpectedSize / 1024);
                events("Failed: corrupted download " . basename($URI) . " expected size {$ExpectedSizeT}/{$ExpectedSize} current:({$sizeT}/{$size})", __LINE__);
                @unlink($TMPFILE);
                continue;
            }
        }
        if (!@copy($TMPFILE, $LocalFile)) {
            @unlink($TMPFILE);
            events("Failed: Translating to {$LocalFile}", __LINE__);
            $NEWBUFFER[] = "{$buffer}";
            continue;
        }
        events("Success: " . basename($TMPFILE) . " ({$sizeT})", __LINE__);
        @unlink($TMPFILE);
        $FF++;
        $size = @filesize($LocalFile);
        $FinalSize = $FinalSize + $size;
        update_mysql($LocalFile, $URI);
    }
    $took = $unix->distanceOfTimeInWords($T1, time(), true);
    if ($FinalSize > 0) {
        $CURLINFO_SPEED_DOWNLOAD = $curl->CURL_ALL_INFOS["CURLINFO_SPEED_DOWNLOAD"];
        events("Downloaded {$FF} files for " . xFormatBytes($FinalSize / 1024, true) . " ({$CURLINFO_SPEED_DOWNLOAD}) took: {$took}", __LINE__);
    }
    $md5finish = md5_file($filepath);
    if (count($NEWBUFFER) > 0) {
        events("Retry " . count($NEWBUFFER) . " requests next time...", __LINE__);
        @file_put_contents($filepath, @implode("\n", $NEWBUFFER));
    } else {
        events("No new file downloaded....", __LINE__);
        events("Removing queue {$filepath}", __LINE__);
        @unlink($filepath);
    }
    DirectorySize();
    events("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * * * END TOOK: {$took} * * *", __LINE__);
}