mirror of
https://github.com/neocities/neocities.git
synced 2025-04-25 01:32:36 +02:00
undo auto-lint changes from my editor
This commit is contained in:
parent
25ca2a879b
commit
26b6f6f6c8
2 changed files with 87 additions and 69 deletions
99
app/api.rb
99
app/api.rb
|
@ -2,14 +2,14 @@ require 'base64'
|
||||||
|
|
||||||
get '/api' do
|
get '/api' do
|
||||||
@title = 'Developers API'
|
@title = 'Developers API'
|
||||||
erb :api
|
erb :'api'
|
||||||
end
|
end
|
||||||
|
|
||||||
post '/api/upload_hash' do
|
post '/api/upload_hash' do
|
||||||
require_api_credentials
|
require_api_credentials
|
||||||
res = {}
|
res = {}
|
||||||
files = []
|
files = []
|
||||||
params.each do |k, v|
|
params.each do |k,v|
|
||||||
res[k] = current_site.sha1_hash_match? k, v
|
res[k] = current_site.sha1_hash_match? k, v
|
||||||
end
|
end
|
||||||
api_success files: res
|
api_success files: res
|
||||||
|
@ -20,11 +20,11 @@ get '/api/list' do
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
file_list = if params[:path].nil? || params[:path].empty?
|
if params[:path].nil? || params[:path].empty?
|
||||||
current_site.site_files
|
file_list = current_site.site_files
|
||||||
else
|
else
|
||||||
current_site.file_list params[:path]
|
file_list = current_site.file_list params[:path]
|
||||||
end
|
end
|
||||||
|
|
||||||
file_list.each do |file|
|
file_list.each do |file|
|
||||||
new_file = {}
|
new_file = {}
|
||||||
|
@ -36,7 +36,7 @@ get '/api/list' do
|
||||||
files << new_file
|
files << new_file
|
||||||
end
|
end
|
||||||
|
|
||||||
files.each { |f| f[:path].sub!(%r{^/}, '') }
|
files.each {|f| f[:path].sub!(/^\//, '')}
|
||||||
|
|
||||||
api_success files: files
|
api_success files: files
|
||||||
end
|
end
|
||||||
|
@ -46,18 +46,20 @@ def extract_files(params, files = [])
|
||||||
if params.is_a?(Array)
|
if params.is_a?(Array)
|
||||||
params.each do |item|
|
params.each do |item|
|
||||||
# Call extract_files on each item if it's an Array or Hash to handle nested structures
|
# Call extract_files on each item if it's an Array or Hash to handle nested structures
|
||||||
extract_files(item, files) if item.is_a?(Array) || item.is_a?(Hash)
|
if item.is_a?(Array) || item.is_a?(Hash)
|
||||||
|
extract_files(item, files)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elsif params.is_a?(Hash)
|
elsif params.is_a?(Hash)
|
||||||
params.each do |_key, value|
|
params.each do |key, value|
|
||||||
# If the value is a Hash and contains a :tempfile key, it's considered an uploaded file.
|
# If the value is a Hash and contains a :tempfile key, it's considered an uploaded file.
|
||||||
if value.is_a?(Hash) && value.has_key?(:tempfile) && !value[:tempfile].nil?
|
if value.is_a?(Hash) && value.has_key?(:tempfile) && !value[:tempfile].nil?
|
||||||
files << { filename: value[:name], tempfile: value[:tempfile] }
|
files << {filename: value[:name], tempfile: value[:tempfile]}
|
||||||
elsif value.is_a?(Array)
|
elsif value.is_a?(Array)
|
||||||
value.each do |val|
|
value.each do |val|
|
||||||
if val.is_a?(Hash) && val.has_key?(:tempfile) && !val[:tempfile].nil?
|
if val.is_a?(Hash) && val.has_key?(:tempfile) && !val[:tempfile].nil?
|
||||||
# Directly add the file info if it's an uploaded file within an array
|
# Directly add the file info if it's an uploaded file within an array
|
||||||
files << { filename: val[:name], tempfile: val[:tempfile] }
|
files << {filename: val[:name], tempfile: val[:tempfile]}
|
||||||
elsif val.is_a?(Hash) || val.is_a?(Array)
|
elsif val.is_a?(Hash) || val.is_a?(Array)
|
||||||
# Recursively search for more files if the element is a Hash or Array
|
# Recursively search for more files if the element is a Hash or Array
|
||||||
extract_files(val, files)
|
extract_files(val, files)
|
||||||
|
@ -76,38 +78,40 @@ post '/api/upload' do
|
||||||
require_api_credentials
|
require_api_credentials
|
||||||
files = extract_files params
|
files = extract_files params
|
||||||
|
|
||||||
unless params[:username].blank?
|
if !params[:username].blank?
|
||||||
site = Site[username: params[:username]]
|
site = Site[username: params[:username]]
|
||||||
|
|
||||||
api_error 400, 'site_not_found', 'could not find site' if site.nil? || site.is_deleted
|
if site.nil? || site.is_deleted
|
||||||
|
api_error 400, 'site_not_found', "could not find site"
|
||||||
|
end
|
||||||
|
|
||||||
if site.owned_by?(current_site)
|
if site.owned_by?(current_site)
|
||||||
@_site = site
|
@_site = site
|
||||||
else
|
else
|
||||||
api_error 400, 'site_not_allowed', 'not allowed to change this site with your current logged in site'
|
api_error 400, 'site_not_allowed', "not allowed to change this site with your current logged in site"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
api_error 400, 'missing_files', 'you must provide files to upload' if files.empty?
|
api_error 400, 'missing_files', 'you must provide files to upload' if files.empty?
|
||||||
|
|
||||||
uploaded_size = files.collect { |f| f[:tempfile].size }.inject { |sum, x| sum + x }
|
uploaded_size = files.collect {|f| f[:tempfile].size}.inject{|sum,x| sum + x }
|
||||||
|
|
||||||
if current_site.file_size_too_large? uploaded_size
|
if current_site.file_size_too_large? uploaded_size
|
||||||
api_error 400, 'too_large', 'files are too large to fit in your space, try uploading smaller (or less) files'
|
api_error 400, 'too_large', 'files are too large to fit in your space, try uploading smaller (or less) files'
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_site.too_many_files?(files.length)
|
if current_site.too_many_files?(files.length)
|
||||||
api_error 400, 'too_many_files',
|
api_error 400, 'too_many_files', "cannot exceed the maximum site files limit (#{current_site.plan_feature(:maximum_site_files)})"
|
||||||
"cannot exceed the maximum site files limit (#{current_site.plan_feature(:maximum_site_files)})"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
unless current_site.okay_to_upload?(file)
|
if !current_site.okay_to_upload?(file)
|
||||||
api_error 400, 'invalid_file_type',
|
api_error 400, 'invalid_file_type', "#{file[:filename]} is not an allowed file type for free sites, supporter required"
|
||||||
"#{file[:filename]} is not an allowed file type for free sites, supporter required"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
api_error 400, 'directory_exists', "#{file[:filename]} being used by a directory" if File.directory? file[:filename]
|
if File.directory? file[:filename]
|
||||||
|
api_error 400, 'directory_exists', "#{file[:filename]} being used by a directory"
|
||||||
|
end
|
||||||
|
|
||||||
if current_site.file_size_too_large? file[:tempfile].size
|
if current_site.file_size_too_large? file[:tempfile].size
|
||||||
api_error 400, 'file_too_large' "#{file[:filename]} is too large"
|
api_error 400, 'file_too_large' "#{file[:filename]} is too large"
|
||||||
|
@ -118,7 +122,7 @@ post '/api/upload' do
|
||||||
end
|
end
|
||||||
|
|
||||||
if SiteFile.name_too_long? file[:filename]
|
if SiteFile.name_too_long? file[:filename]
|
||||||
api_error 400, 'file_name_too_long', "#{file[:filename]} filename is too long. (Longer than 255 characters)"
|
api_error 400, 'file_name_too_long', "#{file[:filename]} filename is too long (exceeds 255 characters)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -129,21 +133,24 @@ end
|
||||||
post '/api/rename' do
|
post '/api/rename' do
|
||||||
require_api_credentials
|
require_api_credentials
|
||||||
|
|
||||||
if params[:path].blank? || params[:new_path].blank?
|
api_error 400, 'missing_arguments', 'you must provide path and new_path' if params[:path].blank? || params[:new_path].blank?
|
||||||
api_error 400, 'missing_arguments',
|
|
||||||
'you must provide path and new_path'
|
|
||||||
end
|
|
||||||
|
|
||||||
path = current_site.scrubbed_path params[:path]
|
path = current_site.scrubbed_path params[:path]
|
||||||
new_path = current_site.scrubbed_path params[:new_path]
|
new_path = current_site.scrubbed_path params[:new_path]
|
||||||
|
|
||||||
api_error 400, 'bad_path', "#{path} is not a valid path, cancelled renaming" unless path.is_a?(String)
|
unless path.is_a?(String)
|
||||||
|
api_error 400, 'bad_path', "#{path} is not a valid path, cancelled renaming"
|
||||||
|
end
|
||||||
|
|
||||||
api_error 400, 'bad_new_path', "#{new_path} is not a valid new_path, cancelled renaming" unless new_path.is_a?(String)
|
unless new_path.is_a?(String)
|
||||||
|
api_error 400, 'bad_new_path', "#{new_path} is not a valid new_path, cancelled renaming"
|
||||||
|
end
|
||||||
|
|
||||||
site_file = current_site.site_files.select { |sf| sf.path == path }.first
|
site_file = current_site.site_files.select {|sf| sf.path == path}.first
|
||||||
|
|
||||||
api_error 400, 'missing_file', "could not find #{path}" if site_file.nil?
|
if site_file.nil?
|
||||||
|
api_error 400, 'missing_file', "could not find #{path}"
|
||||||
|
end
|
||||||
|
|
||||||
res = site_file.rename new_path
|
res = site_file.rename new_path
|
||||||
|
|
||||||
|
@ -157,24 +164,23 @@ end
|
||||||
post '/api/delete' do
|
post '/api/delete' do
|
||||||
require_api_credentials
|
require_api_credentials
|
||||||
|
|
||||||
if params[:filenames].nil? || params[:filenames].empty?
|
api_error 400, 'missing_filenames', 'you must provide files to delete' if params[:filenames].nil? || params[:filenames].empty?
|
||||||
api_error 400, 'missing_filenames',
|
|
||||||
'you must provide files to delete'
|
|
||||||
end
|
|
||||||
|
|
||||||
paths = []
|
paths = []
|
||||||
params[:filenames].each do |path|
|
params[:filenames].each do |path|
|
||||||
api_error 400, 'bad_filename', "#{path} is not a valid filename, canceled deleting" unless path.is_a?(String)
|
unless path.is_a?(String)
|
||||||
|
api_error 400, 'bad_filename', "#{path} is not a valid filename, canceled deleting"
|
||||||
|
end
|
||||||
|
|
||||||
if current_site.files_path(path) == current_site.files_path
|
if current_site.files_path(path) == current_site.files_path
|
||||||
api_error 400, 'cannot_delete_site_directory', 'cannot delete the root directory of the site'
|
api_error 400, 'cannot_delete_site_directory', 'cannot delete the root directory of the site'
|
||||||
end
|
end
|
||||||
|
|
||||||
unless current_site.file_exists?(path)
|
if !current_site.file_exists?(path)
|
||||||
api_error 400, 'missing_files', "#{path} was not found on your site, canceled deleting"
|
api_error 400, 'missing_files', "#{path} was not found on your site, canceled deleting"
|
||||||
end
|
end
|
||||||
|
|
||||||
if ['index.html', '/index.html'].include?(path)
|
if path == 'index.html' || path == '/index.html'
|
||||||
api_error 400, 'cannot_delete_index', 'you cannot delete your index.html file, canceled deleting'
|
api_error 400, 'cannot_delete_index', 'you cannot delete your index.html file, canceled deleting'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -214,7 +220,7 @@ def api_info_for(site)
|
||||||
created_at: site.created_at.rfc2822,
|
created_at: site.created_at.rfc2822,
|
||||||
last_updated: site.site_updated_at ? site.site_updated_at.rfc2822 : nil,
|
last_updated: site.site_updated_at ? site.site_updated_at.rfc2822 : nil,
|
||||||
domain: site.domain,
|
domain: site.domain,
|
||||||
tags: site.tags.collect { |t| t.name }
|
tags: site.tags.collect {|t| t.name}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -234,10 +240,7 @@ def require_api_credentials
|
||||||
|
|
||||||
if !request.env['HTTP_AUTHORIZATION'].nil?
|
if !request.env['HTTP_AUTHORIZATION'].nil?
|
||||||
init_api_credentials
|
init_api_credentials
|
||||||
if email_not_validated?
|
api_error(403, 'email_not_validated', 'you need to validate your email address before using the API') if email_not_validated?
|
||||||
api_error(403, 'email_not_validated',
|
|
||||||
'you need to validate your email address before using the API')
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
api_error_invalid_auth
|
api_error_invalid_auth
|
||||||
end
|
end
|
||||||
|
@ -253,7 +256,7 @@ def init_api_credentials
|
||||||
else
|
else
|
||||||
user, pass = Base64.decode64(auth.match(/Basic (.+)/)[1]).split(':')
|
user, pass = Base64.decode64(auth.match(/Basic (.+)/)[1]).split(':')
|
||||||
end
|
end
|
||||||
rescue StandardError
|
rescue
|
||||||
api_error_invalid_auth
|
api_error_invalid_auth
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -265,7 +268,9 @@ def init_api_credentials
|
||||||
api_error_invalid_auth
|
api_error_invalid_auth
|
||||||
end
|
end
|
||||||
|
|
||||||
api_error_invalid_auth if site.nil? || site.is_banned || site.is_deleted
|
if site.nil? || site.is_banned || site.is_deleted
|
||||||
|
api_error_invalid_auth
|
||||||
|
end
|
||||||
|
|
||||||
DB['update sites set api_calls=api_calls+1 where id=?', site.id].first
|
DB['update sites set api_calls=api_calls+1 where id=?', site.id].first
|
||||||
|
|
||||||
|
@ -273,7 +278,7 @@ def init_api_credentials
|
||||||
end
|
end
|
||||||
|
|
||||||
def api_success(message_or_obj)
|
def api_success(message_or_obj)
|
||||||
output = { result: 'success' }
|
output = {result: 'success'}
|
||||||
|
|
||||||
if message_or_obj.is_a?(String)
|
if message_or_obj.is_a?(String)
|
||||||
output[:message] = message_or_obj
|
output[:message] = message_or_obj
|
||||||
|
@ -285,7 +290,7 @@ def api_success(message_or_obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
def api_response(status, output)
|
def api_response(status, output)
|
||||||
halt status, JSON.pretty_generate(output) + "\n"
|
halt status, JSON.pretty_generate(output)+"\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
def api_error(status, error_type, message)
|
def api_error(status, error_type, message)
|
||||||
|
|
|
@ -13,26 +13,28 @@ class SiteFile < Sequel::Model
|
||||||
|
|
||||||
def self.path_too_long?(filename)
|
def self.path_too_long?(filename)
|
||||||
return true if filename.length > FILE_PATH_CHARACTER_LIMIT
|
return true if filename.length > FILE_PATH_CHARACTER_LIMIT
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.name_too_long?(filename)
|
def self.name_too_long?(filename)
|
||||||
return true if filename.length > FILE_NAME_CHARACTER_LIMIT
|
return true if filename.length > FILE_NAME_CHARACTER_LIMIT
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def before_destroy
|
def before_destroy
|
||||||
if is_directory
|
if is_directory
|
||||||
site.site_files_dataset.where(path: %r{^#{Regexp.quote path}/}, is_directory: true).all.each do |site_file|
|
site.site_files_dataset.where(path: /^#{Regexp.quote path}\//, is_directory: true).all.each do |site_file|
|
||||||
site_file.destroy
|
begin
|
||||||
rescue Sequel::NoExistingObject
|
site_file.destroy
|
||||||
|
rescue Sequel::NoExistingObject
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
site.site_files_dataset.where(path: %r{^#{Regexp.quote path}/}, is_directory: false).all.each do |site_file|
|
site.site_files_dataset.where(path: /^#{Regexp.quote path}\//, is_directory: false).all.each do |site_file|
|
||||||
site_file.destroy
|
begin
|
||||||
rescue Sequel::NoExistingObject
|
site_file.destroy
|
||||||
|
rescue Sequel::NoExistingObject
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -56,26 +58,36 @@ class SiteFile < Sequel::Model
|
||||||
end
|
end
|
||||||
|
|
||||||
def rename(new_path)
|
def rename(new_path)
|
||||||
current_path = path
|
current_path = self.path
|
||||||
new_path = site.scrubbed_path new_path
|
new_path = site.scrubbed_path new_path
|
||||||
|
|
||||||
return false, 'new path too long' if new_path.length > FILE_PATH_CHARACTER_LIMIT
|
if new_path.length > FILE_PATH_CHARACTER_LIMIT
|
||||||
|
return false, 'new path too long'
|
||||||
|
end
|
||||||
|
|
||||||
return false, 'new filename too long' if File.basename(new_path).length > FILE_NAME_CHARACTER_LIMIT
|
if File.basename(new_path).length > FILE_NAME_CHARACTER_LIMIT
|
||||||
|
return false, 'new filename too long'
|
||||||
|
end
|
||||||
|
|
||||||
return false, 'cannot rename to empty path' if new_path == ''
|
if new_path == ''
|
||||||
|
return false, 'cannot rename to empty path'
|
||||||
|
end
|
||||||
|
|
||||||
return false, 'cannot rename or move root index.html' if current_path == 'index.html'
|
if current_path == 'index.html'
|
||||||
|
return false, 'cannot rename or move root index.html'
|
||||||
|
end
|
||||||
|
|
||||||
if site.site_files.select { |sf| sf.path == new_path }.length > 0
|
if site.site_files.select {|sf| sf.path == new_path}.length > 0
|
||||||
return false, "#{is_directory ? 'directory' : 'file'} already exists"
|
return false, "#{is_directory ? 'directory' : 'file'} already exists"
|
||||||
end
|
end
|
||||||
|
|
||||||
if is_directory
|
if is_directory
|
||||||
return false, 'directory name cannot end with .htm or .html' if new_path.match(/\.html?$/)
|
if new_path.match(/\.html?$/)
|
||||||
|
return false, 'directory name cannot end with .htm or .html'
|
||||||
|
end
|
||||||
|
|
||||||
else # a file
|
else # a file
|
||||||
mime_type = Magic.guess_file_mime_type site.files_path(path)
|
mime_type = Magic.guess_file_mime_type site.files_path(self.path)
|
||||||
extname = File.extname new_path
|
extname = File.extname new_path
|
||||||
|
|
||||||
unless site.supporter? || site.class.valid_file_mime_type_and_ext?(mime_type, extname)
|
unless site.supporter? || site.class.valid_file_mime_type_and_ext?(mime_type, extname)
|
||||||
|
@ -89,7 +101,6 @@ class SiteFile < Sequel::Model
|
||||||
site.generate_thumbnail_or_screenshot new_path
|
site.generate_thumbnail_or_screenshot new_path
|
||||||
rescue Errno::ENOENT => e
|
rescue Errno::ENOENT => e
|
||||||
return false, 'destination directory does not exist' if e.message =~ /No such file or directory/i
|
return false, 'destination directory does not exist' if e.message =~ /No such file or directory/i
|
||||||
|
|
||||||
raise e
|
raise e
|
||||||
rescue ArgumentError => e
|
rescue ArgumentError => e
|
||||||
raise e unless e.message =~ /same file/
|
raise e unless e.message =~ /same file/
|
||||||
|
@ -97,13 +108,13 @@ class SiteFile < Sequel::Model
|
||||||
|
|
||||||
DB.transaction do
|
DB.transaction do
|
||||||
self.path = new_path
|
self.path = new_path
|
||||||
save_changes
|
self.save_changes
|
||||||
|
|
||||||
if is_directory
|
if is_directory
|
||||||
site_files_in_dir = site.site_files.select { |sf| sf.path =~ %r{^#{current_path}/} }
|
site_files_in_dir = site.site_files.select {|sf| sf.path =~ /^#{current_path}\//}
|
||||||
site_files_in_dir.each do |site_file|
|
site_files_in_dir.each do |site_file|
|
||||||
original_site_file_path = site_file.path
|
original_site_file_path = site_file.path
|
||||||
site_file.path = site_file.path.gsub(%r{^#{current_path}/}, "#{new_path}\/")
|
site_file.path = site_file.path.gsub(/^#{current_path}\//, "#{new_path}\/")
|
||||||
site_file.save_changes
|
site_file.save_changes
|
||||||
site.delete_thumbnail_or_screenshot original_site_file_path
|
site.delete_thumbnail_or_screenshot original_site_file_path
|
||||||
site.generate_thumbnail_or_screenshot site_file.path
|
site.generate_thumbnail_or_screenshot site_file.path
|
||||||
|
@ -116,12 +127,14 @@ class SiteFile < Sequel::Model
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[true, nil]
|
return true, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_destroy
|
def after_destroy
|
||||||
super
|
super
|
||||||
DB['update sites set space_used=space_used-? where id=?', size, site_id].first unless is_directory
|
unless is_directory
|
||||||
|
DB['update sites set space_used=space_used-? where id=?', size, site_id].first
|
||||||
|
end
|
||||||
|
|
||||||
site.purge_cache site.files_path(path)
|
site.purge_cache site.files_path(path)
|
||||||
SiteChangeFile.filter(site_id: site_id, filename: path).delete
|
SiteChangeFile.filter(site_id: site_id, filename: path).delete
|
||||||
|
|
Loading…
Add table
Reference in a new issue