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