From 8ae2b52e4db45f26c32a4ad9bc65494480936cbf Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 7 Nov 2013 17:10:43 +0100 Subject: Make download work --- apis/download.inc.php | 10 ++++-- fakeremote/list.php | 24 +++++++++++++ inc/message.inc.php | 2 +- inc/util.inc.php | 71 ++++++++++++++++++++++++++++++++----- modules/sysconfig.inc.php | 10 +++--- templates/download-error.html | 1 + templates/download-overwrite.html | 4 +++ templates/page-remote-tgz-list.html | 11 ++++++ templates/page-tgz-list.html | 10 ++++++ templates/remote-tgz-list.html | 11 ------ templates/tgz-list.html | 10 ------ 11 files changed, 126 insertions(+), 38 deletions(-) create mode 100644 fakeremote/list.php create mode 100644 templates/download-error.html create mode 100644 templates/download-overwrite.html create mode 100644 templates/page-remote-tgz-list.html create mode 100644 templates/page-tgz-list.html delete mode 100644 templates/remote-tgz-list.html delete mode 100644 templates/tgz-list.html 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 @@ +" }'; +} +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 @@ +
Downloading {{file}} from {{remote}} failed! ({{code}})
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 @@ +
+ {{file}} ist bereits lokal vorhanden. Soll die lokale Version überschrieben werden? + Überschreiben +
diff --git a/templates/page-remote-tgz-list.html b/templates/page-remote-tgz-list.html new file mode 100644 index 00000000..7cf08dfd --- /dev/null +++ b/templates/page-remote-tgz-list.html @@ -0,0 +1,11 @@ +
+ {{#files}} +
+

Download » {{file}}

+
{{description}}
+
+ {{/files}} + {{^files}} +
Keine Konfigurationspakete gefunden!
+ {{/files}} +
diff --git a/templates/page-tgz-list.html b/templates/page-tgz-list.html new file mode 100644 index 00000000..fec5af63 --- /dev/null +++ b/templates/page-tgz-list.html @@ -0,0 +1,10 @@ +
+ {{#files}} +
{{file}}
+ {{/files}} + {{^files}} +
Keine Konfigurationspakete gefunden!
+ {{/files}} + Konfigurationen herunterladen + Eigene Konfiguration hochladen +
diff --git a/templates/remote-tgz-list.html b/templates/remote-tgz-list.html deleted file mode 100644 index e7abc78a..00000000 --- a/templates/remote-tgz-list.html +++ /dev/null @@ -1,11 +0,0 @@ -
- {{#files}} -
-

Download » {{file}}

-
{{description}}
-
- {{/files}} - {{^files}} -
Keine Konfigurationspakete gefunden!
- {{/files}} -
diff --git a/templates/tgz-list.html b/templates/tgz-list.html deleted file mode 100644 index fec5af63..00000000 --- a/templates/tgz-list.html +++ /dev/null @@ -1,10 +0,0 @@ -
- {{#files}} -
{{file}}
- {{/files}} - {{^files}} -
Keine Konfigurationspakete gefunden!
- {{/files}} - Konfigurationen herunterladen - Eigene Konfiguration hochladen -
-- cgit v1.2.3-55-g7522