summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apis/download.inc.php10
-rw-r--r--fakeremote/list.php24
-rw-r--r--inc/message.inc.php2
-rw-r--r--inc/util.inc.php71
-rw-r--r--modules/sysconfig.inc.php10
-rw-r--r--templates/download-error.html1
-rw-r--r--templates/download-overwrite.html4
-rw-r--r--templates/page-remote-tgz-list.html (renamed from templates/remote-tgz-list.html)4
-rw-r--r--templates/page-tgz-list.html (renamed from templates/tgz-list.html)0
9 files changed, 107 insertions, 19 deletions
diff --git a/apis/download.inc.php b/apis/download.inc.php
index 9ba0f008..4be67521 100644
--- a/apis/download.inc.php
+++ b/apis/download.inc.php
@@ -21,13 +21,19 @@ case 'tgz':
default:
die('Invalid download type');
}
+@mkdir($local, 0755, true);
if (file_exists($local . '/' . $file) && !isset($_REQUEST['exec'])) {
- echo 'FILE EXISTS LOCALLY I SHOULD ASK FOR OVERWRITE NOW';
+ echo Render::parse('download-overwrite', array('file' => $file, 'id' => $id, 'query' => $_SERVER['REQUEST_URI']));;
exit(0);
}
-sleep(2);
+$ret = Util::downloadToFile($local . '/' . $file, $remote . '/' . $file, 20, $code);
+if ($ret === false || $code < 200 || $code >= 300) {
+ @unlink($local . '/' . $file);
+ echo Render::parse('download-error', array('file' => $file, 'remote' => $remote, 'code' => $code));
+ exit(0);
+}
// No execution - just return dialog
echo Render::parse('download-complete', array('file' => $file));
diff --git a/fakeremote/list.php b/fakeremote/list.php
new file mode 100644
index 00000000..5c8d1c67
--- /dev/null
+++ b/fakeremote/list.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+echo '[';
+
+$first = true;
+foreach (glob('./*.tgz') as $file) {
+ if (!$first) echo ', ';
+ $first = false;
+ echo ' { "file" : "' . basename($file) . '", "description" : "<Beschreibung>" }';
+}
+echo ' ]';
+*/
+
+$files = array();
+foreach (glob('./*.tgz') as $file) {
+ $files[] = array(
+ 'file' => basename($file),
+ 'description' => 'Eine sinnvolle Beschreibung'
+ );
+}
+
+echo json_encode($files);
+
diff --git a/inc/message.inc.php b/inc/message.inc.php
index 62c68e98..5896d092 100644
--- a/inc/message.inc.php
+++ b/inc/message.inc.php
@@ -14,7 +14,7 @@ $error_text = array(
'value-invalid' => 'Der Wert {{1}} ist ungültig für die Option {{0}} und wurde ignoriert',
'invalid-action' => 'Ungültige Aktion: {{0}}',
'remote-timeout' => 'Konnte Ressource {{0}} nicht herunterladen',
- 'remote-parse-failed' => 'Parsen der empfangenen Daten fehlgeschlagen',
+ 'remote-parse-failed' => 'Parsen der empfangenen Daten fehlgeschlagen ({{0}})',
);
class Message
diff --git a/inc/util.inc.php b/inc/util.inc.php
index 591c7e79..a93ec439 100644
--- a/inc/util.inc.php
+++ b/inc/util.inc.php
@@ -73,27 +73,80 @@ class Util
}
/**
- * Download file, obey given timeout in seconds
- * Return data on success, false on failure
+ * Common initialization for download and downloadToFile
+ * Return file handle to header file
*/
- function download($url, $timeout, &$code) {
+ private static function initCurl($url, $timeout, &$head)
+ {
$ch = curl_init();
+ if ($ch === false) Util::traceError('Could not initialize cURL');
curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, ceil($timeout / 2));
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_AUTOREFERER, true);
+ curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
+ curl_setopt($ch, CURLOPT_MAXREDIRS, 6);
+ $tmpfile = '/tmp/' . mt_rand() . '-' . time();
+ $head = fopen($tmpfile, 'w+b');
+ if ($head === false) Util::traceError("Could not open temporary head file $tmpfile for writing.");
+ curl_setopt($ch, CURLOPT_WRITEHEADER, $head);
+ return $ch;
+ }
+
+ /**
+ * Read 10kb from the given file handle, seek to 0 first,
+ * close the file after reading. Returns data read
+ */
+ private static function getContents($fh)
+ {
+ fseek($fh, 0, SEEK_SET);
+ return fread($fh, 10000);
+ }
+
+ /**
+ * Download file, obey given timeout in seconds
+ * Return data on success, false on failure
+ */
+ public static function download($url, $timeout, &$code)
+ {
+ $ch = self::initCurl($url, $timeout, $head);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
- $data = explode("\r\n\r\n", $data, 2);
- if (preg_match('#^HTTP/\d+\.\d+ (\d+) #', $data[0], $out)) {
+ $head = self::getContents($head);
+ if (preg_match('#^HTTP/\d+\.\d+ (\d+) #', $head, $out)) {
$code = (int)$out[1];
} else {
$code = 999;
}
curl_close($ch);
- if (count($data) < 2) return '';
- return $data[1];
+ return $data;
+ }
+
+ /**
+ * Download file, obey given timeout in seconds
+ * Return true on success, false on failure
+ */
+ public static function downloadToFile($target, $url, $timeout, &$code)
+ {
+ $fh = fopen($target, 'wb');
+ if ($fh === false) Util::traceError("Could not open $target for writing.");
+ $ch = self::initCurl($url, $timeout, $head);
+ curl_setopt($ch, CURLOPT_FILE, $fh);
+ $res = curl_exec($ch);
+ $head = self::getContents($head);
+ curl_close($ch);
+ fclose($fh);
+ if ($res === false) {
+ @unlink($target);
+ return false;
+ }
+ if (preg_match('#^HTTP/\d+\.\d+ (\d+) #', $head, $out)) {
+ $code = (int)$out[1];
+ } else {
+ $code = 999;
+ }
+ return true;
}
}
diff --git a/modules/sysconfig.inc.php b/modules/sysconfig.inc.php
index f8e6c6ad..e4751ec4 100644
--- a/modules/sysconfig.inc.php
+++ b/modules/sysconfig.inc.php
@@ -30,7 +30,7 @@ function list_configs()
'file' => $file
);
}
- Render::addTemplate('tgz-list', array('files' => $files));
+ Render::addTemplate('page-tgz-list', array('files' => $files));
}
function list_remote_configs()
@@ -39,20 +39,20 @@ function list_remote_configs()
Message::addError('no-permission');
return;
}
- $data = Util::download(CONFIG_REMOTE_TGZ . '/list', 4, $code);
+ $data = Util::download(CONFIG_REMOTE_TGZ . '/list.php', 4, $code);
if ($code !== 200) {
Message::addError('remote-timeout', CONFIG_REMOTE_TGZ);
return;
}
$list = json_decode($data, true);
if (!is_array($list)) {
- Message::addError('remote-parse-failed');
+ Message::addError('remote-parse-failed', $data);
return;
}
$id = 0;
foreach ($list as &$item) {
- $item['id'] = ++$id;
+ $item['id'] = 'download' . (++$id);
}
- Render::addTemplate('remote-tgz-list', array('files' => $list));
+ Render::addTemplate('page-remote-tgz-list', array('files' => $list));
}
diff --git a/templates/download-error.html b/templates/download-error.html
new file mode 100644
index 00000000..ca40acee
--- /dev/null
+++ b/templates/download-error.html
@@ -0,0 +1 @@
+<div class="alert alert-danger">Downloading {{file}} from {{remote}} failed! ({{code}})</div>
diff --git a/templates/download-overwrite.html b/templates/download-overwrite.html
new file mode 100644
index 00000000..eccad5d0
--- /dev/null
+++ b/templates/download-overwrite.html
@@ -0,0 +1,4 @@
+<div class="alert alert-warning">
+ {{file}} ist bereits lokal vorhanden. Soll die lokale Version überschrieben werden?
+ <a class="btn btn-danger" href="#" onclick="this.style.display='none';loadContent('#{{id}}', '{{query}}&amp;exec=1')">Überschreiben</a>
+</div>
diff --git a/templates/remote-tgz-list.html b/templates/page-remote-tgz-list.html
index e7abc78a..7cf08dfd 100644
--- a/templates/remote-tgz-list.html
+++ b/templates/page-remote-tgz-list.html
@@ -1,8 +1,8 @@
<div class="container">
{{#files}}
<div class="panel panel-default">
- <div class="panel-heading"><h4><a class="btn btn-success" href="#" onclick="this.style.display='none';loadContent('#download{{id}}', 'api.php?do=download&amp;type=tgz&amp;file={{file}}&amp;id={{id}}')">Download</a> &raquo; {{file}}</h4></div>
- <div class="panel-body" id="download{{id}}">{{description}}</div>
+ <div class="panel-heading"><h4><a class="btn btn-success" href="#" onclick="this.style.display='none';loadContent('#{{id}}', 'api.php?do=download&amp;type=tgz&amp;file={{file}}&amp;id={{id}}')">Download</a> &raquo; {{file}}</h4></div>
+ <div class="panel-body" id="{{id}}">{{description}}</div>
</div>
{{/files}}
{{^files}}
diff --git a/templates/tgz-list.html b/templates/page-tgz-list.html
index fec5af63..fec5af63 100644
--- a/templates/tgz-list.html
+++ b/templates/page-tgz-list.html