1/*
2   Access control
3   Copyright (C) 2001-2006, Joe Orton <joe@manyfish.co.uk>
4
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Library General Public
7   License as published by the Free Software Foundation; either
8   version 2 of the License, or (at your option) any later version.
9
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Library General Public License for more details.
14
15   You should have received a copy of the GNU Library General Public
16   License along with this library; if not, write to the Free
17   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18   MA 02111-1307, USA
19
20*/
21
22/* Contributed by Arun Garg <arung@pspl.co.in> */
23
24#include "config.h"
25
26#include <sys/types.h>
27
28#ifdef HAVE_STRING_H
29#include <string.h>
30#endif
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34#ifdef HAVE_STDLIB_H
35#include <stdlib.h>
36#endif
37
38#include "ne_request.h"
39#include "ne_locks.h"
40#include "ne_alloc.h"
41#include "ne_string.h"
42#include "ne_acl.h"
43#include "ne_uri.h"
44#include "ne_xml.h" /* for NE_XML_MEDIA_TYPE */
45
46#define EOL "\r\n"
47
48static ne_buffer *acl_body(const ne_acl_entry *right, int count)
49{
50    ne_buffer *body = ne_buffer_create();
51    int m;
52
53    ne_buffer_zappend(body,
54		      "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL
55		      "<acl xmlns='DAV:'>" EOL);
56
57    for (m = 0; m < count; m++) {
58	const char *type;
59
60	type = (right[m].type == ne_acl_grant ? "grant" : "deny");
61
62	ne_buffer_concat(body, "<ace>" EOL "<principal>", NULL);
63
64	switch (right[m].apply) {
65	case ne_acl_all:
66	    ne_buffer_zappend(body, "<all/>" EOL);
67	    break;
68	case ne_acl_property:
69	    ne_buffer_concat(body, "<property><", right[m].principal,
70			     "/></property>" EOL, NULL);
71	    break;
72	case ne_acl_href:
73	    ne_buffer_concat(body, "<href>", right[m].principal,
74			     "</href>" EOL, NULL);
75	    break;
76	}
77
78	ne_buffer_concat(body, "</principal>" EOL "<", type, ">" EOL, NULL);
79
80	if (right[m].read == 0)
81	    ne_buffer_concat(body,
82			     "<privilege>" "<read/>" "</privilege>" EOL,
83			     NULL);
84	if (right[m].read_acl == 0)
85	    ne_buffer_concat(body,
86			     "<privilege>" "<read-acl/>" "</privilege>" EOL,
87			     NULL);
88	if (right[m].write == 0)
89	    ne_buffer_concat(body,
90			     "<privilege>" "<write/>" "</privilege>" EOL,
91			     NULL);
92	if (right[m].write_acl == 0)
93	    ne_buffer_concat(body,
94			     "<privilege>" "<write-acl/>" "</privilege>" EOL,
95			     NULL);
96	if (right[m].read_cuprivset == 0)
97	    ne_buffer_concat(body,
98			     "<privilege>"
99			     "<read-current-user-privilege-set/>"
100			     "</privilege>" EOL, NULL);
101	ne_buffer_concat(body, "</", type, ">" EOL, NULL);
102	ne_buffer_zappend(body, "</ace>" EOL);
103    }
104    ne_buffer_zappend(body, "</acl>" EOL);
105
106    return body;
107}
108
109int ne_acl_set(ne_session *sess, const char *uri,
110	       const ne_acl_entry *entries, int numentries)
111{
112    int ret;
113    ne_request *req = ne_request_create(sess, "ACL", uri);
114    ne_buffer *body = acl_body(entries, numentries);
115
116#ifdef NE_HAVE_DAV
117    ne_lock_using_resource(req, uri, 0);
118#endif
119
120    ne_set_request_body_buffer(req, body->data, ne_buffer_size(body));
121    ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE);
122    ret = ne_request_dispatch(req);
123
124    ne_buffer_destroy(body);
125
126    if (ret == NE_OK && ne_get_status(req)->code == 207) {
127	ret = NE_ERROR;
128    }
129
130    ne_request_destroy(req);
131    return ret;
132}
133