123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185(* Ocsigen
* http://www.ocsigen.org
* Module userconf.ml
* Copyright (C) 2007 Vincent Balat
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)(* Local (users) config files *)openLwt.InfixexceptionNoConfFileletsection=Lwt_log.Section.make"ocsigen:ext:userconf"leterr_500=Ocsigen_extensions.Ext_stop_site(Ocsigen_cookie_map.empty,`Internal_server_error)lethandle_parsing_error{Ocsigen_extensions.request_info;_}=function|Ocsigen_extensions.Error_in_config_files->Lwt_log.ign_error_f~section"Syntax error in userconf configuration file for url %s: %s"(Uri.to_string(Ocsigen_request.urirequest_info))s;Lwt.returnerr_500|Ocsigen_extensions.Error_in_user_config_files->Lwt_log.ign_error_f~section"Unauthorized option in user configuration for url %s: %s"(Uri.to_string(Ocsigen_request.urirequest_info))s;Lwt.returnerr_500|e->Lwt.faile(* Answer returned by userconf when the url matches *)letsubresultnew_requser_parse_siteconfprevious_errreqreq_state=Ocsigen_extensions.Ext_sub_result(funcookies_to_set_rs->(* XXX why is rs above never used ?? *)Lwt.catch(fun()->user_parse_siteconfcookies_to_set(Ocsigen_extensions.Req_not_found(previous_err,new_req))>>=fun(answer,cookies)->(* If the request is not satisfied by userconf, the
changes in configuration (in request_config) are
preserved for the remainder of the enclosing <site> (in
the Ext_continue and Ext_found_continue cases below) *)letrecaux((answer,cts)asr)=matchanswerwith|Ocsigen_extensions.Ext_sub_resultsr->(* XXX Are these the good cookies ?? *)srcookies_to_setreq_state>>=aux|Ocsigen_extensions.Ext_continue_with({Ocsigen_extensions.request_config;_},cookies,err)->Lwt.return(Ocsigen_extensions.Ext_continue_with({reqwithOcsigen_extensions.request_config},cookies,err),cts)|Ocsigen_extensions.Ext_found_continue_withr->(* We keep config information outside userconf! *)Lwt.return(Ocsigen_extensions.Ext_found_continue_with(fun()->r()>|=fun(r,{Ocsigen_extensions.request_config;_})->r,{reqwithOcsigen_extensions.request_config}),cts)|_->Lwt.returnrinaux(answer,cookies))(fune->handle_parsing_errorreqe>>=funanswer->Lwt.return(answer,Ocsigen_cookie_map.empty)))letconf_to_xmlconf=try[Xml.parse_fileconf]with|Sys_error_->raiseNoConfFile|Xml.Error(s,loc)->letbegin_char,end_char=Xml.rangelocandline=Xml.linelocinraise(Ocsigen_extensions.Error_in_config_file(Printf.sprintf"%s, line %d, characters %d-%d"(Xml.error_msgs)linebegin_charend_char))letgenhostpatternsitepath(regexp,conf,url,prefix,localpath)=function|Ocsigen_extensions.Req_found_->(* We do not allow setting filters through userconf files right now *)Lwt.returnOcsigen_extensions.Ext_do_nothing|Ocsigen_extensions.Req_not_found(previous_err,({Ocsigen_extensions.request_info;request_config}asreq))asreq_state->(letpath=Ocsigen_request.sub_path_stringrequest_infoinmatchOcsigen_lib.Netstring_pcre.string_matchregexppath0with|None->Lwt.return(Ocsigen_extensions.Ext_nextprevious_err)|Some_->(tryLwt_log.ign_info~section"Using user configuration";letconf0=Ocsigen_extensions.replace_user_dirregexpconfpathinleturi=Uri.of_string(Ocsigen_lib.Netstring_pcre.global_replaceregexpurlpath)andprefix=Ocsigen_lib.Netstring_pcre.global_replaceregexpprefixpathanduserconf_options={Ocsigen_extensions.localfiles_root=Ocsigen_extensions.replace_user_dirregexplocalpathpath}andconf=conf_to_xmlconf0inletuser_parse_host=Ocsigen_extensions.parse_config_item(Someuserconf_options)hostpatternrequest_configin(* Inside userconf, we create a new virtual site starting
after [prefix], and use a request modified accordingly*)letuser_parse_site=Ocsigen_extensions.make_parse_config(sitepath@[prefix])user_parse_hostandreq={reqwithOcsigen_extensions.request_info=Ocsigen_request.update~urirequest_info}inLwt.return(subresultrequser_parse_siteconfprevious_errreqreq_state)with|Ocsigen_extensions.NoSuchUser|NoConfFile|Unix.Unix_error(Unix.EACCES,_,_)|Unix.Unix_error(Unix.ENOENT,_,_)->Lwt.return(Ocsigen_extensions.Ext_nextprevious_err)|e->handle_parsing_errorreqe))letparse_config_hostpattern_path__config_elem=letregexp=refNoneinletconf=refNoneinleturl=refNoneinletprefix=refNoneinletlocalpath=refNoneinOcsigen_extensions.(Configuration.process_element~in_tag:"host"~other_elements:(funt__->raise(Bad_config_tag_for_extensiont))~elements:[Configuration.element~name:"userconf"~attributes:[Configuration.attribute~name:"regexp"~obligatory:true(funs->lets=Ocsigen_lib.Netstring_pcre.regexp("^"^s^"$")inregexp:=Somes);Configuration.attribute~name:"conf"~obligatory:true(funs->lets=Ocsigen_extensions.parse_user_dirsinconf:=Somes);Configuration.attribute~name:"url"~obligatory:true(funs->url:=Somes);Configuration.attribute~name:"prefix"~obligatory:true(funs->prefix:=Somes);Configuration.attribute~name:"localpath"~obligatory:true(funs->lets=Ocsigen_extensions.parse_user_dirsinlocalpath:=Somes)]()]config_elem);letinfo=match!regexp,!conf,!url,!prefix,!localpathwith|Somer,Somet,Someu,Somep,Somep'->r,t,u,p,p'|_->Ocsigen_extensions.badconfig"Missing attributes for <userconf>"ingenhostpatternpathinfolet()=Ocsigen_extensions.register~name:"userconf"~fun_site:parse_config()