From 5889fcafba3e8bd6bf37f9bd6e8247e8fccdb761 Mon Sep 17 00:00:00 2001 From: Xenthys Date: Wed, 29 Aug 2018 02:00:50 +0200 Subject: [PATCH] Add a safeguard to the random name generator The iteration_count JSON field has therefore been added to indicate how many loop iterations were necessary to generate a unique name. If no unique name is found after 10 iterations, the script will return an HTTP 500 cannot_generate_unique_filename error. The PHP version check has been removed since the script errors immediately, as PHP 5 cannot parse it at all before execution. The random_str function doesn't require mbstring anymore as the keyspace only contains ASCII characters. Unicode keyspaces are therefore not (and have never been) supported at all. Version bumped to 2.1.0 --- README.md | 41 +++++++++++++++++++++-------------------- sharexen.php | 45 ++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 90caba1..b42f466 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # ShareXen -ShareXen is an API, which is really just another ShareX custom uploader PHP script, but done right. It requires at least PHP 7.0 to run, along with the cURL extension if you plan to use Discord webhooks for logging requests. No database is required. +ShareXen is an API, which is really just another ShareX custom uploader PHP script, but done right. It requires at least PHP 7.0 to run, along with the cURL extension if you plan to use Discord webhooks to log requests. No database is required. This API returns strict JSON results. You can easily parse its answers within your own scripts. -If you have any problem setting this up, you can ask for help on [Discord](https://discordapp.com/invite/bn) directly. +If you have any problem setting this up, you can ask for help on [ShareX's Discord server](https://discordapp.com/invite/sharex) directly. ## Features @@ -65,23 +65,24 @@ Using the `filename` parameter for the `upload` endpoint and accessing the `rena The following JSON fields can be returned: -| Name | Endpoints | Type | Description | -| ---------------- | ------------------- | ------- | ------------------------------------------------ | -| `api_version` | all | String | Current API version number (SemVer) | -| `api_source` | all | String | URL to the GitHub source repository | -| `endpoint` | all | String | Called API endpoint, or `unknown` | -| `username` | all | String | Username, only for authenticated requests | -| `status` | all | String | Request status, either `success` or `error` | -| `http_code` | all | Integer | Mirror of the returned HTTP code | -| `filename` | all | String | Name of the file as stored on the server | -| `execution_time` | all | Float | Script execution time, in seconds | -| `url` | `upload` & `rename` | String | URL for the new file | -| `key` | `upload` & `rename` | String | Security key for the new file | -| `deletion_url` | `upload` & `rename` | String | Full deletion URL for the new file | -| `method` | `delete` & `rename` | String | Authentication method used to call the endpoint | -| `old_name` | `rename` | String | Previous name of the file | -| `error` | any | String | Static error code, only sent if anything fails | -| `debug` | any | String | Human-readable information, only for some errors | +| Name | Endpoints | Type | Description | +| ----------------- | ------------------- | ------- | ------------------------------------------------ | +| `api_version` | all | String | Current API version number (SemVer) | +| `api_source` | all | String | URL to the GitHub source repository | +| `endpoint` | all | String | Called API endpoint, or `unknown` | +| `username` | all | String | Username, only for authenticated requests | +| `status` | all | String | Request status, either `success` or `error` | +| `http_code` | all | Integer | Mirror of the returned HTTP code | +| `filename` | all | String | Name of the file as stored on the server | +| `execution_time` | all | Float | Script execution time, in seconds | +| `iteration_count` | `upload` | Integer | Attempts at generating a unique filename | +| `url` | `upload` & `rename` | String | URL for the new file | +| `key` | `upload` & `rename` | String | Security key for the new file | +| `deletion_url` | `upload` & `rename` | String | Full deletion URL for the new file | +| `method` | `delete` & `rename` | String | Authentication method used to call the endpoint | +| `old_name` | `rename` | String | Previous name of the file | +| `error` | any | String | Static error code, only sent if anything fails | +| `debug` | any | String | Human-readable information, only for some errors | The `info` endpoint implements several JSON fields, which can be returned or not depending on your access level, whether you specify a filename, and whether it exists. Here is the full specification: @@ -116,4 +117,4 @@ Security keys are only as secure as your `SALT` is. Make sure to have a **very r ## Contributing -If you want to help improve this API or its documentation, feel free to come on [Discord](https://discordapp.com/invite/bn) to suggest modifications. You can also open a pull-request, but make sure to **sign your commits with GPG** and **respect the script's programming style**, so we can keep it as readable as possible. +If you want to help improve this API or its documentation, feel free to come on [Blackfields Network's Discord server](https://discordapp.com/invite/bn) to suggest modifications. You can also open a pull-request, but make sure to **sign your commits with GPG** and **respect the script's programming style**, so we can keep it as readable as possible. diff --git a/sharexen.php b/sharexen.php index 5a49b84..445bb6c 100644 --- a/sharexen.php +++ b/sharexen.php @@ -25,6 +25,7 @@ ]); // Security keys salt - NEVER SHARE THIS +// Format: define('SALT', 'randomstring'); // Used to generate and compute security keys // Changing this will render all previously generated // deletion URLs invalid without any exception @@ -83,12 +84,16 @@ /***************************************\ * CHANGE THEM AT YOUR OWN RISK AND ONLY * * IF YOU REALLY KNOW WHAT YOU ARE DOING * +***************************************** +* DO NOT ASK FOR SUPPORT IF THOSE BREAK * +* ANYTHING IN THIS SCRIPT AFTER EDITION * \***************************************/ // Characters used to randomly generate the filename // By security and to avoid breaking this application, // do not use the following characters: / \ . : # ? & // This isn't a comprehensive list of dangerous characters +// The random_str function might break if you mess with this define('KEYSPACE', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'); // Characters listed here will be allowed within @@ -114,7 +119,7 @@ \*****************************/ -define('VERSION', '2.0.0'); +define('VERSION', '2.1.0'); define('SOURCE', 'https://github.com/Xenthys/ShareXen'); $data = [ @@ -122,23 +127,6 @@ 'api_source' => SOURCE ]; -if (version_compare(PHP_VERSION, '7.0.0', '<')) -{ - http_response_code(500); - - header('Content-Type: application/json; charset=utf-8'); - - error_log('ShareXen v'.VERSION.': you need to use at least PHP 7.0'. - ' in order to run this script. You are running PHP '.PHP_VERSION); - - $data['http_code'] = 500; - $data['status'] = 'error'; - $data['error'] = 'outdated_php_version'; - $data['debug'] = PHP_VERSION.' < 7.0.0'; - - die(json_encode($data)); -} - $endpoints = [ 'upload' => "\u{1F517}", 'delete' => "\u{1F5D1}", @@ -401,7 +389,7 @@ function user_is_admin(&$data) function random_str($length = NAME_LENGTH, $keyspace = KEYSPACE) { $pieces = []; - $max = mb_strlen($keyspace, '8bit') - 1; + $max = strlen($keyspace) - 1; for ($i = 0; $i < $length; ++$i) { $pieces []= $keyspace[random_int(0, $max)]; @@ -604,12 +592,23 @@ function upload_endpoint(&$data) if (!$name) { - $name = random_str().$ext; - - while (file_exists($name)) + for ($i = 1; $i <= 10; $i++) { - error_log('ShareXen Collision: File "'.$name.'" already exists.'); $name = random_str().$ext; + + if (!file_exists($name)) + { + $data['iteration_count'] = $i; + break; + } + + error_log('ShareXen Collision (iteration #'. + $i.'): File "'.$name.'" already exists.'); + + if ($i == 10) + { + error_die($data, 500, 'cannot_generate_unique_filename'); + } } }