Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(api_archive, [ locator_uri/2, with_input_from_uri/2, uri_absolute_path/2, archive_file/3, archive_file/2 ]). Daniel@0: Daniel@0: :- use_module(library(http/http_dispatch)). Daniel@0: :- use_module(library(http/http_parameters)). Daniel@0: :- use_module(library(xmlarchive)). Daniel@0: :- use_module(library(httpfiles)). Daniel@0: :- use_module(library(fileutils)). Daniel@0: :- use_module(library(insist)). Daniel@0: Daniel@0: :- set_prolog_flag(double_quotes,string). Daniel@0: :- rdf_register_prefix(file,'file://'). Daniel@0: :- http_handler(api(archive/get), archive_get, []). Daniel@0: :- setting(archive:root,string,"~/lib/dml-archive","Directory containing accessible files"). Daniel@0: Daniel@0: user:file_search_path(archive,Path) :- setting(archive:root,DD), expand_file_name(DD,[Path]). Daniel@0: Daniel@0: archive_get(Request) :- Daniel@0: http_parameters(Request, [uri(URI, [optional(false), description("URI of archive entry")])]), Daniel@0: file_name_extension(_,Ext,URI), Daniel@0: with_input_from_uri(URI,reply_from_stream(Ext)). Daniel@0: Daniel@0: uri_absolute_path(URI,Path) :- var(Path), !, Daniel@0: insist(string_concat("file://",LocString,URI)), Daniel@0: absolute_file_name(archive(LocString),Path,[access(read)]). Daniel@0: uri_absolute_path(URI,Path) :- Daniel@0: file_search_path(archive,Root), Daniel@0: atom_concat(Root,Rel,Path), Daniel@0: atom_concat('file:/',Rel,URI). Daniel@0: Daniel@0: :- meta_predicate with_input_from_uri(+,1). Daniel@0: with_input_from_uri(URI,Goal) :- Daniel@0: insist(string_concat("file://",LocString,URI)), Daniel@0: ( sub_string(LocString,PathLen,1,FragLen,"#") Daniel@0: -> sub_string(LocString,0,PathLen,_,Path), Daniel@0: sub_atom(LocString,_,FragLen,0,Frag), Daniel@0: absolute_file_name(archive(Path),ArchivePath,[access(read)]), Daniel@0: with_archive_stream(ArchivePath,Frag,Goal) Daniel@0: ; absolute_file_name(archive(LocString),AbsPath,[access(read)]), Daniel@0: with_stream(S, open(AbsPath,read,S), call(Goal,S)) Daniel@0: ). Daniel@0: Daniel@0: reply_from_stream(Ext,Stream) :- reply_stream(Stream,Ext). Daniel@0: Daniel@0: locator_uri(file(Parts), URI) :- atomic_list_concat(['file:/'|Parts],'/',URI). Daniel@0: locator_uri(archive_entry(ArchivePath,EntryName), URI) :- Daniel@0: atomic_list_concat(['file://',ArchivePath,'#',EntryName],URI). Daniel@0: Daniel@0: %% archive_file(+Ext:atom, +In:path, -Out:uri) is det. Daniel@0: %% archive_file(+In:path,-Out:uri) is det. Daniel@0: % Daniel@0: % This procedure finds a permanent home for the file In, moving it into Daniel@0: % the directory tree managed by the archive, giving it a unique file name, Daniel@0: % and returning the URI of the location. Daniel@0: % Daniel@0: % !! could add extension if necessary Daniel@0: archive_file(In,Out) :- archive_file('',In,Out). Daniel@0: archive_file(Ext,In,Out) :- Daniel@0: get_time(Time), Daniel@0: format_time(atom(Dir),'auto/%Y%m%d',Time), Daniel@0: expand_file_search_path(archive(Dir),FullDir), Daniel@0: ( exists_directory(FullDir) -> true Daniel@0: ; make_directory(FullDir) Daniel@0: ), Daniel@0: once( ( repeat, random_name(Ext,8,Str), Daniel@0: directory_file_path(FullDir,Str,Path), Daniel@0: \+exists_file(Path) )), Daniel@0: rename_file(In,Path), Daniel@0: uri_absolute_path(Out,Path). Daniel@0: Daniel@0: random_name(Ext,Len,String) :- Daniel@0: length(Chars,Len), Daniel@0: maplist(web_storage:random_char,Chars), Daniel@0: format(string(String),'~s~s',[Chars,Ext]). Daniel@0: Daniel@0: