From 75986bb272ed6925d480880c4525857c417cbcdf Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Fri, 16 Oct 2015 22:09:57 -0500 Subject: [PATCH] Issue 81: Allow users to create downloads that point offsite --- indefero/src/IDF/Form/Upload.php | 28 ++++++++- .../src/IDF/Migrations/32ExternalFile.php | 29 +++++++++ indefero/src/IDF/Upload.php | 61 ++++++++++++++++++- indefero/src/IDF/Views/Download.php | 14 +++-- .../IDF/templates/idf/downloads/create.html | 6 ++ .../src/IDF/templates/idf/downloads/view.html | 5 ++ 6 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 indefero/src/IDF/Migrations/32ExternalFile.php diff --git a/indefero/src/IDF/Form/Upload.php b/indefero/src/IDF/Form/Upload.php index c973581..52046a7 100644 --- a/indefero/src/IDF/Form/Upload.php +++ b/indefero/src/IDF/Form/Upload.php @@ -44,6 +44,15 @@ class IDF_Form_Upload extends Pluf_Form 'size' => 67, ), )); + $this->fields['ext_file'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('External File'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); $this->fields['changelog'] = new Pluf_Form_Field_Varchar( array('required' => false, 'label' => __('Description'), @@ -55,7 +64,7 @@ class IDF_Form_Upload extends Pluf_Form ), )); $this->fields['file'] = new Pluf_Form_Field_File( - array('required' => true, + array('required' => false, 'label' => __('File'), 'initial' => '', 'max_size' => Pluf::f('max_upload_size', 2097152), @@ -80,6 +89,9 @@ class IDF_Form_Upload extends Pluf_Form public function clean_file() { // FIXME: we do the same in IDF_Form_WikiResourceCreate and a couple of other places as well + if (empty($this->cleaned_data['file'])) { + return $this->cleaned_data['file']; + } $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); if (strlen($extra)) $extra .= '|'; if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) { @@ -121,6 +133,9 @@ class IDF_Form_Upload extends Pluf_Form throw new Pluf_Form_Invalid(__('You provided an invalid label.')); } } + if (empty($this->cleaned_data["file"]) && empty($this->cleaned_data["ext_file"])) { + throw new Pluf_Form_Invalid(__("Must upload a file or specify an external file")); + } return $this->cleaned_data; } @@ -162,14 +177,21 @@ class IDF_Form_Upload extends Pluf_Form $tags[] = IDF_Tag::add($name, $this->project, $class); } } + // Create the upload $upload = new IDF_Upload(); $upload->project = $this->project; $upload->submitter = $this->user; $upload->summary = trim($this->cleaned_data['summary']); $upload->changelog = trim($this->cleaned_data['changelog']); - $upload->file = $this->cleaned_data['file']; - $upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + if (!empty($this->cleaned_data["file"])) { + $upload->file = $this->cleaned_data['file']; + $upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + } else { + $upload->file = end(explode("/", $this->cleaned_data["ext_file"])); + $upload->ext_file = $this->cleaned_data['ext_file']; + } + $upload->downloads = 0; $upload->create(); foreach ($tags as $tag) { diff --git a/indefero/src/IDF/Migrations/32ExternalFile.php b/indefero/src/IDF/Migrations/32ExternalFile.php new file mode 100644 index 0000000..03c2594 --- /dev/null +++ b/indefero/src/IDF/Migrations/32ExternalFile.php @@ -0,0 +1,29 @@ +getSqlTable(); + + $sql = array(); + + $sql["MySQL"] = "ALTER TABLE " . $table . " ADD COLUMN `ext_file` VARCHAR(250) NULL AFTER `modif_dtime`;"; + + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + + $db->execute($sql[$engine]); +} + +function IDF_Migrations_32ExternalFile_down() +{ + $table = Pluf::factory('IDF_Upload')->getSqlTable(); + + $sql = array(); + + $sql["MySQL"] = "ALTER TABLE " . $table . " DROP COLUMN `ext_file`;"; + + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + + $db->execute($sql[$engine]); +} \ No newline at end of file diff --git a/indefero/src/IDF/Upload.php b/indefero/src/IDF/Upload.php index 2fa7aec..fa49d9a 100644 --- a/indefero/src/IDF/Upload.php +++ b/indefero/src/IDF/Upload.php @@ -56,6 +56,13 @@ class IDF_Upload extends Pluf_Model 'size' => 250, 'verbose' => __('summary'), ), + 'ext_file' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('External File URL'), + ), 'changelog' => array( 'type' => 'Pluf_DB_Field_Text', @@ -140,6 +147,54 @@ class IDF_Upload extends Pluf_Model return $this->file; } + /** + * Get the file size of any remote resource (using get_headers()), + * either in bytes or - default - as human-readable formatted string. + * + * @author Stephan Schmitz + * @license MIT + * @url + * + * @param string $url Takes the remote object's URL. + * @param boolean $formatSize Whether to return size in bytes or formatted. + * @param boolean $useHead Whether to use HEAD requests. If false, uses GET. + * @return string Returns human-readable formatted size + * or size in bytes (default: formatted). + * + * + * //example + * echo getRemoteFilesize('https://github.com/eyecatchup/SEOstats/archive/master.zip'); + * + */ + private function getRemoteFilesize($url, $formatSize = true, $useHead = true) + { + if (false !== $useHead) { + stream_context_set_default(array('http' => array('method' => 'HEAD'))); + } + $head = array_change_key_case(get_headers($url, 1)); + // content-length of download (in bytes), read from Content-Length: field + $clen = isset($head['content-length']) ? $head['content-length'] : 0; + // cannot retrieve file size, return "-1" + if (!$clen) { + return -1; + } + if (!$formatSize) { + return $clen; // return size in bytes + } + $size = $clen; + switch ($clen) { + case $clen < 1024: + $size = $clen .' B'; break; + case $clen < 1048576: + $size = round($clen / 1024, 2) .' KiB'; break; + case $clen < 1073741824: + $size = round($clen / 1048576, 2) . ' MiB'; break; + case $clen < 1099511627776: + $size = round($clen / 1073741824, 2) . ' GiB'; break; + } + return $size; // return formatted size + } + function _toIndex() { return ''; @@ -150,7 +205,11 @@ class IDF_Upload extends Pluf_Model if ($this->id == '') { $this->creation_dtime = gmdate('Y-m-d H:i:s'); $this->modif_dtime = gmdate('Y-m-d H:i:s'); - $this->md5 = md5_file ($this->getFullPath()); + if ($this->ext_file == "") { + $this->md5 = md5_file ($this->getFullPath()); + } else { + $this->filesize = $this->getRemoteFilesize($this->ext_file, false); + } } } diff --git a/indefero/src/IDF/Views/Download.php b/indefero/src/IDF/Views/Download.php index f3e06f1..a2d1f0a 100644 --- a/indefero/src/IDF/Views/Download.php +++ b/indefero/src/IDF/Views/Download.php @@ -204,11 +204,15 @@ class IDF_Views_Download $prj->inOr404($upload); $upload->downloads += 1; $upload->update(); - $path = $upload->getFullPath(); - $mime = IDF_FileUtil::getMimeType($path); - $render = new Pluf_HTTP_Response_File($path, $mime[0]); - $render->headers['Content-MD5'] = $upload->md5; - $render->headers['Content-Disposition'] = 'attachment; filename="'.$upload->file.'"'; + if ($upload->ext_file == "") { + $path = $upload->getFullPath(); + $mime = IDF_FileUtil::getMimeType($path); + $render = new Pluf_HTTP_Response_File($path, $mime[0]); + $render->headers['Content-MD5'] = $upload->md5; + $render->headers['Content-Disposition'] = 'attachment; filename="'.$upload->file.'"'; + } else { + $render = new Pluf_HTTP_Response_Redirect($upload->ext_file); + } return $render; } diff --git a/indefero/src/IDF/templates/idf/downloads/create.html b/indefero/src/IDF/templates/idf/downloads/create.html index c032004..b42e577 100644 --- a/indefero/src/IDF/templates/idf/downloads/create.html +++ b/indefero/src/IDF/templates/idf/downloads/create.html @@ -18,6 +18,12 @@ {$form.f.summary|unsafe} + + {$form.f.ext_file.labelTag}: + {if $form.f.ext_file.errors}{$form.f.ext_file.fieldErrors}{/if} + {$form.f.ext_file|unsafe} + + {$form.f.changelog.labelTag}: {if $form.f.changelog.errors}{$form.f.changelog.fieldErrors}{/if} diff --git a/indefero/src/IDF/templates/idf/downloads/view.html b/indefero/src/IDF/templates/idf/downloads/view.html index 478a0b9..ed85c4f 100644 --- a/indefero/src/IDF/templates/idf/downloads/view.html +++ b/indefero/src/IDF/templates/idf/downloads/view.html @@ -4,9 +4,14 @@
{if $deprecated}

{blocktrans}Attention! This file is marked as deprecated, download it only if you are sure you need this specific version.{/blocktrans}

{/if} + {$file} - {$file.filesize|size} +{if !$file.ext_file}
{trans 'md5:'} {$file.md5} +{/if} + +
{if $file.changelog}

{trans 'Changes'}