From d59962443687127ea1defc2f8ac41af1c2c02fe4 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 25 Oct 2014 13:55:08 +0200
Subject: first go at reworking; needs to be redesigned
Signed-off-by: Florian Pritz
---
application/config/routes.php | 1 +
application/controllers/api.php | 38 ++++++++
application/controllers/api/api_controller.php | 15 ++++
application/controllers/api/v1.php | 83 ++++++++++++++++++
application/controllers/file.php | 92 ++++----------------
application/helpers/filebin_helper.php | 16 ++++
application/service/files.php | 116 +++++++++++++++++++++++++
7 files changed, 285 insertions(+), 76 deletions(-)
create mode 100644 application/controllers/api.php
create mode 100644 application/controllers/api/api_controller.php
create mode 100644 application/controllers/api/v1.php
create mode 100644 application/service/files.php
(limited to 'application')
diff --git a/application/config/routes.php b/application/config/routes.php
index e0d963405..23c9bebee 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -42,6 +42,7 @@ $route['default_controller'] = "file";
$route['user/(:any)'] = "user/$1";
$route['file/(:any)'] = "file/$1";
$route['tools/(:any)'] = "tools/$1";
+$route['api/(:any)'] = "api/route/$1";
$route['(:any)'] = "file/index/$1";
$route['404_override'] = '';
diff --git a/application/controllers/api.php b/application/controllers/api.php
new file mode 100644
index 000000000..626e7b91a
--- /dev/null
+++ b/application/controllers/api.php
@@ -0,0 +1,38 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+class Api extends MY_Controller {
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('mfile');
+ $this->load->model('mmultipaste');
+ }
+
+ public function route() {
+ $requested_version = $this->uri->segment(2);
+ $function = $this->uri->segment(3);
+ $major = intval(explode(".", $requested_version)[0]);
+
+ $class = "controllers\\api\\v".$major;
+
+ if (!class_exists($class) || version_compare($class::get_version(), $requested_version, "<")) {
+ return send_json_error_reply("Requested API version is not supported");
+ }
+
+ if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
+ return send_json_error_reply("Invalid function requested");
+ }
+
+ $controller = new $class;
+ return $controller->$function();
+ }
+}
diff --git a/application/controllers/api/api_controller.php b/application/controllers/api/api_controller.php
new file mode 100644
index 000000000..ca24dae59
--- /dev/null
+++ b/application/controllers/api/api_controller.php
@@ -0,0 +1,15 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace controllers\api;
+
+abstract class api_controller {
+ abstract static public function get_version();
+}
+
diff --git a/application/controllers/api/v1.php b/application/controllers/api/v1.php
new file mode 100644
index 000000000..e6d3c56fe
--- /dev/null
+++ b/application/controllers/api/v1.php
@@ -0,0 +1,83 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+namespace controllers\api;
+
+class v1 extends api_controller {
+ protected $json_enabled_functions = array(
+ "upload",
+ "get_config",
+ "history",
+ );
+
+ static public function get_version()
+ {
+ return "1.0.1";
+ }
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('mfile');
+ $this->load->model('mmultipaste');
+ }
+
+ public function upload()
+ {
+ $this->muser->require_access("basic");
+
+ $files = getNormalizedFILES();
+
+ if (empty($files)) {
+ show_error("No file was uploaded or unknown error occured.");
+ }
+
+ $errors = service\files::verify_uploaded_files($files);
+ if (!empty($errors)) {
+ return send_json_reply($errors, "upload-error");
+ }
+
+ $limits = $this->muser->get_upload_id_limits();
+ $urls = array();
+
+ foreach ($files as $file) {
+ $id = $this->mfile->new_id($limits[0], $limits[1]);
+ service\files::add_file($id, $file["tmp_name"], $file["name"]);
+ $ids[] = $id;
+ $urls[] = site_url($id).'/';
+ }
+
+ return send_json_reply(array(
+ "ids" => $ids,
+ "urls" => $urls,
+ ));
+ }
+
+ public function get_config()
+ {
+ return send_json_reply(array(
+ "upload_max_size" => $this->config->item("upload_max_size"),
+ ));
+ }
+
+ public function history()
+ {
+ $this->muser->require_access("apikey");
+ $history = service\files::history($this->muser->get_userid());
+ return send_json_reply($history);
+ }
+
+ public function delete()
+ {
+ $this->muser->require_access("apikey");
+
+
+ }
+}
+# vim: set noet:
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 2617d4840..ac2c4b4ca 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -623,10 +623,7 @@ class File extends MY_Controller {
{
$this->muser->require_access("apikey");
- $user = $this->muser->get_userid();
-
- $query = array();
- $lengths = array();
+ $history = service\files::history($this->muser->get_userid());
// key: database field name; value: display name
$fields = array(
@@ -645,22 +642,7 @@ class File extends MY_Controller {
$order = is_cli_client() ? "ASC" : "DESC";
- $items = $this->db->select(implode(',', array_keys($fields)))
- ->from('files')
- ->where('user', $user)
- ->get()->result_array();
-
- $query = $this->db->query("
- SELECT m.url_id id, sum(f.filesize) filesize, m.date, '' hash, '' mimetype, concat(count(*), ' file(s)') filename
- FROM multipaste m
- JOIN multipaste_file_map mfm ON m.multipaste_id = mfm.multipaste_id
- JOIN files f ON f.id = mfm.file_url_id
- WHERE m.user_id = ?
- GROUP BY m.url_id
- ", array($user))->result_array();
-
- $items = array_merge($items, $query);
- uasort($items, function($a, $b) use ($order) {
+ uasort($history["items"], function($a, $b) use ($order) {
if ($order == "ASC") {
return $a["date"] - $b["date"];
} else {
@@ -668,12 +650,8 @@ class File extends MY_Controller {
}
});
- if (static_storage("response_type") == "json") {
- return send_json_reply($items);
- }
-
- foreach($items as $key => $item) {
- $items[$key]["filesize"] = format_bytes($item["filesize"]);
+ foreach($history["items"] as $key => $item) {
+ $history["items"][$key]["filesize"] = format_bytes($item["filesize"]);
if (is_cli_client()) {
// Keep track of longest string to pad plaintext output correctly
foreach($fields as $length_key => $value) {
@@ -685,19 +663,10 @@ class File extends MY_Controller {
}
}
- $total_size = $this->db->query("
- SELECT sum(filesize) sum
- FROM (
- SELECT DISTINCT hash, filesize
- FROM files
- WHERE user = ?
- ) sub
- ", array($user))->row_array();
-
- $this->data["items"] = $items;
+ $this->data["items"] = $history["items"];
$this->data["lengths"] = $lengths;
$this->data["fields"] = $fields;
- $this->data["total_size"] = format_bytes($total_size["sum"]);
+ $this->data["total_size"] = format_bytes($history["total_size"]);
$this->load->view('header', $this->data);
$this->load->view($this->var->view_dir.'/upload_history', $this->data);
@@ -882,6 +851,7 @@ class File extends MY_Controller {
show_error("Error while uploading: File too big", 413);
}
+ // FIXME: this duplicates service\files::add_file (kind of)
$limits = $this->muser->get_upload_id_limits();
$id = $this->mfile->new_id($limits[0], $limits[1]);
$hash = md5($content);
@@ -915,44 +885,19 @@ class File extends MY_Controller {
show_error("No file was uploaded or unknown error occured.");
}
- // Check for errors before doing anything
- // First error wins and is displayed, these shouldn't happen that often anyway.
- foreach ($files as $key => $file) {
- // getNormalizedFILES() removes any file with error == 4
- if ($file['error'] !== UPLOAD_ERR_OK) {
- // ERR_OK only for completeness, condition above ignores it
- $errors = array(
- UPLOAD_ERR_OK => "There is no error, the file uploaded with success",
- UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
- UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded",
- UPLOAD_ERR_NO_FILE => "No file was uploaded",
- UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder",
- UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk",
- UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload",
- );
-
- $msg = "Unknown error.";
-
- if (isset($errors[$file['error']])) {
- $msg = $errors[$file['error']];
- } else {
- $msg = "Unknown error code: ".$file['error'].". Please report a bug.";
- }
-
- show_error("Error while uploading: ".$msg, 400);
- }
-
- $filesize = filesize($file['tmp_name']);
- if ($filesize > $this->config->item('upload_max_size')) {
- show_error("Error while uploading: File too big", 413);
+ $errors = service\files::verify_uploaded_files($files);
+ if (!empty($errors)) {
+ $messages = array();
+ foreach ($errors as $error) {
+ $messages[] = htmlspecialchars($error["filename"]).": ".$error["message"];
}
+ show_error("Error(s) occured while uploading:
".implode("
", $messages), 400);
}
+ $limits = $this->muser->get_upload_id_limits();
+
foreach ($files as $key => $file) {
- $limits = $this->muser->get_upload_id_limits();
$id = $this->mfile->new_id($limits[0], $limits[1]);
- $hash = md5_file($file['tmp_name']);
// work around a curl bug and allow the client to send the real filename base64 encoded
// TODO: this interface currently sets the same filename for every file if you use multiupload
@@ -968,12 +913,7 @@ class File extends MY_Controller {
$filename = trim($filename, "\r\n\0\t\x0B");
- $folder = $this->mfile->folder($hash);
- file_exists($folder) || mkdir ($folder);
- $file_path = $this->mfile->file($hash);
-
- move_uploaded_file($file['tmp_name'], $file_path);
- $this->mfile->add_file($hash, $id, $filename);
+ service\files::add_file($id, $file["tmp_name"], $filename);
$ids[] = $id;
}
diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php
index e5637ce94..465f865f6 100644
--- a/application/helpers/filebin_helper.php
+++ b/application/helpers/filebin_helper.php
@@ -235,6 +235,22 @@ function send_json_reply($array, $status = "success")
$CI->output->set_output(json_encode($reply));
}
+function send_json_error_reply($message, $array = null)
+{
+ $reply = array();
+ $reply["status"] = "error";
+ $reply["message"] = $message;
+
+ if ($array !== null) {
+ $reply["data"] = $array;
+ }
+
+ $CI =& get_instance();
+ $CI->output->set_status_header(400);
+ $CI->output->set_content_type('application/json');
+ $CI->output->set_output(json_encode($reply));
+}
+
function static_storage($key, $value = null)
{
static $storage = array();
diff --git a/application/service/files.php b/application/service/files.php
new file mode 100644
index 000000000..68072e95a
--- /dev/null
+++ b/application/service/files.php
@@ -0,0 +1,116 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace service;
+
+class files {
+
+ static public function history($user)
+ {
+ $CI =& get_instance();
+ $query = array();
+
+ $fields = array("id", "filename", "mimetype", "date", "hash", "filesize");
+
+ $items = $CI->db->select(implode(',', $fields))
+ ->from('files')
+ ->where('user', $user)
+ ->get()->result_array();
+
+ // TODO: split this and provide an array of pastes for a multipaste?
+ $query = $CI->db->query("
+ SELECT m.url_id id, sum(f.filesize) filesize, m.date, '' hash, '' mimetype, concat(count(*), ' file(s)') filename
+ FROM multipaste m
+ JOIN multipaste_file_map mfm ON m.multipaste_id = mfm.multipaste_id
+ JOIN files f ON f.id = mfm.file_url_id
+ WHERE m.user_id = ?
+ GROUP BY m.url_id
+ ", array($user))->result_array();
+
+ $items = array_merge($items, $query);
+
+ $total_size = $CI->db->query("
+ SELECT sum(filesize) sum
+ FROM (
+ SELECT DISTINCT hash, filesize
+ FROM files
+ WHERE user = ?
+ ) sub
+ ", array($user))->row_array();
+
+ $ret["items"] = $items;
+ $ret["total_size"] = $total_size["sum"];
+
+ return $ret;
+ }
+
+ static public function add_file($id, $file, $filename)
+ {
+ $CI =& get_instance();
+ $hash = md5_file($file);
+
+ $dir = $CI->mfile->folder($hash);
+ file_exists($dir) || mkdir ($dir);
+ $new_path = $CI->mfile->file($hash);
+
+ // TODO: make this operation atomic (move to temp name, then to final)
+ // the source can be a different file system so this might do a copy
+ move_uploaded_file($file, $new_path);
+ $CI->mfile->add_file($hash, $id, $filename);
+ }
+
+ static public function verify_uploaded_files($files)
+ {
+ $CI =& get_instance();
+ $errors = array();
+
+ foreach ($files as $key => $file) {
+ $error_message = "";
+
+ // getNormalizedFILES() removes any file with error == 4
+ if ($file['error'] !== UPLOAD_ERR_OK) {
+ // ERR_OK only for completeness, condition above ignores it
+ $error_msgs = array(
+ UPLOAD_ERR_OK => "There is no error, the file uploaded with success",
+ UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
+ UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
+ UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded",
+ UPLOAD_ERR_NO_FILE => "No file was uploaded",
+ UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder",
+ UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk",
+ UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload",
+ );
+
+ $error_message = "Unknown error.";
+
+ if (isset($error_msgs[$file['error']])) {
+ $error_message = $error_msgs[$file['error']];
+ } else {
+ $error_message = "Unknown error code: ".$file['error'].". Please report a bug.";
+ }
+
+ }
+
+ $filesize = filesize($file['tmp_name']);
+ if ($filesize > $CI->config->item('upload_max_size')) {
+ $error_message = "File too big";
+ }
+
+ if ($error_message != "") {
+ $errors[] = array(
+ "filename" => $file["name"],
+ "formfield" => $file["formfield"],
+ "message" => $error_message,
+ );
+ }
+ }
+
+ return $errors;
+ }
+}
--
cgit v1.2.3-24-g4f1b
From 349e9f6dc7da0c44ee80d0a73963c1c5cef87131 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 26 Oct 2014 21:39:58 +0100
Subject: misc
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 28 ++++++---
application/controllers/api/api_controller.php | 3 +-
application/controllers/api/v1.php | 83 --------------------------
application/core/MY_Controller.php | 6 +-
4 files changed, 27 insertions(+), 93 deletions(-)
delete mode 100644 application/controllers/api/v1.php
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index 626e7b91a..a7bd09f34 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -19,20 +19,34 @@ class Api extends MY_Controller {
public function route() {
$requested_version = $this->uri->segment(2);
- $function = $this->uri->segment(3);
+ $controller = $this->uri->segment(3);
+ $function = $this->uri->segment(4);
$major = intval(explode(".", $requested_version)[0]);
- $class = "controllers\\api\\v".$major;
-
- if (!class_exists($class) || version_compare($class::get_version(), $requested_version, "<")) {
- return send_json_error_reply("Requested API version is not supported");
+ if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
+ return send_json_error_reply("Invalid controller requested");
}
if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
return send_json_error_reply("Invalid function requested");
}
- $controller = new $class;
- return $controller->$function();
+ $namespace = "controllers\\api\\v".$major;
+ $class = $namespace."\\".$controller;
+ $class_info = $namespace."\\api_info";
+
+ if (!class_exists($class_info) || version_compare($class_info::get_version(), $requested_version, "<")) {
+ return send_json_error_reply("Requested API version is not supported");
+ }
+
+ if (!class_exists($class)) {
+ return send_json_error_reply("Unknown controller requested");
+ }
+
+ $c= new $class;
+ if (!method_exists($c, $function)) {
+ return send_json_error_reply("Unknown function requested");
+ }
+ return $c->$function();
}
}
diff --git a/application/controllers/api/api_controller.php b/application/controllers/api/api_controller.php
index ca24dae59..2b9054b17 100644
--- a/application/controllers/api/api_controller.php
+++ b/application/controllers/api/api_controller.php
@@ -9,7 +9,6 @@
namespace controllers\api;
-abstract class api_controller {
- abstract static public function get_version();
+abstract class api_controller extends \CI_Controller {
}
diff --git a/application/controllers/api/v1.php b/application/controllers/api/v1.php
deleted file mode 100644
index e6d3c56fe..000000000
--- a/application/controllers/api/v1.php
+++ /dev/null
@@ -1,83 +0,0 @@
-
- *
- * Licensed under AGPLv3
- * (see COPYING for full license text)
- *
- */
-namespace controllers\api;
-
-class v1 extends api_controller {
- protected $json_enabled_functions = array(
- "upload",
- "get_config",
- "history",
- );
-
- static public function get_version()
- {
- return "1.0.1";
- }
-
- public function __construct()
- {
- parent::__construct();
-
- $this->load->model('mfile');
- $this->load->model('mmultipaste');
- }
-
- public function upload()
- {
- $this->muser->require_access("basic");
-
- $files = getNormalizedFILES();
-
- if (empty($files)) {
- show_error("No file was uploaded or unknown error occured.");
- }
-
- $errors = service\files::verify_uploaded_files($files);
- if (!empty($errors)) {
- return send_json_reply($errors, "upload-error");
- }
-
- $limits = $this->muser->get_upload_id_limits();
- $urls = array();
-
- foreach ($files as $file) {
- $id = $this->mfile->new_id($limits[0], $limits[1]);
- service\files::add_file($id, $file["tmp_name"], $file["name"]);
- $ids[] = $id;
- $urls[] = site_url($id).'/';
- }
-
- return send_json_reply(array(
- "ids" => $ids,
- "urls" => $urls,
- ));
- }
-
- public function get_config()
- {
- return send_json_reply(array(
- "upload_max_size" => $this->config->item("upload_max_size"),
- ));
- }
-
- public function history()
- {
- $this->muser->require_access("apikey");
- $history = service\files::history($this->muser->get_userid());
- return send_json_reply($history);
- }
-
- public function delete()
- {
- $this->muser->require_access("apikey");
-
-
- }
-}
-# vim: set noet:
diff --git a/application/core/MY_Controller.php b/application/core/MY_Controller.php
index 22c1a9a1a..1e724a865 100644
--- a/application/core/MY_Controller.php
+++ b/application/core/MY_Controller.php
@@ -58,7 +58,11 @@ class MY_Controller extends CI_Controller {
static_storage("response_type", "json");
}
- if (static_storage("response_type") == "json" && ! in_array($this->uri->rsegment(2), $this->json_enabled_functions)) {
+ // TODO: this should probably call a function in the controller that does the checking
+ // instead of checking if the controller name == "api"
+ if (static_storage("response_type") == "json"
+ && $this->uri->segment(1) != "api"
+ && ! in_array($this->uri->rsegment(2), $this->json_enabled_functions)) {
show_error("Function not JSON enabled");
}
--
cgit v1.2.3-24-g4f1b
From 0c53ebac6e0328aea4551f5f1a97783f34c82866 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 2 Nov 2014 13:30:21 +0100
Subject: add missing files
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/api_info.php | 16 +++++++
application/controllers/api/v1/file.php | 72 +++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
create mode 100644 application/controllers/api/v1/api_info.php
create mode 100644 application/controllers/api/v1/file.php
(limited to 'application')
diff --git a/application/controllers/api/v1/api_info.php b/application/controllers/api/v1/api_info.php
new file mode 100644
index 000000000..3feaadfda
--- /dev/null
+++ b/application/controllers/api/v1/api_info.php
@@ -0,0 +1,16 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+namespace controllers\api\v1;
+
+class api_info extends \controllers\api\api_controller {
+ static public function get_version()
+ {
+ return "1.0.0";
+ }
+}
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
new file mode 100644
index 000000000..fc855f7f9
--- /dev/null
+++ b/application/controllers/api/v1/file.php
@@ -0,0 +1,72 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+namespace controllers\api\v1;
+
+class file extends \controllers\api\api_controller {
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('mfile');
+ $this->load->model('mmultipaste');
+ }
+
+ public function upload()
+ {
+ $this->muser->require_access("basic");
+
+ $files = getNormalizedFILES();
+
+ if (empty($files)) {
+ show_error("No file was uploaded or unknown error occured.");
+ }
+
+ $errors = \service\files::verify_uploaded_files($files);
+ if (!empty($errors)) {
+ return send_json_reply($errors, "upload-error");
+ }
+
+ $limits = $this->muser->get_upload_id_limits();
+ $urls = array();
+
+ foreach ($files as $file) {
+ $id = $this->mfile->new_id($limits[0], $limits[1]);
+ \service\files::add_file($id, $file["tmp_name"], $file["name"]);
+ $ids[] = $id;
+ $urls[] = site_url($id).'/';
+ }
+
+ return send_json_reply(array(
+ "ids" => $ids,
+ "urls" => $urls,
+ ));
+ }
+
+ public function get_config()
+ {
+ return send_json_reply(array(
+ "upload_max_size" => $this->config->item("upload_max_size"),
+ ));
+ }
+
+ public function history()
+ {
+ $this->muser->require_access("apikey");
+ $history = \service\files::history($this->muser->get_userid());
+ return send_json_reply($history);
+ }
+
+ public function delete()
+ {
+ $this->muser->require_access("apikey");
+
+
+ }
+}
+# vim: set noet:
--
cgit v1.2.3-24-g4f1b
From 7f74792c2f82aee3cd98bd6304ced55894b43683 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 4 Jan 2015 17:08:51 +0100
Subject: Improve history api for multipastes
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 16 ++++++++++++++++
application/service/files.php | 32 +++++++++++++++++++++-----------
2 files changed, 37 insertions(+), 11 deletions(-)
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index ac2c4b4ca..5451836de 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -640,6 +640,22 @@ class File extends MY_Controller {
$lengths[$length_key] = mb_strlen($value);
}
+ foreach ($history["multipaste_items"] as $key => $item) {
+ $size = 0;
+ foreach ($item["items"] as $i) {
+ $size += $i["filesize"];
+ }
+
+ $history["items"][] = array(
+ "id" => $item["url_id"],
+ "filename" => count($item["items"])." file(s)",
+ "mimetype" => "",
+ "date" => $item["date"],
+ "hash" => "",
+ "filesize" => $size,
+ );
+ }
+
$order = is_cli_client() ? "ASC" : "DESC";
uasort($history["items"], function($a, $b) use ($order) {
diff --git a/application/service/files.php b/application/service/files.php
index 68072e95a..7b320078e 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -14,7 +14,8 @@ class files {
static public function history($user)
{
$CI =& get_instance();
- $query = array();
+ $multipaste_items_grouped = array();
+ $multipaste_items = array();
$fields = array("id", "filename", "mimetype", "date", "hash", "filesize");
@@ -23,17 +24,25 @@ class files {
->where('user', $user)
->get()->result_array();
- // TODO: split this and provide an array of pastes for a multipaste?
- $query = $CI->db->query("
- SELECT m.url_id id, sum(f.filesize) filesize, m.date, '' hash, '' mimetype, concat(count(*), ' file(s)') filename
- FROM multipaste m
- JOIN multipaste_file_map mfm ON m.multipaste_id = mfm.multipaste_id
- JOIN files f ON f.id = mfm.file_url_id
- WHERE m.user_id = ?
- GROUP BY m.url_id
- ", array($user))->result_array();
+ $multipaste_items_query = $CI->db
+ ->select("m.url_id, f.filename, f.id, f.filesize, f.date, f.hash, f.mimetype")
+ ->from("multipaste m")
+ ->join("multipaste_file_map mfm", "m.multipaste_id = mfm.multipaste_id")
+ ->join("files f", "f.id = mfm.file_url_id")
+ ->where("m.user_id", $user)
+ ->get()->result_array();
+
+ foreach ($multipaste_items_query as $item) {
+ $key = $item["url_id"];
+ unset($item["url_id"]);
+ $multipaste_items_grouped[$key][] = $item;
+ }
- $items = array_merge($items, $query);
+ foreach ($multipaste_items_grouped as $key => $items) {
+ $multipaste_info = $CI->db->get_where("multipaste", array("url_id" => $key))->row_array();
+ $multipaste_info["items"] = $items;
+ $multipaste_items[] = $multipaste_info;
+ }
$total_size = $CI->db->query("
SELECT sum(filesize) sum
@@ -45,6 +54,7 @@ class files {
", array($user))->row_array();
$ret["items"] = $items;
+ $ret["multipaste_items"] = $multipaste_items;
$ret["total_size"] = $total_size["sum"];
return $ret;
--
cgit v1.2.3-24-g4f1b
From 9670d794be886c036408de85773a0b7d204979b9 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 4 Jan 2015 17:09:07 +0100
Subject: Fix error in file/upload_history
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 5451836de..57faa62f2 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -671,7 +671,7 @@ class File extends MY_Controller {
if (is_cli_client()) {
// Keep track of longest string to pad plaintext output correctly
foreach($fields as $length_key => $value) {
- $len = mb_strlen($items[$key][$length_key]);
+ $len = mb_strlen($history["items"][$key][$length_key]);
if ($len > $lengths[$length_key]) {
$lengths[$length_key] = $len;
}
--
cgit v1.2.3-24-g4f1b
From 434143c2b01c203bf9030669a14055872121b2c0 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 01:39:22 +0100
Subject: improve api errors
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 10 +++++-----
application/controllers/api/v1/file.php | 2 +-
application/helpers/filebin_helper.php | 5 +++--
3 files changed, 9 insertions(+), 8 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index a7bd09f34..7557c6c99 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -24,11 +24,11 @@ class Api extends MY_Controller {
$major = intval(explode(".", $requested_version)[0]);
if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
- return send_json_error_reply("Invalid controller requested");
+ return send_json_error_reply("api/invalid-controller-value", "Invalid controller requested");
}
if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
- return send_json_error_reply("Invalid function requested");
+ return send_json_error_reply("api/invalid-function-value", "Invalid function requested");
}
$namespace = "controllers\\api\\v".$major;
@@ -36,16 +36,16 @@ class Api extends MY_Controller {
$class_info = $namespace."\\api_info";
if (!class_exists($class_info) || version_compare($class_info::get_version(), $requested_version, "<")) {
- return send_json_error_reply("Requested API version is not supported");
+ return send_json_error_reply("api/version-not-supported", "Requested API version is not supported");
}
if (!class_exists($class)) {
- return send_json_error_reply("Unknown controller requested");
+ return send_json_error_reply("api/unknown-controller", "Unknown controller requested");
}
$c= new $class;
if (!method_exists($c, $function)) {
- return send_json_error_reply("Unknown function requested");
+ return send_json_error_reply("api/unknown-function", "Unknown function requested");
}
return $c->$function();
}
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index fc855f7f9..869d29ed1 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -29,7 +29,7 @@ class file extends \controllers\api\api_controller {
$errors = \service\files::verify_uploaded_files($files);
if (!empty($errors)) {
- return send_json_reply($errors, "upload-error");
+ return send_json_error_reply("file/upload-verify-failed", "Failed to verify uploaded file", $errors);
}
$limits = $this->muser->get_upload_id_limits();
diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php
index 465f865f6..a1b540b1d 100644
--- a/application/helpers/filebin_helper.php
+++ b/application/helpers/filebin_helper.php
@@ -235,10 +235,11 @@ function send_json_reply($array, $status = "success")
$CI->output->set_output(json_encode($reply));
}
-function send_json_error_reply($message, $array = null)
+function send_json_error_reply($error_id, $message, $array = null, $status_code = 400)
{
$reply = array();
$reply["status"] = "error";
+ $reply["error_id"] = $error_id;
$reply["message"] = $message;
if ($array !== null) {
@@ -246,7 +247,7 @@ function send_json_error_reply($message, $array = null)
}
$CI =& get_instance();
- $CI->output->set_status_header(400);
+ $CI->output->set_status_header($status_code);
$CI->output->set_content_type('application/json');
$CI->output->set_output(json_encode($reply));
}
--
cgit v1.2.3-24-g4f1b
From 32e68c2dfff62cbdd82950b4b4e20a3c895dfb1f Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 01:39:40 +0100
Subject: add max_files_per_request to api/file/get_config
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 1 +
1 file changed, 1 insertion(+)
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 869d29ed1..515286462 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -52,6 +52,7 @@ class file extends \controllers\api\api_controller {
{
return send_json_reply(array(
"upload_max_size" => $this->config->item("upload_max_size"),
+ "max_files_per_request" => intval(ini_get("max_file_uploads")),
));
}
--
cgit v1.2.3-24-g4f1b
From 8fd7c6c2ab80240ab1d163c9a4134822c7524144 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 01:40:07 +0100
Subject: add initial user api
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/user.php | 24 +++++++++++
application/controllers/user.php | 42 ++----------------
application/service/user.php | 75 +++++++++++++++++++++++++++++++++
3 files changed, 102 insertions(+), 39 deletions(-)
create mode 100644 application/controllers/api/v1/user.php
create mode 100644 application/service/user.php
(limited to 'application')
diff --git a/application/controllers/api/v1/user.php b/application/controllers/api/v1/user.php
new file mode 100644
index 000000000..831fdb883
--- /dev/null
+++ b/application/controllers/api/v1/user.php
@@ -0,0 +1,24 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+namespace controllers\api\v1;
+
+class user extends \controllers\api\api_controller {
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('muser');
+ }
+
+ public function apikeys()
+ {
+ $this->muser->require_access("full");
+ return send_json_reply(\service\user::apikeys($this->muser->get_userid()));
+ }
+}
diff --git a/application/controllers/user.php b/application/controllers/user.php
index a702b63c7..62569e1f1 100644
--- a/application/controllers/user.php
+++ b/application/controllers/user.php
@@ -91,24 +91,7 @@ class User extends MY_Controller {
$access_level = "apikey";
}
- $valid_levels = $this->muser->get_access_levels();
- if (array_search($access_level, $valid_levels) === false) {
- show_error("Invalid access levels requested.");
- }
-
- if (strlen($comment) > 255) {
- show_error("Comment may only be 255 chars long.");
- }
-
- $key = random_alphanum(32);
-
- $this->db->set(array(
- 'key' => $key,
- 'user' => $userid,
- 'comment' => $comment,
- 'access_level' => $access_level
- ))
- ->insert('apikeys');
+ $key = \service\user::create_apikey($userid, $comment, $access_level);
if (static_storage("response_type") == "json") {
return send_json_reply(array("new_key" => $key));
@@ -140,27 +123,8 @@ class User extends MY_Controller {
$this->muser->require_access();
$userid = $this->muser->get_userid();
-
- $query = $this->db->select('key, created, comment, access_level')
- ->from('apikeys')
- ->where('user', $userid)
- ->order_by('created', 'desc')
- ->get()->result_array();
-
- // Convert timestamp to unix timestamp
- // TODO: migrate database to integer timestamp and get rid of this
- foreach ($query as &$record) {
- if (!empty($record['created'])) {
- $record['created'] = strtotime($record['created']);
- }
- }
- unset($record);
-
- if (static_storage("response_type") == "json") {
- return send_json_reply($query);
- }
-
- $this->data["query"] = $query;
+ $apikeys = \service\user::apikeys($userid);
+ $this->data["query"] = $apikeys;
$this->load->view('header', $this->data);
$this->load->view($this->var->view_dir.'apikeys', $this->data);
diff --git a/application/service/user.php b/application/service/user.php
new file mode 100644
index 000000000..d06f78855
--- /dev/null
+++ b/application/service/user.php
@@ -0,0 +1,75 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace service;
+
+class user {
+
+ /**
+ * Create a new api key.
+ *
+ * @param userid TODO
+ * @param comment TODO
+ * @param access_level TODO
+ * @return the new key
+ */
+ static public function create_apikey($userid, $comment, $access_level)
+ {
+ $CI =& get_instance();
+
+
+ $valid_levels = $CI->muser->get_access_levels();
+ if (array_search($access_level, $valid_levels) === false) {
+ show_error("Invalid access levels requested.");
+ }
+
+ if (strlen($comment) > 255) {
+ show_error("Comment may only be 255 chars long.");
+ }
+
+ $key = random_alphanum(32);
+
+ $CI->db->set(array(
+ 'key' => $key,
+ 'user' => $userid,
+ 'comment' => $comment,
+ 'access_level' => $access_level
+ ))
+ ->insert('apikeys');
+
+ return $key;
+ }
+
+ /**
+ * Get apikeys for a user
+ * @param userid TODO
+ * @return array with the key data
+ */
+ static public function apikeys($userid)
+ {
+ $CI =& get_instance();
+
+ $query = $CI->db->select('key, created, comment, access_level')
+ ->from('apikeys')
+ ->where('user', $userid)
+ ->order_by('created', 'desc')
+ ->get()->result_array();
+
+ // Convert timestamp to unix timestamp
+ // TODO: migrate database to integer timestamp and get rid of this
+ foreach ($query as &$record) {
+ if (!empty($record['created'])) {
+ $record['created'] = strtotime($record['created']);
+ }
+ }
+ unset($record);
+
+ return $query;
+ }
+}
--
cgit v1.2.3-24-g4f1b
From c8e5f5a20c9e558efbd5e9c152f086ab72015ba3 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 12:21:27 +0100
Subject: refactor service/file/history
Signed-off-by: Florian Pritz
---
application/service/files.php | 52 +++++++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 24 deletions(-)
(limited to 'application')
diff --git a/application/service/files.php b/application/service/files.php
index 7b320078e..b4bf7b9ee 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -14,36 +14,13 @@ class files {
static public function history($user)
{
$CI =& get_instance();
- $multipaste_items_grouped = array();
- $multipaste_items = array();
$fields = array("id", "filename", "mimetype", "date", "hash", "filesize");
-
$items = $CI->db->select(implode(',', $fields))
->from('files')
->where('user', $user)
->get()->result_array();
- $multipaste_items_query = $CI->db
- ->select("m.url_id, f.filename, f.id, f.filesize, f.date, f.hash, f.mimetype")
- ->from("multipaste m")
- ->join("multipaste_file_map mfm", "m.multipaste_id = mfm.multipaste_id")
- ->join("files f", "f.id = mfm.file_url_id")
- ->where("m.user_id", $user)
- ->get()->result_array();
-
- foreach ($multipaste_items_query as $item) {
- $key = $item["url_id"];
- unset($item["url_id"]);
- $multipaste_items_grouped[$key][] = $item;
- }
-
- foreach ($multipaste_items_grouped as $key => $items) {
- $multipaste_info = $CI->db->get_where("multipaste", array("url_id" => $key))->row_array();
- $multipaste_info["items"] = $items;
- $multipaste_items[] = $multipaste_info;
- }
-
$total_size = $CI->db->query("
SELECT sum(filesize) sum
FROM (
@@ -54,12 +31,39 @@ class files {
", array($user))->row_array();
$ret["items"] = $items;
- $ret["multipaste_items"] = $multipaste_items;
+ $ret["multipaste_items"] = self::get_multipaste_history($user);
$ret["total_size"] = $total_size["sum"];
return $ret;
}
+ static private function get_multipaste_history($user)
+ {
+ $CI =& get_instance();
+ $multipaste_items_grouped = array();
+ $multipaste_items = array();
+
+ $query = $CI->db->get_where("multipaste", array("user_id" => $user))->result_array();
+ $multipaste_info = array();
+ foreach ($query as $item) {
+ $multipaste_info[$item["url_id"]] = $item;
+ }
+
+ $multipaste_items_query = $CI->db
+ ->select("m.url_id, f.id")
+ ->from("multipaste m")
+ ->join("multipaste_file_map mfm", "m.multipaste_id = mfm.multipaste_id")
+ ->join("files f", "f.id = mfm.file_url_id")
+ ->where("m.user_id", $user)
+ ->get()->result_array();
+
+ foreach ($multipaste_items_query as $item) {
+ $multipaste_info[$item["url_id"]]["items"][$item["id"]] = array("id" => $item["id"]);
+ }
+
+ return $multipaste_info;
+ }
+
static public function add_file($id, $file, $filename)
{
$CI =& get_instance();
--
cgit v1.2.3-24-g4f1b
From 01c881fd2c0f0c701a83e135f2142c9db3052422 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 23:35:38 +0100
Subject: fix multipaste in service/history
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 2 +-
application/service/files.php | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 57faa62f2..5fce8afc8 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -643,7 +643,7 @@ class File extends MY_Controller {
foreach ($history["multipaste_items"] as $key => $item) {
$size = 0;
foreach ($item["items"] as $i) {
- $size += $i["filesize"];
+ $size += $history["items"][$i["id"]]["filesize"];
}
$history["items"][] = array(
diff --git a/application/service/files.php b/application/service/files.php
index b4bf7b9ee..8d0760b87 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -14,12 +14,16 @@ class files {
static public function history($user)
{
$CI =& get_instance();
+ $items = array();
$fields = array("id", "filename", "mimetype", "date", "hash", "filesize");
- $items = $CI->db->select(implode(',', $fields))
+ $query = $CI->db->select(implode(',', $fields))
->from('files')
->where('user', $user)
->get()->result_array();
+ foreach ($query as $key => $item) {
+ $items[$item["id"]] = $item;
+ }
$total_size = $CI->db->query("
SELECT sum(filesize) sum
--
cgit v1.2.3-24-g4f1b
From 0bed4fd5c9f67b60173df6638dc524d7b833c4e1 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 11 Jan 2015 23:35:46 +0100
Subject: add some TODOs
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 3 ++-
application/controllers/api/v1/user.php | 5 +++++
application/service/files.php | 1 +
3 files changed, 8 insertions(+), 1 deletion(-)
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 515286462..56455c01e 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -50,6 +50,7 @@ class file extends \controllers\api\api_controller {
public function get_config()
{
+ // TODO: return more fields?
return send_json_reply(array(
"upload_max_size" => $this->config->item("upload_max_size"),
"max_files_per_request" => intval(ini_get("max_file_uploads")),
@@ -67,7 +68,7 @@ class file extends \controllers\api\api_controller {
{
$this->muser->require_access("apikey");
-
+ // TODO: implement
}
}
# vim: set noet:
diff --git a/application/controllers/api/v1/user.php b/application/controllers/api/v1/user.php
index 831fdb883..4c2e5345d 100644
--- a/application/controllers/api/v1/user.php
+++ b/application/controllers/api/v1/user.php
@@ -21,4 +21,9 @@ class user extends \controllers\api\api_controller {
$this->muser->require_access("full");
return send_json_reply(\service\user::apikeys($this->muser->get_userid()));
}
+
+ public function create_apikey()
+ {
+ // TODO: implement
+ }
}
diff --git a/application/service/files.php b/application/service/files.php
index 8d0760b87..8d8b1d01a 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -16,6 +16,7 @@ class files {
$CI =& get_instance();
$items = array();
+ // TODO: thumbnail urls where available
$fields = array("id", "filename", "mimetype", "date", "hash", "filesize");
$query = $CI->db->select(implode(',', $fields))
->from('files')
--
cgit v1.2.3-24-g4f1b
From 33efe571e3e7ebd607e92345c2e94e7fd8ae27f0 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Mon, 2 Feb 2015 19:45:11 +0100
Subject: Rework api error handling
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 62 ++++++++++++++-------------
application/controllers/api/v1/file.php | 4 +-
application/exceptions/ApiException.php | 30 +++++++++++++
application/exceptions/PublicApiException.php | 10 +++++
application/service/user.php | 4 +-
5 files changed, 77 insertions(+), 33 deletions(-)
create mode 100644 application/exceptions/ApiException.php
create mode 100644 application/exceptions/PublicApiException.php
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index 7557c6c99..490f59c2c 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -18,35 +18,39 @@ class Api extends MY_Controller {
}
public function route() {
- $requested_version = $this->uri->segment(2);
- $controller = $this->uri->segment(3);
- $function = $this->uri->segment(4);
- $major = intval(explode(".", $requested_version)[0]);
-
- if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
- return send_json_error_reply("api/invalid-controller-value", "Invalid controller requested");
- }
-
- if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
- return send_json_error_reply("api/invalid-function-value", "Invalid function requested");
- }
-
- $namespace = "controllers\\api\\v".$major;
- $class = $namespace."\\".$controller;
- $class_info = $namespace."\\api_info";
-
- if (!class_exists($class_info) || version_compare($class_info::get_version(), $requested_version, "<")) {
- return send_json_error_reply("api/version-not-supported", "Requested API version is not supported");
- }
-
- if (!class_exists($class)) {
- return send_json_error_reply("api/unknown-controller", "Unknown controller requested");
- }
-
- $c= new $class;
- if (!method_exists($c, $function)) {
- return send_json_error_reply("api/unknown-function", "Unknown function requested");
+ try {
+ $requested_version = $this->uri->segment(2);
+ $controller = $this->uri->segment(3);
+ $function = $this->uri->segment(4);
+ $major = intval(explode(".", $requested_version)[0]);
+
+ if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
+ throw new \exceptions\PublicApiException("api/invalid-controller-value", "Invalid controller requested");
+ }
+
+ if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
+ throw new \exceptions\PublicApiException("api/invalid-function-value", "Invalid function requested");
+ }
+
+ $namespace = "controllers\\api\\v".$major;
+ $class = $namespace."\\".$controller;
+ $class_info = $namespace."\\api_info";
+
+ if (!class_exists($class_info) || version_compare($class_info::get_version(), $requested_version, "<")) {
+ throw new \exceptions\PublicApiException("api/version-not-supported", "Requested API version is not supported");
+ }
+
+ if (!class_exists($class)) {
+ throw new \exceptions\PublicApiException("api/unknown-controller", "Unknown controller requested");
+ }
+
+ $c= new $class;
+ if (!method_exists($c, $function)) {
+ throw new \exceptions\PublicApiException("api/unknown-function", "Unknown function requested");
+ }
+ return $c->$function();
+ } catch (\exceptions\PublicApiException $e) {
+ return send_json_error_reply($e->get_error_id(), $e->getMessage(), $e->get_data());
}
- return $c->$function();
}
}
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 56455c01e..c291ae879 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -24,12 +24,12 @@ class file extends \controllers\api\api_controller {
$files = getNormalizedFILES();
if (empty($files)) {
- show_error("No file was uploaded or unknown error occured.");
+ throw new \exceptions\PublicApiException("file/no-file", "No file was uploaded or unknown error occured.");
}
$errors = \service\files::verify_uploaded_files($files);
if (!empty($errors)) {
- return send_json_error_reply("file/upload-verify-failed", "Failed to verify uploaded file", $errors);
+ throw new \exceptions\PublicApiException("file/upload-verify-failed", "Failed to verify uploaded file", $errors);
}
$limits = $this->muser->get_upload_id_limits();
diff --git a/application/exceptions/ApiException.php b/application/exceptions/ApiException.php
new file mode 100644
index 000000000..b288bbaa2
--- /dev/null
+++ b/application/exceptions/ApiException.php
@@ -0,0 +1,30 @@
+error_id = $error_id;
+ $this->data = $data;
+ }
+
+ public function get_error_id()
+ {
+ return $this->error_id;
+ }
+
+ public function get_data()
+ {
+ return $this->data;
+ }
+}
diff --git a/application/exceptions/PublicApiException.php b/application/exceptions/PublicApiException.php
new file mode 100644
index 000000000..e7aa4360a
--- /dev/null
+++ b/application/exceptions/PublicApiException.php
@@ -0,0 +1,10 @@
+muser->get_access_levels();
if (array_search($access_level, $valid_levels) === false) {
- show_error("Invalid access levels requested.");
+ throw new \exceptions\UserInputException("user/validation/access_level/invalid", "Invalid access levels requested.");
}
if (strlen($comment) > 255) {
- show_error("Comment may only be 255 chars long.");
+ throw new \exceptions\UserInputException("user/validation/comment/too-long", "Comment may only be 255 chars long.");
}
$key = random_alphanum(32);
--
cgit v1.2.3-24-g4f1b
From cb52a4cdc2daa45a61c728f5ec83603e6c6a71fa Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 00:23:12 +0100
Subject: Rework error handling in upload validator
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 5 +----
application/controllers/file.php | 14 +------------
.../exceptions/FileUploadVerifyException.php | 23 ++++++++++++++++++++++
application/exceptions/PublicApiException.php | 4 ++++
application/exceptions/UserInputException.php | 10 ++++++++++
application/service/files.php | 8 +++++---
application/service/user.php | 1 -
7 files changed, 44 insertions(+), 21 deletions(-)
create mode 100644 application/exceptions/FileUploadVerifyException.php
create mode 100644 application/exceptions/UserInputException.php
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index c291ae879..82060e420 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -27,10 +27,7 @@ class file extends \controllers\api\api_controller {
throw new \exceptions\PublicApiException("file/no-file", "No file was uploaded or unknown error occured.");
}
- $errors = \service\files::verify_uploaded_files($files);
- if (!empty($errors)) {
- throw new \exceptions\PublicApiException("file/upload-verify-failed", "Failed to verify uploaded file", $errors);
- }
+ \service\files::verify_uploaded_files($files);
$limits = $this->muser->get_upload_id_limits();
$urls = array();
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 5fce8afc8..e35978a1e 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -897,19 +897,7 @@ class File extends MY_Controller {
$files = getNormalizedFILES();
- if (empty($files)) {
- show_error("No file was uploaded or unknown error occured.");
- }
-
- $errors = service\files::verify_uploaded_files($files);
- if (!empty($errors)) {
- $messages = array();
- foreach ($errors as $error) {
- $messages[] = htmlspecialchars($error["filename"]).": ".$error["message"];
- }
- show_error("Error(s) occured while uploading:
".implode("
", $messages), 400);
- }
-
+ service\files::verify_uploaded_files($files);
$limits = $this->muser->get_upload_id_limits();
foreach ($files as $key => $file) {
diff --git a/application/exceptions/FileUploadVerifyException.php b/application/exceptions/FileUploadVerifyException.php
new file mode 100644
index 000000000..d091c1eab
--- /dev/null
+++ b/application/exceptions/FileUploadVerifyException.php
@@ -0,0 +1,23 @@
+getMessage()."\n";
+ $data = $this->get_data();
+ $errors = array();
+
+ foreach ($data as $error) {
+ $errors[] = sprintf("%s: %s", $error["filename"], $error["message"]);
+ }
+
+ $ret .= implode("\n", $errors);
+ return $ret;
+ }
+}
diff --git a/application/exceptions/PublicApiException.php b/application/exceptions/PublicApiException.php
index e7aa4360a..d22309478 100644
--- a/application/exceptions/PublicApiException.php
+++ b/application/exceptions/PublicApiException.php
@@ -7,4 +7,8 @@
namespace exceptions;
class PublicApiException extends ApiException {
+ public function __toString()
+ {
+ return $this->getMessage();
+ }
}
diff --git a/application/exceptions/UserInputException.php b/application/exceptions/UserInputException.php
new file mode 100644
index 000000000..150d0204b
--- /dev/null
+++ b/application/exceptions/UserInputException.php
@@ -0,0 +1,10 @@
+ $file) {
$error_message = "";
@@ -113,7 +117,6 @@ class files {
} else {
$error_message = "Unknown error code: ".$file['error'].". Please report a bug.";
}
-
}
$filesize = filesize($file['tmp_name']);
@@ -127,9 +130,8 @@ class files {
"formfield" => $file["formfield"],
"message" => $error_message,
);
+ throw new \exceptions\FileUploadVerifyException("file/upload-verify", "Failed to verify uploaded file(s)", $errors);
}
}
-
- return $errors;
}
}
diff --git a/application/service/user.php b/application/service/user.php
index 97f2531f9..16fa62272 100644
--- a/application/service/user.php
+++ b/application/service/user.php
@@ -23,7 +23,6 @@ class user {
{
$CI =& get_instance();
-
$valid_levels = $CI->muser->get_access_levels();
if (array_search($access_level, $valid_levels) === false) {
throw new \exceptions\UserInputException("user/validation/access_level/invalid", "Invalid access levels requested.");
--
cgit v1.2.3-24-g4f1b
From e2c2740365b1f25beca1e174c8c5bda2950b7466 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 00:44:46 +0100
Subject: implement api/user/create_apikey
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/user.php | 14 ++++++++++++--
application/core/MY_Controller.php | 8 +++++++-
2 files changed, 19 insertions(+), 3 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api/v1/user.php b/application/controllers/api/v1/user.php
index 4c2e5345d..39c833d86 100644
--- a/application/controllers/api/v1/user.php
+++ b/application/controllers/api/v1/user.php
@@ -21,9 +21,19 @@ class user extends \controllers\api\api_controller {
$this->muser->require_access("full");
return send_json_reply(\service\user::apikeys($this->muser->get_userid()));
}
-
+
public function create_apikey()
{
- // TODO: implement
+ $this->muser->require_access("full");
+ $userid = $this->muser->get_userid();
+ $comment = $this->input->post("comment");
+ $comment = $comment === false ? "" : $comment;
+ $access_level = $this->input->post("access_level");
+
+ $key = \service\user::create_apikey($userid, $comment, $access_level);
+
+ return send_json_reply(array(
+ "new_key" => $key,
+ ));
}
}
diff --git a/application/core/MY_Controller.php b/application/core/MY_Controller.php
index 1e724a865..fc08b10ae 100644
--- a/application/core/MY_Controller.php
+++ b/application/core/MY_Controller.php
@@ -66,7 +66,13 @@ class MY_Controller extends CI_Controller {
show_error("Function not JSON enabled");
}
- if ($this->input->post("apikey") !== false) {
+ if ($this->uri->segment(1) == "api") {
+ is_cli_client(true);
+ }
+
+ if ($this->input->post("apikey") !== false
+ || ($this->input->post("username") !== false
+ && $this->input->post("password") !== false)) {
/* This relies on the authentication code always verifying the supplied
* apikey. If the key is not verified/logged in an attacker could simply
* add an empty "apikey" field to the CSRF form to circumvent the
--
cgit v1.2.3-24-g4f1b
From 6816970229c6d0bd46ba46ecd70199c0687952da Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 11:12:01 +0100
Subject: api: handle json reply in api controller
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 2 +-
application/controllers/api/v1/file.php | 10 +++++-----
application/controllers/api/v1/user.php | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index 490f59c2c..dc31f47d2 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -48,7 +48,7 @@ class Api extends MY_Controller {
if (!method_exists($c, $function)) {
throw new \exceptions\PublicApiException("api/unknown-function", "Unknown function requested");
}
- return $c->$function();
+ return send_json_reply($c->$function());
} catch (\exceptions\PublicApiException $e) {
return send_json_error_reply($e->get_error_id(), $e->getMessage(), $e->get_data());
}
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 82060e420..3aafd4732 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -39,26 +39,26 @@ class file extends \controllers\api\api_controller {
$urls[] = site_url($id).'/';
}
- return send_json_reply(array(
+ return array(
"ids" => $ids,
"urls" => $urls,
- ));
+ );
}
public function get_config()
{
// TODO: return more fields?
- return send_json_reply(array(
+ return array(
"upload_max_size" => $this->config->item("upload_max_size"),
"max_files_per_request" => intval(ini_get("max_file_uploads")),
- ));
+ );
}
public function history()
{
$this->muser->require_access("apikey");
$history = \service\files::history($this->muser->get_userid());
- return send_json_reply($history);
+ return $history;
}
public function delete()
diff --git a/application/controllers/api/v1/user.php b/application/controllers/api/v1/user.php
index 39c833d86..e49b7c657 100644
--- a/application/controllers/api/v1/user.php
+++ b/application/controllers/api/v1/user.php
@@ -19,7 +19,7 @@ class user extends \controllers\api\api_controller {
public function apikeys()
{
$this->muser->require_access("full");
- return send_json_reply(\service\user::apikeys($this->muser->get_userid()));
+ return \service\user::apikeys($this->muser->get_userid());
}
public function create_apikey()
@@ -32,8 +32,8 @@ class user extends \controllers\api\api_controller {
$key = \service\user::create_apikey($userid, $comment, $access_level);
- return send_json_reply(array(
+ return array(
"new_key" => $key,
- ));
+ );
}
}
--
cgit v1.2.3-24-g4f1b
From 9ea78213f8e505b5fde7372106adc1947d1f7de2 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 11:14:29 +0100
Subject: Improve general exception handling
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 3 +++
1 file changed, 3 insertions(+)
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index dc31f47d2..3297f0614 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -51,6 +51,9 @@ class Api extends MY_Controller {
return send_json_reply($c->$function());
} catch (\exceptions\PublicApiException $e) {
return send_json_error_reply($e->get_error_id(), $e->getMessage(), $e->get_data());
+ } catch (\Exception $e) {
+ _log_exception($e);
+ return send_json_error_reply("internal-error", "An unhandled internal server error occured");
}
}
}
--
cgit v1.2.3-24-g4f1b
From d9c895ce4f53b180fc11c3b5a172c4cf787b1279 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 11:18:28 +0100
Subject: Remove unstable json api
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 20 --------------------
application/controllers/user.php | 9 ---------
application/core/MY_Controller.php | 29 ++---------------------------
application/errors/error_general.php | 11 -----------
4 files changed, 2 insertions(+), 67 deletions(-)
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index e35978a1e..63f6a71b5 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -9,13 +9,6 @@
class File extends MY_Controller {
- protected $json_enabled_functions = array(
- "upload_history",
- "do_upload",
- "do_delete",
- "do_multipaste",
- );
-
function __construct()
{
parent::__construct();
@@ -470,10 +463,6 @@ class File extends MY_Controller {
}
}
- if (static_storage("response_type") == "json") {
- return send_json_reply($this->data["urls"]);
- }
-
if (is_cli_client()) {
$redirect = false;
}
@@ -740,15 +729,6 @@ class File extends MY_Controller {
);
}
- if (static_storage("response_type") == "json") {
- return send_json_reply(array(
- "errors" => $errors,
- "deleted" => $deleted,
- "total_count" => $total_count,
- "deleted_count" => $deleted_count,
- ));
- }
-
$this->data["errors"] = $errors;
$this->data["deleted_count"] = $deleted_count;
$this->data["total_count"] = $total_count;
diff --git a/application/controllers/user.php b/application/controllers/user.php
index 62569e1f1..aba2a8ec1 100644
--- a/application/controllers/user.php
+++ b/application/controllers/user.php
@@ -8,11 +8,6 @@
*/
class User extends MY_Controller {
- protected $json_enabled_functions = array(
- "create_apikey",
- "apikeys",
- );
-
function __construct()
{
@@ -93,10 +88,6 @@ class User extends MY_Controller {
$key = \service\user::create_apikey($userid, $comment, $access_level);
- if (static_storage("response_type") == "json") {
- return send_json_reply(array("new_key" => $key));
- }
-
if (is_cli_client()) {
echo "$key\n";
} else {
diff --git a/application/core/MY_Controller.php b/application/core/MY_Controller.php
index fc08b10ae..0f71a7fdc 100644
--- a/application/core/MY_Controller.php
+++ b/application/core/MY_Controller.php
@@ -11,9 +11,6 @@ class MY_Controller extends CI_Controller {
public $data = array();
public $var;
- protected $json_enabled_functions = array(
- );
-
function __construct()
{
parent::__construct();
@@ -46,33 +43,11 @@ class MY_Controller extends CI_Controller {
$this->load->helper(array('form', 'filebin'));
$this->load->library('customautoloader');
- // TODO: proper accept header handling or is this enough?
- if (isset($_SERVER["HTTP_ACCEPT"])) {
- if ($_SERVER["HTTP_ACCEPT"] == "application/json") {
- static_storage("response_type", "json");
- }
- }
-
- // Allow for easier testing in browser
- if ($this->input->get("json") !== false) {
- static_storage("response_type", "json");
- }
-
- // TODO: this should probably call a function in the controller that does the checking
- // instead of checking if the controller name == "api"
- if (static_storage("response_type") == "json"
- && $this->uri->segment(1) != "api"
- && ! in_array($this->uri->rsegment(2), $this->json_enabled_functions)) {
- show_error("Function not JSON enabled");
- }
-
if ($this->uri->segment(1) == "api") {
is_cli_client(true);
}
- if ($this->input->post("apikey") !== false
- || ($this->input->post("username") !== false
- && $this->input->post("password") !== false)) {
+ if ($this->input->post("apikey") !== false || is_cli_client()) {
/* This relies on the authentication code always verifying the supplied
* apikey. If the key is not verified/logged in an attacker could simply
* add an empty "apikey" field to the CSRF form to circumvent the
@@ -119,7 +94,7 @@ class MY_Controller extends CI_Controller {
$this->security->csrf_verify();
}
- if ($this->config->item("environment") == "development" && static_storage("response_type") != "json") {
+ if ($this->config->item("environment") == "development") {
$this->output->enable_profiler(true);
}
diff --git a/application/errors/error_general.php b/application/errors/error_general.php
index 844dfb74d..87d5b62f6 100644
--- a/application/errors/error_general.php
+++ b/application/errors/error_general.php
@@ -15,17 +15,6 @@ if (class_exists("CI_Controller") && !isset($GLOBALS["is_error_page"])) {
is_cli_client(true);
}
- if (static_storage("response_type") == "json") {
- $message = str_replace("
", "\n", $message);
- $array = array(
- "status" => "error",
- "message" => strip_tags($message),
- );
- header('Content-type: application/json');
- echo json_encode($array);
- exit();
- }
-
if (is_cli_client()) {
$message = str_replace("", "\n", $message);
$message = strip_tags($message);
--
cgit v1.2.3-24-g4f1b
From a788fe55713e7c44068ee2dd8377b98037d9375f Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 11:38:03 +0100
Subject: api: implement file/delete
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 4 +--
application/controllers/file.php | 51 +++------------------------
application/service/files.php | 62 +++++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+), 49 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 3aafd4732..0035d0a02 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -64,8 +64,8 @@ class file extends \controllers\api\api_controller {
public function delete()
{
$this->muser->require_access("apikey");
-
- // TODO: implement
+ $ids = $this->input->post("ids");
+ return \service\files::delete($ids);
}
}
# vim: set noet:
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 63f6a71b5..1b45c1ba3 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -683,55 +683,12 @@ class File extends MY_Controller {
$this->muser->require_access("apikey");
$ids = $this->input->post("ids");
- $userid = $this->muser->get_userid();
- $errors = array();
- $deleted = array();
- $deleted_count = 0;
- $total_count = 0;
-
- if (!$ids || !is_array($ids)) {
- show_error("No IDs specified");
- }
- foreach ($ids as $id) {
- $total_count++;
- $next = false;
-
- foreach (array($this->mfile, $this->mmultipaste) as $model) {
- if ($model->id_exists($id)) {
- if ($model->get_owner($id) !== $userid) {
- $errors[] = array(
- "id" => $id,
- "reason" => "wrong owner",
- );
- continue;
- }
- if ($model->delete_id($id)) {
- $deleted[] = $id;
- $deleted_count++;
- $next = true;
- } else {
- $errors[] = array(
- "id" => $id,
- "reason" => "unknown error",
- );
- }
- }
- }
-
- if ($next) {
- continue;
- }
-
- $errors[] = array(
- "id" => $id,
- "reason" => "doesn't exist",
- );
- }
+ $ret = \service\files::delete($ids);
- $this->data["errors"] = $errors;
- $this->data["deleted_count"] = $deleted_count;
- $this->data["total_count"] = $total_count;
+ $this->data["errors"] = $ret["errors"];
+ $this->data["deleted_count"] = $ret["deleted_count"];
+ $this->data["total_count"] = $ret["total_count"];
$this->load->view('header', $this->data);
$this->load->view($this->var->view_dir.'/deleted', $this->data);
diff --git a/application/service/files.php b/application/service/files.php
index c270500ef..3fa73c5ca 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -134,4 +134,66 @@ class files {
}
}
}
+
+ // TODO: streamline this interface to be somewhat atomic in regards to
+ // wrong owner/unknown ids (verify first and throw exception)
+ static public function delete($ids)
+ {
+ $CI =& get_instance();
+
+ $userid = $CI->muser->get_userid();
+ $errors = array();
+ $deleted = array();
+ $deleted_count = 0;
+ $total_count = 0;
+
+ if (!$ids || !is_array($ids)) {
+ throw new \exceptions\UserInputException("file/delete/no-ids", "No IDs specified");
+ }
+
+ foreach ($ids as $id) {
+ $total_count++;
+ $next = false;
+
+ foreach (array($CI->mfile, $CI->mmultipaste) as $model) {
+ if ($model->id_exists($id)) {
+ if ($model->get_owner($id) !== $userid) {
+ $errors[$id] = array(
+ "id" => $id,
+ "reason" => "wrong owner",
+ );
+ continue;
+ }
+ if ($model->delete_id($id)) {
+ $deleted[$id] = array(
+ "id" => $id,
+ );
+ $deleted_count++;
+ $next = true;
+ } else {
+ $errors[$id] = array(
+ "id" => $id,
+ "reason" => "unknown error",
+ );
+ }
+ }
+ }
+
+ if ($next) {
+ continue;
+ }
+
+ $errors[$id] = array(
+ "id" => $id,
+ "reason" => "doesn't exist",
+ );
+ }
+
+ return array(
+ "errors" => $errors,
+ "deleted" => $deleted,
+ "total_count" => $total_count,
+ "deleted_count" => $deleted_count,
+ );
+ }
}
--
cgit v1.2.3-24-g4f1b
From 5816cbcad0e9c4cda4dc10b730a5a1ea2c4e419a Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 12:11:28 +0100
Subject: api: implement file/create_multipaste
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 10 ++++
application/controllers/file.php | 49 ++------------------
.../exceptions/FileUploadVerifyException.php | 2 +-
application/exceptions/VerifyException.php | 23 ++++++++++
application/service/files.php | 53 ++++++++++++++++++++++
5 files changed, 90 insertions(+), 47 deletions(-)
create mode 100644 application/exceptions/VerifyException.php
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index 0035d0a02..fc5565416 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -67,5 +67,15 @@ class file extends \controllers\api\api_controller {
$ids = $this->input->post("ids");
return \service\files::delete($ids);
}
+
+ public function create_multipaste()
+ {
+ $this->muser->require_access("apikey");
+ $ids = $this->input->post("ids");
+ $userid = $this->muser->get_userid();
+ $limits = $this->muser->get_upload_id_limits();
+
+ return \service\files::create_multipaste($ids, $userid, $limits);
+ }
}
# vim: set noet:
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 1b45c1ba3..c60831cba 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -700,55 +700,12 @@ class File extends MY_Controller {
$this->muser->require_access("apikey");
$ids = $this->input->post("ids");
- $errors = array();
-
- if (!$ids || !is_array($ids)) {
- show_error("No IDs specified");
- }
-
- if (count(array_unique($ids)) != count($ids)) {
- show_error("Duplicate IDs are not supported");
- }
-
- foreach ($ids as $id) {
- if (!$this->mfile->id_exists($id)) {
- $errors[] = array(
- "id" => $id,
- "reason" => "doesn't exist",
- );
- }
-
- $filedata = $this->mfile->get_filedata($id);
- if ($filedata["user"] != $this->muser->get_userid()) {
- $errors[] = array(
- "id" => $id,
- "reason" => "not owned by you",
- );
- }
- }
-
- if (!empty($errors)) {
- $errorstring = "";
- foreach ($errors as $error) {
- $errorstring .= $error["id"]." ".$error["reason"]."
\n";
- }
- show_error($errorstring);
- }
-
+ $userid = $this->muser->get_userid();
$limits = $this->muser->get_upload_id_limits();
- $url_id = $this->mmultipaste->new_id($limits[0], $limits[1]);
-
- $multipaste_id = $this->mmultipaste->get_multipaste_id($url_id);
- assert($multipaste_id !== false);
- foreach ($ids as $id) {
- $this->db->insert("multipaste_file_map", array(
- "file_url_id" => $id,
- "multipaste_id" => $multipaste_id,
- ));
- }
+ $ret = \service\files::create_multipaste($ids, $userid, $limits);
- return $this->_show_url(array($url_id), false);
+ return $this->_show_url(array($ret["url_id"]), false);
}
function delete()
diff --git a/application/exceptions/FileUploadVerifyException.php b/application/exceptions/FileUploadVerifyException.php
index d091c1eab..5125e4822 100644
--- a/application/exceptions/FileUploadVerifyException.php
+++ b/application/exceptions/FileUploadVerifyException.php
@@ -6,7 +6,7 @@
*/
namespace exceptions;
-class FileUploadVerifyException extends UserInputException {
+class FileUploadVerifyException extends VerifyException {
public function __toString()
{
$ret = $this->getMessage()."\n";
diff --git a/application/exceptions/VerifyException.php b/application/exceptions/VerifyException.php
new file mode 100644
index 000000000..0e9d8b93a
--- /dev/null
+++ b/application/exceptions/VerifyException.php
@@ -0,0 +1,23 @@
+getMessage()."\n";
+ $data = $this->get_data();
+ $errors = array();
+
+ foreach ($data as $error) {
+ $errors[] = sprintf("%s: %s", $error["id"], $error["reason"]);
+ }
+
+ $ret .= implode("\n", $errors);
+ return $ret;
+ }
+}
diff --git a/application/service/files.php b/application/service/files.php
index 3fa73c5ca..b4b7759e0 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -196,4 +196,57 @@ class files {
"deleted_count" => $deleted_count,
);
}
+
+ static public function create_multipaste($ids, $userid, $limits)
+ {
+ $CI =& get_instance();
+
+ if (!$ids || !is_array($ids)) {
+ throw new \exceptions\UserInputException("file/create_multipaste/no-ids", "No IDs specified");
+ }
+
+ if (count(array_unique($ids)) != count($ids)) {
+ throw new \exceptions\UserInputException("file/create_multipaste/duplicate_id", "Duplicate IDs are not supported");
+ }
+
+ $errors = array();
+
+ foreach ($ids as $id) {
+ if (!$CI->mfile->id_exists($id)) {
+ $errors[$id] = array(
+ "id" => $id,
+ "reason" => "doesn't exist",
+ );
+ continue;
+ }
+
+ $filedata = $CI->mfile->get_filedata($id);
+ if ($filedata["user"] != $userid) {
+ $errors[$id] = array(
+ "id" => $id,
+ "reason" => "not owned by you",
+ );
+ }
+ }
+
+ if (!empty($errors)) {
+ throw new \exceptions\VerifyException("file/create_multipaste/verify-failed", "Failed to verify ID(s)", $errors);
+ }
+
+ $url_id = $CI->mmultipaste->new_id($limits[0], $limits[1]);
+
+ $multipaste_id = $CI->mmultipaste->get_multipaste_id($url_id);
+ assert($multipaste_id !== false);
+
+ foreach ($ids as $id) {
+ $CI->db->insert("multipaste_file_map", array(
+ "file_url_id" => $id,
+ "multipaste_id" => $multipaste_id,
+ ));
+ }
+
+ return array(
+ "url_id" => $url_id,
+ );
+ }
}
--
cgit v1.2.3-24-g4f1b
From bcd7920b817b60df9b1b266118419e44c39900db Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 13:59:59 +0100
Subject: generalize authentication handling
Signed-off-by: Florian Pritz
---
application/exceptions/ApiException.php | 5 +++++
.../InsufficientPermissionsException.php | 14 ++++++++++++++
.../exceptions/NotAuthenticatedException.php | 14 ++++++++++++++
application/exceptions/UserInputException.php | 4 ++++
application/models/muser.php | 22 ++++++++++------------
5 files changed, 47 insertions(+), 12 deletions(-)
create mode 100644 application/exceptions/InsufficientPermissionsException.php
create mode 100644 application/exceptions/NotAuthenticatedException.php
(limited to 'application')
diff --git a/application/exceptions/ApiException.php b/application/exceptions/ApiException.php
index b288bbaa2..b3b9decff 100644
--- a/application/exceptions/ApiException.php
+++ b/application/exceptions/ApiException.php
@@ -27,4 +27,9 @@ class ApiException extends \Exception {
{
return $this->data;
}
+
+ public function get_http_error_code()
+ {
+ return 500;
+ }
}
diff --git a/application/exceptions/InsufficientPermissionsException.php b/application/exceptions/InsufficientPermissionsException.php
new file mode 100644
index 000000000..a036edf9d
--- /dev/null
+++ b/application/exceptions/InsufficientPermissionsException.php
@@ -0,0 +1,14 @@
+access_levels);
if ($wanted === false || $have === false) {
- show_error("Failed to determine access level");
+ throw new \exceptions\PublicApiException("api/invalid-accesslevel", "Failed to determine access level");
}
if ($have >= $wanted) {
- return true;
+ return;
}
- show_error("Access denied: Access level too low", 403);
+ throw new \exceptions\InsufficientPermissionsException("api/insufficient-permissions", "Access denied: Access level too low");
}
function require_access($wanted_level = "full")
@@ -184,17 +184,15 @@ class Muser extends CI_Model {
return $this->check_access_level($wanted_level);
}
- if (!stateful_client()) {
- show_error("Not authenticated. FileBin requires you to have an account, please go to the homepage for more information.\n", 401);
+ if (stateful_client()) {
+ // desktop clients get redirected to the login form
+ $this->require_session();
+ if (!$this->session->userdata("flash:new:uri")) {
+ $this->session->set_flashdata("uri", $this->uri->uri_string());
+ }
}
- // desktop clients get redirected to the login form
- $this->require_session();
- if (!$this->session->userdata("flash:new:uri")) {
- $this->session->set_flashdata("uri", $this->uri->uri_string());
- }
- redirect('user/login');
- exit();
+ throw new \exceptions\NotAuthenticatedException("api/not-authenticated", "Not authenticated. FileBin requires you to have an account, please go to the homepage for more information.");
}
function username_exists($username)
--
cgit v1.2.3-24-g4f1b
From 08dbb3590d64a5c1bf8981f275e47aef84acb4e0 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 14:00:56 +0100
Subject: use function instead of variable
Signed-off-by: Florian Pritz
---
application/models/muser.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/models/muser.php b/application/models/muser.php
index fb8abad8b..398253c6a 100644
--- a/application/models/muser.php
+++ b/application/models/muser.php
@@ -156,8 +156,8 @@ class Muser extends CI_Model {
{
$session_level = $this->session->userdata("access_level");
- $wanted = array_search($wanted_level, $this->access_levels);
- $have = array_search($session_level, $this->access_levels);
+ $wanted = array_search($wanted_level, $this->get_access_levels());
+ $have = array_search($session_level, $this->get_access_levels());
if ($wanted === false || $have === false) {
throw new \exceptions\PublicApiException("api/invalid-accesslevel", "Failed to determine access level");
--
cgit v1.2.3-24-g4f1b
From a842392c30e9ef1d1d2bd9b4eb271c3fd23b853f Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 17:17:27 +0100
Subject: Use exceptions instead of show_error
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 22 ++++++++++++----------
application/controllers/tools.php | 4 ++--
application/controllers/user.php | 10 +++++-----
application/core/MY_Controller.php | 7 ++++---
application/exceptions/NotFoundException.php | 14 ++++++++++++++
application/exceptions/RequestTooBigException.php | 14 ++++++++++++++
.../Ddownload/drivers/Ddownload_lighttpd.php | 2 +-
.../Ddownload/drivers/Ddownload_nginx.php | 2 +-
application/libraries/Duser/Duser.php | 2 +-
application/libraries/Duser/drivers/Duser_db.php | 2 +-
application/libraries/Duser/drivers/Duser_ldap.php | 2 +-
application/libraries/Image.php | 4 ++--
application/migrations/012_add_constraints.php | 2 +-
application/migrations/013_add_multipaste.php | 2 +-
application/models/mfile.php | 2 +-
application/models/mmultipaste.php | 2 +-
application/models/muser.php | 6 +++---
17 files changed, 65 insertions(+), 34 deletions(-)
create mode 100644 application/exceptions/NotFoundException.php
create mode 100644 application/exceptions/RequestTooBigException.php
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index c60831cba..538155c55 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -108,7 +108,7 @@ class File extends MY_Controller {
default:
if ($is_multipaste) {
- show_error("Invalid action \"".htmlspecialchars($lexer)."\"");
+ throw new \exceptions\UserInputException("file/download/invalid-action", "Invalid action \"".htmlspecialchars($lexer)."\"");
}
break;
}
@@ -384,7 +384,7 @@ class File extends MY_Controller {
}
if ($total_size > $this->config->item("tarball_max_size")) {
- show_error("Tarball too large, refusing to create.");
+ throw new \exceptions\PublicApiException("file/tarball/tarball-filesize-limit", "Tarball too large, refusing to create.");
}
$tmpfile = $archive->begin();
@@ -554,7 +554,7 @@ class File extends MY_Controller {
$filedata = $this->mfile->get_filedata($id);
if (!$filedata) {
- show_error("Failed to get file data");
+ throw new \exceptions\ApiException("file/thumbnail/filedata-unavailable", "Failed to get file data");
}
$cache_key = $filedata['hash'].'_thumb_'.$thumb_size;
@@ -566,7 +566,7 @@ class File extends MY_Controller {
$thumb = $img->get(IMAGETYPE_JPEG);
if ($thumb === false) {
- show_error("Failed to generate thumbnail");
+ throw new \exceptions\PublicApiException("file/thumbnail/generation-failed", "Failed to generate thumbnail");
}
return $thumb;
@@ -713,7 +713,7 @@ class File extends MY_Controller {
$this->muser->require_access("apikey");
if (!is_cli_client()) {
- show_error("Not a listed cli client, please use the history to delete uploads.\n", 403);
+ throw new \exceptions\InsufficientPermissionsException("file/delete/unlisted-client", "Not a listed cli client, please use the history to delete uploads");
}
$id = $this->uri->segment(3);
@@ -735,7 +735,9 @@ class File extends MY_Controller {
}
}
- show_error("Unknown ID '$id'.", 404);
+ throw new \exceptions\NotFoundException("file/delete/unknown-id", "Unknown ID '$id'.", array(
+ "id" => $id,
+ ));
}
// Handle pastes
@@ -754,11 +756,11 @@ class File extends MY_Controller {
$filename = "stdin";
if (!$content) {
- show_error("Nothing was pasted, content is empty.", 400);
+ throw new \exceptions\UserInputException("file/do_paste/empty-input", "Nothing was pasted, content is empty.");
}
if ($filesize > $this->config->item('upload_max_size')) {
- show_error("Error while uploading: File too big", 413);
+ throw new \exceptions\RequestTooBigException("file/do_paste/request-too-big", "Error while uploading: File too big");
}
// FIXME: this duplicates service\files::add_file (kind of)
@@ -840,7 +842,7 @@ class File extends MY_Controller {
$last_upload = $this->session->userdata("last_upload");
if ($last_upload === false) {
- show_error("Failed to get last upload data");
+ throw new \exceptions\PublicApiException("file/claim_id/last_upload-failed", "Failed to get last upload data, unable to claim uploads");
}
$ids = $last_upload["ids"];
@@ -859,7 +861,7 @@ class File extends MY_Controller {
}
if (!empty($errors)) {
- show_error("Someone already owns '".implode(", ", $errors)."', can't reassign.");
+ throw new \exceptions\PublicApiException("file/claim_id/already-owned", "Someone already owns '".implode(", ", $errors)."', can't reassign.");
}
$this->session->unset_userdata("last_upload");
diff --git a/application/controllers/tools.php b/application/controllers/tools.php
index b80dc5024..8c0785409 100644
--- a/application/controllers/tools.php
+++ b/application/controllers/tools.php
@@ -15,7 +15,7 @@ class Tools extends MY_Controller {
$this->load->model('mfile');
if (!$this->input->is_cli_request()) {
- show_error("This can only be called via CLI");
+ throw new \exceptions\ApiException("api/cli-only", "This can only be called via CLI");
}
}
@@ -39,7 +39,7 @@ class Tools extends MY_Controller {
{
$this->load->library('migration');
if ( ! $this->migration->current()) {
- show_error($this->migration->error_string());
+ throw new \exceptions\ApiException("tools/update_database/migration-error", $this->migration->error_string());
}
}
}
diff --git a/application/controllers/user.php b/application/controllers/user.php
index aba2a8ec1..5b4e85141 100644
--- a/application/controllers/user.php
+++ b/application/controllers/user.php
@@ -136,7 +136,7 @@ class User extends MY_Controller {
->count_all_results();
if ($invitations + 1 > 3) {
- show_error("You can't create more invitation keys at this time.");
+ throw new \exceptions\PublicApiException("user/invitation-limit", "You can't create more invitation keys at this time.");
}
$key = random_alphanum(12, 16);
@@ -277,7 +277,7 @@ class User extends MY_Controller {
$username = $this->input->post("username");
if (!$this->muser->username_exists($username)) {
- show_error("Invalid username");
+ throw new \exceptions\PublicApiException("user/reset_password/invalid-username", "Invalid username");
}
$userinfo = $this->db->select('id, email, username')
@@ -388,18 +388,18 @@ class User extends MY_Controller {
$values = explode("-", $value);
if (!is_array($values) || count($values) != 2) {
- show_error("Invalid upload id limit value");
+ throw new \exceptions\PublicApiException("user/profile/invalid-upload-id-limit", "Invalid upload id limit value");
}
$lower = intval($values[0]);
$upper = intval($values[1]);
if ($lower > $upper) {
- show_error("lower limit > upper limit");
+ throw new \exceptions\PublicApiException("user/profile/lower-bigger-than-upper", "lower limit > upper limit");
}
if ($lower < 3 || $upper > 64) {
- show_error("upper or lower limit out of bounds (3-64)");
+ throw new \exceptions\PublicApiException("user/profile/limit-out-of-bounds", "upper or lower limit out of bounds (3-64)");
}
return $lower."-".$upper;
diff --git a/application/core/MY_Controller.php b/application/core/MY_Controller.php
index 0f71a7fdc..a58d03563 100644
--- a/application/core/MY_Controller.php
+++ b/application/core/MY_Controller.php
@@ -18,10 +18,12 @@ class MY_Controller extends CI_Controller {
$this->var = new StdClass();
$csrf_protection = true;
+ $this->load->library('customautoloader');
+
// check if DB is up to date
if (!$this->input->is_cli_request()) {
if (!$this->db->table_exists('migrations')){
- show_error("Database not initialized. Can't find migrations table. Please run the migration script. (php index.php tools update_database)");
+ throw new \exceptions\PublicApiException("general/db/not-initialized", "Database not initialized. Can't find migrations table. Please run the migration script. (php index.php tools update_database)");
} else {
$this->config->load("migration", true);
$target_version = $this->config->item("migration_version", "migration");
@@ -31,7 +33,7 @@ class MY_Controller extends CI_Controller {
$current_version = $row ? $row->version : 0;
if ($current_version != $target_version) {
- show_error("Database version is $current_version, we want $target_version. Please run the migration script. (php index.php tools update_database)");
+ throw new \exceptions\PublicApiException("general/db/wrong-version", "Database version is $current_version, we want $target_version. Please run the migration script. (php index.php tools update_database)");
}
}
}
@@ -41,7 +43,6 @@ class MY_Controller extends CI_Controller {
mb_internal_encoding('UTF-8');
$this->load->helper(array('form', 'filebin'));
- $this->load->library('customautoloader');
if ($this->uri->segment(1) == "api") {
is_cli_client(true);
diff --git a/application/exceptions/NotFoundException.php b/application/exceptions/NotFoundException.php
new file mode 100644
index 000000000..c4b9d1537
--- /dev/null
+++ b/application/exceptions/NotFoundException.php
@@ -0,0 +1,14 @@
+config->item('upload_path');
if (strpos($file, $upload_path) !== 0) {
- show_error('Invalid file path');
+ throw new \exceptions\ApiException("libraries/ddownload/lighttpd/invalid-file-path", 'Invalid file path');
}
header('Content-disposition: inline; filename="'.$filename."\"\n");
diff --git a/application/libraries/Ddownload/drivers/Ddownload_nginx.php b/application/libraries/Ddownload/drivers/Ddownload_nginx.php
index 2410df4d4..58c7502a7 100644
--- a/application/libraries/Ddownload/drivers/Ddownload_nginx.php
+++ b/application/libraries/Ddownload/drivers/Ddownload_nginx.php
@@ -18,7 +18,7 @@ class Ddownload_nginx extends Ddownload_Driver {
if (strpos($file, $upload_path) === 0) {
$file_path = substr($file, strlen($upload_path));
} else {
- show_error('Invalid file path');
+ throw new \exceptions\ApiException("libraries/ddownload/nginx/invalid-file-path", 'Invalid file path');
}
header('Content-disposition: inline; filename="'.$filename."\"\n");
diff --git a/application/libraries/Duser/Duser.php b/application/libraries/Duser/Duser.php
index 07a16190c..bf765d690 100644
--- a/application/libraries/Duser/Duser.php
+++ b/application/libraries/Duser/Duser.php
@@ -62,7 +62,7 @@ class Duser extends CI_Driver_Library {
// require an optional function to be implemented
public function require_implemented($function) {
if (!$this->is_implemented($function)) {
- show_error(""
+ throw new \exceptions\PublicApiException("libraries/duser/optional-function-not-implemented", ""
."Optional function '".$function."' not implemented in user adapter '".$this->_adapter."'. "
."Requested functionally unavailable.");
}
diff --git a/application/libraries/Duser/drivers/Duser_db.php b/application/libraries/Duser/drivers/Duser_db.php
index 258de1820..157a91395 100644
--- a/application/libraries/Duser/drivers/Duser_db.php
+++ b/application/libraries/Duser/drivers/Duser_db.php
@@ -67,7 +67,7 @@ class Duser_db extends Duser_Driver {
->get()->row_array();
if (empty($query)) {
- show_error("Failed to get email address from db");
+ throw new \exceptions\ApiException("libraries/duser/db/get_email-failed", "Failed to get email address from db");
}
return $query["email"];
diff --git a/application/libraries/Duser/drivers/Duser_ldap.php b/application/libraries/Duser/drivers/Duser_ldap.php
index 1f1581620..b80385fe0 100644
--- a/application/libraries/Duser/drivers/Duser_ldap.php
+++ b/application/libraries/Duser/drivers/Duser_ldap.php
@@ -37,7 +37,7 @@ class Duser_ldap extends Duser_Driver {
$r = ldap_search($ds, $config['basedn'], $config["username_field"].'='.$username);
break;
default:
- show_error("Invalid LDAP scope");
+ throw new \exceptions\ApiException("libraries/duser/ldap/invalid-ldap-scope", "Invalid LDAP scope");
}
if ($r === false) {
return false;
diff --git a/application/libraries/Image.php b/application/libraries/Image.php
index 32c4717e9..ae7be844e 100644
--- a/application/libraries/Image.php
+++ b/application/libraries/Image.php
@@ -35,7 +35,7 @@ class Image {
{
$img = imagecreatefromstring(file_get_contents($file));
if ($img === false) {
- show_error("Unsupported image type");
+ throw new \exceptions\ApiException("libraries/Image/unsupported-image-type", "Unsupported image type");
}
$this->set_img_object($img);
$this->fix_alpha();
@@ -94,7 +94,7 @@ class Image {
$result = ob_get_clean();
if (!$ret) {
- show_error("Failed to create thumbnail");
+ throw new \exceptions\ApiException("libraries/Image/thumbnail-creation-failed", "Failed to create thumbnail");
}
return $result;
diff --git a/application/migrations/012_add_constraints.php b/application/migrations/012_add_constraints.php
index 1ed4abf08..f298ceb5f 100644
--- a/application/migrations/012_add_constraints.php
+++ b/application/migrations/012_add_constraints.php
@@ -29,6 +29,6 @@ class Migration_add_constraints extends CI_Migration {
public function down()
{
- show_error("downgrade not supported");
+ throw new \exceptions\ApiException("migration/downgrade-not-supported", "downgrade not supported");
}
}
diff --git a/application/migrations/013_add_multipaste.php b/application/migrations/013_add_multipaste.php
index 96092b4ee..539e9d292 100644
--- a/application/migrations/013_add_multipaste.php
+++ b/application/migrations/013_add_multipaste.php
@@ -55,6 +55,6 @@ class Migration_add_multipaste extends CI_Migration {
public function down()
{
- show_error("downgrade not supported");
+ throw new \exceptions\ApiException("migration/downgrade-not-supported", "downgrade not supported");
}
}
diff --git a/application/models/mfile.php b/application/models/mfile.php
index eee2c4e5b..0ec27a817 100644
--- a/application/models/mfile.php
+++ b/application/models/mfile.php
@@ -40,7 +40,7 @@ class Mfile extends CI_Model {
return $id;
}
- show_error("Failed to find unused ID after $max_tries tries.");
+ throw new \exceptions\PublicApiException("file/new_id-try-limit", "Failed to find unused ID after $max_tries tries");
}
function id_exists($id)
diff --git a/application/models/mmultipaste.php b/application/models/mmultipaste.php
index 6cbf6518b..2b0196531 100644
--- a/application/models/mmultipaste.php
+++ b/application/models/mmultipaste.php
@@ -54,7 +54,7 @@ class Mmultipaste extends CI_Model {
return $id;
}
- show_error("Failed to find unused ID after $max_tries tries.");
+ throw new \exceptions\PublicApiException("file/new_id-try-limit", "Failed to find unused ID after $max_tries tries");
}
public function id_exists($id)
diff --git a/application/models/muser.php b/application/models/muser.php
index 398253c6a..6f6129ca2 100644
--- a/application/models/muser.php
+++ b/application/models/muser.php
@@ -83,7 +83,7 @@ class Muser extends CI_Model {
if ($this->login($username, $password)) {
return true;
} else {
- show_error("Login failed", 401);
+ throw new \exceptions\NotAuthenticatedException("user/login-failed", "Login failed");
}
}
@@ -112,7 +112,7 @@ class Muser extends CI_Model {
return true;
}
- show_error("API key login failed", 401);
+ throw new \exceptions\NotAuthenticatedException("user/api-login-failed", "API key login failed");
}
function logout()
@@ -208,7 +208,7 @@ class Muser extends CI_Model {
->get()->row_array();
if (!isset($query["key"]) || $key != $query["key"]) {
- show_error("Invalid action key");
+ throw new \exceptions\ApiException("user/get_action/invalid-action", "Invalid action key");
}
return $query;
--
cgit v1.2.3-24-g4f1b
From 46fe1f6db8395381c71e2e7fba3d1c2d979cbfbc Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 17:27:40 +0100
Subject: lib/Image->get: check if ob_get_clean worked
Signed-off-by: Florian Pritz
---
application/controllers/file.php | 5 -----
application/libraries/Image.php | 2 +-
2 files changed, 1 insertion(+), 6 deletions(-)
(limited to 'application')
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 538155c55..fa34ecba9 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -564,11 +564,6 @@ class File extends MY_Controller {
$img = new libraries\Image($this->mfile->file($filedata["hash"]));
$img->makeThumb($thumb_size, $thumb_size);
$thumb = $img->get(IMAGETYPE_JPEG);
-
- if ($thumb === false) {
- throw new \exceptions\PublicApiException("file/thumbnail/generation-failed", "Failed to generate thumbnail");
- }
-
return $thumb;
});
diff --git a/application/libraries/Image.php b/application/libraries/Image.php
index ae7be844e..0f920358a 100644
--- a/application/libraries/Image.php
+++ b/application/libraries/Image.php
@@ -93,7 +93,7 @@ class Image {
}
$result = ob_get_clean();
- if (!$ret) {
+ if (!$ret || $result === false) {
throw new \exceptions\ApiException("libraries/Image/thumbnail-creation-failed", "Failed to create thumbnail");
}
--
cgit v1.2.3-24-g4f1b
From 6f1258fbf27b05092ed0712c7d20bafda42074ea Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 3 Feb 2015 23:30:13 +0100
Subject: Support database table prefixes
This also cleans up some inconsistencies with quotes.
Signed-off-by: Florian Pritz
---
application/migrations/001_add_files.php | 14 +++---
application/migrations/002_add_users.php | 42 ++++++++---------
application/migrations/003_add_referrers.php | 30 +++++++------
application/migrations/004_add_filesize.php | 16 ++++---
application/migrations/005_drop_file_password.php | 12 +++--
application/migrations/006_add_username_index.php | 14 +++---
.../migrations/007_repurpose_invitations.php | 38 +++++++++-------
application/migrations/008_add_profiles.php | 28 +++++++-----
application/migrations/009_add_apikeys.php | 12 ++---
application/migrations/010_files_innodb.php | 8 ++--
.../migrations/011_apikeys_add_access_level.php | 16 ++++---
application/migrations/012_add_constraints.php | 28 ++++++------
application/migrations/013_add_multipaste.php | 22 ++++-----
.../migrations/014_deduplicate_file_storage.php | 52 ++++++++++++++++++++++
14 files changed, 212 insertions(+), 120 deletions(-)
create mode 100644 application/migrations/014_deduplicate_file_storage.php
(limited to 'application')
diff --git a/application/migrations/001_add_files.php b/application/migrations/001_add_files.php
index 30f567325..dd37d08c3 100644
--- a/application/migrations/001_add_files.php
+++ b/application/migrations/001_add_files.php
@@ -5,9 +5,11 @@ class Migration_Add_files extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE IF NOT EXISTS "files" (
+ CREATE TABLE IF NOT EXISTS "'.$prefix.'files" (
"hash" varchar(32) NOT NULL,
"id" varchar(6) NOT NULL,
"filename" varchar(256) NOT NULL,
@@ -16,12 +18,12 @@ class Migration_Add_files extends CI_Migration {
"mimetype" varchar(255) NOT NULL,
PRIMARY KEY ("id")
);
- CREATE INDEX "files_date_idx" ON files ("date");
- CREATE INDEX "files_hash_id_idx" ON files ("hash", "id");
+ CREATE INDEX "files_date_idx" ON '.$prefix.'files ("date");
+ CREATE INDEX "files_hash_id_idx" ON '.$prefix.'files ("hash", "id");
');
} else {
- $this->db->query("
- CREATE TABLE IF NOT EXISTS `files` (
+ $this->db->query('
+ CREATE TABLE IF NOT EXISTS `'.$prefix.'files` (
`hash` varchar(32) CHARACTER SET ascii NOT NULL,
`id` varchar(6) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`filename` varchar(256) COLLATE utf8_bin NOT NULL,
@@ -32,7 +34,7 @@ class Migration_Add_files extends CI_Migration {
KEY `date` (`date`),
KEY `hash` (`hash`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- ");
+ ');
}
}
diff --git a/application/migrations/002_add_users.php b/application/migrations/002_add_users.php
index 322415d9b..5ccef6669 100644
--- a/application/migrations/002_add_users.php
+++ b/application/migrations/002_add_users.php
@@ -5,9 +5,11 @@ class Migration_Add_users extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE IF NOT EXISTS "users" (
+ CREATE TABLE IF NOT EXISTS "'.$prefix.'users" (
"id" serial PRIMARY KEY,
"username" character varying(32) NOT NULL,
"password" character varying(60) NOT NULL,
@@ -16,7 +18,7 @@ class Migration_Add_users extends CI_Migration {
');
$this->db->query('
- CREATE TABLE IF NOT EXISTS "ci_sessions" (
+ CREATE TABLE IF NOT EXISTS "'.$prefix.'ci_sessions" (
"session_id" character varying(40) NOT NULL DEFAULT 0,
"ip_address" character varying(16) NOT NULL DEFAULT 0,
"user_agent" character varying(120) NOT NULL,
@@ -24,43 +26,43 @@ class Migration_Add_users extends CI_Migration {
"user_data" text NOT NULL,
PRIMARY KEY ("session_id")
);
- CREATE INDEX "ci_sessions_last_activity_idx" ON "ci_sessions" ("last_activity");
+ CREATE INDEX "ci_sessions_last_activity_idx" ON "'.$prefix.'ci_sessions" ("last_activity");
');
$this->db->query('
- ALTER TABLE "files" ADD "user" integer NOT NULL DEFAULT 0;
- CREATE INDEX "user_idx" ON "files" ("user");
+ ALTER TABLE "'.$prefix.'files" ADD "user" integer NOT NULL DEFAULT 0;
+ CREATE INDEX "user_idx" ON "'.$prefix.'files" ("user");
');
} else {
- $this->db->query("
- CREATE TABLE IF NOT EXISTS `users` (
+ $this->db->query('
+ CREATE TABLE IF NOT EXISTS `'.$prefix.'users` (
`id` int(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE ascii_general_ci NOT NULL,
`password` varchar(60) COLLATE ascii_general_ci NOT NULL,
`email` varchar(255) COLLATE ascii_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
- ");
+ ');
- $this->db->query("
- CREATE TABLE IF NOT EXISTS `ci_sessions` (
- `session_id` varchar(40) NOT NULL DEFAULT '0',
- `ip_address` varchar(16) NOT NULL DEFAULT '0',
+ $this->db->query('
+ CREATE TABLE IF NOT EXISTS `'.$prefix.'ci_sessions` (
+ `session_id` varchar(40) NOT NULL DEFAULT 0,
+ `ip_address` varchar(16) NOT NULL DEFAULT 0,
`user_agent` varchar(120) NOT NULL,
- `last_activity` int(10) unsigned NOT NULL DEFAULT '0',
+ `last_activity` int(10) unsigned NOT NULL DEFAULT 0,
`user_data` text NOT NULL,
PRIMARY KEY (`session_id`),
KEY `last_activity_idx` (`last_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- ");
+ ');
- $this->db->query("
- ALTER TABLE `files`
- ADD `user` INT(8) UNSIGNED NOT NULL DEFAULT '0',
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'files`
+ ADD `user` INT(8) UNSIGNED NOT NULL DEFAULT 0,
ADD INDEX (`user`)
- ");
+ ');
}
}
@@ -69,9 +71,9 @@ class Migration_Add_users extends CI_Migration {
$this->dbforge->drop_table('users');
$this->dbforge->drop_table('ci_sessions');
if ($this->db->dbdriver == 'postgre') {
- $this->db->query('ALTER TABLE "files" DROP "user"');
+ $this->db->query('ALTER TABLE "'.$prefix.'files" DROP "user"');
} else {
- $this->db->query('ALTER TABLE `files` DROP `user`');
+ $this->db->query('ALTER TABLE `'.$prefix.'files` DROP `user`');
}
}
}
diff --git a/application/migrations/003_add_referrers.php b/application/migrations/003_add_referrers.php
index e30f1faef..c504b5539 100644
--- a/application/migrations/003_add_referrers.php
+++ b/application/migrations/003_add_referrers.php
@@ -5,26 +5,28 @@ class Migration_Add_referrers extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE "invitations" (
+ CREATE TABLE "'.$prefix.'invitations" (
"user" integer NOT NULL,
"key" character varying(16) NOT NULL,
"date" integer NOT NULL,
PRIMARY KEY ("key")
);
- CREATE INDEX "invitations_user_idx" ON "invitations" ("user");
- CREATE INDEX "invitations_date_idx" ON "invitations" ("date");
+ CREATE INDEX "invitations_user_idx" ON "'.$prefix.'invitations" ("user");
+ CREATE INDEX "invitations_date_idx" ON "'.$prefix.'invitations" ("date");
');
$this->db->query('
- ALTER TABLE "users"
+ ALTER TABLE "'.$prefix.'users"
ADD "referrer" integer NOT NULL DEFAULT 0
');
} else {
- $this->db->query("
- CREATE TABLE `invitations` (
+ $this->db->query('
+ CREATE TABLE `'.$prefix.'invitations` (
`user` int(8) unsigned NOT NULL,
`key` varchar(16) CHARACTER SET ascii NOT NULL,
`date` int(11) unsigned NOT NULL,
@@ -32,23 +34,25 @@ class Migration_Add_referrers extends CI_Migration {
KEY `user` (`user`),
KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
- ");
- $this->db->query("
- ALTER TABLE `users`
- ADD `referrer` INT(8) UNSIGNED NOT NULL DEFAULT '0'
- ");
+ ');
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'users`
+ ADD `referrer` INT(8) UNSIGNED NOT NULL DEFAULT 0
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- ALTER TABLE "users" DROP "referrer"
+ ALTER TABLE "'.$prefix.'users" DROP "referrer"
');
} else {
$this->db->query('
- ALTER TABLE `users` DROP `referrer`
+ ALTER TABLE `'.$prefix.'users` DROP `referrer`
');
}
$this->dbforge->drop_table('invitations');
diff --git a/application/migrations/004_add_filesize.php b/application/migrations/004_add_filesize.php
index f2367937a..ca10e7dc3 100644
--- a/application/migrations/004_add_filesize.php
+++ b/application/migrations/004_add_filesize.php
@@ -5,28 +5,32 @@ class Migration_Add_filesize extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- ALTER TABLE "files"
+ ALTER TABLE "'.$prefix.'files"
ADD "filesize" integer NOT NULL
');
} else {
- $this->db->query("
- ALTER TABLE `files`
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'files`
ADD `filesize` INT UNSIGNED NOT NULL
- ");
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- ALTER TABLE "files" DROP "filesize"
+ ALTER TABLE "'.$prefix.'files" DROP "filesize"
');
} else {
$this->db->query('
- ALTER TABLE `files` DROP `filesize`
+ ALTER TABLE `'.$prefix.'files` DROP `filesize`
');
}
}
diff --git a/application/migrations/005_drop_file_password.php b/application/migrations/005_drop_file_password.php
index e8b7f8952..1b3b5fc12 100644
--- a/application/migrations/005_drop_file_password.php
+++ b/application/migrations/005_drop_file_password.php
@@ -5,23 +5,27 @@ class Migration_Drop_file_password extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
- $this->db->query('ALTER TABLE "files" DROP "password"');
+ $this->db->query('ALTER TABLE "'.$prefix.'files" DROP "password"');
} else {
- $this->db->query("ALTER TABLE `files` DROP `password`;");
+ $this->db->query('ALTER TABLE `'.$prefix.'files` DROP `password`;');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- ALTER TABLE "files"
+ ALTER TABLE "'.$prefix.'files"
ADD "password" character varying(40) DEFAULT NULL
');
} else {
$this->db->query("
- ALTER TABLE `files`
+ ALTER TABLE `'.$prefix.'files`
ADD `password` varchar(40) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL;
");
}
diff --git a/application/migrations/006_add_username_index.php b/application/migrations/006_add_username_index.php
index 5b8c3584f..0e6dc7650 100644
--- a/application/migrations/006_add_username_index.php
+++ b/application/migrations/006_add_username_index.php
@@ -5,25 +5,29 @@ class Migration_Add_username_index extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE UNIQUE INDEX "users_username_idx" ON "users" ("username")
+ CREATE UNIQUE INDEX "users_username_idx" ON "'.$prefix.'users" ("username")
');
} else {
- $this->db->query("
- ALTER TABLE `users`
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'users`
ADD UNIQUE `username` (`username`);
- ");
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('DROP INDEX "users_username_idx"');
} else {
$this->db->query("
- ALTER TABLE `users`
+ ALTER TABLE `'.$prefix.'users`
DROP INDEX `username`;
");
}
diff --git a/application/migrations/007_repurpose_invitations.php b/application/migrations/007_repurpose_invitations.php
index fb40e8179..ed9b136a0 100644
--- a/application/migrations/007_repurpose_invitations.php
+++ b/application/migrations/007_repurpose_invitations.php
@@ -5,56 +5,60 @@ class Migration_Repurpose_invitations extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- ALTER TABLE "invitations"
+ ALTER TABLE "'.$prefix.'invitations"
ADD "action" character varying(255) NOT NULL,
ADD "data" TEXT NULL;
- CREATE INDEX "invitations_action_idx" ON invitations ("action");
+ CREATE INDEX "invitations_action_idx" ON '.$prefix.'invitations ("action");
');
$this->db->query('
- UPDATE "invitations" SET "action" = \'invitation\' WHERE "action" = \'\'
+ UPDATE "'.$prefix.'invitations" SET "action" = \'invitation\' WHERE "action" = \'\'
');
$this->db->query('
- ALTER TABLE "invitations" RENAME TO "actions";
+ ALTER TABLE "'.$prefix.'invitations" RENAME TO "actions";
');
} else {
- $this->db->query("
- ALTER TABLE `invitations`
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'invitations`
ADD `action` VARCHAR(255) NOT NULL,
ADD `data` TEXT NULL,
ADD INDEX `action` (`action`);
- ");
+ ');
- $this->db->query("
- UPDATE `invitations` SET `action` = 'invitation' WHERE `action` = '';
- ");
+ $this->db->query('
+ UPDATE `'.$prefix.'invitations` SET `action` = \'invitation\' WHERE `action` = \'\';
+ ');
- $this->db->query("
- ALTER TABLE `invitations` RENAME `actions`;
- ");
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'invitations` RENAME `'.$prefix.'actions`;
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
- $this->db->query('ALTER TABLE "actions" RENAME TO "invitations"');
+ $this->db->query('ALTER TABLE "'.$prefix.'actions" RENAME TO "'.$prefix.'invitations"');
$this->db->query('
- ALTER TABLE "invitations"
+ ALTER TABLE "'.$prefix.'invitations"
DROP "action",
DROP "data";
');
} else {
- $this->db->query('ALTER TABLE `actions` RENAME `invitations`');
+ $this->db->query('ALTER TABLE `'.$prefix.'actions` RENAME `'.$prefix.'invitations`');
$this->db->query('
- ALTER TABLE `invitations`
+ ALTER TABLE `'.$prefix.'invitations`
DROP `action`,
DROP `data`;
');
diff --git a/application/migrations/008_add_profiles.php b/application/migrations/008_add_profiles.php
index 9958fb03e..4cdd14de0 100644
--- a/application/migrations/008_add_profiles.php
+++ b/application/migrations/008_add_profiles.php
@@ -5,9 +5,11 @@ class Migration_Add_profiles extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE "profiles" (
+ CREATE TABLE "'.$prefix.'profiles" (
"user" integer NOT NULL,
"upload_id_limits" varchar(255) NOT NULL,
PRIMARY KEY ("user")
@@ -15,42 +17,44 @@ class Migration_Add_profiles extends CI_Migration {
');
$this->db->query('
- ALTER TABLE "files" ALTER COLUMN "id" TYPE varchar(255);
+ ALTER TABLE "'.$prefix.'files" ALTER COLUMN "id" TYPE varchar(255);
');
} else {
- $this->db->query("
- CREATE TABLE `profiles` (
+ $this->db->query('
+ CREATE TABLE `'.$prefix.'profiles` (
`user` int(8) unsigned NOT NULL,
`upload_id_limits` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
- ");
+ ');
- $this->db->query("
- ALTER TABLE `files` CHANGE `id` `id` VARCHAR( 255 );
- ");
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'files` CHANGE `id` `id` VARCHAR( 255 );
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- DROP TABLE "profiles";
+ DROP TABLE "'.$prefix.'profiles";
');
$this->db->query('
- ALTER TABLE "files" ALTER COLUMN "id" TYPE varchar(6);
+ ALTER TABLE "'.$prefix.'files" ALTER COLUMN "id" TYPE varchar(6);
');
} else {
$this->db->query("
- DROP TABLE `profiles`;
+ DROP TABLE `'.$prefix.'profiles`;
");
$this->db->query("
- ALTER TABLE `files` CHANGE `id` `id` VARCHAR( 6 );
+ ALTER TABLE `'.$prefix.'files` CHANGE `id` `id` VARCHAR( 6 );
");
}
}
diff --git a/application/migrations/009_add_apikeys.php b/application/migrations/009_add_apikeys.php
index 8f2882e49..a5af809fc 100644
--- a/application/migrations/009_add_apikeys.php
+++ b/application/migrations/009_add_apikeys.php
@@ -5,22 +5,24 @@ class Migration_Add_apikeys extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE "apikeys" (
+ CREATE TABLE "'.$prefix.'apikeys" (
"key" varchar(64) NOT NULL,
"user" integer NOT NULL,
"created" timestamp WITH TIME ZONE NOT NULL DEFAULT NOW(),
"comment" varchar(255) NOT NULL,
PRIMARY KEY ("key")
);
- CREATE INDEX "apikeys_user_idx" ON "apikeys" ("user");
+ CREATE INDEX "apikeys_user_idx" ON "'.$prefix.'apikeys" ("user");
');
} else {
- $this->db->query("
- CREATE TABLE `apikeys` (
+ $this->db->query('
+ CREATE TABLE `'.$prefix.'apikeys` (
`key` varchar(64) COLLATE utf8_bin NOT NULL,
`user` int(8) unsigned NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -28,7 +30,7 @@ class Migration_Add_apikeys extends CI_Migration {
PRIMARY KEY (`key`),
KEY `user` (`user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
- ");
+ ');
}
}
diff --git a/application/migrations/010_files_innodb.php b/application/migrations/010_files_innodb.php
index 318314bd3..98f9dea31 100644
--- a/application/migrations/010_files_innodb.php
+++ b/application/migrations/010_files_innodb.php
@@ -5,10 +5,12 @@ class Migration_files_innodb extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver != 'postgre') {
- $this->db->query("
- ALTER TABLE `files` ENGINE = InnoDB;
- ");
+ $this->db->query('
+ ALTER TABLE `'.$prefix.'files` ENGINE = InnoDB;
+ ');
}
}
diff --git a/application/migrations/011_apikeys_add_access_level.php b/application/migrations/011_apikeys_add_access_level.php
index 2fdbc7271..14d0b03d3 100644
--- a/application/migrations/011_apikeys_add_access_level.php
+++ b/application/migrations/011_apikeys_add_access_level.php
@@ -5,26 +5,30 @@ class Migration_apikeys_add_access_level extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- alter table "apikeys" add "access_level" varchar(255) default \'apikey\'
+ alter table "'.$prefix.'apikeys" add "access_level" varchar(255) default \'apikey\'
');
} else {
- $this->db->query("
- alter table `apikeys` add `access_level` varchar(255) default 'apikey';
- ");
+ $this->db->query('
+ alter table `'.$prefix.'apikeys` add `access_level` varchar(255) default \'apikey\';
+ ');
}
}
public function down()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- alter table "apikeys" drop "access_level"
+ alter table "'.$prefix.'apikeys" drop "access_level"
');
} else {
$this->db->query('
- alter table `apikeys` drop `access_level`
+ alter table `'.$prefix.'apikeys` drop `access_level`
');
}
}
diff --git a/application/migrations/012_add_constraints.php b/application/migrations/012_add_constraints.php
index f298ceb5f..40a4540f6 100644
--- a/application/migrations/012_add_constraints.php
+++ b/application/migrations/012_add_constraints.php
@@ -5,25 +5,27 @@ class Migration_add_constraints extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
- $this->db->query('ALTER TABLE "users" ALTER COLUMN "referrer" TYPE integer');
- $this->db->query('ALTER TABLE "users" ALTER COLUMN "referrer" DROP NOT NULL');
- $this->db->query('CREATE INDEX "users_referrer_idx" ON "users" ("referrer")');
- $this->db->query('UPDATE "users" SET "referrer" = NULL where "referrer" = 0');
+ $this->db->query('ALTER TABLE "'.$prefix.'users" ALTER COLUMN "referrer" TYPE integer');
+ $this->db->query('ALTER TABLE "'.$prefix.'users" ALTER COLUMN "referrer" DROP NOT NULL');
+ $this->db->query('CREATE INDEX "users_referrer_idx" ON "'.$prefix.'users" ("referrer")');
+ $this->db->query('UPDATE "'.$prefix.'users" SET "referrer" = NULL where "referrer" = 0');
$this->db->query('
- ALTER TABLE "users"
- ADD CONSTRAINT "referrer_user_fkey" FOREIGN KEY ("referrer")
- REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE RESTRICT
+ ALTER TABLE "'.$prefix.'users"
+ ADD CONSTRAINT "'.$prefix.'referrer_user_fkey" FOREIGN KEY ("referrer")
+ REFERENCES "'.$prefix.'users"("id") ON DELETE RESTRICT ON UPDATE RESTRICT
');
} else {
- $this->db->query("ALTER TABLE `users` ADD INDEX(`referrer`);");
- $this->db->query("ALTER TABLE `users` CHANGE `referrer` `referrer`
- INT(8) UNSIGNED NULL;");
- $this->db->query("UPDATE `users` SET `referrer` = NULL where `referrer` = 0;");
- $this->db->query("ALTER TABLE `users` ADD FOREIGN KEY (`referrer`)
- REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;");
+ $this->db->query('ALTER TABLE `'.$prefix.'users` ADD INDEX(`referrer`);');
+ $this->db->query('ALTER TABLE `'.$prefix.'users` CHANGE `referrer` `referrer`
+ INT(8) UNSIGNED NULL;');
+ $this->db->query('UPDATE `'.$prefix.'users` SET `referrer` = NULL where `referrer` = 0;');
+ $this->db->query('ALTER TABLE `'.$prefix.'users` ADD FOREIGN KEY (`referrer`)
+ REFERENCES `'.$prefix.'users`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;');
}
}
diff --git a/application/migrations/013_add_multipaste.php b/application/migrations/013_add_multipaste.php
index 539e9d292..6dd9bcb7b 100644
--- a/application/migrations/013_add_multipaste.php
+++ b/application/migrations/013_add_multipaste.php
@@ -5,31 +5,33 @@ class Migration_add_multipaste extends CI_Migration {
public function up()
{
+ $prefix = $this->db->dbprefix;
+
if ($this->db->dbdriver == 'postgre') {
$this->db->query('
- CREATE TABLE "multipaste" (
+ CREATE TABLE "'.$prefix.'multipaste" (
"url_id" varchar(255) NOT NULL PRIMARY KEY,
"multipaste_id" serial UNIQUE,
"user_id" integer NOT NULL,
"date" integer NOT NULL
);
- CREATE INDEX "multipaste_user_idx" ON "multipaste" ("user_id");
+ CREATE INDEX "'.$prefix.'multipaste_user_idx" ON "'.$prefix.'multipaste" ("user_id");
');
$this->db->query('
- CREATE TABLE "multipaste_file_map" (
- "multipaste_id" integer NOT NULL REFERENCES "multipaste" ("multipaste_id") ON DELETE CASCADE ON UPDATE CASCADE,
- "file_url_id" varchar(255) NOT NULL REFERENCES "files"("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CREATE TABLE "'.$prefix.'multipaste_file_map" (
+ "multipaste_id" integer NOT NULL REFERENCES "'.$prefix.'multipaste" ("multipaste_id") ON DELETE CASCADE ON UPDATE CASCADE,
+ "file_url_id" varchar(255) NOT NULL REFERENCES "'.$prefix.'files"("id") ON DELETE CASCADE ON UPDATE CASCADE,
"sort_order" serial PRIMARY KEY,
UNIQUE ("multipaste_id", "file_url_id")
);
- CREATE INDEX "multipaste_file_map_file_idx" ON "multipaste_file_map" ("file_url_id");
+ CREATE INDEX "'.$prefix.'multipaste_file_map_file_idx" ON "'.$prefix.'multipaste_file_map" ("file_url_id");
');
} else {
$this->db->query('
- CREATE TABLE `multipaste` (
+ CREATE TABLE `'.$prefix.'multipaste` (
`url_id` varchar(255) NOT NULL,
`multipaste_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
@@ -40,15 +42,15 @@ class Migration_add_multipaste extends CI_Migration {
) ENGINE=InnoDB DEFAULT CHARSET=utf8;');
$this->db->query('
- CREATE TABLE `multipaste_file_map` (
+ CREATE TABLE `'.$prefix.'multipaste_file_map` (
`multipaste_id` int(11) NOT NULL,
`file_url_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`sort_order` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sort_order`),
UNIQUE KEY `multipaste_id` (`multipaste_id`,`file_url_id`),
KEY `multipaste_file_map_ibfk_2` (`file_url_id`),
- CONSTRAINT `multipaste_file_map_ibfk_1` FOREIGN KEY (`multipaste_id`) REFERENCES `multipaste` (`multipaste_id`) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT `multipaste_file_map_ibfk_2` FOREIGN KEY (`file_url_id`) REFERENCES `files` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `'.$prefix.'multipaste_file_map_ibfk_1` FOREIGN KEY (`multipaste_id`) REFERENCES `'.$prefix.'multipaste` (`multipaste_id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `'.$prefix.'multipaste_file_map_ibfk_2` FOREIGN KEY (`file_url_id`) REFERENCES `'.$prefix.'files` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;');
}
}
diff --git a/application/migrations/014_deduplicate_file_storage.php b/application/migrations/014_deduplicate_file_storage.php
new file mode 100644
index 000000000..8f8f40430
--- /dev/null
+++ b/application/migrations/014_deduplicate_file_storage.php
@@ -0,0 +1,52 @@
+db->dbprefix;
+
+ // FIXME: use prefix
+
+ if ($this->db->dbdriver == 'postgre') {
+ throw new \exceptions\ApiException("migration/postgres/not-implemented", "migration 14 not implemented yet for postgres");
+ } else {
+ $this->db->query('
+ CREATE TABLE `file_storage` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `filesize` int(11) NOT NULL,
+ `mimetype` varchar(255) NOT NULL,
+ `hash` char(32) NOT NULL,
+ `hash_collision_counter` int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `data_id` (`hash`, `hash_collision_counter`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ ');
+ $this->db->query('
+ ALTER TABLE `files`
+ ADD `file_storage_id` INT NOT NULL,
+ ADD INDEX (`file_storage_id`),
+ ADD FOREIGN KEY (`file_storage_id`) REFERENCES `filebin_test`.`file_storage`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
+ ');
+
+ $this->db->query('
+ INSERT INTO file_storage (storage-id, filesize, mimetype)
+ SELECT hash, filesize, mimetype FROM files;
+ ');
+
+ $this->db->query('
+ UPDATE files f
+ JOIN file_storage fs ON fs.data_id = f.hash
+ SET f.file_storage_id = fs.id
+ ');
+
+ $this->dbforge->drop_column("files", array("hash", "mimetype", "filesize"));
+ }
+ }
+
+ public function down()
+ {
+ throw new \exceptions\ApiException("migration/downgrade-not-supported", "downgrade not supported");
+ }
+}
--
cgit v1.2.3-24-g4f1b
From a8d1fb52d1dadbd6d4aa4ea50f6f27a967030aa4 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:38:22 +0100
Subject: Add Test-More
Signed-off-by: Florian Pritz
---
.../third_party/test-more-php/Test-More-OO.php | 441 +++++++++++++++++++++
.../third_party/test-more-php/Test-More.php | 41 ++
.../third_party/test-more-php/Test-Simple-OO.php | 232 +++++++++++
.../third_party/test-more-php/Test-Simple.php | 18 +
.../third_party/test-more-php/t/PHProvable.pl | 35 ++
application/third_party/test-more-php/t/badlib.php | 5 +
.../third_party/test-more-php/t/borklib.php | 5 +
.../third_party/test-more-php/t/goodlib.php | 5 +
.../third_party/test-more-php/t/goodpage.php | 5 +
.../t/testertests_bail_badplan_negative.php | 9 +
.../t/testertests_bail_badplan_noninteger.php | 9 +
.../test-more-php/t/testertests_bundle.php | 42 ++
.../t/testertests_deprecated_comparisons.php | 27 ++
.../t/testertests_deprecated_comparisons.pl | 25 ++
.../test-more-php/t/testertests_exit_0.php | 8 +
.../test-more-php/t/testertests_exit_fail_260.php | 14 +
.../test-more-php/t/testertests_exit_fail_5.php | 14 +
.../test-more-php/t/testertests_func_ok.php | 24 ++
.../t/testertests_func_ok.php_Test-More.out | 24 ++
.../t/testertests_func_ok.php_Test-Simple.out | 16 +
.../test-more-php/t/testertests_func_ok.pl | 24 ++
.../t/testertests_func_ok.pl_Test-More.out | 24 ++
.../t/testertests_func_ok.pl_Test-Simple.out | 24 ++
.../test-more-php/t/testertests_func_skip.php | 11 +
.../test-more-php/t/testertests_func_skip.pl | 9 +
.../t/testertests_include_ok_badlib.php | 21 +
.../t/testertests_include_ok_fatal.php | 17 +
.../test-more-php/t/testertests_interp.php | 10 +
.../test-more-php/t/testertests_interp_env.php | 19 +
.../test-more-php/t/testertests_interp_set.php | 18 +
.../test-more-php/t/testertests_is_deeply.php | 31 ++
.../t/testertests_require_ok_badlib.php | 12 +
.../t/testertests_require_ok_borklib.php | 12 +
.../t/testertests_require_ok_missing.php | 12 +
application/third_party/test-more-php/t/try.php | 7 +
35 files changed, 1250 insertions(+)
create mode 100755 application/third_party/test-more-php/Test-More-OO.php
create mode 100755 application/third_party/test-more-php/Test-More.php
create mode 100755 application/third_party/test-more-php/Test-Simple-OO.php
create mode 100755 application/third_party/test-more-php/Test-Simple.php
create mode 100755 application/third_party/test-more-php/t/PHProvable.pl
create mode 100755 application/third_party/test-more-php/t/badlib.php
create mode 100755 application/third_party/test-more-php/t/borklib.php
create mode 100755 application/third_party/test-more-php/t/goodlib.php
create mode 100755 application/third_party/test-more-php/t/goodpage.php
create mode 100755 application/third_party/test-more-php/t/testertests_bail_badplan_negative.php
create mode 100755 application/third_party/test-more-php/t/testertests_bail_badplan_noninteger.php
create mode 100755 application/third_party/test-more-php/t/testertests_bundle.php
create mode 100755 application/third_party/test-more-php/t/testertests_deprecated_comparisons.php
create mode 100755 application/third_party/test-more-php/t/testertests_deprecated_comparisons.pl
create mode 100755 application/third_party/test-more-php/t/testertests_exit_0.php
create mode 100755 application/third_party/test-more-php/t/testertests_exit_fail_260.php
create mode 100755 application/third_party/test-more-php/t/testertests_exit_fail_5.php
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.php
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.php_Test-More.out
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.php_Test-Simple.out
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.pl
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.pl_Test-More.out
create mode 100755 application/third_party/test-more-php/t/testertests_func_ok.pl_Test-Simple.out
create mode 100755 application/third_party/test-more-php/t/testertests_func_skip.php
create mode 100755 application/third_party/test-more-php/t/testertests_func_skip.pl
create mode 100755 application/third_party/test-more-php/t/testertests_include_ok_badlib.php
create mode 100755 application/third_party/test-more-php/t/testertests_include_ok_fatal.php
create mode 100755 application/third_party/test-more-php/t/testertests_interp.php
create mode 100755 application/third_party/test-more-php/t/testertests_interp_env.php
create mode 100755 application/third_party/test-more-php/t/testertests_interp_set.php
create mode 100755 application/third_party/test-more-php/t/testertests_is_deeply.php
create mode 100755 application/third_party/test-more-php/t/testertests_require_ok_badlib.php
create mode 100755 application/third_party/test-more-php/t/testertests_require_ok_borklib.php
create mode 100755 application/third_party/test-more-php/t/testertests_require_ok_missing.php
create mode 100755 application/third_party/test-more-php/t/try.php
(limited to 'application')
diff --git a/application/third_party/test-more-php/Test-More-OO.php b/application/third_party/test-more-php/Test-More-OO.php
new file mode 100755
index 000000000..195c27b00
--- /dev/null
+++ b/application/third_party/test-more-php/Test-More-OO.php
@@ -0,0 +1,441 @@
+plan(2);
+ $t->ok(1 + 1 = 2, 'One plus one equals two');
+ $t->ok( doSomethingAndReturnTrue() , 'doSomethingAndReturnTrue() successful');
+
+ Procedural Example:
+ require_once('Test-More.php');
+ plan(2);
+ ok(1 + 1 = 2, 'One plus one equals two');
+ ok( doSomethingAndReturnTrue() , 'doSomethingAndReturnTrue() successful');
+
+ From a browser
+ If you are running Test-Simple on a web server and want slightly more web-readable
+ output, call the web_output() method/function.
+
+ Updates
+ Updates will be posted to the Google code page:
+ http://code.google.com/p/test-more-php/
+
+ Bugs
+ Please file bug reports via the Issues tracker at the google code page.
+
+ Acknowledgements
+ Michael G Schwern: http://search.cpan.org/~mschwern/Test-Simple/
+ Chris Shiflet: http://shiflett.org/code/test-more.php
+
+ Author
+ Copyright RJ Herrick 2009, 2010
+
+*/
+
+require_once('Test-Simple-OO.php');
+
+class TestMore extends TestSimple {
+
+/* Test-More extensions */
+ private $interp;
+
+ function pass ($name = NULL) {
+ return $this->ok(TRUE, $name);
+ }
+
+ function fail ($name = NULL) {
+ return $this->ok(FALSE, $name);
+ }
+
+ function _compare ($operator, $thing1, $thing2, $name = NULL) {
+ // Test.php's cmp_ok function accepts coderefs, hmmm
+
+ $result = eval("return (\$thing1 $operator \$thing2);");
+
+ return $this->ok($result, $name);
+ }
+
+ function is ($thing1, $thing2, $name = NULL) {
+ $pass = $this->_compare ('==',$thing1,$thing2,$name);
+ if (!$pass) {
+ $this->diag(" got: '$thing1'",
+ " expected: '$thing2'");
+ }
+ return $pass;
+ }
+
+ function isnt ($thing1, $thing2, $name = NULL) {
+ $pass = $this->_compare ('!=',$thing1,$thing2,$name);
+ if (!$pass) {
+ $this->diag(" got: '$thing1'",
+ " expected: '$thing2'");
+ }
+ return $pass;
+ }
+
+ function like ($string, $pattern, $name = NULL) {
+ $pass = preg_match($pattern, $string);
+
+ $ok = $this->ok($pass, $name);
+
+ if (!$ok) {
+ $this->diag(" '$string'");
+ $this->diag(" doesn't match '$pattern'");
+ }
+
+ return $ok;
+ }
+
+ function unlike ($string, $pattern, $name = NULL) {
+ $pass = !preg_match($pattern, $string);
+
+ $ok = $this->ok($pass, $name);
+
+ if (!$ok) {
+ $this->diag(" '$string'");
+ $this->diag(" matches '$pattern'");
+ }
+
+ return $ok;
+ }
+
+ function cmp_ok ($thing1, $operator, $thing2, $name = NULL) {
+ eval("\$pass = (\$thing1 $operator \$thing2);");
+
+ ob_start();
+ var_dump($thing1);
+ $_thing1 = trim(ob_get_clean());
+
+ ob_start();
+ var_dump($thing2);
+ $_thing2 = trim(ob_get_clean());
+
+ $ok = $this->ok($pass, $name);
+
+ if (!$ok) {
+ $this->diag(" got: $_thing1");
+ $this->diag(" expected: $_thing2");
+ }
+
+ return $ok;
+ }
+
+ function can_ok ($object, $methods) {
+ $pass = TRUE;
+ $errors = array();
+ if (!is_array($methods)) $methods = array($methods);
+
+ foreach ($methods as $method) {
+ if (!method_exists($object, $method)) {
+ $pass = FALSE;
+ $errors[] = " method_exists(\$object, $method) failed";
+ }
+ }
+
+ $ok = $this->ok($pass, "method_exists(\$object, ...)");
+
+ if (!$ok) {
+ $this->diag($errors);
+ }
+
+ return $ok;
+ }
+
+ function isa_ok ($object, $expected_class, $object_name = 'The object') {
+ $got_class = get_class($object);
+
+ if (version_compare(phpversion(), '5', '>=')) {
+ $pass = ($got_class == $expected_class);
+ } else {
+ $pass = ($got_class == strtolower($expected_class));
+ }
+
+ if ($pass) {
+ $ok = $this->ok(TRUE, "$object_name isa $expected_class");
+ } else {
+ $ok = $this->ok(FALSE, "$object_name isn't a '$expected_class' it's a '$got_class'");
+ }
+
+ return $ok;
+ }
+
+ function _include_fatal_error_handler ($buffer) {
+
+ // Finish successfully? Carry on.
+ if ($buffer === 'included OK') return '';
+
+ $module = $this->LastModuleTested;
+
+ // Inside ob_start, won't see the output
+ $this->ok(FALSE,"include $module");
+
+ $message = trim($buffer);
+ $unrunmsg = '';
+
+ if ( is_int($this->NumberOfTests) ) {
+ $unrun = $this->NumberOfTests - (int)$this->TestsRun;
+ $plural = $unrun == 1 ? '' : 's';
+ $unrunmsg = "# Looks like ${unrun} planned test${plural} never ran.\n";
+ }
+
+ $gasp = $this->LastFail . "\n"
+ . "# Tried to include '$module'\n"
+ . "# $message\n"
+ . $unrunmsg
+ . "# Looks like 1 test aborted before it could finish due to a fatal error!\n"
+ . "Bail out! Terminating prematurely due to fatal error.\n"
+ ;
+
+ return $gasp;
+ }
+
+ function _include_ok ($module,$type) {
+ $path = null;
+ $full_path = null;
+ $retval = 999;
+
+ // Resolve full path, nice to know although only necessary on windows
+ foreach (explode(PATH_SEPARATOR,get_include_path()) as $prefix) {
+ // Repeat existance test and find full path
+ $full_path = realpath($prefix.DIRECTORY_SEPARATOR.$module);
+ $lines = @file($full_path);
+ // Stop on success
+ if ($lines) {
+ $path = $full_path;
+ break;
+ }
+ }
+ // Make sure, if we would include it, it's not going to choke on syntax
+ $error = false;
+ if ($path) {
+ @exec('"'.$this->interp().'" -l '.$path, $bunk, $retval);
+ if ($retval===0) {
+ // Prep in case we hit error handler
+ $this->Backtrace = debug_backtrace();
+ $this->LastModuleTested = $module;
+ ob_start(array($this,'_include_fatal_error_handler'));
+ if ($type === 'include') {
+ $done = (include $module);
+ } else if ($type === 'require') {
+ $done = (require $module);
+ } else {
+ $this->bail("Second argument to _include_ok() must be 'require' or 'include'");
+ }
+ echo "included OK";
+ ob_end_flush();
+ if (!$done) $error = " Unable to $type '$module'";
+ } else {
+ $error = " Syntax check for '$module' failed";
+ }
+ } else {
+ $error = " Cannot find ${type}d file '$module'";
+ }
+
+ $pass = !$retval && $done;
+ $ok = $this->ok($pass, "$type $module" );
+ if ($error) $this->diag($error);
+ if ($error && $path) $this->diag(" Resolved $module as $full_path");
+ return $ok;
+ }
+
+ function include_ok ($module) {
+ // Test success of including file, but continue testing if possible even if unable to include
+
+ return $this->_include_ok($module,'include');
+ }
+
+
+ function require_ok ($module) {
+ // As include_ok() but exit gracefully if requirement missing
+
+ $ok = $this->_include_ok($module,'require');
+
+ // Stop testing if we fail a require test
+ // Not a bail because you asked for it
+ if ($ok == FALSE) {
+ $this->diag(" Exiting due to missing requirement.");
+ exit();
+ }
+
+ return $ok;
+ }
+
+ function skip($why, $num) {
+
+ if ($num < 0) $num = 0;
+
+ $this->Skips += $num;
+ $this->SkipReason = $why;
+
+ return TRUE;
+ }
+
+ function eq_array ($thing1, $thing2) {
+ // Deprecated comparison function provided for compatibility
+ // Look only at values, order is important
+ $this->diag(" ! eq_array() is a deprecated comparison function provided for compatibility. Use array_diff() or similar instead.");
+ return !array_diff($thing1, $thing2);
+ }
+
+ function eq_hash ($thing1, $thing2) {
+ // Deprecated comparison function provided for compatibility
+ // Look at keys and values, order is NOT important
+ $this->diag(" ! eq_hash() is a deprecated comparison function provided for compatibility. Use array_diff() or similar instead.");
+ return !array_diff_assoc($thing1, $thing2);
+ }
+
+ function eq_set ($thing1, $thing2, $name = NULL) {
+ // Deprecated comparison function provided for compatibility
+ // Look only at values, duplicates are NOT important
+ $this->diag(" ! eq_set() is a deprecated comparison function provided for compatibility. Use array_diff() or similar instead.");
+ $a = $thing1;
+ sort($a);
+ $b = $thing2;
+ sort($b);
+ return !array_diff($a, $b);
+ }
+
+ function is_deeply ($thing1, $thing2, $name = NULL) {
+
+ $pass = $this->_compare_deeply($thing1, $thing2, $name);
+
+ $ok = $this->ok($pass,$name);
+
+ if (!$ok) {
+ foreach(array($thing1,$thing2) as $it){
+ ob_start();
+ var_dump($it);
+ $dump = ob_get_clean();
+ #$stringified[] = implode("\n#",explode("\n",$dump));
+ $stringified[] = str_replace("\n","\n# ",$dump);
+ }
+ $this->diag(" wanted: ".$stringified[0]);
+ $this->diag(" got: ".$stringified[1]);
+ }
+
+ return $ok;
+ }
+
+ function isnt_deeply ($thing1, $thing2, $name = NULL) {
+
+ $pass = !$this->_compare_deeply($thing1, $thing2, $name);
+
+ $ok = $this->ok($pass,$name);
+
+ if (!$ok) $this->diag("Structures are identical.\n");
+
+ return $ok;
+ }
+
+ function _compare_deeply ($thing1, $thing2) {
+
+ if (is_array($thing1) && is_array($thing2)) {
+ if ((count($thing1) === count($thing2)) && !array_diff_key($thing1,$thing2)) {
+ foreach(array_keys($thing1) as $key){
+ $pass = $this->_compare_deeply($thing1[$key],$thing2[$key]);
+ if(!$pass) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+
+ } else {
+ return FALSE;
+ }
+
+ } else {
+ return $thing1 === $thing2;
+ }
+ }
+
+ function todo ($why, $howmany) {
+ // Marks tests as expected to fail, then runs them anyway
+
+ if ($howmany < 0) $howmany = 0;
+
+ $this->Todo = $howmany;
+ $this->TodoReason = $why;
+
+ return TRUE;
+ }
+
+ function todo_skip ($why, $howmany) {
+ // Marks tests as expected to fail, then skips them, as they are expected to also create fatal errors
+
+ $this->todo($why, $howmany);
+ $this->skip($why, $howmany);
+
+ return TRUE;
+ }
+
+ function todo_start ($why) {
+ // as starting a TODO block in Perl- instead of using todo() to set a number of tests, all
+ // tests until todo_end are expected to fail and run anyway
+
+ $this->TodoBlock = FALSE;
+ $this->TodoReason = $why;
+
+ return TRUE;
+ }
+
+ function todo_end () {
+ // as ending a SKIP block in Perl
+
+ $this->TodoBlock = FALSE;
+ unset($this->TodoReason);
+
+ return TRUE;
+ }
+
+ function interp ($new_interp_command=NULL) {
+ // Return the command used to invoke the PHP interpreter, such as for exec()
+
+ if ($new_interp_command == NULL && $this->interp == '') {
+ // In some situations you might need to specify a php interpreter.
+ if ( isset($_SERVER['PHP']) ) {
+ $new_interp_command = escapeshellcmd($_SERVER['PHP']);
+ } else {
+ $new_interp_command = 'php';
+ }
+ }
+ if ($new_interp_command != $this->interp) {
+ $this->interp = $new_interp_command;
+
+ // Check that we can use the interpreter
+ @exec('"'.$this->interp.'" -v', $bunk, $retval);
+ if ($retval!==0) $this->bail("Unable to run PHP interpreter with '$this->interp'. Try setting the PHP environmant variable to the path of the interpreter.");
+ }
+
+ return $this->interp;
+ }
+
+
+}
+
+?>
diff --git a/application/third_party/test-more-php/Test-More.php b/application/third_party/test-more-php/Test-More.php
new file mode 100755
index 000000000..3cdf1ad37
--- /dev/null
+++ b/application/third_party/test-more-php/Test-More.php
@@ -0,0 +1,41 @@
+
diff --git a/application/third_party/test-more-php/Test-Simple-OO.php b/application/third_party/test-more-php/Test-Simple-OO.php
new file mode 100755
index 000000000..e91a5645b
--- /dev/null
+++ b/application/third_party/test-more-php/Test-Simple-OO.php
@@ -0,0 +1,232 @@
+plan(2);
+ $t->ok(1 + 1 = 2, 'One plus one equals two');
+ $t->ok( doSomethingAndReturnTrue() , 'doSomethingAndReturnTrue() successful');
+
+ Procedural Example:
+ require_once('Test-Simple');
+ plan(2);
+ ok(1 + 1 = 2, 'One plus one equals two');
+ ok( doSomethingAndReturnTrue() , 'doSomethingAndReturnTrue() successful');
+
+ From a browser
+ If you are running Test-Simple on a web server and want slightly more web-readable
+ output, call the web_output() method/function.
+
+ Updates
+ Updates will be posted to the Google code page:
+ http://code.google.com/p/test-more-php/
+
+ Bugs
+ Please file bug reports via the Issues tracker at the google code page.
+
+ Acknowledgements
+ Michael G Schwern: http://search.cpan.org/~mschwern/Test-Simple/
+ Chris Shiflet: http://shiflett.org/code/test-more.php
+
+ Author
+ Copyright RJ Herrick 2009, 2010
+
+*/
+
+class TestSimple {
+
+ protected $Results = array('Failed'=>NULL,'Passed'=>NULL);
+ protected $TestName = array();
+ protected $TestsRun = 0;
+ protected $Skips;
+ protected $NumberOfTests;
+ protected $Filter;
+
+ protected $notes;
+
+ function plan ($NumberOfTests = NULL, $SkipReason = '') {
+ // Get/set intended number of tests
+
+ if ( is_int($this->NumberOfTests) && !is_null($NumberOfTests) ) $this->diag('The plan was already output.');
+
+ if ( $NumberOfTests === 'no_plan' ) {
+ // Equivalent to done_testing() at end of test script
+ $this->NumberOfTests = $NumberOfTests;
+ return;
+ } else if ( $NumberOfTests === 'skip_all' ) {
+ // Equivalent to done_testing() at end of test script
+ $this->NumberOfTests = $NumberOfTests;
+ $this->SkipAllReason = $SkipReason;
+ $this->diag("Skipping all tests: $SkipReason");
+ exit();
+ }
+
+ // Return current value if no params passed (query to the plan)
+ if ( !func_num_args() && isset($this->NumberOfTests) ) return $this->NumberOfTests;
+
+ // Number of tests looks acceptable
+ if (!is_int($NumberOfTests) || 0 > $NumberOfTests) $this->bail( "Number of tests must be a positive integer. You gave it '$NumberOfTests'" );
+
+ // If just reporting
+ $skipinfo = '';
+ if ($this->NumberOfTests === 'skip_all') $skipinfo = ' # '.$this->SkipAllReason;
+
+ echo "1..${NumberOfTests}${skipinfo}\n";
+ $this->NumberOfTests = $NumberOfTests;
+
+ return;
+ }
+
+ function ok ($Result = NULL, $TestName = NULL) {
+ // Confirm param 1 is true (in the PHP sense)
+ // Unload the buffer regularly
+ if ($this->Filter) {
+ ob_flush();
+ }
+
+ $this->CurrentTestNumber++;
+ $this->TestsRun++;
+
+ if ($this->Skips) {
+ $this->Skips--;
+ $this->TestsSkipped++;
+ echo('ok '.$this->CurrentTestNumber.' # skip '.$this->SkipReason."\n");
+ return TRUE;
+ }
+
+ if ($this->NumberOfTests === 'skip_all') {
+ $this->TestsSkipped++;
+ $this->diag("SKIP '$TestName'");
+ echo('ok '.$this->CurrentTestNumber." # skip\n");
+ return TRUE;
+ }
+
+ if ( func_num_args() == 0 ) $this->bail('You must pass ok() a result to evaluate.');
+ if ( func_num_args() == 2 ) $this->TestName[$this->CurrentTestNumber] = $TestName;
+ if ( func_num_args() > 2 ) $this->bail('Wrong number of arguments passed to ok()');
+
+ $verdict = $Result ? 'Passed' : 'Failed';
+
+ $this->Results[$verdict]++;
+ #$this->TestResult[$this->CurrentTestNumber] = $verdict;
+
+ $caption = isset($this->TestName[$this->CurrentTestNumber]) ? $this->TestName[$this->CurrentTestNumber] : '';
+
+ $title = $this->CurrentTestNumber
+ . (isset($this->TestName[$this->CurrentTestNumber]) ? (' - '.$this->TestName[$this->CurrentTestNumber]) : '');
+
+ if ($verdict === 'Passed') {
+ echo "ok $title\n";
+ return TRUE;
+
+ } else {
+ echo $this->LastFail = "not ok $title\n";
+
+ $stack = isset($this->Backtrace) ? $this->Backtrace : debug_backtrace();
+ $call = array_pop($stack);
+ $file = basename($call['file']);
+ $line = $call['line'];
+ unset($this->Backtrace);
+
+ if ($caption) {
+ $this->diag(" Failed test '$caption'"," at $file line $line.");
+ $this->LastFail .= "# Failed test '$caption'\n# at $file line $line.";
+ } else {
+ $this->diag(" Failed test at $file line $line.");
+ $this->LastFail .= "# Failed test at $file line $line.";
+ }
+
+ return FALSE;
+ }
+ }
+
+ function done_testing () {
+ // Change of plans (if there was one in the first place)
+ $this->plan((int)$this->TestsRun);
+ exit();
+ }
+
+ function bail ($message = '') {
+ // Problem running the program
+ TestSimple::_bail($message);
+ }
+
+ static function _bail ($message = '') {
+ echo "Bail out! $message\n";
+ exit(255);
+ }
+
+ function diag() {
+ // Print a diagnostic comment
+ $diagnostics = func_get_args();
+ $msg = '';
+ foreach ($diagnostics as $line) $msg .= "# ".str_replace("\n","\n# ",$line)."\n";
+ echo $msg;
+ if ($this->Filter) ob_flush();
+ return $msg;
+ }
+
+ function __destruct () {
+ // Parting remarks and proper exit code
+
+ # if ($this->NumberOfTests === 'no_plan') done_testing();
+ # if ($this->NumberOfTests === 'skip_all') plan(0);
+
+ if ($this->TestsRun && !isset($this->NumberOfTests)) {
+ echo "# Tests were run but no plan() was declared and done_testing() was not seen.\n";
+ } else {
+ if ($this->TestsRun !== $this->NumberOfTests) echo("# Looks like you planned ".(int)$this->NumberOfTests .' tests but ran '.(int)$this->TestsRun.".\n");
+
+ if ($this->Results['Failed']) echo("# Looks like you failed ". $this->Results['Failed'] .' tests of '.(int)$this->TestsRun.".\n");
+ }
+
+ // an extension to help debug
+ if ($this->notes) echo $this->notes;
+
+ if ($this->Filter) ob_end_flush();
+
+ $retval = ($this->Results['Failed'] > 254) ? 254 : $this->Results['Failed'];
+ exit($retval);
+ }
+
+ function web_output($callback = NULL) {
+ // Basic web formatting (newlines) of output via ob filter
+ if (isset($callback)) $this->Filter = $callback;
+ if (!isset($this->Filter)) $this->Filter = create_function('$string','$output = str_replace("\n","
\n",$string); return $output;');
+ ob_start($this->Filter);
+ }
+
+}
+
+?>
diff --git a/application/third_party/test-more-php/Test-Simple.php b/application/third_party/test-more-php/Test-Simple.php
new file mode 100755
index 000000000..5005383df
--- /dev/null
+++ b/application/third_party/test-more-php/Test-Simple.php
@@ -0,0 +1,18 @@
+
diff --git a/application/third_party/test-more-php/t/PHProvable.pl b/application/third_party/test-more-php/t/PHProvable.pl
new file mode 100755
index 000000000..1d2295895
--- /dev/null
+++ b/application/third_party/test-more-php/t/PHProvable.pl
@@ -0,0 +1,35 @@
+#!/bin/env perl
+
+# PHProveable.pl
+#
+# A wrapper/dummy for
+#
+# This script allows you to use the prove program with PHP test scripts
+# that output TAP, such as those written with Test-Simple or Test-More,
+# without requiring that the php test script be writen with a UNIX style
+# shebang line pointing to the processor:
+#
+# #!/bin/env php
+#
+# USAGE:
+# Your PHP test script should be named like this: TESTSCRIPTNAME.t.php.
+# You can either copy this file and name it TESTSCRIPTNAME.t or call it
+# explicitly as the first and only argument:
+# PHProvable.pl TESTSCRIPTNAME.t.php
+# The first method means you end up with a stub for each PHP script,
+# although on a system with symlinks you can use a symlink instead of
+# copying PHProveable:
+# ln -s PHPRoveable.pl TESTSCRIPTNAME.t
+# The stub method allows you to just run `prove` in a directory and have
+# it look for a /t directory, then find your *.t stubs and run them as
+# usual.
+#
+# NOTES:
+# Yeah, there are many ways to skin a cat. You could just leave the .php
+# off your test script and add the shebang line, but then you can't just
+# run the script via CGI without the shebang showing up as extra content,
+# and it won't work on windows via the CLI.
+
+my $script = $ARGV[0] ? $ARGV[0] : "$0.php";
+my $php_interp = $ENV{'PHP'} ? $ENV{'PHP'} : 'php';
+exec("$php_interp $script");
diff --git a/application/third_party/test-more-php/t/badlib.php b/application/third_party/test-more-php/t/badlib.php
new file mode 100755
index 000000000..ef7ee536a
--- /dev/null
+++ b/application/third_party/test-more-php/t/badlib.php
@@ -0,0 +1,5 @@
+
diff --git a/application/third_party/test-more-php/t/borklib.php b/application/third_party/test-more-php/t/borklib.php
new file mode 100755
index 000000000..da1ed4da9
--- /dev/null
+++ b/application/third_party/test-more-php/t/borklib.php
@@ -0,0 +1,5 @@
+
diff --git a/application/third_party/test-more-php/t/goodlib.php b/application/third_party/test-more-php/t/goodlib.php
new file mode 100755
index 000000000..5b2140962
--- /dev/null
+++ b/application/third_party/test-more-php/t/goodlib.php
@@ -0,0 +1,5 @@
+
diff --git a/application/third_party/test-more-php/t/goodpage.php b/application/third_party/test-more-php/t/goodpage.php
new file mode 100755
index 000000000..ce38cb818
--- /dev/null
+++ b/application/third_party/test-more-php/t/goodpage.php
@@ -0,0 +1,5 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_bail_badplan_negative.php b/application/third_party/test-more-php/t/testertests_bail_badplan_negative.php
new file mode 100755
index 000000000..81488367a
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_bail_badplan_negative.php
@@ -0,0 +1,9 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_bail_badplan_noninteger.php b/application/third_party/test-more-php/t/testertests_bail_badplan_noninteger.php
new file mode 100755
index 000000000..843b13d31
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_bail_badplan_noninteger.php
@@ -0,0 +1,9 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_bundle.php b/application/third_party/test-more-php/t/testertests_bundle.php
new file mode 100755
index 000000000..91bf79569
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_bundle.php
@@ -0,0 +1,42 @@
+', 10, 'cmp_ok() is ok');
+ can_ok($__Test, 'plan' );
+ isa_ok($__Test, 'TestMore', 'Default Testing object');
+ include_ok('t/goodlib.php');
+ require_ok('t/goodpage.php');
+
+ $foo = array(1,'B','third');
+ $oof = array('third','B',1);
+
+ $bar = array('q'=>23,'Y'=>42,);
+ $rab = array('Y'=>42,'q'=>23,);
+
+ is_deeply($foo,$foo,'is_deeply() is ok');
+ isnt_deeply($foo,$bar,'isnt_deeply() is ok');
+
+ /*
+ function skip($SkipReason, $num) {
+ function todo ($why, $howmany) {
+ function todo_skip ($why, $howmany) {
+ function todo_start ($why) {
+ function todo_end () {
+ */
+
+ diag("Should fail 1 test, testing fail()");
+ done_testing();
+?>
diff --git a/application/third_party/test-more-php/t/testertests_deprecated_comparisons.php b/application/third_party/test-more-php/t/testertests_deprecated_comparisons.php
new file mode 100755
index 000000000..3fb42ee6d
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_deprecated_comparisons.php
@@ -0,0 +1,27 @@
+1,1=>'B',2=>'third');
+ $oof = array(0=>'third',1=>'B',2=>1);
+
+
+
+ $bar = array('q'=>23,'Y'=>42,);
+ $rab = array('Y'=>42,'q'=>23,);
+
+
+
+ ok(eq_array($foo,$oof),'eq_array() with misordered array is ok');
+ ok(eq_array($bar,$rab),'eq_array() with misordered assoc is ok');
+ ok(eq_hash($foo,$oof),'eq_hash() with misordered array is ok');
+ ok(eq_hash($bar,$rab),'eq_hash() with misordered assoc is ok');
+ ok(eq_set($foo,$oof),'eq_set() with misordered array is ok');
+ ok(eq_set($bar,$rab),'eq_set() with misordered assoc is ok');
+
+ done_testing();
+
+?>
diff --git a/application/third_party/test-more-php/t/testertests_deprecated_comparisons.pl b/application/third_party/test-more-php/t/testertests_deprecated_comparisons.pl
new file mode 100755
index 000000000..2bea27ec4
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_deprecated_comparisons.pl
@@ -0,0 +1,25 @@
+#!/bin/env perl
+ use strict;
+ use warnings;
+ use Test::More ('no_plan');
+
+ diag('Test of deprecated Test::More functions provided for compatibility completeness.');
+
+ my $foo = [1,'B','third'];
+ my $oof = ['third','B',1];
+ my $foo_h = {0=>1,1=>'B',2=>'third'};
+ my $oof_h = {0=>'third',1=>'B',2=>1};
+
+ my $bar = [23,42,];
+ my $rab = [42,23,];
+ my $bar_h = {'q'=>23,'Y'=>42,};
+ my $rab_h = {'Y'=>42,'q'=>23,};
+
+ ok(eq_array($foo,$oof),'eq_array() with misordered array is ok');
+ ok(eq_array($bar,$rab),'eq_array() with misordered assoc is ok');
+ ok(eq_hash($foo_h,$oof_h),'eq_hash() with misordered array is ok');
+ ok(eq_hash($bar_h,$rab_h),'eq_hash() with misordered assoc is ok');
+ ok(eq_set($foo,$oof),'eq_set() with misordered array is ok');
+ ok(eq_set($bar,$rab),'eq_set() with misordered assoc is ok');
+
+ done_testing();
diff --git a/application/third_party/test-more-php/t/testertests_exit_0.php b/application/third_party/test-more-php/t/testertests_exit_0.php
new file mode 100755
index 000000000..7b407016f
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_exit_0.php
@@ -0,0 +1,8 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_exit_fail_260.php b/application/third_party/test-more-php/t/testertests_exit_fail_260.php
new file mode 100755
index 000000000..7737ba0ae
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_exit_fail_260.php
@@ -0,0 +1,14 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_exit_fail_5.php b/application/third_party/test-more-php/t/testertests_exit_fail_5.php
new file mode 100755
index 000000000..4b6596746
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_exit_fail_5.php
@@ -0,0 +1,14 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.php b/application/third_party/test-more-php/t/testertests_func_ok.php
new file mode 100755
index 000000000..1561faf91
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.php
@@ -0,0 +1,24 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.php_Test-More.out b/application/third_party/test-more-php/t/testertests_func_ok.php_Test-More.out
new file mode 100755
index 000000000..d06ec52d4
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.php_Test-More.out
@@ -0,0 +1,24 @@
+# OK
+# (No message for next test)
+ok 1
+ok 2 - 1 is ok
+ok 3 - TRUE is ok
+ok 4 - 'string' is ok
+# Not OK
+# (No message for next test)
+not ok 5
+# Failed test at testertests_func_ok.php line 18.
+not ok 6 - 0 is not ok
+# Failed test '0 is not ok'
+# at testertests_func_ok.php line 19.
+not ok 7 - FALSE is not ok
+# Failed test 'FALSE is not ok'
+# at testertests_func_ok.php line 20.
+not ok 8 - '' is not ok
+# Failed test ''' is not ok'
+# at testertests_func_ok.php line 21.
+not ok 9 - NULL is not ok
+# Failed test 'NULL is not ok'
+# at testertests_func_ok.php line 22.
+1..9
+# Looks like you failed 5 tests of 9.
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.php_Test-Simple.out b/application/third_party/test-more-php/t/testertests_func_ok.php_Test-Simple.out
new file mode 100755
index 000000000..771678b8e
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.php_Test-Simple.out
@@ -0,0 +1,16 @@
+# OK
+# (No message for next test)
+ok 1
+ok 2 - 1 is ok
+ok 3 - TRUE is ok
+ok 4 - 'string' is ok
+# Not OK
+# (No message for next test)
+not ok 5
+not ok 6 - 0 is not ok
+not ok 7 - FALSE is not ok
+not ok 8 - '' is not ok
+not ok 9 - NULL is not ok
+1..9
+
+# Looks like you failed 5 tests of 9.
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.pl b/application/third_party/test-more-php/t/testertests_func_ok.pl
new file mode 100755
index 000000000..e87d97bb1
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.pl
@@ -0,0 +1,24 @@
+#!/bin/env perl
+ use strict;
+ use warnings;
+
+ my $lib = defined($ENV{'TESTLIB'}) ? $ENV{'TESTLIB'} : 'Test::Simple';
+ eval "use $lib;";
+
+ print "# OK\n";
+ print "# (No message for next test)\n";
+ ok(1);
+ ok(1,"1 is ok");
+ ok( !0,"TRUE is ok");
+ ok('string',"'string' is ok");
+
+ print "# Not OK\n";
+ print "# (No message for next test)\n";
+ ok(0);
+ ok(0,"0 is not ok");
+ ok( !1,"FALSE is not ok");
+ ok('',"'' is not ok");
+ ok(undef,"undef is not ok");
+
+ done_testing();
+
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-More.out b/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-More.out
new file mode 100755
index 000000000..e72f09462
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-More.out
@@ -0,0 +1,24 @@
+# OK
+# (No message for next test)
+ok 1
+ok 2 - 1 is ok
+ok 3 - TRUE is ok
+ok 4 - 'string' is ok
+# Not OK
+# (No message for next test)
+not ok 5
+# Failed test at testertests_func_ok.pl line 18.
+not ok 6 - 0 is not ok
+# Failed test '0 is not ok'
+# at testertests_func_ok.pl line 19.
+not ok 7 - FALSE is not ok
+# Failed test 'FALSE is not ok'
+# at testertests_func_ok.pl line 20.
+not ok 8 - '' is not ok
+# Failed test ''' is not ok'
+# at testertests_func_ok.pl line 21.
+not ok 9 - undef is not ok
+# Failed test 'undef is not ok'
+# at testertests_func_ok.pl line 22.
+1..9
+# Looks like you failed 5 tests of 9.
diff --git a/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-Simple.out b/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-Simple.out
new file mode 100755
index 000000000..54c1e576a
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_ok.pl_Test-Simple.out
@@ -0,0 +1,24 @@
+# OK
+# (No message for next test)
+ok 1
+ok 2 - 1 is ok
+ok 3 - !0 is ok
+ok 4 - 'string' is ok
+# Not OK
+# (No message for next test)
+not ok 5
+# Failed test at testertests_func_ok.pl line 17.
+not ok 6 - 0 is not ok
+# Failed test '0 is not ok'
+# at testertests_func_ok.pl line 18.
+not ok 7 - !1 is not ok
+# Failed test '!1 is not ok'
+# at testertests_func_ok.pl line 19.
+not ok 8 - '' is not ok
+# Failed test ''' is not ok'
+# at testertests_func_ok.pl line 20.
+not ok 9 - undef is not ok
+# Failed test 'undef is not ok'
+# at testertests_func_ok.pl line 21.
+Undefined subroutine &main::done_testing called at testertests_func_ok.pl line 23.
+# Tests were run but no plan was declared and done_testing() was not seen.
diff --git a/application/third_party/test-more-php/t/testertests_func_skip.php b/application/third_party/test-more-php/t/testertests_func_skip.php
new file mode 100755
index 000000000..1a5f03823
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_skip.php
@@ -0,0 +1,11 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_func_skip.pl b/application/third_party/test-more-php/t/testertests_func_skip.pl
new file mode 100755
index 000000000..4f3c545b0
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_func_skip.pl
@@ -0,0 +1,9 @@
+#!/bin/env perl
+ use strict;
+ use warnings;
+ use Test::More;
+ plan(tests=>2);
+
+ skip("Test: Skip one",1);
+ fail("Gets skipped");
+ pass("Gets run ok");
diff --git a/application/third_party/test-more-php/t/testertests_include_ok_badlib.php b/application/third_party/test-more-php/t/testertests_include_ok_badlib.php
new file mode 100755
index 000000000..52764fb53
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_include_ok_badlib.php
@@ -0,0 +1,21 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_include_ok_fatal.php b/application/third_party/test-more-php/t/testertests_include_ok_fatal.php
new file mode 100755
index 000000000..982cd5caf
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_include_ok_fatal.php
@@ -0,0 +1,17 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_interp.php b/application/third_party/test-more-php/t/testertests_interp.php
new file mode 100755
index 000000000..f646f81d8
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_interp.php
@@ -0,0 +1,10 @@
+plan(1);
+
+ $t->is( $t->interp(),'php',"interp defaults to php");
+
+?>
diff --git a/application/third_party/test-more-php/t/testertests_interp_env.php b/application/third_party/test-more-php/t/testertests_interp_env.php
new file mode 100755
index 000000000..8c12f0a12
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_interp_env.php
@@ -0,0 +1,19 @@
+plan(1);
+
+ if (strpos(strtoupper($_SERVER['OS']),'WINDOWS') !== FALSE) {
+ // Should also accept extension
+ $newinterp = 'php.exe';
+ } else {
+ // Fair guess
+ $newinterp = '/usr/local/bin/php';
+ }
+
+ $_SERVER['PHP'] = $newinterp;
+ $t->is( $t->interp(),$newinterp,"set valid alternate interp via PHP environment variable ($newinterp)");
+
+?>
diff --git a/application/third_party/test-more-php/t/testertests_interp_set.php b/application/third_party/test-more-php/t/testertests_interp_set.php
new file mode 100755
index 000000000..6e5fa2276
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_interp_set.php
@@ -0,0 +1,18 @@
+plan(1);
+
+ if (strpos(strtoupper($_SERVER['OS']),'WINDOWS') !== FALSE) {
+ // Should also accept extension
+ $newinterp = 'php.exe';
+ } else {
+ // Fair guess
+ $newinterp = '/usr/local/bin/php';
+ }
+
+ $t->is( $t->interp($newinterp),$newinterp,"set valid alternate interp by passing arg: interp($newinterp)");
+
+?>
diff --git a/application/third_party/test-more-php/t/testertests_is_deeply.php b/application/third_party/test-more-php/t/testertests_is_deeply.php
new file mode 100755
index 000000000..de30f2b82
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_is_deeply.php
@@ -0,0 +1,31 @@
+1,1=>'abc'));
+
+ diag("Denials:");
+
+ isnt_deeply(NULL, TRUE, 'NULL !== TRUE');
+ isnt_deeply(NULL, FALSE, 'NULL !== FALSE');
+ isnt_deeply(NULL, 0, 'NULL !== 0');
+ isnt_deeply(NULL, '', "NULL !== ''");
+ isnt_deeply(0, FALSE, '0 !== FALSE');
+ isnt_deeply(1, TRUE, '1 !== TRUE');
+
+?>
diff --git a/application/third_party/test-more-php/t/testertests_require_ok_badlib.php b/application/third_party/test-more-php/t/testertests_require_ok_badlib.php
new file mode 100755
index 000000000..12d0e8b7e
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_require_ok_badlib.php
@@ -0,0 +1,12 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_require_ok_borklib.php b/application/third_party/test-more-php/t/testertests_require_ok_borklib.php
new file mode 100755
index 000000000..4472ca795
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_require_ok_borklib.php
@@ -0,0 +1,12 @@
+
diff --git a/application/third_party/test-more-php/t/testertests_require_ok_missing.php b/application/third_party/test-more-php/t/testertests_require_ok_missing.php
new file mode 100755
index 000000000..087d5d0c0
--- /dev/null
+++ b/application/third_party/test-more-php/t/testertests_require_ok_missing.php
@@ -0,0 +1,12 @@
+
diff --git a/application/third_party/test-more-php/t/try.php b/application/third_party/test-more-php/t/try.php
new file mode 100755
index 000000000..1ca9c2410
--- /dev/null
+++ b/application/third_party/test-more-php/t/try.php
@@ -0,0 +1,7 @@
+#!/usr/bin/env php
+
--
cgit v1.2.3-24-g4f1b
From a0b991d7de4bfbcc823c113a8438142827bf7cba Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:39:25 +0100
Subject: Make Test-More useable for our usecase
Signed-off-by: Florian Pritz
---
application/third_party/test-more-php/Test-More-OO.php | 2 +-
application/third_party/test-more-php/Test-Simple-OO.php | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
(limited to 'application')
diff --git a/application/third_party/test-more-php/Test-More-OO.php b/application/third_party/test-more-php/Test-More-OO.php
index 195c27b00..aa769e3ee 100755
--- a/application/third_party/test-more-php/Test-More-OO.php
+++ b/application/third_party/test-more-php/Test-More-OO.php
@@ -280,7 +280,7 @@ class TestMore extends TestSimple {
// Not a bail because you asked for it
if ($ok == FALSE) {
$this->diag(" Exiting due to missing requirement.");
- exit();
+ throw new RuntimeException("Missing requirement");
}
return $ok;
diff --git a/application/third_party/test-more-php/Test-Simple-OO.php b/application/third_party/test-more-php/Test-Simple-OO.php
index e91a5645b..1d33eff2e 100755
--- a/application/third_party/test-more-php/Test-Simple-OO.php
+++ b/application/third_party/test-more-php/Test-Simple-OO.php
@@ -71,6 +71,7 @@ class TestSimple {
protected $TestsRun = 0;
protected $Skips;
protected $NumberOfTests;
+ protected $CurrentTestNumber;
protected $Filter;
protected $notes;
@@ -89,7 +90,7 @@ class TestSimple {
$this->NumberOfTests = $NumberOfTests;
$this->SkipAllReason = $SkipReason;
$this->diag("Skipping all tests: $SkipReason");
- exit();
+ return;
}
// Return current value if no params passed (query to the plan)
@@ -174,7 +175,7 @@ class TestSimple {
function done_testing () {
// Change of plans (if there was one in the first place)
$this->plan((int)$this->TestsRun);
- exit();
+ return;
}
function bail ($message = '') {
@@ -184,7 +185,7 @@ class TestSimple {
static function _bail ($message = '') {
echo "Bail out! $message\n";
- exit(255);
+ throw new RuntimeException("Bail out! $message");
}
function diag() {
@@ -217,7 +218,7 @@ class TestSimple {
if ($this->Filter) ob_end_flush();
$retval = ($this->Results['Failed'] > 254) ? 254 : $this->Results['Failed'];
- exit($retval);
+ return;
}
function web_output($callback = NULL) {
--
cgit v1.2.3-24-g4f1b
From 5f0f6b7c843596a05fb311e4636959ea71e7aaac Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:39:52 +0100
Subject: Improve error line information in Test-More
This finds the last frame before Test-More instead of using the
topmost frame.
Signed-off-by: Florian Pritz
---
application/third_party/test-more-php/Test-Simple-OO.php | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
(limited to 'application')
diff --git a/application/third_party/test-more-php/Test-Simple-OO.php b/application/third_party/test-more-php/Test-Simple-OO.php
index 1d33eff2e..9bbe4aada 100755
--- a/application/third_party/test-more-php/Test-Simple-OO.php
+++ b/application/third_party/test-more-php/Test-Simple-OO.php
@@ -154,10 +154,14 @@ class TestSimple {
} else {
echo $this->LastFail = "not ok $title\n";
- $stack = isset($this->Backtrace) ? $this->Backtrace : debug_backtrace();
- $call = array_pop($stack);
- $file = basename($call['file']);
- $line = $call['line'];
+ $stack = isset($this->Backtrace) ? $this->Backtrace : debug_backtrace();
+ foreach (array_reverse($stack) as $frame) {
+ if (isset($frame["object"]) && $frame["object"] == $this) {
+ $file = $frame["file"];
+ $line = $frame["line"];
+ break;
+ }
+ }
unset($this->Backtrace);
if ($caption) {
--
cgit v1.2.3-24-g4f1b
From db8a70bbcb941fde96a0ac98919702c49814d0c5 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:48:16 +0100
Subject: fixup! Support database table prefixes
Signed-off-by: Florian Pritz
---
application/models/mmultipaste.php | 12 ++++++------
application/service/files.php | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
(limited to 'application')
diff --git a/application/models/mmultipaste.php b/application/models/mmultipaste.php
index 2b0196531..9be4dc416 100644
--- a/application/models/mmultipaste.php
+++ b/application/models/mmultipaste.php
@@ -65,7 +65,7 @@ class Mmultipaste extends CI_Model {
$sql = '
SELECT multipaste.url_id
- FROM multipaste
+ FROM '.$this->db->dbprefix.'multipaste
WHERE multipaste.url_id = ?
LIMIT 1';
$query = $this->db->query($sql, array($id));
@@ -113,7 +113,7 @@ class Mmultipaste extends CI_Model {
{
return $this->db->query("
SELECT user_id
- FROM multipaste
+ FROM ".$this->db->dbprefix."multipaste
WHERE url_id = ?
", array($id))->row_array()["user_id"];
}
@@ -122,7 +122,7 @@ class Mmultipaste extends CI_Model {
{
return $this->db->query("
SELECT url_id, user_id, date
- FROM multipaste
+ FROM ".$this->db->dbprefix."multipaste
WHERE url_id = ?
", array($id))->row_array();
}
@@ -133,8 +133,8 @@ class Mmultipaste extends CI_Model {
$query = $this->db->query("
SELECT mfm.file_url_id
- FROM multipaste_file_map mfm
- JOIN multipaste m ON m.multipaste_id = mfm.multipaste_id
+ FROM ".$this->db->dbprefix."multipaste_file_map mfm
+ JOIN ".$this->db->dbprefix."multipaste m ON m.multipaste_id = mfm.multipaste_id
WHERE m.url_id = ?
ORDER BY mfm.sort_order
", array($url_id))->result_array();
@@ -151,7 +151,7 @@ class Mmultipaste extends CI_Model {
{
$query = $this->db->query("
SELECT multipaste_id
- FROM multipaste
+ FROM ".$this->db->dbprefix."multipaste
WHERE url_id = ?
", array($url_id));
diff --git a/application/service/files.php b/application/service/files.php
index b4b7759e0..962939c87 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -30,7 +30,7 @@ class files {
SELECT sum(filesize) sum
FROM (
SELECT DISTINCT hash, filesize
- FROM files
+ FROM `".$CI->db->dbprefix."files`
WHERE user = ?
) sub
", array($user))->row_array();
--
cgit v1.2.3-24-g4f1b
From d3726c7c0e497def97efcf610fdcac9bbebb0f3e Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:49:12 +0100
Subject: Add simple testsuite
Signed-off-by: Florian Pritz
---
application/config/config.php | 6 +-
application/controllers/tools.php | 37 ++++++++++++
application/tests/Test.php | 98 +++++++++++++++++++++++++++++++
application/tests/test_api_v1.php | 118 ++++++++++++++++++++++++++++++++++++++
4 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 application/tests/Test.php
create mode 100644 application/tests/test_api_v1.php
(limited to 'application')
diff --git a/application/config/config.php b/application/config/config.php
index 2748e97c0..16f5af4bb 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -126,7 +126,11 @@ $config['subclass_prefix'] = 'MY_';
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
*/
-$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
+if (php_sapi_name() == "cli") {
+ $config['permitted_uri_chars'] = '';
+} else {
+ $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
+}
/*
diff --git a/application/controllers/tools.php b/application/controllers/tools.php
index 8c0785409..f04f86224 100644
--- a/application/controllers/tools.php
+++ b/application/controllers/tools.php
@@ -42,4 +42,41 @@ class Tools extends MY_Controller {
throw new \exceptions\ApiException("tools/update_database/migration-error", $this->migration->error_string());
}
}
+
+ function drop_all_tables_using_prefix()
+ {
+ $tables = $this->db->list_tables();
+ $prefix = $this->db->dbprefix;
+ $tables_to_drop = array();
+
+ foreach ($tables as $table) {
+ if (strpos($table, $prefix) === 0) {
+ $tables_to_drop[] = $this->db->protect_identifiers($table);
+ }
+ }
+
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 0');
+ $this->db->query('DROP TABLE '.implode(", ", $tables_to_drop));
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 1');
+ }
+
+ function test()
+ {
+ global $argv;
+ $url = $argv[3];
+ $testcase = $argv[4];
+
+ $testclass = '\tests\\'.$testcase;
+ $test = new $testclass();
+ $test->setServer($url);
+
+ $refl = new ReflectionClass($test);
+ foreach ($refl->getMethods() as $method) {
+ if (strpos($method->name, "test_") === 0) {
+ $test->init();
+ $test->{$method->name}();
+ $test->cleanup();
+ }
+ }
+ }
}
diff --git a/application/tests/Test.php b/application/tests/Test.php
new file mode 100644
index 000000000..81225b312
--- /dev/null
+++ b/application/tests/Test.php
@@ -0,0 +1,98 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace tests;
+
+abstract class Test {
+ protected $t;
+ protected $server = "";
+
+ public function __construct()
+ {
+ require_once APPPATH."/third_party/test-more-php/Test-More-OO.php";
+ $this->t = new \TestMore();
+ $this->t->plan("no_plan");
+ }
+
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ // Method: POST, PUT, GET etc
+ // Data: array("param" => "value") ==> index.php?param=value
+ // Source: http://stackoverflow.com/a/9802854/953022
+ protected function CallAPI($method, $url, $data = false)
+ {
+ $curl = curl_init();
+
+ switch ($method) {
+ case "POST":
+ curl_setopt($curl, CURLOPT_POST, 1);
+
+ if ($data)
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
+ break;
+ case "PUT":
+ curl_setopt($curl, CURLOPT_PUT, 1);
+ break;
+ default:
+ if ($data)
+ $url = sprintf("%s?%s", $url, http_build_query($data));
+ }
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+ "Accept: application/json",
+ ));
+
+ $result = curl_exec($curl);
+
+ curl_close($curl);
+
+ $json = json_decode($result, true);
+ if ($json === NULL) {
+ $this->t->fail("json decode");
+ $this->diagReply($result);
+ }
+
+ return $json;
+ }
+
+ protected function expectSuccess($testname, $reply)
+ {
+ if (!isset($reply["status"]) || $reply["status"] != "success") {
+ $this->t->fail($testname);
+ $this->diagReply($reply);
+ } else {
+ $this->t->pass($testname);
+ }
+ return $reply;
+ }
+
+ protected function diagReply($reply)
+ {
+ $this->t->diag("Request got unexpected response:");
+ $this->t->diag(var_export($reply, true));
+ }
+
+ public function init()
+ {
+ }
+
+ public function cleanup()
+ {
+ }
+
+ public function __destruct()
+ {
+ $this->t->done_testing();
+ }
+}
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
new file mode 100644
index 000000000..387e3fe6c
--- /dev/null
+++ b/application/tests/test_api_v1.php
@@ -0,0 +1,118 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace tests;
+
+class test_api_v1 extends Test {
+
+ private $apikeys = array();
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $CI =& get_instance();
+ $CI->load->model("muser");
+ $CI->load->model("mfile");
+
+ foreach (array(1,2,3,4,5) as $i) {
+ $CI->db->insert("users", array(
+ 'username' => "testuser-api_v1-$i",
+ 'password' => $CI->muser->hash_password("testpass$i"),
+ 'email' => "testuser$i@localhost.invalid",
+ 'referrer' => NULL
+ ));
+ $this->apikeys[$i] = \service\user::create_apikey($CI->db->insert_id(), "", "apikey");
+ }
+
+ }
+
+ public function test_create_apikey_createNewKey()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/user/create_apikey", array(
+ "username" => "testuser-api_v1-1",
+ "password" => "testpass1",
+ "access_level" => "apikey",
+ "comment" => "main api key",
+ ));
+ $this->expectSuccess("create-apikey", $ret);
+
+ $this->t->isnt($ret["data"]["new_key"], "", "apikey not empty");
+ }
+
+ public function test_history_empty()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[1],
+ ));
+ $this->expectSuccess("get history", $ret);
+
+ $this->t->ok(empty($ret["data"]["items"]), "items key exists and empty");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "multipaste_items key exists and empty");
+ $this->t->is($ret["data"]["total_size"], 0, "total_size = 0 since no uploads");
+ }
+
+ public function test_get_config()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/get_config", array(
+ ));
+ $this->expectSuccess("get_config", $ret);
+
+ $this->t->like($ret["data"]["upload_max_size"], '/[0-9]+/', "upload_max_size is int");
+ $this->t->like($ret["data"]["max_files_per_request"], '/[0-9]+/', "max_files_per_request is int");
+ }
+
+ public function test_upload_uploadFile()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[2],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $this->t->ok(!empty($ret["data"]["ids"]), "got IDs");
+ $this->t->ok(!empty($ret["data"]["urls"]), "got URLs");
+ }
+
+ public function test_history_notEmptyAfterUpload()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[3],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[3],
+ ));
+ $this->expectSuccess("history not empty after upload", $ret);
+
+ $this->t->ok(!empty($ret["data"]["items"]), "history not empty after upload (items)");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "didn't upload multipaste");
+ $this->t->is($ret["data"]["total_size"], filesize("data/tests/small-file"), "total_size == uploaded file");
+ }
+
+ public function test_history_notSharedBetweenUsers()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[4],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[5],
+ ));
+ $this->expectSuccess("get history", $ret);
+
+ $this->t->ok(empty($ret["data"]["items"]), "items key exists and empty");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "multipaste_items key exists and empty");
+ $this->t->is($ret["data"]["total_size"], 0, "total_size = 0 since no uploads");
+ }
+}
--
cgit v1.2.3-24-g4f1b
From 03e9a7abbf2851f3f8ac4c9a1d0bc072f4a9e103 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Thu, 5 Feb 2015 21:52:43 +0100
Subject: service/files::history: Fix total_size if no results
Signed-off-by: Florian Pritz
---
application/service/files.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'application')
diff --git a/application/service/files.php b/application/service/files.php
index 962939c87..59a096d1b 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -27,7 +27,7 @@ class files {
}
$total_size = $CI->db->query("
- SELECT sum(filesize) sum
+ SELECT coalesce(sum(filesize), 0) sum
FROM (
SELECT DISTINCT hash, filesize
FROM `".$CI->db->dbprefix."files`
--
cgit v1.2.3-24-g4f1b
From 67ed287e97daa9965521c9d133714bde72145711 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Fri, 6 Feb 2015 12:40:28 +0100
Subject: fixup! Support database table prefixes
Signed-off-by: Florian Pritz
---
application/models/mmultipaste.php | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
(limited to 'application')
diff --git a/application/models/mmultipaste.php b/application/models/mmultipaste.php
index 9be4dc416..ed3b8e3a7 100644
--- a/application/models/mmultipaste.php
+++ b/application/models/mmultipaste.php
@@ -64,9 +64,9 @@ class Mmultipaste extends CI_Model {
}
$sql = '
- SELECT multipaste.url_id
- FROM '.$this->db->dbprefix.'multipaste
- WHERE multipaste.url_id = ?
+ SELECT url_id
+ FROM `'.$this->db->dbprefix.'multipaste`
+ WHERE url_id = ?
LIMIT 1';
$query = $this->db->query($sql, array($id));
@@ -113,7 +113,7 @@ class Mmultipaste extends CI_Model {
{
return $this->db->query("
SELECT user_id
- FROM ".$this->db->dbprefix."multipaste
+ FROM `".$this->db->dbprefix."multipaste`
WHERE url_id = ?
", array($id))->row_array()["user_id"];
}
@@ -122,7 +122,7 @@ class Mmultipaste extends CI_Model {
{
return $this->db->query("
SELECT url_id, user_id, date
- FROM ".$this->db->dbprefix."multipaste
+ FROM `".$this->db->dbprefix."multipaste`
WHERE url_id = ?
", array($id))->row_array();
}
@@ -133,8 +133,8 @@ class Mmultipaste extends CI_Model {
$query = $this->db->query("
SELECT mfm.file_url_id
- FROM ".$this->db->dbprefix."multipaste_file_map mfm
- JOIN ".$this->db->dbprefix."multipaste m ON m.multipaste_id = mfm.multipaste_id
+ FROM `".$this->db->dbprefix."multipaste_file_map` mfm
+ JOIN `".$this->db->dbprefix."multipaste` m ON m.multipaste_id = mfm.multipaste_id
WHERE m.url_id = ?
ORDER BY mfm.sort_order
", array($url_id))->result_array();
@@ -151,7 +151,7 @@ class Mmultipaste extends CI_Model {
{
$query = $this->db->query("
SELECT multipaste_id
- FROM ".$this->db->dbprefix."multipaste
+ FROM `".$this->db->dbprefix."multipaste`
WHERE url_id = ?
", array($url_id));
--
cgit v1.2.3-24-g4f1b
From f5cab9d96aec1464978b556f2ca02e79b2c4d8d8 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Fri, 6 Feb 2015 12:40:58 +0100
Subject: service/files::delete: Fix incorrect error when wrong owner
Also improve the variable name for easier understanding.
Signed-off-by: Florian Pritz
---
application/service/files.php | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
(limited to 'application')
diff --git a/application/service/files.php b/application/service/files.php
index 59a096d1b..802ba70af 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -153,7 +153,7 @@ class files {
foreach ($ids as $id) {
$total_count++;
- $next = false;
+ $nextID = false;
foreach (array($CI->mfile, $CI->mmultipaste) as $model) {
if ($model->id_exists($id)) {
@@ -162,6 +162,7 @@ class files {
"id" => $id,
"reason" => "wrong owner",
);
+ $nextID = true;
continue;
}
if ($model->delete_id($id)) {
@@ -169,7 +170,7 @@ class files {
"id" => $id,
);
$deleted_count++;
- $next = true;
+ $nextID = true;
} else {
$errors[$id] = array(
"id" => $id,
@@ -179,7 +180,7 @@ class files {
}
}
- if ($next) {
+ if ($nextID) {
continue;
}
--
cgit v1.2.3-24-g4f1b
From 5b225c751d60d79916da4a7db761f823e12148de Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Fri, 6 Feb 2015 12:42:08 +0100
Subject: Add more tests
Signed-off-by: Florian Pritz
---
application/tests/Test.php | 14 +++++++++++--
application/tests/test_api_v1.php | 44 +++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/tests/Test.php b/application/tests/Test.php
index 81225b312..192061db9 100644
--- a/application/tests/Test.php
+++ b/application/tests/Test.php
@@ -66,9 +66,9 @@ abstract class Test {
return $json;
}
- protected function expectSuccess($testname, $reply)
+ protected function excpectStatus($testname, $reply, $status)
{
- if (!isset($reply["status"]) || $reply["status"] != "success") {
+ if (!isset($reply["status"]) || $reply["status"] != $status) {
$this->t->fail($testname);
$this->diagReply($reply);
} else {
@@ -77,6 +77,16 @@ abstract class Test {
return $reply;
}
+ protected function expectSuccess($testname, $reply)
+ {
+ return $this->excpectStatus($testname, $reply, "success");
+ }
+
+ protected function expectError($testname, $reply)
+ {
+ return $this->excpectStatus($testname, $reply, "error");
+ }
+
protected function diagReply($reply)
{
$this->t->diag("Request got unexpected response:");
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index 387e3fe6c..9f415abbd 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -115,4 +115,48 @@ class test_api_v1 extends Test {
$this->t->ok(empty($ret["data"]["multipaste_items"]), "multipaste_items key exists and empty");
$this->t->is($ret["data"]["total_size"], 0, "total_size = 0 since no uploads");
}
+
+ public function test_delete_canDeleteUploaded()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[2],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $id = $ret["data"]["ids"][0];
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/delete", array(
+ "apikey" => $this->apikeys[2],
+ "ids[1]" => $id,
+ ));
+ $this->expectSuccess("delete uploaded file", $ret);
+
+ $this->t->ok(empty($ret["data"]["errors"]), "no errors");
+ $this->t->is_deeply(array($id => array("id" => $id)), $ret["data"]["deleted"], "deleted wanted ID");
+ $this->t->is($ret["data"]["total_count"], 1, "total_count correct");
+ $this->t->is($ret["data"]["deleted_count"], 1, "deleted_count correct");
+ }
+
+ public function test_delete_errorIfNotOwner()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[2],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $id = $ret["data"]["ids"][0];
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/delete", array(
+ "apikey" => $this->apikeys[1],
+ "ids[1]" => $id,
+ ));
+ $this->expectSuccess("delete file of someone else", $ret);
+
+ $this->t->ok(empty($ret["data"]["deleted"]), "not deleted");
+ $this->t->is_deeply(array($id => array("id" => $id, "reason" => "wrong owner")), $ret["data"]["errors"], "error wanted ID");
+ $this->t->is($ret["data"]["total_count"], 1, "total_count correct");
+ $this->t->is($ret["data"]["deleted_count"], 0, "deleted_count correct");
+ }
}
--
cgit v1.2.3-24-g4f1b
From 89191e702cad9dae78151addd19185695fb19d39 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 01:14:26 +0100
Subject: run-tests.sh: Clean up old database before running tests
Signed-off-by: Florian Pritz
---
application/controllers/tools.php | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'application')
diff --git a/application/controllers/tools.php b/application/controllers/tools.php
index f04f86224..e36b09b79 100644
--- a/application/controllers/tools.php
+++ b/application/controllers/tools.php
@@ -55,6 +55,10 @@ class Tools extends MY_Controller {
}
}
+ if (empty($tables_to_drop)) {
+ return;
+ }
+
$this->db->query('SET FOREIGN_KEY_CHECKS = 0');
$this->db->query('DROP TABLE '.implode(", ", $tables_to_drop));
$this->db->query('SET FOREIGN_KEY_CHECKS = 1');
--
cgit v1.2.3-24-g4f1b
From 56879097fd4246c78175867086af6d0c24a4ae89 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 01:19:37 +0100
Subject: Improve testcases
- create apikeys/users on demand (no magic numbers)
- add some more testcases
- extract api version into function
- readability cleanup
Signed-off-by: Florian Pritz
---
application/tests/test_api_v1.php | 237 ++++++++++++++++++++++++++++++--------
1 file changed, 189 insertions(+), 48 deletions(-)
(limited to 'application')
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index 9f415abbd..18f2a37f6 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -11,8 +11,6 @@ namespace tests;
class test_api_v1 extends Test {
- private $apikeys = array();
-
public function __construct()
{
parent::__construct();
@@ -21,21 +19,75 @@ class test_api_v1 extends Test {
$CI->load->model("muser");
$CI->load->model("mfile");
- foreach (array(1,2,3,4,5) as $i) {
- $CI->db->insert("users", array(
- 'username' => "testuser-api_v1-$i",
- 'password' => $CI->muser->hash_password("testpass$i"),
- 'email' => "testuser$i@localhost.invalid",
- 'referrer' => NULL
+ }
+
+ private function uploadFile($apikey, $file)
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $apikey,
+ "file[1]" => curl_file_create($file),
+ ));
+ $this->expectSuccess("upload file", $ret);
+ return $ret;
+ }
+
+ private function createUser($counter)
+ {
+ $CI =& get_instance();
+ $CI->db->insert("users", array(
+ 'username' => "testuser-api_v1-$counter",
+ 'password' => $CI->muser->hash_password("testpass$counter"),
+ 'email' => "testuser$counter@localhost.invalid",
+ 'referrer' => NULL
+ ));
+
+ return $CI->db->insert_id();
+ }
+
+ private function createApikey($userid)
+ {
+ return \service\user::create_apikey($userid, "", "apikey");
+ }
+
+ private function createUserAndApikey()
+ {
+ static $counter = 100;
+ $counter++;
+ $userid = $this->createUser($counter);
+ return $this->createApikey($userid);
+ }
+
+ private function callEndpoint($verb, $endpoint, $data)
+ {
+ return $this->CallAPI($verb, "$this->server/api/1.0.0/$endpoint", $data);
+ }
+
+ public function test_callPrivateEndpointsWithoutApikey()
+ {
+ $endpoints = array(
+ "file/upload",
+ "file/history",
+ "file/delete",
+ "file/create_multipaste",
+ "user/apikeys",
+ "user/create_apikey",
+ );
+ foreach ($endpoints as $endpoint) {
+ $ret = $this->CallEndpoint("POST", $endpoint, array(
));
- $this->apikeys[$i] = \service\user::create_apikey($CI->db->insert_id(), "", "apikey");
+ $this->expectError("call $endpoint without apikey", $ret);
+ $this->t->is_deeply(array(
+ 'status' => 'error',
+ 'error_id' => 'api/not-authenticated',
+ 'message' => 'Not authenticated. FileBin requires you to have an account, please go to the homepage for more information.',
+ ), $ret, "expected error");
}
-
}
public function test_create_apikey_createNewKey()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/user/create_apikey", array(
+ $this->createUser(1);
+ $ret = $this->CallEndpoint("POST", "user/create_apikey", array(
"username" => "testuser-api_v1-1",
"password" => "testpass1",
"access_level" => "apikey",
@@ -48,8 +100,9 @@ class test_api_v1 extends Test {
public function test_history_empty()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
- "apikey" => $this->apikeys[1],
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->CallEndpoint("POST", "file/history", array(
+ "apikey" => $apikey,
));
$this->expectSuccess("get history", $ret);
@@ -60,7 +113,7 @@ class test_api_v1 extends Test {
public function test_get_config()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/get_config", array(
+ $ret = $this->CallEndpoint("GET", "file/get_config", array(
));
$this->expectSuccess("get_config", $ret);
@@ -70,8 +123,9 @@ class test_api_v1 extends Test {
public function test_upload_uploadFile()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
- "apikey" => $this->apikeys[2],
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->CallEndpoint("POST", "file/upload", array(
+ "apikey" => $apikey,
"file[1]" => curl_file_create("data/tests/small-file"),
));
$this->expectSuccess("upload file", $ret);
@@ -80,16 +134,27 @@ class test_api_v1 extends Test {
$this->t->ok(!empty($ret["data"]["urls"]), "got URLs");
}
- public function test_history_notEmptyAfterUpload()
+ public function test_upload_uploadNothing()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
- "apikey" => $this->apikeys[3],
- "file[1]" => curl_file_create("data/tests/small-file"),
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->CallEndpoint("POST", "file/upload", array(
+ "apikey" => $apikey,
));
- $this->expectSuccess("upload file", $ret);
+ $this->expectError("upload no file", $ret);
+ $this->t->is_deeply(array(
+ 'status' => 'error',
+ 'error_id' => 'file/no-file',
+ 'message' => 'No file was uploaded or unknown error occured.',
+ ), $ret, "expected reply");
+ }
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
- "apikey" => $this->apikeys[3],
+ public function test_history_notEmptyAfterUpload()
+ {
+ $apikey = $this->createUserAndApikey();
+ $this->uploadFile($apikey, "data/tests/small-file");
+
+ $ret = $this->CallEndpoint("POST", "file/history", array(
+ "apikey" => $apikey,
));
$this->expectSuccess("history not empty after upload", $ret);
@@ -100,14 +165,12 @@ class test_api_v1 extends Test {
public function test_history_notSharedBetweenUsers()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
- "apikey" => $this->apikeys[4],
- "file[1]" => curl_file_create("data/tests/small-file"),
- ));
- $this->expectSuccess("upload file", $ret);
+ $apikey = $this->createUserAndApikey();
+ $apikey2 = $this->createUserAndApikey();
+ $this->uploadFile($apikey, "data/tests/small-file");
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
- "apikey" => $this->apikeys[5],
+ $ret = $this->CallEndpoint("POST", "file/history", array(
+ "apikey" => $apikey2,
));
$this->expectSuccess("get history", $ret);
@@ -118,45 +181,123 @@ class test_api_v1 extends Test {
public function test_delete_canDeleteUploaded()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
- "apikey" => $this->apikeys[2],
- "file[1]" => curl_file_create("data/tests/small-file"),
- ));
- $this->expectSuccess("upload file", $ret);
-
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
$id = $ret["data"]["ids"][0];
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/delete", array(
- "apikey" => $this->apikeys[2],
+ $ret = $this->CallEndpoint("POST", "file/delete", array(
+ "apikey" => $apikey,
"ids[1]" => $id,
));
$this->expectSuccess("delete uploaded file", $ret);
$this->t->ok(empty($ret["data"]["errors"]), "no errors");
- $this->t->is_deeply(array($id => array("id" => $id)), $ret["data"]["deleted"], "deleted wanted ID");
+ $this->t->is_deeply(array(
+ $id => array(
+ "id" => $id
+ )
+ ), $ret["data"]["deleted"], "deleted wanted ID");
$this->t->is($ret["data"]["total_count"], 1, "total_count correct");
$this->t->is($ret["data"]["deleted_count"], 1, "deleted_count correct");
}
public function test_delete_errorIfNotOwner()
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
- "apikey" => $this->apikeys[2],
- "file[1]" => curl_file_create("data/tests/small-file"),
- ));
- $this->expectSuccess("upload file", $ret);
-
+ $apikey = $this->createUserAndApikey();
+ $apikey2 = $this->createUserAndApikey();
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
$id = $ret["data"]["ids"][0];
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/delete", array(
- "apikey" => $this->apikeys[1],
+ $ret = $this->CallEndpoint("POST", "file/delete", array(
+ "apikey" => $apikey2,
"ids[1]" => $id,
));
$this->expectSuccess("delete file of someone else", $ret);
$this->t->ok(empty($ret["data"]["deleted"]), "not deleted");
- $this->t->is_deeply(array($id => array("id" => $id, "reason" => "wrong owner")), $ret["data"]["errors"], "error wanted ID");
+ $this->t->is_deeply(array(
+ $id => array(
+ "id" => $id,
+ "reason" => "wrong owner"
+ )
+ ), $ret["data"]["errors"], "error wanted ID");
$this->t->is($ret["data"]["total_count"], 1, "total_count correct");
$this->t->is($ret["data"]["deleted_count"], 0, "deleted_count correct");
}
+
+ public function test_create_multipaste_canCreate()
+ {
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
+ $id = $ret["data"]["ids"][0];
+
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
+ $id2 = $ret["data"]["ids"][0];
+
+ $ret = $this->CallEndpoint("POST", "file/create_multipaste", array(
+ "apikey" => $apikey,
+ "ids[1]" => $id,
+ "ids[2]" => $id2,
+ ));
+ $this->expectSuccess("create multipaste", $ret);
+
+ $this->t->isnt($ret["data"]["url_id"], "", "got a multipaste ID");
+ }
+
+ public function test_create_multipaste_errorOnWrongID()
+ {
+ $apikey = $this->createUserAndApikey();
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
+ $id = $ret["data"]["ids"][0];
+
+ $id2 = $id."invalid";
+ $ret = $this->CallEndpoint("POST", "file/create_multipaste", array(
+ "apikey" => $apikey,
+ "ids[1]" => $id,
+ "ids[2]" => $id2,
+ ));
+ $this->expectError("create multipaste with wrong ID", $ret);
+
+ $this->t->is_deeply(array(
+ 'status' => 'error',
+ 'error_id' => 'file/create_multipaste/verify-failed',
+ 'message' => 'Failed to verify ID(s)',
+ 'data' =>
+ array (
+ $id2 =>
+ array (
+ 'id' => $id2,
+ 'reason' => 'doesn\'t exist',
+ ),
+ ),
+ ), $ret, "expected error response");
+ }
+
+ public function test_create_multipaste_errorOnWrongOwner()
+ {
+ $apikey = $this->createUserAndApikey();
+ $apikey2 = $this->createUserAndApikey();
+ $ret = $this->uploadFile($apikey, "data/tests/small-file");
+ $id = $ret["data"]["ids"][0];
+
+ $ret = $this->CallEndpoint("POST", "file/create_multipaste", array(
+ "apikey" => $apikey2,
+ "ids[1]" => $id,
+ ));
+ $this->expectError("create multipaste with wrong owner", $ret);
+
+ $this->t->is_deeply(array(
+ 'status' => 'error',
+ 'error_id' => 'file/create_multipaste/verify-failed',
+ 'message' => 'Failed to verify ID(s)',
+ 'data' =>
+ array (
+ $id =>
+ array (
+ 'id' => $id,
+ 'reason' => 'not owned by you',
+ ),
+ ),
+ ), $ret, "expected error response");
+ }
}
--
cgit v1.2.3-24-g4f1b
From c302c5cc0143d96391aa544c15e4e0b64cba1182 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 01:34:01 +0100
Subject: Add more tests
Signed-off-by: Florian Pritz
---
application/tests/test_api_v1.php | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
(limited to 'application')
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index 18f2a37f6..faf0d9af7 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -84,6 +84,26 @@ class test_api_v1 extends Test {
}
}
+ public function test_callEndpointsWithoutEnoughPermissions()
+ {
+ $apikey = $this->createUserAndApikey();
+ $endpoints = array(
+ "user/apikeys",
+ "user/create_apikey",
+ );
+ foreach ($endpoints as $endpoint) {
+ $ret = $this->CallEndpoint("POST", $endpoint, array(
+ "apikey" => $apikey,
+ ));
+ $this->expectError("call $endpoint without enough permissions", $ret);
+ $this->t->is_deeply(array(
+ 'status' => "error",
+ 'error_id' => "api/insufficient-permissions",
+ 'message' => "Access denied: Access level too low",
+ ), $ret, "expected error");
+ }
+ }
+
public function test_create_apikey_createNewKey()
{
$this->createUser(1);
@@ -98,6 +118,22 @@ class test_api_v1 extends Test {
$this->t->isnt($ret["data"]["new_key"], "", "apikey not empty");
}
+ public function test_apikeys_getApikey()
+ {
+ $userid = $this->createUser(2);
+ $apikey = $this->createApikey($userid);
+ $ret = $this->CallEndpoint("POST", "user/apikeys", array(
+ "username" => "testuser-api_v1-2",
+ "password" => "testpass2",
+ ));
+ $this->expectSuccess("get apikeys", $ret);
+
+ $this->t->is($ret["data"][0]["key"], $apikey, "expected key 1");
+ $this->t->is($ret["data"][0]["access_level"], "apikey", "expected key 1 acces_level");
+ $this->t->is($ret["data"][0]["comment"], "", "expected key 1 comment");
+ $this->t->ok(is_int($ret["data"][0]["created"]) , "expected key 1 creation time is int");
+ }
+
public function test_history_empty()
{
$apikey = $this->createUserAndApikey();
--
cgit v1.2.3-24-g4f1b
From 1e18ad9d38e0cf6e0e37d3c1ad66eace2bb82003 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 10:57:48 +0100
Subject: tests: Fix php dev server being slow
Signed-off-by: Florian Pritz
---
application/tests/Test.php | 1 +
1 file changed, 1 insertion(+)
(limited to 'application')
diff --git a/application/tests/Test.php b/application/tests/Test.php
index 192061db9..e18aa9374 100644
--- a/application/tests/Test.php
+++ b/application/tests/Test.php
@@ -51,6 +51,7 @@ abstract class Test {
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"Accept: application/json",
+ "Expect: ",
));
$result = curl_exec($curl);
--
cgit v1.2.3-24-g4f1b
From f8513511ff5c77aca1cd2b7fc570d0dd34c4a417 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 11:11:16 +0100
Subject: Add tests for invalid login
Signed-off-by: Florian Pritz
---
application/tests/test_api_v1.php | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
(limited to 'application')
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index faf0d9af7..7fe06ca36 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -134,6 +134,38 @@ class test_api_v1 extends Test {
$this->t->ok(is_int($ret["data"][0]["created"]) , "expected key 1 creation time is int");
}
+ public function test_authentication_invalidPassword()
+ {
+ $userid = $this->createUser(3);
+ $ret = $this->CallEndpoint("POST", "user/apikeys", array(
+ "username" => "testuser-api_v1-3",
+ "password" => "wrongpass",
+ ));
+ $this->expectError("invalid password", $ret);
+
+ $this->t->is_deeply(array (
+ 'status' => 'error',
+ 'error_id' => 'user/login-failed',
+ 'message' => 'Login failed',
+ ), $ret, "expected error");
+ }
+
+ public function test_authentication_invalidUser()
+ {
+ $userid = $this->createUser(4);
+ $ret = $this->CallEndpoint("POST", "user/apikeys", array(
+ "username" => "testuser-api_v1-invalid",
+ "password" => "testpass4",
+ ));
+ $this->expectError("invalid username", $ret);
+
+ $this->t->is_deeply(array (
+ 'status' => 'error',
+ 'error_id' => 'user/login-failed',
+ 'message' => 'Login failed',
+ ), $ret, "expected error");
+ }
+
public function test_history_empty()
{
$apikey = $this->createUserAndApikey();
--
cgit v1.2.3-24-g4f1b
From c8ff6f56b9b971f88fed840c2af50df11b7dc948 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sun, 8 Feb 2015 23:29:25 +0100
Subject: Add tests for \s\f::verify_uploaded_files
Signed-off-by: Florian Pritz
---
application/tests/test_service_files.php | 85 ++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
create mode 100644 application/tests/test_service_files.php
(limited to 'application')
diff --git a/application/tests/test_service_files.php b/application/tests/test_service_files.php
new file mode 100644
index 000000000..3330e8c22
--- /dev/null
+++ b/application/tests/test_service_files.php
@@ -0,0 +1,85 @@
+
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace tests;
+
+class test_service_files extends Test {
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $CI =& get_instance();
+ $CI->load->model("muser");
+ $CI->load->model("mfile");
+
+ }
+
+ public function test_verify_uploaded_files_noFiles()
+ {
+ $a = array();
+ try {
+ \service\files::verify_uploaded_files($a);
+ $this->t->fail("verify should error");
+ } catch (\exceptions\UserInputException $e) {
+ $this->t->is($e->get_error_id(), "file/no-file", "verify should error");
+ }
+ }
+
+ public function test_verify_uploaded_files_normal()
+ {
+ $CI =& get_instance();
+ $a = array(
+ array(
+ "name" => "foobar.txt",
+ "type" => "text/plain",
+ "tmp_name" => NULL,
+ "error" => UPLOAD_ERR_OK,
+ "size" => 1,
+ "formfield" => "file[1]",
+ )
+ );
+
+ \service\files::verify_uploaded_files($a);
+ $this->t->pass("verify should work");
+ }
+
+ public function test_verify_uploaded_files_uploadError()
+ {
+ $CI =& get_instance();
+ $a = array(
+ array(
+ "name" => "foobar.txt",
+ "type" => "text/plain",
+ "tmp_name" => NULL,
+ "error" => UPLOAD_ERR_NO_FILE,
+ "size" => 1,
+ "formfield" => "file[1]",
+ )
+ );
+
+ try {
+ \service\files::verify_uploaded_files($a);
+ $this->t->fail("verify should error");
+ } catch (\exceptions\UserInputException $e) {
+ $data = $e->get_data();
+ $this->t->is($e->get_error_id(), "file/upload-verify", "verify should error");
+ $this->t->is_deeply(array(
+ array(
+ 'filename' => 'foobar.txt',
+ 'formfield' => 'file[1]',
+ 'message' => 'No file was uploaded',
+ ),
+ ), $data, "expected data in exception");
+ }
+ }
+
+
+}
+
--
cgit v1.2.3-24-g4f1b
From cb2df59b45d4cb35790472f76b06c59b22c6213b Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Tue, 10 Feb 2015 23:32:23 +0100
Subject: api: Require the version to start with v
Makes the URL easier to understand (especially the v1 case).
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 7 +++++++
application/tests/test_api_v1.php | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index 3297f0614..837f62e89 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -22,6 +22,13 @@ class Api extends MY_Controller {
$requested_version = $this->uri->segment(2);
$controller = $this->uri->segment(3);
$function = $this->uri->segment(4);
+
+ if (!preg_match("/^v([0-9]+)(.[0-9]+){0,2}$/", $requested_version)) {
+ throw new \exceptions\PublicApiException("api/invalid-version", "Invalid API version requested");
+ }
+
+ $requested_version = substr($requested_version, 1);
+
$major = intval(explode(".", $requested_version)[0]);
if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index 7fe06ca36..bba0f9180 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -23,7 +23,7 @@ class test_api_v1 extends Test {
private function uploadFile($apikey, $file)
{
- $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ $ret = $this->CallAPI("POST", "$this->server/api/v1.0.0/file/upload", array(
"apikey" => $apikey,
"file[1]" => curl_file_create($file),
));
@@ -59,7 +59,7 @@ class test_api_v1 extends Test {
private function callEndpoint($verb, $endpoint, $data)
{
- return $this->CallAPI($verb, "$this->server/api/1.0.0/$endpoint", $data);
+ return $this->CallAPI($verb, "$this->server/api/v1.0.0/$endpoint", $data);
}
public function test_callPrivateEndpointsWithoutApikey()
--
cgit v1.2.3-24-g4f1b
From bfbbf4082779a7535cac2fb270fd928178ae7e70 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 14 Feb 2015 19:10:19 +0100
Subject: Unify exceptions for unknown/invalid endpoints
Signed-off-by: Florian Pritz
---
application/controllers/api.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api.php b/application/controllers/api.php
index 837f62e89..644a726e7 100644
--- a/application/controllers/api.php
+++ b/application/controllers/api.php
@@ -32,11 +32,11 @@ class Api extends MY_Controller {
$major = intval(explode(".", $requested_version)[0]);
if (!preg_match("/^[a-zA-Z-_]+$/", $controller)) {
- throw new \exceptions\PublicApiException("api/invalid-controller-value", "Invalid controller requested");
+ throw new \exceptions\PublicApiException("api/invalid-endpoint", "Invalid endpoint requested");
}
if (!preg_match("/^[a-zA-Z-_]+$/", $function)) {
- throw new \exceptions\PublicApiException("api/invalid-function-value", "Invalid function requested");
+ throw new \exceptions\PublicApiException("api/invalid-endpoint", "Invalid endpoint requested");
}
$namespace = "controllers\\api\\v".$major;
@@ -48,12 +48,12 @@ class Api extends MY_Controller {
}
if (!class_exists($class)) {
- throw new \exceptions\PublicApiException("api/unknown-controller", "Unknown controller requested");
+ throw new \exceptions\PublicApiException("api/unknown-endpoint", "Unknown endpoint requested");
}
$c= new $class;
if (!method_exists($c, $function)) {
- throw new \exceptions\PublicApiException("api/unknown-function", "Unknown function requested");
+ throw new \exceptions\PublicApiException("api/unknown-endpoint", "Unknown endpoint requested");
}
return send_json_reply($c->$function());
} catch (\exceptions\PublicApiException $e) {
--
cgit v1.2.3-24-g4f1b
From b8facbbd7a9a29c6274c435932b9c810155e2460 Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 14 Feb 2015 19:12:13 +0100
Subject: Fix typo in error message
Signed-off-by: Florian Pritz
---
application/controllers/api/v1/file.php | 2 +-
application/tests/test_api_v1.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/controllers/api/v1/file.php b/application/controllers/api/v1/file.php
index fc5565416..a10aaf63a 100644
--- a/application/controllers/api/v1/file.php
+++ b/application/controllers/api/v1/file.php
@@ -24,7 +24,7 @@ class file extends \controllers\api\api_controller {
$files = getNormalizedFILES();
if (empty($files)) {
- throw new \exceptions\PublicApiException("file/no-file", "No file was uploaded or unknown error occured.");
+ throw new \exceptions\PublicApiException("file/no-file", "No file was uploaded or unknown error occurred.");
}
\service\files::verify_uploaded_files($files);
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index bba0f9180..e179abc69 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -212,7 +212,7 @@ class test_api_v1 extends Test {
$this->t->is_deeply(array(
'status' => 'error',
'error_id' => 'file/no-file',
- 'message' => 'No file was uploaded or unknown error occured.',
+ 'message' => 'No file was uploaded or unknown error occurred.',
), $ret, "expected reply");
}
--
cgit v1.2.3-24-g4f1b
From d7fc5f46a8b6faec4ec0c18089d94d21e505c36c Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 14 Feb 2015 19:13:26 +0100
Subject: Use assoc array for service/user/apikeys
Signed-off-by: Florian Pritz
---
application/controllers/user.php | 2 +-
application/service/user.php | 6 +++++-
application/tests/test_api_v1.php | 8 ++++----
3 files changed, 10 insertions(+), 6 deletions(-)
(limited to 'application')
diff --git a/application/controllers/user.php b/application/controllers/user.php
index 5b4e85141..33d0efb6b 100644
--- a/application/controllers/user.php
+++ b/application/controllers/user.php
@@ -115,7 +115,7 @@ class User extends MY_Controller {
$userid = $this->muser->get_userid();
$apikeys = \service\user::apikeys($userid);
- $this->data["query"] = $apikeys;
+ $this->data["query"] = $apikeys["apikeys"];
$this->load->view('header', $this->data);
$this->load->view($this->var->view_dir.'apikeys', $this->data);
diff --git a/application/service/user.php b/application/service/user.php
index 16fa62272..cab14dbab 100644
--- a/application/service/user.php
+++ b/application/service/user.php
@@ -53,6 +53,7 @@ class user {
static public function apikeys($userid)
{
$CI =& get_instance();
+ $ret = array();
$query = $CI->db->select('key, created, comment, access_level')
->from('apikeys')
@@ -66,9 +67,12 @@ class user {
if (!empty($record['created'])) {
$record['created'] = strtotime($record['created']);
}
+ $ret[$record["key"]] = $record;
}
unset($record);
- return $query;
+ return array(
+ "apikeys" => $ret,
+ );
}
}
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
index e179abc69..44b559852 100644
--- a/application/tests/test_api_v1.php
+++ b/application/tests/test_api_v1.php
@@ -128,10 +128,10 @@ class test_api_v1 extends Test {
));
$this->expectSuccess("get apikeys", $ret);
- $this->t->is($ret["data"][0]["key"], $apikey, "expected key 1");
- $this->t->is($ret["data"][0]["access_level"], "apikey", "expected key 1 acces_level");
- $this->t->is($ret["data"][0]["comment"], "", "expected key 1 comment");
- $this->t->ok(is_int($ret["data"][0]["created"]) , "expected key 1 creation time is int");
+ $this->t->is($ret["data"]["apikeys"][$apikey]["key"], $apikey, "expected key 1");
+ $this->t->is($ret["data"]["apikeys"][$apikey]["access_level"], "apikey", "expected key 1 acces_level");
+ $this->t->is($ret["data"]["apikeys"][$apikey]["comment"], "", "expected key 1 comment");
+ $this->t->ok(is_int($ret["data"]["apikeys"][$apikey]["created"]) , "expected key 1 creation time is int");
}
public function test_authentication_invalidPassword()
--
cgit v1.2.3-24-g4f1b
From 4f5f2f496bdc182ac9edeb2f416d12fa5e56a9ca Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 14 Feb 2015 19:13:59 +0100
Subject: Use assoc array for service/files/verify_uploaded_files
Signed-off-by: Florian Pritz
---
application/service/files.php | 2 +-
application/tests/test_service_files.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'application')
diff --git a/application/service/files.php b/application/service/files.php
index 802ba70af..922320e11 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -125,7 +125,7 @@ class files {
}
if ($error_message != "") {
- $errors[] = array(
+ $errors[$file["formfield"]] = array(
"filename" => $file["name"],
"formfield" => $file["formfield"],
"message" => $error_message,
diff --git a/application/tests/test_service_files.php b/application/tests/test_service_files.php
index 3330e8c22..8789a9888 100644
--- a/application/tests/test_service_files.php
+++ b/application/tests/test_service_files.php
@@ -71,7 +71,7 @@ class test_service_files extends Test {
$data = $e->get_data();
$this->t->is($e->get_error_id(), "file/upload-verify", "verify should error");
$this->t->is_deeply(array(
- array(
+ 'file[1]' => array(
'filename' => 'foobar.txt',
'formfield' => 'file[1]',
'message' => 'No file was uploaded',
--
cgit v1.2.3-24-g4f1b
From 01226a9afd760a920e9cb3377913ee296f0ab2ca Mon Sep 17 00:00:00 2001
From: Florian Pritz
Date: Sat, 14 Feb 2015 19:23:49 +0100
Subject: Fix consistency of error_ids
Signed-off-by: Florian Pritz
---
application/service/files.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'application')
diff --git a/application/service/files.php b/application/service/files.php
index 922320e11..e31efacc1 100644
--- a/application/service/files.php
+++ b/application/service/files.php
@@ -207,7 +207,7 @@ class files {
}
if (count(array_unique($ids)) != count($ids)) {
- throw new \exceptions\UserInputException("file/create_multipaste/duplicate_id", "Duplicate IDs are not supported");
+ throw new \exceptions\UserInputException("file/create_multipaste/duplicate-id", "Duplicate IDs are not supported");
}
$errors = array();
--
cgit v1.2.3-24-g4f1b