View source with raw comments or as raw
    1/*  Part of ClioPatria SeRQL and SPARQL server
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@cs.vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (C): 2004-2015, University of Amsterdam,
    7			      VU University Amsterdam
    8
    9    This program is free software; you can redistribute it and/or
   10    modify it under the terms of the GNU General Public License
   11    as published by the Free Software Foundation; either version 2
   12    of the License, or (at your option) any later version.
   13
   14    This program is distributed in the hope that it will be useful,
   15    but WITHOUT ANY WARRANTY; without even the implied warranty of
   16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17    GNU General Public License for more details.
   18
   19    You should have received a copy of the GNU General Public
   20    License along with this library; if not, write to the Free Software
   21    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22
   23    As a special exception, if you link this library with other files,
   24    compiled with a Free Software compiler, to produce an executable, this
   25    library does not by itself cause the resulting executable to be covered
   26    by the GNU General Public License. This exception does not however
   27    invalidate any other reasons why the executable file might be covered by
   28    the GNU General Public License.
   29*/
   30
   31:- module(cpa_user, []).   32
   33:- use_module(rdfql(serql_xml_result)).   34:- use_module(library(http/http_open)).   35:- use_module(library(http/http_path)).   36:- use_module(library(http/html_head)).   37:- use_module(library(http/html_write)).   38:- use_module(library(http/js_write)).   39:- use_module(library(http/http_dispatch)).   40:- use_module(library(http/http_host)).   41:- use_module(library(http/cp_jquery)).   42:- use_module(api(rdflib)).   43:- use_module(user(user_db)).   44:- use_module(library(debug)).   45:- use_module(components(server_statistics)).   46:- use_module(components(query)).   47:- use_module(components(basics)).   48:- use_module(library(semweb/rdf_db)).   49:- use_module(library(semweb/rdf_library)).   50:- use_module(library(occurs)).

This module contains the main front-end of ClioPatria. It notably provides the HTTP-handlers for / and /home:

/
This handler, with id=root, redirects either to /home (id=home) or to id=create_admin. The latter is issued if there is no initialised user-db.
/home
Provides the default welcome page of ClioPatria.

If one develops an application on top of ClioPatria, it is adviced to redefine the handler for home, as in:

:- http_handler('/welcome', home, []).

home(Request) :-
    ...

If the application wants to provide a link to the generic ClioPatria administrative interface, it can do so by linking to the id=admin, as in:

    ...,
    { http_link_to_id(admin, [], AdminRef) },
    html(a(href(AdminRef), admin)),
    ...

*/

   87:- http_handler(root('.'),			     root,
   88		[ priority(-100) ]).   89:- http_handler(cliopatria(home),		     home,
   90		[ priority(-100) ]).   91:- http_handler(cliopatria(admin),		     home,
   92		[ id(admin) ]).   93:- http_handler(cliopatria('user/query'),	     query_form,
   94		[id(sparql_query_form)]).   95:- http_handler(cliopatria('user/statistics'),	     statistics,	      []).   96:- http_handler(cliopatria('user/loadFile'),	     load_file_form,	      []).   97:- http_handler(cliopatria('user/loadURL'),	     load_url_form,	      []).   98:- http_handler(cliopatria('user/loadLibraryRDF'),   load_library_rdf_form,   []).   99:- http_handler(cliopatria('user/clearRepository'),  clear_repository_form,   []).  100:- http_handler(cliopatria('user/removeStatements'), remove_statements_form,  []).
 root(+Request)
Default ClioPatria handler for /. The default handler redirects to id=home, unless the use-info is not initialised. in that case it redirects to id=create_admin.
  109root(Request) :-
  110	redirect_create_admin(Request),
  111	http_redirect(moved_temporary,
  112		      location_by_id(home),
  113		      Request).
  114
  115redirect_create_admin(Request) :-
  116	\+ current_user(_), !,
  117	http_redirect(moved_temporary,
  118		      location_by_id(create_admin),
  119		      Request).
  120redirect_create_admin(_).
 home(+Request)
Reply with the normal welcome page. The welcome page is a decorated version of html('welcome.html').
  127home(Request) :-
  128	redirect_create_admin(Request),
  129	reply_decorated_file(html('welcome.html'), Request).
 reply_decorated_file(+Alias, +Request) is det
Present an HTML file embedded using the server styling. This is achieved by parsing the HTML and passing the parsed DOM to reply_html_page/3.
  138reply_decorated_file(Alias, _Request) :-
  139	absolute_file_name(Alias, Page, [access(read)]),
  140	load_html_file(Page, DOM),
  141	contains_term(element(title, _, Title), DOM),
  142	contains_term(element(body, _, Body), DOM),
  143	Style = element(style, _, _),
  144	findall(Style, sub_term(Style, DOM), Styles),
  145	append(Styles, Body, Content),
  146	reply_html_page(cliopatria(html_file),
  147			title(Title), Content).
  148
  149
  150		 /*******************************
  151		 *	    STATISTICS		*
  152		 *******************************/
 statistics(+Request)
Provide elementary statistics on the server.
  158statistics(Request) :-
  159	http_current_host(Request, Host, _Port, [global(true)]),
  160	reply_html_page(cliopatria(default),
  161			title('RDF statistics'),
  162			[ div(id('rdf-statistics'),
  163			      [ h1([id(stattitle)], ['RDF statistics for ', Host]),
  164				ol([id(toc)],
  165				   [ li(a(href('#ntriples'),    'Triples in database')),
  166				     li(a(href('#callstats'),   'Call statistics')),
  167				     li(a(href('#sessions'),    'Active sessions')),
  168				     li(a(href('#serverstats'), 'Server statistics'))
  169				   ]),
  170				h2([id(ntriples)], 'Triples in database'),
  171				\triple_statistics,
  172				h2([id(callstats)],'Call statistics'),
  173				\rdf_call_statistics_table,
  174				h2([id(sessions)], 'Active sessions'),
  175				\http_session_table,
  176				h2([id(serverstats)], 'Server statistics'),
  177				h3('Static workers and statistics:'),
  178				\http_server_statistics,
  179				h3('Defined dynamic worker pools:'),
  180				\http_server_pool_table
  181			      ])
  182			]).
  183
  184
  185triple_statistics -->
  186	{ rdf_statistics(triples(Total)),
  187	  graph_count(Count),
  188	  http_link_to_id(list_graphs, [], ListGraphs)
  189	},
  190	html(p([ 'The RDF store contains ', \n(human, Total), ' triples in ',
  191		 \n(human, Count), ' ', a(href(ListGraphs), graphs),
  192		 \using_core])).
  193
  194:- if((rdf_version(V),V<30000)).  195using_core -->
  196	{ rdf_statistics(core(Core)) }, !,
  197	html([', using ', \n(human, Core), 'b memory']).
  198:- endif.  199using_core -->
  200	[].
  201
  202graph_count(Count) :-
  203	aggregate_all(count, rdf_graph(_), Count).
 query_form(+Request)
Provide a page for issuing a SELECT query.
  209query_form(_Request) :-
  210	reply_html_page(cliopatria(default),
  211			title('Specify a query'),
  212			[ \query_form([]),
  213			  \query_docs,
  214			  \warn_interactive
  215			]).
  216
  217
  218
  219warn_interactive -->
  220	{ http_location_by_id(sparql_query, HREF),
  221	  SparqlAPI = 'http://www.w3.org/TR/rdf-sparql-protocol/'
  222	},
  223	html([ br(clear(all)),
  224	       p(class(footnote),
  225		 [ 'This form is to test SPARQL queries ', i(interactively), '. ',
  226		   'Machines should use ', b([HREF,'?query=...']),
  227		   ', which provides a ',
  228		   a(href(SparqlAPI), 'SPARQL compliant HTTP API'), '.'
  229		 ])
  230	     ]).
  231
  232query_docs -->
  233	html(ul([ li(a(href('http://www.w3.org/TR/rdf-sparql-query/'),
  234		       'SPARQL Documentation')),
  235		  li(a(href('http://rdf4j.org/'),
  236		       'Sesame and SeRQL site'))
  237		])).
 load_file_form(+Request)
Provide a form for uploading triples from a local file.
  243load_file_form(Request) :-
  244	authorized(write(default, load(posted))),
  245	reply_html_page(cliopatria(default),
  246			title('Upload RDF'),
  247			[ h1('Upload an RDF document'),
  248
  249			  \explain_file_form,
  250
  251			  form([ action(location_by_id(upload_data)),
  252				 method('POST'),
  253				 enctype('multipart/form-data')
  254			       ],
  255			       [ \hidden(resultFormat, html),
  256				 table(class(form),
  257				       [tr([ th(class(label), 'File:'),
  258					     td(input([ name(data),
  259							id(filename),
  260							type(file),
  261							size(50)
  262						      ]))
  263					   ]),
  264					tr([ th(class(label), 'Graph:'),
  265					     td(input([ name(baseURI),
  266							id(namedgraph),
  267							size(50)
  268						      ]))
  269					   ]),
  270					tr(class(buttons),
  271					   [ th([align(right), colspan(2)],
  272						input([ type(submit),
  273							value('Upload now')
  274						      ]))
  275					   ])
  276				       ])
  277			       ]),
  278			  \graph_script(Request)
  279			]).
  280
  281explain_file_form -->
  282	html({|html||
  283<p>Upload RDF to the ClioPatria triple store. The uploaded file may
  284contain <a href="http://www.w3.org/TR/REC-rdf-syntax/">RDF/XML</a>, <a
  285href="http://www.w3.org/TR/turtle/">Turtle</a> or <a
  286href="http://www.w3.org/TR/n-triples/">ntriples</a>. The file is
  287processed using <a href="http://www.libarchive.org/"> libarchive</a>,
  288which implies it can be a (nested) archive and may optionally be
  289compressed. </p>
  290
  291<p>
  292Alternatively you can use <a href="loadURL">loadURL</a> to load data from a web server.
  293</p>
  294	     |}).
  295
  296
  297graph_script(Request) -->
  298	{ http_public_host_url(Request, Host),
  299	  http_absolute_location(root(data/uploaded), Location, []),
  300	  string_concat(Host, Location, URL)
  301	},
  302	html_requires(jquery),
  303	js_script({|javascript(URL)||
  304$(function() {
  305  if ( $("#filename").val() ) {
  306    $("#namedgraph").val(URL+"/"+$("#filename").val());
  307  }
  308
  309  $("#filename").on("change", function(ev) {
  310    var filename = $(ev.target).val();
  311    console.log("Changed file", filename);
  312    $("#namedgraph").val(URL+"/"+filename);
  313  });
  314});
  315		  |}).
 load_url_form(+Request)
Provide a form for uploading triples from a URL.
  322load_url_form(_Request) :-
  323	reply_html_page(cliopatria(default),
  324			title('Load RDF from HTTP server'),
  325			[ h1('Load RDF from HTTP server'),
  326
  327			  \explain_url_form,
  328
  329			  form([ action(location_by_id(upload_url)),
  330				 method('GET')
  331			       ],
  332			       [ \hidden(resultFormat, html),
  333				 table(class(form),
  334				       [tr([ th(class(label), 'URL:'),
  335					     td(input([ name(url),
  336							id(url),
  337							value('http://'),
  338							size(50)
  339						      ]))
  340					   ]),
  341					tr([ th(class(label), 'Graph:'),
  342					     td(input([ name(baseURI),
  343							id(namedgraph),
  344							value('http://'),
  345							size(50)
  346						      ]))
  347					   ]),
  348					tr(class(buttons),
  349					   [ td([align(right), colspan(2)],
  350						input([ type(submit),
  351							value('Load RDF')
  352						      ]))
  353					   ])
  354				       ])
  355			       ]),
  356			  \url_graph_script
  357			]).
  358
  359
  360url_graph_script -->
  361	html_requires(jquery),
  362	js_script({|javascript||
  363$(function() {
  364  $("#url").on("change keyup", function(ev) {
  365    var url = $(ev.target).val();
  366    $("#namedgraph").val(url);
  367  });
  368});
  369		   |}).
  370
  371
  372explain_url_form -->
  373	html({|html||
  374
  375<p>Download RDF from an URL and insert it into the ClioPatria triple
  376store. The downloaded document may contain <a
  377href="http://www.w3.org/TR/REC-rdf-syntax/">RDF/XML</a>, <a
  378href="http://www.w3.org/TR/turtle/">Turtle</a> or <a
  379href="http://www.w3.org/TR/n-triples/">ntriples</a>. The file is
  380processed using <a href="http://www.libarchive.org/"> libarchive</a>,
  381which implies it can be a (nested) archive and may optionally be
  382compressed. </p>
  383
  384<p>
  385Alternatively you can use <a href="loadFile">loadFile</a> to upload
  386a file through your browser.
  387</p>
  388	     |}).
 load_library_rdf_form(+Request)
Provide a form for loading an ontology from the library. Libraries are made available through the file search path ontology. Directories found through this alias are searched recursively for files named Manifest.ttl.
See also
- file_search_path/2
- rdf_attach_library/1.
  400load_library_rdf_form(Request) :-
  401	authorized(read(status, listBaseOntologies)),
  402	get_base_ontologies(Request, Ontologies),
  403	reply_html_page(cliopatria(default),
  404			title('Load server-side RDF library'),
  405			[ h1('Load a registered RDF library'),
  406			  p('Select a resource from the registered libraries'),
  407			  \load_base_ontology_form(Ontologies)
  408			]).
 load_base_ontology_form(+Ontologies)//
HTML component that emits a form to load a base-ontology and its dependencies. Ontologies is a list of ontology-identifiers as used by rdf_load_library/1.
  417load_base_ontology_form(Ontologies) -->
  418	html(form([ action(location_by_id(load_library_ontology)),
  419		    method('GET')
  420		  ],
  421		  [ \hidden(resultFormat, html),
  422		    table(class(form),
  423			  [ tr([ th('Ontology:'),
  424				 td(select(name(ontology),
  425					   [ option([], '')
  426					   | \emit_base_ontologies(Ontologies)
  427					   ]))
  428			       ]),
  429			    tr(class(buttons),
  430			       td([colspan(2), align(right)],
  431				  input([ type(submit),
  432					  value('Load')
  433					])))
  434			  ])
  435		  ])).
  436
  437
  438emit_base_ontologies([]) -->
  439	[].
  440emit_base_ontologies([H|T]) -->
  441	(   { rdf_library_index(H, title(Title)) }
  442	->  html(option([value(H)], [H, ' -- ', Title]))
  443	;   html(option([value(H)], H))
  444	),
  445	emit_base_ontologies(T).
  446
  447
  448get_base_ontologies(_Request, List) :-
  449	catch(findall(O, library_ontology(O), List0), _, fail), !,
  450	sort(List0, List).
  451get_base_ontologies(Request, List) :-
  452	http_current_host(Request, Host, Port, []),
  453	http_location_by_id(list_base_ontologies, ListBaseOntos),
  454	debug(base_ontologies, 'Opening http://~w:~w~w',
  455	      [Host, Port, ListBaseOntos]),
  456	http_open([ protocol(http),
  457		    host(Host),
  458		    port(Port),
  459		    path(ListBaseOntos),
  460		    search([resultFormat(xml)])
  461		  ],
  462		  In,
  463		  [ % request_header('Cookie', Cookie)
  464		  ]),
  465	debug(base_ontologies, '--> Reading from ~w', [In]),
  466	xml_read_result_table(In, Rows, _VarNames),
  467	maplist(arg(1), Rows, List).
 clear_repository_form(+Request)
HTTP handle presenting a form to clear the repository.
  473clear_repository_form(_Request) :-
  474	reply_html_page(cliopatria(default),
  475			title('Clear triple store'),
  476			[ h1('Clear entire repository'),
  477
  478			  p(['This operation removes ', b(all), ' triples from \c
  479			  the RDF store.']),
  480
  481			  form([ action(location_by_id(clear_repository)),
  482				 method('GET')
  483			       ],
  484			       [ \hidden(repository, default),
  485				 \hidden(resultFormat, html),
  486				 input([ type(submit),
  487					 value('Clear repository now')
  488				       ])
  489			       ])
  490			]).
 remove_statements_form(+Request)
HTTP handler providing a form to remove RDF statements.
  497remove_statements_form(_Request) :-
  498	reply_html_page(cliopatria(default),
  499			title('Remove triples from store'),
  500			[ h1('Remove statements'),
  501
  502			  p(['Remove matching triples from the database.  The three ',
  503			     'fields are in ntriples/Turtle notation.  Omitted fields ',
  504			     'match any value.'
  505			    ]),
  506
  507			  \remove_statements_form
  508			]).
  509
  510remove_statements_form -->
  511	html(form([ action(location_by_id(remove_statements)),
  512		    method('GET')
  513		  ],
  514		  [ \hidden(repository, default),
  515		    \hidden(resultFormat, html),
  516		    table([ class(form)
  517			  ],
  518			  [ tr([ th(class(label), 'Subject:'),
  519				 td(input([ name(subject),
  520					    size(50)
  521					  ]))
  522			       ]),
  523			    tr([ th(class(label), 'Predicate:'),
  524				 td(input([ name(predicate),
  525					    size(50)
  526					  ]))
  527			       ]),
  528			    tr([ th(class(label), 'Object:'),
  529				 td(input([ name(object),
  530					    size(50)
  531					  ]))
  532			       ]),
  533			    tr(class(buttons),
  534			       [ td([ align(right),
  535				      colspan(2)
  536				    ],
  537				    input([ type(submit),
  538					    value('Remove')
  539					  ]))
  540			       ])
  541			  ])
  542		  ]))