Contribution from Fabian Murer, as part of an ETH student project. Supervised, refactorized and merged by Jocelyn Fiat. Signed-off-by: Fabian Murer <fmurer@student.ethz.ch> Signed-off-by: Jocelyn Fiat <git@djoce.net>
273 lines
5.5 KiB
Plaintext
273 lines
5.5 KiB
Plaintext
note
|
|
description: "API to manage files."
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
|
|
class
|
|
CMS_FILES_API
|
|
|
|
inherit
|
|
CMS_MODULE_API
|
|
|
|
REFACTORING_HELPER
|
|
|
|
create
|
|
make
|
|
|
|
feature -- Access : path
|
|
|
|
uploads_relative_path: PATH
|
|
-- Path relative to `{CMS_API}.files_location'.
|
|
do
|
|
create Result.make_from_string (uploads_directory_name)
|
|
end
|
|
|
|
uploads_directory: PATH
|
|
do
|
|
Result := cms_api.files_location.extended (uploads_directory_name)
|
|
end
|
|
|
|
uploaded_file_path (f: READABLE_STRING_GENERAL): PATH
|
|
do
|
|
Result := uploads_directory.extended (f)
|
|
end
|
|
|
|
thumbnail_directory: PATH
|
|
do
|
|
Result := uploads_directory.extended (thumbnail_directory_name)
|
|
end
|
|
|
|
feature {CMS_FILES_MODULE} -- Access : metadata path
|
|
|
|
metadata_path (f: READABLE_STRING_GENERAL): PATH
|
|
do
|
|
Result := metadata_directory.extended (f).appended_with_extension ("cms-metadata")
|
|
end
|
|
|
|
metadata_directory: PATH
|
|
do
|
|
Result := uploads_directory.extended (metadata_directory_name)
|
|
end
|
|
|
|
feature -- Access : links
|
|
|
|
file_link (f: CMS_FILE): CMS_LOCAL_LINK
|
|
local
|
|
s: STRING
|
|
do
|
|
s := "files"
|
|
across
|
|
f.relative_path.components as ic
|
|
loop
|
|
s.append_character ('/')
|
|
s.append (percent_encoded (ic.item.name))
|
|
end
|
|
create Result.make (f.filename, s)
|
|
end
|
|
|
|
feature {NONE} -- Constants
|
|
|
|
uploads_directory_name: STRING = "uploads"
|
|
|
|
metadata_directory_name: STRING = ".metadata"
|
|
|
|
thumbnail_directory_name: STRING = ".thumbnails"
|
|
|
|
feature -- Factory
|
|
|
|
new_file (a_relative_path: PATH): CMS_FILE
|
|
-- New CMS_FILE for path `a_relative_path' relative to `files' directory.
|
|
do
|
|
create Result.make (a_relative_path, cms_api)
|
|
end
|
|
|
|
new_uploads_file (p: PATH): CMS_FILE
|
|
-- New uploaded path from `p' relative to `uploads_directory'.
|
|
do
|
|
create Result.make (uploads_relative_path.extended_path (p), cms_api)
|
|
end
|
|
|
|
feature -- Storage
|
|
|
|
delete_file (fn: READABLE_STRING_GENERAL)
|
|
-- Delete file at `fn'.
|
|
local
|
|
p: PATH
|
|
do
|
|
error_handler.reset
|
|
p := uploaded_file_path (fn)
|
|
safe_delete (p)
|
|
if not has_error then
|
|
p := metadata_path (fn)
|
|
safe_delete (p)
|
|
end
|
|
end
|
|
|
|
save_uploaded_file (uf: CMS_UPLOADED_FILE)
|
|
local
|
|
p: PATH
|
|
ut: FILE_UTILITIES
|
|
stored: BOOLEAN
|
|
original_name: STRING_32
|
|
n: INTEGER_32
|
|
finished: BOOLEAN
|
|
do
|
|
reset_error
|
|
create original_name.make_from_string (uf.filename)
|
|
|
|
p := uf.location
|
|
if not p.is_absolute then
|
|
p := uploads_directory.extended_path (p)
|
|
end
|
|
|
|
if ut.file_path_exists (p) then
|
|
|
|
from
|
|
n := 1
|
|
until
|
|
finished
|
|
loop
|
|
if ut.file_path_exists (p) then
|
|
uf.set_new_location_with_number (n)
|
|
p := uf.location
|
|
if p.is_absolute then
|
|
else
|
|
p := uploads_directory.extended_path (p)
|
|
end
|
|
n := n + 1
|
|
else
|
|
finished := True
|
|
end
|
|
end
|
|
stored := uf.move_to (p)
|
|
else
|
|
-- move file to path
|
|
stored := uf.move_to (p)
|
|
end
|
|
|
|
if stored then
|
|
save_metadata_from_uploaded_file (uf, cms_api.user)
|
|
else
|
|
error_handler.add_custom_error (-1, "uploaded file storage failed", "Issue occurred when saving uploaded file!")
|
|
end
|
|
end
|
|
|
|
save_metadata_from_uploaded_file (a_uploaded_file: CMS_UPLOADED_FILE; u: detachable CMS_USER)
|
|
local
|
|
f: detachable RAW_FILE
|
|
h_date: HTTP_DATE
|
|
retried: BOOLEAN
|
|
do
|
|
if retried then
|
|
-- FIXME: Report error?
|
|
if f /= Void and then not f.is_closed then
|
|
f.close
|
|
end
|
|
else
|
|
-- create a file for metadata
|
|
create f.make_with_path (metadata_path (a_uploaded_file.filename))
|
|
|
|
if f.exists then
|
|
f.open_write
|
|
else
|
|
f.create_read_write
|
|
end
|
|
-- insert username
|
|
if u /= Void then
|
|
f.put_string (u.id.out)
|
|
f.put_new_line
|
|
-- f.put_string (utf.utf_32_string_to_utf_8_string_8 (u.name))
|
|
-- f.put_new_line
|
|
else
|
|
f.put_new_line
|
|
f.put_new_line
|
|
end
|
|
-- insert uploaded_time
|
|
create h_date.make_now_utc
|
|
f.put_string (h_date.timestamp.out)
|
|
f.put_new_line
|
|
|
|
-- insert size of file
|
|
f.put_string (a_uploaded_file.size.out)
|
|
f.put_new_line
|
|
|
|
-- insert file type
|
|
if attached a_uploaded_file.type as type then
|
|
f.put_string (type.out)
|
|
f.put_new_line
|
|
end
|
|
|
|
f.close
|
|
end
|
|
rescue
|
|
retried := True
|
|
retry
|
|
end
|
|
|
|
metadata (a_cms_file: CMS_FILE): detachable CMS_FILE_METADATA
|
|
local
|
|
f: RAW_FILE
|
|
s: READABLE_STRING_8
|
|
do
|
|
if attached metadata_path (a_cms_file.filename) as p then
|
|
create f.make_with_path (p)
|
|
if f.exists and then f.is_access_readable then
|
|
create Result.make_empty
|
|
|
|
f.open_read
|
|
|
|
f.read_line
|
|
s := f.last_string
|
|
if s.is_integer_64 then
|
|
Result.set_user (cms_api.user_api.user_by_id (s.to_integer_64))
|
|
else
|
|
Result.set_user (cms_api.user_api.user_by_name (s))
|
|
end
|
|
|
|
f.read_line
|
|
s := f.last_string
|
|
if s.is_integer_64 then
|
|
Result.set_date ((create {HTTP_DATE}.make_from_timestamp (s.to_integer_64)).date_time)
|
|
end
|
|
|
|
f.read_line
|
|
s := f.last_string
|
|
if s.is_integer_32 then
|
|
Result.set_size (s.to_integer_32)
|
|
else
|
|
Result.set_size (-1)
|
|
end
|
|
|
|
if not f.end_of_file then
|
|
f.read_line
|
|
Result.set_file_type (f.last_string)
|
|
end
|
|
f.close
|
|
end
|
|
end
|
|
end
|
|
|
|
safe_delete (p: PATH)
|
|
-- Safe remove file at path `p'.
|
|
local
|
|
f: RAW_FILE
|
|
retried: BOOLEAN
|
|
do
|
|
if retried then
|
|
error_handler.add_custom_error (-1, "Can not delete file", {STRING_32} "Can not delete file %"" + p.name + "%"")
|
|
else
|
|
create f.make_with_path (p)
|
|
if f.exists then
|
|
f.delete
|
|
else
|
|
-- Not considered as failure.
|
|
end
|
|
end
|
|
rescue
|
|
retried := True
|
|
retry
|
|
end
|
|
|
|
|
|
end
|