<commit_before>const config = require('../config.js')
const path = require('path')
const multer = require('multer')
const randomstring = require('randomstring')
const db = require('knex')(config.database)
const crypto = require('crypto')
const fs = require('fs')
const utils = require('./utilsController.js')

let uploadsController = {}

const storage = multer.diskStorage({
	destination: function(req, file, cb) {
		cb(null, path.join(__dirname, '..', config.uploads.folder))
	},
	filename: function(req, file, cb) {
		cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname))
	}
})

const upload = multer({
	storage: storage,
	limits: { fileSize: config.uploads.maxSize },
	fileFilter: function(req, file, cb) {
		if (config.blockedExtensions !== undefined) {
			if (config.blockedExtensions.some(extension => path.extname(file.originalname).toLowerCase() === extension)) {
				return cb('This file extension is not allowed');
			}
			return cb(null, true);
		}
		return cb(null, true);
	}
}).array('files[]')

uploadsController.upload = function(req, res, next) {

	// Get the token
	let token = req.headers.token

	// If we're running in private and there's no token, error
	if (config.private === true)
		if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })

	// If there is no token then just leave it blank so the query fails
	if (token === undefined) token = ''

	db.table('users').where('token', token).then((user) => {

		if(user.length === 0)
			if(config.private === true)
				return res.status(401).json({ success: false, description: 'Invalid token provided' })

		let userid
		if(user.length > 0)
			userid = user[0].id

		// Check if user is trying to upload to an album
		let album
		if (userid !== undefined) {
			album = req.headers.albumid
			if (album === undefined)
				album = req.params.albumid
		}

		db.table('albums').where({ id: album, userid: userid }).then((albums) => {
			if (albums.length === 0) {
				return res.json({
					success: false,
					description: 'Album doesn\'t exist or it doesn\'t belong to the user'
				})
			}

			upload(req, res, function (err) {
				if (err) {
					console.error(err)
					return res.json({
						success: false,
						description: err
					})
				}

				if (req.files.length === 0) return res.json({ success: false, description: 'no-files' })

				let files = []
				let existingFiles = []
				let iteration = 1

				req.files.forEach(function(file) {

					// Check if the file exists by checking hash and size
					let hash = crypto.createHash('md5')
					let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename))

					stream.on('data', function (data) {
						hash.update(data, 'utf8')
					})

					stream.on('end', function () {
						let fileHash = hash.digest('hex')

						db.table('files')
						.where(function() {
							if (userid === undefined)
								this.whereNull('userid')
							else
								this.where('userid', userid)
						})
						.where({
							hash: fileHash,
							size: file.size
						}).then((dbfile) => {

							if (dbfile.length !== 0) {
								uploadsController.deleteFile(file.filename).then(() => {}).catch((e) => console.error(e))
								existingFiles.push(dbfile[0])
							} else {
								files.push({
									name: file.filename,
									original: file.originalname,
									type: file.mimetype,
									size: file.size,
									hash: fileHash,
									ip: req.ip,
									albumid: album,
									userid: userid,
									timestamp: Math.floor(Date.now() / 1000)
								})
							}

							if (iteration === req.files.length)
								return uploadsController.processFilesForDisplay(req, res, files, existingFiles)
							iteration++
						}).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) })
					})
				})
			})
		})
	}).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) })
}

uploadsController.processFilesForDisplay = function(req, res, files, existingFiles) {

	let basedomain = req.get('host')
	for (let domain of config.domains)
		if (domain.host === req.get('host'))
			if (domain.hasOwnProperty('resolve'))
				basedomain = domain.resolve

	if (files.length === 0) {
		return res.json({
			success: true,
			files: existingFiles.map(file => {
				return {
					name: file.name,<commit_msg>Fixed last night's fuckup<commit_after>const config = require('../config.js')
const path = require('path')
const multer = require('multer')
const randomstring = require('randomstring')
const db = require('knex')(config.database)
const crypto = require('crypto')
const fs = require('fs')
const utils = require('./utilsController.js')

let uploadsController = {}

const storage = multer.diskStorage({
	destination: function(req, file, cb) {
		cb(null, path.join(__dirname, '..', config.uploads.folder))
	},
	filename: function(req, file, cb) {
		cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname))
	}
})

const upload = multer({
	storage: storage,
	limits: { fileSize: config.uploads.maxSize },
	fileFilter: function(req, file, cb) {
		if (config.blockedExtensions !== undefined) {
			if (config.blockedExtensions.some(extension => path.extname(file.originalname).toLowerCase() === extension)) {
				return cb('This file extension is not allowed');
			}
			return cb(null, true);
		}
		return cb(null, true);
	}
}).array('files[]')

uploadsController.upload = function(req, res, next) {

	// Get the token
	let token = req.headers.token

	// If we're running in private and there's no token, error
	if (config.private === true)
		if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' })

	// If there is no token then just leave it blank so the query fails
	if (token === undefined) token = ''

	db.table('users').where('token', token).then((user) => {

		if(user.length === 0)
			if(config.private === true)
				return res.status(401).json({ success: false, description: 'Invalid token provided' })

		let userid
		if(user.length > 0)
			userid = user[0].id

		// Check if user is trying to upload to an album
		let album
		if (userid !== undefined) {
			album = req.headers.albumid
			if (album === undefined)
				album = req.params.albumid
		}

		/*
			A rewrite is due so might as well do awful things here and fix them later :bloblul:
		*/

		if (album !== undefined && userid !== undefined) {
			// If both values are present, check if the album owner is the user uploading
			db.table('albums').where({ id: album, userid: userid }).then((albums) => {
				if (albums.length === 0) {
					return res.json({
						success: false,
						description: 'Album doesn\'t exist or it doesn\'t belong to the user'
					})
				}
				uploadsController.actuallyUpload(req, res, userid, album);
			})
		} else {
			uploadsController.actuallyUpload(req, res, userid, album);
		}
	}).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) })
}

uploadsController.actuallyUpload = function(req, res, userid, album) {
	upload(req, res, function (err) {
		if (err) {
			console.error(err)
			return res.json({
				success: false,
				description: err
			})
		}

		if (req.files.length === 0) return res.json({ success: false, description: 'no-files' })

		let files = []
		let existingFiles = []
		let iteration = 1

		req.files.forEach(function(file) {

			// Check if the file exists by checking hash and size
			let hash = crypto.createHash('md5')
			let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename))

			stream.on('data', function (data) {
				hash.update(data, 'utf8')
			})

			stream.on('end', function () {
				let fileHash = hash.digest('hex')

				db.table('files')
				.where(function() {
					if (userid === undefined)
						this.whereNull('userid')
					else
						this.where('userid', userid)
				})
				.where({
					hash: fileHash,
					size: file.size
				}).then((dbfile) => {

					if (dbfile.length !== 0) {
						uploadsController.deleteFile(file.filename).then(() => {}).catch((e) => console.error(e))
						existingFiles.push(dbfile[0])
					} else {
						files.push({
							name: file.filename,
							original: file.originalname,
							type: file.mimetype,
							size: file.size,
							hash: fileHash,
							ip: req.ip,
							albumid: album,
							userid: userid,
							timestamp: Math.floor(Date.now() / 1000)
						})
					}

					if (iteration === req.files.length)
						return uploadsController.processFilesForDisplay(req, res, files, existingFiles)
					iteration++
				}).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) })
			})
		})
	})
}
uploadsController.processFilesForDisplay = function(req, res, files, existingFiles) {

	let basedomain = req.get('host')
	for (let domain of config.domains)
		if (domain.host === req.get('host'))
			if (domain.hasOwnProperty('resolve'))
				basedomain = domain.resolve

	if (files.length === 0) {
		return res.json({
			success: true,
			files: existingFiles.map(file => {
				return {
					name: file.name,
{'fraction_non_alphanumeric': 0.15412070084360804, 'fraction_numerical': 0.004542504866969501, 'mean_word_length': 3.212756264236902, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4098884', 'n_tokens_mistral': 3591, 'n_tokens_neox': 2852, 'n_words': 752}