Compare commits

...

14 Commits

Author SHA1 Message Date
nokonoko 5d44b61c16 things 2021-06-23 14:31:48 +02:00
nokonoko 85d74c0d22 reload 2021-06-22 21:30:58 +02:00
nokonoko e3b2d66ef3 clean slate 2021-06-22 18:18:18 +02:00
nokonoko 8ea87bf207 Merge branch 'testing' of https://github.com/nokonoko/Uguu into testing 2021-06-22 18:15:45 +02:00
nokonoko cf1d2267e3 a 2021-06-22 18:15:36 +02:00
Eric Johansson (neku) 7002081c5c
Update X.Y.conf 2021-06-22 15:45:49 +02:00
nokonoko 8c2ebd4b8e Update dist.json 2021-06-22 15:25:47 +02:00
nokonoko 8a32b18eae Update .gitignore 2021-06-22 15:21:54 +02:00
nokonoko c685ab1fc3 Update .gitignore 2021-06-22 15:18:42 +02:00
nokonoko 30bd416912 revert 2021-06-22 14:29:33 +02:00
nokonoko 48233fb137 saner code 2021-06-22 13:25:57 +02:00
nokonoko 74d3554fa6 slim down 2021-06-22 12:55:44 +02:00
nokonoko 1d15881dee anti-dupe option 2021-06-22 11:39:26 +02:00
nokonoko b873b00865 start of admin panel 2021-06-21 23:44:27 +02:00
10 changed files with 179 additions and 87 deletions

BIN
.DS_Store vendored

Binary file not shown.

8
.gitignore vendored
View File

@ -1,3 +1,7 @@
DS_Store
.DS_Store dist
node_modules
build
package.json
package-lock.json
.DS_Store .DS_Store

105
README.md
View File

@ -1,6 +1,6 @@
# What is Uguu? # What is Uguu?
Uguu is a simple lightweight temporary file uploading and sharing platform where files get deleted after X amount of time. Uguu is a simple lightweight file uploading and sharing platform, with the option for files to expire.
## Features ## Features
@ -23,9 +23,110 @@ See the real world example at [uguu.se](https://uguu.se).
Original development environment is Nginx + PHP5.3 + SQLite, but is confirmed to Original development environment is Nginx + PHP5.3 + SQLite, but is confirmed to
work with Apache 2.4 and newer PHP versions like PHP7.3. work with Apache 2.4 and newer PHP versions like PHP7.3.
Node is used to compile Uguu.
## Install ## Install
A detailed installation and configuration can be found at [Uguu/Pomf Documentation](https://blog.yeet.nu/blog/uguu-docs). **Detailed installation and configuration can be found at [Uguu Documentation](https://blog.yeet.nu/blog/uguu-docs).**
If you don't need a detailed one just follow the instructions below.
### Compiling
First you must get a copy of the uguu code. To do so, clone this git repo.
```bash
git clone https://github.com/nokonoko/uguu
```
**Run the following commands to do so, please configure `dist.json` before you compile.**
```bash
cd uguu/
make
make install
```
OR
```bash
make install DESTDIR=/desired/path/for/site
```
After this, the uguu site is now compressed and set up inside `dist/`, or, if specified, `DESTDIR`.
## Configuring
Front-end related settings, such as the name of the site, and maximum allowable
file size, are found in `dist.json`. Changes made here will
only take effect after rebuilding the site pages. This may be done by running
`make` from the root of the site directory.
**Back-end related settings, such as database configuration, and path for uploaded files, are found in `includes/settings.inc.php`. Changes made here take effect immediately. Change the following settings:**
```php
define('UGUU_DB_CONN', 'sqlite:/path/to/db/uguu.sq3');
define('UGUU_FILES_ROOT', '/path/to/file/');
define('UGUU_URL', 'https://subdomainforyourfiles.your.site');
```
**If you intend to allow uploading files larger than 2 MB, you may also need to
increase POST size limits in `php.ini` and webserver configuration. For PHP,
modify `upload_max_filesize` and `post_max_size` values. The configuration
option for nginx webserver is `client_max_body_size`.**
**Edit checkdb.sh and checkfiles.sh to the proper paths:**
```bash
sqlite3 /path/to/db/uguu.sq3 "DELETE FROM files WHERE date <= strftime('%s', datetime('now', '-1 day'));"
```
```bash
find /path/to/files/ -mmin +1440 -exec rm -f {} \;
```
**Then add them to your crontab:**
```bash
0,30 * * * * bash /path/to/checkfiles.sh
0,30 * * * * bash /path/to/checkdb.sh
```
These scripts check if DB entries and files are older then 24 hours and if they are deletes them.
## MIME/EXT Blocking
**Blocking certain filetypes from being uploaded can be changed by editing the following settings in `includes/settings.inc.php`:**
```php
define('CONFIG_BLOCKED_EXTENSIONS', serialize(['exe', 'scr', 'com', 'vbs', 'bat', 'cmd', 'htm', 'html', 'jar', 'msi', 'apk', 'phtml', 'svg']));
define('CONFIG_BLOCKED_MIME', serialize(['application/msword', 'text/html', 'application/x-dosexec', 'application/java', 'application/java-archive', 'application/x-executable', 'application/x-mach-binary', 'image/svg+xml']));
```
By default the most common malicious filetypes are blocked.
## IP logging
This is turned off by default, but you can enable it by changing:
```php
define('LOG_IP', 'false');
```
## Anti dupe
This is turned off by default, if a user uploads a file already uploaded the link to the already existing file will be returned instead.
```php
define('ANTI_DUPE', 'false');
```
## Using SQLite as DB engine
We need to create the SQLite database before it may be used by uguu.
Fortunately, this is incredibly simple.
First create a directory for the database, e.g. `mkdir /var/db/uguu`.
Then, create a new SQLite database from the schema, e.g. `sqlite3 /var/db/uguu/uguu.sq3 -init /home/uguu/sqlite_schema.sql`.
Then, finally, ensure the permissions are correct, e.g.
```bash
chown www-data:www-data /var/db/uguu
chmod 0750 /var/db/uguu
chmod 0640 /var/db/uguu/uguu.sq3
```
Finally, edit `includes/settings.inc.php` to indicate this is the database engine you would like to use. Make the changes outlined below
```php
define('UGUU_DB_CONN', '[stuff]'); ---> define('UGUU_DB_CONN', 'sqlite:/var/db/uguu/uguu.sq3');
define('UGUU_DB_USER', '[stuff]'); ---> define('UGUU_DB_USER', null);
define('UGUU_DB_PASS', '[stuff]'); ---> define('UGUU_DB_PASS', null);
```
*NOTE: The directory where the SQLite database is stored, must be writable by the web server user*
## API ## API
To upload using curl or make a tool you can post using: To upload using curl or make a tool you can post using:

View File

@ -18,7 +18,7 @@
"max_upload_size": 128, "max_upload_size": 128,
"production": false, "production": false,
"siteName": "SITENAME", "siteName": "SITENAME",
"siteUrl": "https://yoursite.com", "siteUrl": "http://localhost",
"abuseContact": "abuse@example.com", "abuseContact": "abuse@example.com",
"infoContact": "info@example.com", "infoContact": "info@example.com",
"ServerCountryLocation": "Sweden", "ServerCountryLocation": "Sweden",

View File

@ -1,27 +0,0 @@
{
"name": "uguu",
"version": "1.0.0",
"description": "Kawaii file host",
"homepage": "https://uguu.se/",
"repository": {
"type": "git",
"url": "https://github.com/nokonoko/pomf"
},
"author": "Eric Johansson <neku@pomf.se>",
"contributors": [
"Pomf Community <github.com/pomf/pomf>"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/nokonoko/uguu/issues"
},
"devDependencies": {
"clean-css": "^4.2.1",
"clean-css-cli": "^4.3.0",
"uglify-js": "^2.6.2",
"swig": "^1.4.2"
},
"dependencies": {
"htmlmin": "0.0.6"
}
}

View File

@ -4,29 +4,27 @@ class UploadedFile
{ {
/* Public attributes */ /* Public attributes */
public $name; public $name;
public $mime;
public $size; public $size;
public $tempfile; public $tempfile;
public $error; public $error;
/**
* SHA-1 checksum
*
* @var string 40 digit hexadecimal hash (160 bits)
*/
private $sha1; private $sha1;
/**
* Generates the SHA-1 or returns the cached SHA-1 hash for the file.
*
* @return string|false $sha1
*/
public function getSha1() public function getSha1()
{ {
if (!$this->sha1) { if (!$this->sha1) {
$this->sha1 = sha1_file($this->tempfile); $this->sha1 = sha1_file($this->tempfile);
} }
return $this->sha1; return $this->sha1;
} }
private $mime;
public function getMime()
{
if (!$this->mime) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$this->mime = finfo_file($finfo, $this->tempfile);
finfo_close($finfo);
}
return $this->mime;
}
} }

View File

@ -26,7 +26,10 @@ define('UGUU_DB_USER', 'NULL');
define('UGUU_DB_PASS', 'NULL'); define('UGUU_DB_PASS', 'NULL');
/** Log IP of uploads */ /** Log IP of uploads */
define('LOG_IP', 'no'); define('LOG_IP', 'false');
/** Dont upload a file already in the DB */
define('ANTI_DUPE', 'false');
/* /*
* File system location where to store uploaded files * File system location where to store uploaded files

View File

@ -3,7 +3,6 @@
* Handles POST uploads, generates filenames, moves files around and commits * Handles POST uploads, generates filenames, moves files around and commits
* uploaded metadata to database. * uploaded metadata to database.
*/ */
require_once 'classes/Response.class.php'; require_once 'classes/Response.class.php';
require_once 'classes/UploadException.class.php'; require_once 'classes/UploadException.class.php';
require_once 'classes/UploadedFile.class.php'; require_once 'classes/UploadedFile.class.php';
@ -24,12 +23,9 @@ function generateName($file)
// We start at N retries, and --N until we give up // We start at N retries, and --N until we give up
$tries = UGUU_FILES_RETRIES; $tries = UGUU_FILES_RETRIES;
$length = UGUU_FILES_LENGTH; $length = UGUU_FILES_LENGTH;
//Get EXT //Get EXT
$ext = pathinfo($file->name, PATHINFO_EXTENSION); $ext = pathinfo($file->name, PATHINFO_EXTENSION);
//Get mime
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$type_mime = finfo_file($finfo, $file->tempfile);
finfo_close($finfo);
// Check if extension is a double-dot extension and, if true, override $ext // Check if extension is a double-dot extension and, if true, override $ext
$revname = strrev($file->name); $revname = strrev($file->name);
@ -60,17 +56,16 @@ function generateName($file)
$name .= '.'.$ext; $name .= '.'.$ext;
} }
//Check if mime is blacklisted //Check if MIME is blacklisted
if (in_array($type_mime, unserialize(CONFIG_BLOCKED_MIME))) { if (in_array($file->getMime(), unserialize(CONFIG_BLOCKED_MIME))) {
http_response_code(415); http_response_code(415);
throw new Exception ('Extension type not allowed.'); throw new UploadException(UPLOAD_ERR_EXTENSION);
exit(0); exit(0);
} }
//Check if EXT is blacklisted //Check if EXT is blacklisted
if (in_array($ext, unserialize(CONFIG_BLOCKED_EXTENSIONS))) { if (in_array($ext, unserialize(CONFIG_BLOCKED_EXTENSIONS))) {
http_response_code(415); http_response_code(415);
throw new Exception ('Extension type not allowed.'); throw new UploadException(UPLOAD_ERR_EXTENSION);
exit(0); exit(0);
} }
@ -81,8 +76,9 @@ function generateName($file)
$result = $q->fetchColumn(); $result = $q->fetchColumn();
// If it does, generate a new name // If it does, generate a new name
} while ($result > 0); } while ($result > 0);
return $name; return $name;
} }
/** /**
* Handles the uploading and db entry for a file. * Handles the uploading and db entry for a file.
@ -102,14 +98,36 @@ function uploadFile($file)
throw new UploadException($file->error); throw new UploadException($file->error);
} }
// Generate a name for the file //fixes a bug
$newname = generateName($file); $lol = $file->getSha1();
// Check if a file with the same hash and size (a file which is the same)
// does already exist in the database; if it does, return the proper link
// and data. PHP deletes the temporary file just uploaded automatically.
if(ANTI_DUPE == 'true'){
$q = $db->prepare('SELECT filename, COUNT(*) AS count FROM files WHERE hash = (:hash) AND size = (:size)');
$q->bindValue(':hash', $file->getSha1(), PDO::PARAM_STR);
$q->bindValue(':size', $file->size, PDO::PARAM_INT);
$q->execute();
$result = $q->fetch();
if ($result['count'] > 0) {
return [
'hash' => $file->getSha1(),
'name' => $file->name,
'url' => UGUU_URL.rawurlencode($result['filename']),
'size' => $file->size,
];
}
}
// Get IP // Get IP
$ip = $_SERVER['REMOTE_ADDR']; $ip = $_SERVER['REMOTE_ADDR'];
// Generate a name for the file
$newname = generateName($file);
// Store the file's full file path in memory // Store the file's full file path in memory
$uploadFile = UGUU_FILES_ROOT . $newname; $uploadFile = UGUU_FILES_ROOT.$newname;
// Attempt to move it to the static directory // Attempt to move it to the static directory
if (!move_uploaded_file($file->tempfile, $uploadFile)) { if (!move_uploaded_file($file->tempfile, $uploadFile)) {
@ -130,39 +148,38 @@ function uploadFile($file)
} }
// Add it to the database // Add it to the database
if(LOG_IP == 'yes'){ if(LOG_IP == 'true'){
$q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ip) VALUES (:hash, :orig, :name, :size, :date, :ip)'); $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ip) VALUES (:hash, :orig, :name, :size, :date, :ip)');
}else{ } else {
$ip = '0'; $ip = '0';
$q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ip) VALUES (:hash, :orig, :name, :size, :date, :ip)'); $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, ip) VALUES (:hash, :orig, :name, :size, :date, :ip)');
} }
// Common parameters binding // Common parameters binding
$q->bindValue(':hash', $file->getSha1(), PDO::PARAM_STR); $q->bindValue(':hash', $file->getSha1(), PDO::PARAM_STR);
$q->bindValue(':orig', strip_tags($file->name), PDO::PARAM_STR); $q->bindValue(':orig', strip_tags($file->name), PDO::PARAM_STR);
$q->bindValue(':name', $newname, PDO::PARAM_STR); $q->bindValue(':name', $newname, PDO::PARAM_STR);
$q->bindValue(':size', $file->size, PDO::PARAM_INT); $q->bindValue(':size', $file->size, PDO::PARAM_INT);
$q->bindValue(':date', time(), PDO::PARAM_INT); $q->bindValue(':date', time(), PDO::PARAM_STR);
$q->bindValue(':ip', $ip, PDO::PARAM_STR); $q->bindValue(':ip', $ip, PDO::PARAM_STR);
$q->execute(); $q->execute();
return array( return [
'hash' => $file->getSha1(), 'hash' => $file->getSha1(),
'name' => $file->name, 'name' => $file->name,
'url' => UGUU_URL.rawurlencode($newname), 'url' => UGUU_URL.rawurlencode($newname),
'size' => $file->size, 'size' => $file->size,
); ];
} }
/** /**
* Reorder files array by file. * Reorder files array by file.
* *
* @param $_FILES
*
* @return array * @return array
*/ */
function diverseArray($files) function diverseArray($files)
{ {
$result = array(); $result = [];
foreach ($files as $key1 => $value1) { foreach ($files as $key1 => $value1) {
foreach ($value1 as $key2 => $value2) { foreach ($value1 as $key2 => $value2) {
@ -176,19 +193,16 @@ function diverseArray($files)
/** /**
* Reorganize the $_FILES array into something saner. * Reorganize the $_FILES array into something saner.
* *
* @param $_FILES
*
* @return array * @return array
*/ */
function refiles($files) function refiles($files)
{ {
$result = array(); $result = [];
$files = diverseArray($files); $files = diverseArray($files);
foreach ($files as $file) { foreach ($files as $file) {
$f = new UploadedFile(); $f = new UploadedFile();
$f->name = $file['name']; $f->name = $file['name'];
$f->mime = $file['type'];
$f->size = $file['size']; $f->size = $file['size'];
$f->tempfile = $file['tmp_name']; $f->tempfile = $file['tmp_name'];
$f->error = $file['error']; $f->error = $file['error'];

View File

@ -2,6 +2,6 @@
<ul> <ul>
<li><a href="/">{{siteName}}</a></li> <li><a href="/">{{siteName}}</a></li>
<li><a href="tools.html">Tools</a></li> <li><a href="tools.html">Tools</a></li>
<li><a href="https://github.com/nokonoko/uguu">Github</a></li> <li><a href="https://github.com/nokonoko/uguu">GitHub</a></li>
</ul> </ul>
</nav> </nav>

View File

@ -37,4 +37,3 @@ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
} }
} }
Use