34
35:- module(doc_access,
36 [ host_access_options/2 37 ]). 38:- if(exists_source(library(http/http_hook))). 39:- use_module(library(http/http_hook)). 40:- endif. 41:- use_module(library(dcg/basics)). 42
43:- dynamic
44 can_edit/1,
45 allow_from/1,
46 deny_from/1. 47
48:- meta_predicate
49 match_peer(1, +, +). 50
61
62http:authenticate(pldoc(read), Request, []) :-
63 !,
64 memberchk(peer(Peer), Request),
65 allowed_peer(Peer).
66http:authenticate(pldoc(edit), Request, []) :-
67 !,
68 ( can_edit(false)
69 -> fail
70 ; ( memberchk(x_forwarded_for(Forwarded), Request),
71 primary_forwarded_host(Forwarded, IPAtom),
72 parse_ip(IPAtom, Peer)
73 -> true
74 ; memberchk(peer(Peer), Request)
75 ),
76 match_peer(localhost, +, Peer)
77 ).
85host_access_options([], []).
86host_access_options([H|T0], T) :-
87 host_access_option(H),
88 !,
89 host_access_options(T0, T).
90host_access_options([H|T0], [H|T]) :-
91 host_access_options(T0, T).
92
93host_access_option(allow(From)) :-
94 assert(allow_from(From)).
95host_access_option(deny(From)) :-
96 assert(deny_from(From)).
97host_access_option(edit(Bool)) :-
98 assert(can_edit(Bool)).
112match_peer(Spec, _, Peer) :-
113 call(Spec, Peer),
114 !.
115match_peer(Spec, PM, Peer) :-
116 ( call(Spec, HOrDom), atom(HOrDom)
117 -> ( catch(tcp_host_to_address(Host, Peer), E, true),
118 var(E)
119 -> call(Spec, HostOrDomain),
120 atom(HostOrDomain),
121 ( sub_atom(HostOrDomain, 0, _, _, '.')
122 -> sub_atom(Host, _, _, 0, HostOrDomain)
123 ; HostOrDomain == Host
124 )
125 ; PM == (+)
126 -> !, fail
127 ; true
128 )
129 ).
135allowed_peer(Peer) :-
136 match_peer(deny_from, -, Peer),
137 !,
138 match_peer(allow_from, +, Peer).
139allowed_peer(Peer) :-
140 allow_from(_),
141 !,
142 match_peer(allow_from, +, Peer).
143allowed_peer(_).
144
145
146:- dynamic
147 can_edit/1.
155primary_forwarded_host(Spec, Host) :-
156 sub_atom(Spec, B, _, _, ','),
157 !,
158 sub_atom(Spec, 0, B, _, Host).
159primary_forwarded_host(Host, Host).
160
161
162localhost(ip(127,0,0,1)).
163localhost(localhost).
164
165parse_ip(Atom, IP) :-
166 atom_codes(Atom, Codes),
167 phrase(ip(IP), Codes).
173ip(ip(A,B,C,D)) -->
174 integer(A), ".", integer(B), ".", integer(C), ".", integer(D)