diff --git a/post.php b/post.php
index 0265fb29..bd1591d9 100644
--- a/post.php
+++ b/post.php
@@ -61,6 +61,88 @@ function strip_symbols($input) {
}
}
+/**
+ * Download the url's target with curl.
+ *
+ * @param string $url Url to the file to download.
+ * @param int $timeout Request timeout in seconds.
+ * @param File $fd File descriptor to save the content to.
+ * @return null|string Returns a string on error.
+ */
+function download_file_into($url, $timeout, $fd) {
+ $err = null;
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_FAILONERROR, true);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
+ curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
+ curl_setopt($curl, CURLOPT_USERAGENT, 'Tinyboard');
+ curl_setopt($curl, CURLOPT_FILE, $fd);
+ curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+ curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+
+ if (curl_exec($curl) === false) {
+ $err = curl_error($curl);
+ }
+
+ curl_close($curl);
+ return $err;
+}
+
+/**
+ * Download a remote file from the given url.
+ * The file is deleted at shutdown.
+ *
+ * @param string $file_url The url to download the file from.
+ * @param int $request_timeout Timeout to retrieve the file.
+ * @param array $extra_extensions Allowed file extensions.
+ * @param string $tmp_dir Temporary directory to save the file into.
+ * @param array $error_array An array with error codes, used to create exceptions on failure.
+ * @return array Returns an array describing the file on success.
+ * @throws Exception on error.
+ */
+function download_file_from_url($file_url, $request_timeout, $allowed_extensions, $tmp_dir, &$error_array) {
+ if (!preg_match('@^https?://@', $file_url)) {
+ throw new InvalidArgumentException($error_array['invalidimg']);
+ }
+
+ if (mb_strpos($file_url, '?') !== false) {
+ $url_without_params = mb_substr($file_url, 0, mb_strpos($file_url, '?'));
+ } else {
+ $url_without_params = $file_url;
+ }
+
+ $extension = strtolower(mb_substr($url_without_params, mb_strrpos($url_without_params, '.') + 1));
+
+ if (!in_array($extension, $allowed_extensions)) {
+ throw new InvalidArgumentException($error_array['unknownext']);
+ }
+
+ $tmp_file = tempnam($tmp_dir, 'url');
+ function unlink_tmp_file($file) {
+ @unlink($file);
+ fatal_error_handler();
+ }
+ register_shutdown_function('unlink_tmp_file', $tmp_file);
+
+ $fd = fopen($tmp_file, 'w');
+
+ $dl_err = download_file_into($tmp_file, $request_timeout, $fd);
+ fclose($fd);
+ if ($dl_err !== null) {
+ throw new Exception($error_array['nomove'] . '
Curl says: ' . $dl_err);
+ }
+
+ return array(
+ 'name' => basename($url_without_params),
+ 'tmp_name' => $tmp_file,
+ 'file_tmp' => true,
+ 'error' => 0,
+ 'size' => filesize($tmp_file)
+ );
+}
+
/**
* Method handling functions
*/
@@ -609,58 +691,18 @@ if (isset($_POST['delete'])) {
}
if ($config['allow_upload_by_url'] && isset($_POST['file_url']) && !empty($_POST['file_url'])) {
- $post['file_url'] = $_POST['file_url'];
- if (!preg_match('@^https?://@', $post['file_url']))
- error($config['error']['invalidimg']);
-
- if (mb_strpos($post['file_url'], '?') !== false)
- $url_without_params = mb_substr($post['file_url'], 0, mb_strpos($post['file_url'], '?'));
- else
- $url_without_params = $post['file_url'];
-
- $post['extension'] = strtolower(mb_substr($url_without_params, mb_strrpos($url_without_params, '.') + 1));
+ $allowed_extensions = $config['allowed_ext_files'];
+ // Add allowed extensions for OP, if enabled.
if ($post['op'] && $config['allowed_ext_op']) {
- if (!in_array($post['extension'], $config['allowed_ext_op']))
- error($config['error']['unknownext']);
+ array_merge($allowed_extensions, $config['allowed_ext_op']);
}
- else if (!in_array($post['extension'], $config['allowed_ext']) && !in_array($post['extension'], $config['allowed_ext_files']))
- error($config['error']['unknownext']);
- $post['file_tmp'] = tempnam($config['tmp'], 'url');
- function unlink_tmp_file($file) {
- @unlink($file);
- fatal_error_handler();
+ try {
+ $_FILES['file'] = download_file_from_url($_POST['file_url'], $config['upload_by_url_timeout'], $allowed_extensions, $config['tmp'], $config['error']);
+ } catch (Exception $e) {
+ error($e->getMessage());
}
- register_shutdown_function('unlink_tmp_file', $post['file_tmp']);
-
- $fp = fopen($post['file_tmp'], 'w');
-
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $post['file_url']);
- curl_setopt($curl, CURLOPT_FAILONERROR, true);
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
- curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
- curl_setopt($curl, CURLOPT_TIMEOUT, $config['upload_by_url_timeout']);
- curl_setopt($curl, CURLOPT_USERAGENT, 'Tinyboard');
- curl_setopt($curl, CURLOPT_BINARYTRANSFER, true);
- curl_setopt($curl, CURLOPT_FILE, $fp);
- curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
-
- if (curl_exec($curl) === false)
- error($config['error']['nomove'] . '
Curl says: ' . curl_error($curl));
-
- curl_close($curl);
-
- fclose($fp);
-
- $_FILES['file'] = array(
- 'name' => basename($url_without_params),
- 'tmp_name' => $post['file_tmp'],
- 'file_tmp' => true,
- 'error' => 0,
- 'size' => filesize($post['file_tmp'])
- );
}
$post['name'] = $_POST['name'] != '' ? $_POST['name'] : $config['anonymous'];