Forráskód Böngészése

modules_k/xcap_server: Added support for the org.openmobilealliance.xcap-directory auid

- Directory listing worked out on-the-fly based on DB contents
Peter Dunkley 13 éve
szülő
commit
4d48c5d485

+ 15 - 19
modules_k/xcap_server/xcap_misc.c

@@ -40,24 +40,18 @@ extern str xcaps_root;
 
 static param_t *_xcaps_xpath_ns_root = NULL;
 
-typedef struct xcaps_auid_list {
-	str auid;  /* auid value */
-	char term; /* ending char (next one after auid) */
-	int type;  /* internaly type id for auid */
-} xcaps_auid_list_t;
-
-/* list of supported auid */
-static xcaps_auid_list_t _xcaps_auid_list[] = {
+/* list of supported auid  - ordered ascending by type */
+xcaps_auid_list_t xcaps_auid_list[] = {
 	{ { "pres-rules", 10 },
 			'/', PRES_RULES },
 	{ { "org.openmobilealliance.pres-rules", 33 },
 			'/', PRES_RULES },
+	{ { "resource-lists", 14 },
+			'/', RESOURCE_LIST },
 	{ { "rls-services", 12 },
 			'/', RLS_SERVICE },
 	{ { "pidf-manipulation", 17 },
 			'/', PIDF_MANIPULATION },
-	{ { "resource-lists", 14 },
-			'/', RESOURCE_LIST },
 	{ { "xcap-caps", 9 },
 			'/', XCAP_CAPS },
 	{ { "org.openmobilealliance.user-profile", 35},
@@ -66,6 +60,8 @@ static xcaps_auid_list_t _xcaps_auid_list[] = {
 			'/', PRES_CONTENT },
 	{ { "org.openmobilealliance.search", 29},
 			'?', SEARCH },
+	{ { "org.openmobilealliance.xcap-directory", 37},
+			'/', DIRECTORY },
 
 	{ { 0, 0 }, 0, 0 }
 };
@@ -73,18 +69,18 @@ static xcaps_auid_list_t _xcaps_auid_list[] = {
 static int xcaps_find_auid(str *s, xcap_uri_t *xuri)
 {
 	int i;
-	for(i=0; _xcaps_auid_list[i].auid.s!=NULL; i++)
+	for(i=0; xcaps_auid_list[i].auid.s!=NULL; i++)
 	{
-		if(s->len > _xcaps_auid_list[i].auid.len
-			&& s->s[_xcaps_auid_list[i].auid.len] == _xcaps_auid_list[i].term
-			&& strncmp(s->s, _xcaps_auid_list[i].auid.s,
-							_xcaps_auid_list[i].auid.len) == 0)
+		if(s->len > xcaps_auid_list[i].auid.len
+			&& s->s[xcaps_auid_list[i].auid.len] == xcaps_auid_list[i].term
+			&& strncmp(s->s, xcaps_auid_list[i].auid.s,
+							xcaps_auid_list[i].auid.len) == 0)
 		{
-			LM_DBG("matched %.*s\n", _xcaps_auid_list[i].auid.len,
-					_xcaps_auid_list[i].auid.s);
-			xuri->type = _xcaps_auid_list[i].type;
+			LM_DBG("matched %.*s\n", xcaps_auid_list[i].auid.len,
+					xcaps_auid_list[i].auid.s);
+			xuri->type = xcaps_auid_list[i].type;
 			xuri->auid.s = s->s;
-			xuri->auid.len = _xcaps_auid_list[i].auid.len;
+			xuri->auid.len = xcaps_auid_list[i].auid.len;
 			return 0;
 		}
 	}

+ 8 - 0
modules_k/xcap_server/xcap_misc.h

@@ -50,6 +50,14 @@ typedef struct xcap_uri {
 	str domain;
 } xcap_uri_t;
 
+typedef struct xcaps_auid_list {
+	str auid;  /* auid value */
+	char term; /* ending char (next one after auid) */
+	int type;  /* internaly type id for auid */
+} xcaps_auid_list_t;
+
+extern xcaps_auid_list_t xcaps_auid_list[];
+
 int xcap_parse_uri(str *huri, str *xroot, xcap_uri_t *xuri);
 int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf);
 int xcaps_xpath_get(str *inbuf, str *xpaths, str *outbuf);

+ 390 - 194
modules_k/xcap_server/xcap_server.c

@@ -85,8 +85,8 @@ static int xcaps_etag_counter = 1;
 str xcaps_root = str_init("/xcap-root/");
 
 static str xcaps_buf = {0, 8192};
-#define XCAPS_ETAG_SIZE	128
-static char xcaps_etag_buf[XCAPS_ETAG_SIZE];
+#define XCAPS_HDR_SIZE	128
+static char xcaps_hdr_buf[XCAPS_HDR_SIZE];
 
 static str str_id_col = str_init("id");
 static str str_source_col = str_init("source");
@@ -243,7 +243,7 @@ static int xcaps_send_reply(sip_msg_t *msg, int code, str *reason,
 {
 	str tbuf;
 
-	if(hdrs->len>0)
+	if(hdrs && hdrs->len>0)
 	{
 		if (add_lump_rpl(msg, hdrs->s, hdrs->len, LUMP_RPL_HDR) == 0)
 		{
@@ -252,7 +252,7 @@ static int xcaps_send_reply(sip_msg_t *msg, int code, str *reason,
 		}
 	}
 
-	if(ctype->len>0)
+	if(ctype && ctype->len>0)
 	{
 		/* add content-type */
 		tbuf.len=sizeof("Content-Type: ") - 1 + ctype->len + CRLF_LEN;
@@ -275,7 +275,7 @@ static int xcaps_send_reply(sip_msg_t *msg, int code, str *reason,
 		}
 		pkg_free(tbuf.s);
 	}
-	if(body->len>0)
+	if(body && body->len>0)
 	{
 		if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) < 0)
 		{
@@ -460,12 +460,13 @@ error:
 	return -1;
 }
 
-static str xcaps_str_empty	= {"", 0};
 static str xcaps_str_ok		= {"OK", 2};
 static str xcaps_str_srverr	= {"Server error", 12};
 static str xcaps_str_notfound	= {"Not found", 9};
 static str xcaps_str_precon	= {"Precondition Failed", 19};
 static str xcaps_str_notmod	= {"Not Modified", 12};
+static str xcaps_str_notallowed = {"Method Not Allowed", 18};
+static str xcaps_str_notimplemented = {"Not Implemented", 15};
 static str xcaps_str_appxml	= {"application/xml", 15};
 static str xcaps_str_apprlxml	= {"application/resource-lists+xml", 30};
 static str xcaps_str_apprsxml	= {"application/rls-services+xml", 28};
@@ -478,6 +479,7 @@ static str xcaps_str_appapxml	= {"application/auth-policy+xml", 27};
 static str xcaps_str_appupxml	= {"application/vnd.oma.user-profile+xml", 36}; 
 static str xcaps_str_apppcxml	= {"application/vnd.oma.pres-content+xml", 36};
 static str xcaps_str_apppdxml	= {"application/pidf+xml", 20};
+static str xcaps_str_appdrxml	= {"application/vnd.oma.xcap-directory+xml", 38};
 
 
 /**
@@ -494,6 +496,7 @@ static int w_xcaps_put(sip_msg_t* msg, char* puri, char* ppath,
 	str etag_hdr;
 	str tbuf;
 	str nbuf = {0, 0};
+	str allow = {0, 0};
 	pv_elem_t *xm;
 	xcap_uri_t xuri;
 
@@ -522,37 +525,14 @@ static int w_xcaps_put(sip_msg_t* msg, char* puri, char* ppath,
 	if(path.s==NULL || path.len == 0)
 	{
 		LM_ERR("invalid path parameter\n");
-		goto error;
-	}
-
-	xm = (pv_elem_t*)pbody;
-	body.len = xcaps_buf.len - 1;
-	if(pv_printf(msg, xm, xcaps_buf.s, &body.len)<0)
-	{
-		LM_ERR("unable to get body\n");
-		goto error;
-	}
-	if(body.len <= 0)
-	{
-		LM_ERR("invalid body parameter\n");
-		goto error;
-	}
-	body.s = (char*)pkg_malloc(body.len+1);
-	if(body.s==NULL)
-	{
-		LM_ERR("no more pkg\n");
-		goto error;
+		return -1;
 	}
 
-	memcpy(body.s, xcaps_buf.s, body.len);
-	body.s[body.len] = '\0';
-
 	if(parse_uri(uri.s, uri.len, &turi)!=0)
 	{
 		LM_ERR("parsing uri parameter\n");
 		goto error;
 	}
-	/* TODO: do xml parsing for validation */
 
 	if(xcap_parse_uri(&path, &xcaps_root, &xuri)<0)
 	{
@@ -561,72 +541,110 @@ static int w_xcaps_put(sip_msg_t* msg, char* puri, char* ppath,
 		goto error;
 	}
 
-	xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag);
-	if(check_preconditions(msg, etag)!=1)
+	switch(xuri.type)
 	{
-		xcaps_send_reply(msg, 412, &xcaps_str_precon, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-
-		pkg_free(body.s);
-		return -2;
-	}
-
-	if(xuri.nss!=NULL && xuri.node.len>0)
-	{
-		/* partial document upload
-		 *   - fetch, update, delete and store
-		 */
-		if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0)
+	case DIRECTORY:
+	case XCAP_CAPS:
+		allow.s = xcaps_hdr_buf;
+		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: GET\r\n");
+		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
+		break;
+	case SEARCH:
+		allow.s = xcaps_hdr_buf;
+		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n");
+		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
+		break;
+	default:
+		xm = (pv_elem_t*)pbody;
+		body.len = xcaps_buf.len - 1;
+		if(pv_printf(msg, xm, xcaps_buf.s, &body.len)<0)
 		{
-			LM_ERR("could not fetch xcap document\n");
+			LM_ERR("unable to get body\n");
 			goto error;
 		}
-		if(xcaps_xpath_hack(&tbuf, 0)<0)
+		if(body.len <= 0)
 		{
-			LM_ERR("could not hack xcap document\n");
+			LM_ERR("invalid body parameter\n");
 			goto error;
 		}
-		if(xcaps_xpath_set(&tbuf, &xuri.node, &body, &nbuf)<0)
+		body.s = (char*)pkg_malloc(body.len+1);
+		if(body.s==NULL)
 		{
-			LM_ERR("could not update xcap document\n");
+			LM_ERR("no more pkg\n");
 			goto error;
 		}
-		if(nbuf.len<=0)
+		memcpy(body.s, xcaps_buf.s, body.len);
+		body.s[body.len] = '\0';
+
+		xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag);
+		if(check_preconditions(msg, etag)!=1)
+		{
+			xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL, NULL, NULL);
+
+			pkg_free(body.s);
+			return -2;
+		}
+
+		if(xuri.nss!=NULL && xuri.node.len>0)
 		{
-			LM_ERR("no new content\n");
+			/* partial document upload
+			 *   - fetch, update, delete and store
+			 */
+			if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0)
+			{
+				LM_ERR("could not fetch xcap document\n");
+				goto error;
+			}
+			if(xcaps_xpath_hack(&tbuf, 0)<0)
+			{
+				LM_ERR("could not hack xcap document\n");
+				goto error;
+			}
+			if(xcaps_xpath_set(&tbuf, &xuri.node, &body, &nbuf)<0)
+			{
+				LM_ERR("could not update xcap document\n");
+				goto error;
+			}
+			if(nbuf.len<=0)
+			{
+				LM_ERR("no new content\n");
+				goto error;
+			}
+			pkg_free(body.s);
+			body = nbuf;
+			if(xcaps_xpath_hack(&body, 1)<0)
+			{
+				LM_ERR("could not hack xcap document\n");
+				goto error;
+			}
+		}
+
+		if(xcaps_generate_etag_hdr(&etag_hdr)<0)
+		{
+			LM_ERR("could not generate etag\n");
 			goto error;
 		}
-		pkg_free(body.s);
-		body = nbuf;
-		if(xcaps_xpath_hack(&body, 1)<0)
+		etag.s = etag_hdr.s + 7; /* 'ETag: "' */
+		etag.len = etag_hdr.len - 10; /* 'ETag: "  "\r\n' */
+		if(xcaps_put_db(&turi.user, &turi.host,
+					&xuri, &etag, &body)<0)
 		{
-			LM_ERR("could not hack xcap document\n");
+			LM_ERR("could not store document\n");
 			goto error;
 		}
-	}
+		xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr,
+					NULL, NULL);
 
-	if(xcaps_generate_etag_hdr(&etag_hdr)<0)
-	{
-		LM_ERR("could not generate etag\n");
-		goto error;
-	}
-	etag.s = etag_hdr.s + 7; /* 'ETag: "' */
-	etag.len = etag_hdr.len - 10; /* 'ETag: "  "\r\n' */
-	if(xcaps_put_db(&turi.user, &turi.host,
-				&xuri, &etag, &body)<0)
-	{
-		LM_ERR("could not store document\n");
-		goto error;
+		if(body.s!=NULL)
+			pkg_free(body.s);
+
+		break;
 	}
-	xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr,
-				&xcaps_str_empty, &xcaps_str_empty);
-	if(body.s!=NULL)
-		pkg_free(body.s);
+
 	return 1;
 
 error:
-	xcaps_send_reply(msg, 500, &xcaps_str_srverr, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
+	xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL, NULL, NULL);
 	if(body.s!=NULL)
 		pkg_free(body.s);
 	return -1;
@@ -820,20 +838,20 @@ static int xcaps_get_db_etag(str* user, str *domain, xcap_uri_t *xuri, str *etag
 		LM_ERR("no etag in db record\n");
 		goto error;
 	}
-	etag->len = snprintf(xcaps_etag_buf, XCAPS_ETAG_SIZE,
+	etag->len = snprintf(xcaps_hdr_buf, XCAPS_HDR_SIZE,
 			"ETag: \"%.*s\"\r\n", s.len, s.s);
 	if(etag->len < 0)
 	{
 		LM_ERR("error printing etag hdr\n ");
 		goto error;
 	}
-	if(etag->len >= XCAPS_ETAG_SIZE)
+	if(etag->len >= XCAPS_HDR_SIZE)
 	{
 		LM_ERR("etag buffer overflow\n");
 		goto error;
 	}
 
-	etag->s = xcaps_etag_buf;
+	etag->s = xcaps_hdr_buf;
 	etag->s[etag->len] = '\0';
 
 	xcaps_dbf.free_result(xcaps_db, db_res);
@@ -849,6 +867,136 @@ error:
 	return -1;
 }
 
+static int xcaps_get_directory(struct sip_msg *msg, str *user, str *domain, str *directory)
+{
+	db_key_t qcols[2];
+	db_val_t qvals[2], *values;
+	db_key_t rcols[3];
+	db_row_t *rows;
+	db1_res_t* db_res = NULL;
+	int n_qcols = 0, n_rcols = 0;
+	int i, cur_type = 0, cur_pos = 0;
+	int doc_type_col, doc_uri_col, etag_col;
+	str auid_string = {0, 0};
+	struct hdr_field *hdr = msg->headers;
+	str server_name = {0, 0};
+
+	qcols[n_qcols] = &str_username_col;
+	qvals[n_qcols].type = DB1_STR;
+	qvals[n_qcols].nul = 0;
+	qvals[n_qcols].val.str_val = *user;
+	n_qcols++;
+	
+	qcols[n_qcols] = &str_domain_col;
+	qvals[n_qcols].type = DB1_STR;
+	qvals[n_qcols].nul = 0;
+	qvals[n_qcols].val.str_val = *domain;
+	n_qcols++;
+
+	rcols[doc_type_col = n_rcols++] = &str_doc_type_col;
+	rcols[doc_uri_col = n_rcols++] = &str_doc_uri_col;
+	rcols[etag_col = n_rcols++] = &str_etag_col;
+
+	if (xcaps_dbf.use_table(xcaps_db, &xcaps_db_table) < 0) 
+	{
+		LM_ERR("in use_table-[table]= %.*s\n", xcaps_db_table.len,
+				xcaps_db_table.s);
+		goto error;
+	}
+
+	if (xcaps_dbf.query(xcaps_db, qcols, 0, qvals, rcols, n_qcols,
+				n_rcols, &str_doc_type_col, &db_res) < 0)
+	{
+		LM_ERR("in sql query\n");
+		goto error;
+
+	}
+
+	if (db_res == NULL)
+		goto error;
+
+	while (hdr != NULL)
+	{
+		LM_ERR("Found header: %.*s\n", hdr->name.len, hdr->name.s);
+		if (cmp_hdrname_strzn(&hdr->name, "Host", 4) == 0)
+		{
+			LM_ERR("Found %.*s\n", hdr->body.len, hdr->body.s);
+			server_name = hdr->body;
+			break;
+		}
+		hdr = hdr->next;
+	}
+
+	directory->s = xcaps_buf.s;
+	directory->len = 0;
+
+	directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+		"<xcap-directory xmlns=\"urn:oma:xml:xdm:xcap-directory\">\r\n");
+
+	rows = RES_ROWS(db_res);
+	for (i = 0; i < RES_ROW_N(db_res); i++)
+	{
+		values = ROW_VALUES(&rows[i]);
+
+		if (cur_type != VAL_INT(&values[doc_type_col]))
+		{
+			if (cur_type != 0)
+			{
+				directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"</folder>\r\n");
+			}
+			cur_type = VAL_INT(&values[doc_type_col]);
+
+			memset(&auid_string, 0, sizeof(str));
+			while(xcaps_auid_list[cur_pos].auid.s != NULL)
+			{
+				if (xcaps_auid_list[cur_pos].type == cur_type)
+				{
+					auid_string.s = xcaps_auid_list[cur_pos].auid.s;
+					auid_string.len = xcaps_auid_list[cur_pos].auid.len;
+					break;
+				}
+				cur_pos++;
+			}
+
+			if (auid_string.s == NULL)
+			{
+				goto error;
+			}
+
+			directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"<folder auid=\"%.*s\">\r\n",
+						auid_string.len, auid_string.s);
+		}
+
+		directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"<entry uri=\"%s%.*s%s\" etag=\"%s\"/>\r\n",
+					server_name.len ? (msg->rcv.proto == PROTO_TLS ? "https://" : "http://") : "",
+					server_name.len, server_name.len ? server_name.s : "",
+					VAL_STRING(&values[doc_uri_col]),
+					VAL_STRING(&values[etag_col]));
+	}
+
+	if (cur_type != 0)
+	{
+		directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"</folder>\r\n");
+	}
+	directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
+		"</xcap-directory>");
+
+	if (db_res != NULL)
+		xcaps_dbf.free_result(xcaps_db, db_res);
+
+	return 0;
+
+error:
+	if (db_res != NULL)
+		xcaps_dbf.free_result(xcaps_db, db_res);
+	return -1;
+}
+
 /**
  *
  */
@@ -862,6 +1010,7 @@ static int w_xcaps_get(sip_msg_t* msg, char* puri, char* ppath)
 	int ret = 0;
 	xcap_uri_t xuri;
 	str *ctype;
+	str allow;
 
 	if(puri==0 || ppath==0)
 	{
@@ -904,63 +1053,92 @@ static int w_xcaps_get(sip_msg_t* msg, char* puri, char* ppath)
 		goto error;
 	}
 
-	if((ret=xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag))<0)
-	{ 
-		LM_ERR("could not fetch etag for xcap document\n");
-		goto error;
-	}
-	if (ret==1)
+	switch(xuri.type)
 	{
-		/* doc not found */
-		xcaps_send_reply(msg, 404, &xcaps_str_notfound, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-		return 1;
-	}
+	case DIRECTORY:
+		if (strncmp(xuri.file.s, "directory.xml", xuri.file.len) == 0)
+		{
+			if (xcaps_get_directory(msg, &turi.user, &turi.host, &body) < 0)
+				goto error;
+
+			xcaps_send_reply(msg, 200, &xcaps_str_ok, NULL, &xcaps_str_appdrxml, &body);
+		}
+		else
+		{
+			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL);
+		}
+		break;
+	case XCAP_CAPS:
+		xcaps_send_reply(msg, 501, &xcaps_str_notimplemented, NULL, NULL, NULL);
+		break;
+	case SEARCH:
+		allow.s = xcaps_hdr_buf;
+		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n");
+		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
+		break;
+	default:
+		if((ret=xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag))<0)
+		{ 
+			LM_ERR("could not fetch etag for xcap document\n");
+			goto error;
+		}
+		if (ret==1)
+		{
+			/* doc not found */
+			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL,
+					NULL, NULL);
+			return 1;
+		}
 	
-	if((ret=check_preconditions(msg, etag))==-1)
-	{
-		xcaps_send_reply(msg, 412, &xcaps_str_precon, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-		return -2;
-	} else if (ret==-2) {
-		xcaps_send_reply(msg, 304, &xcaps_str_notmod, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-		return -2;
-	}
+		if((ret=check_preconditions(msg, etag))==-1)
+		{
+			xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL,
+					NULL, NULL);
+			return -2;
+		} else if (ret==-2) {
+			xcaps_send_reply(msg, 304, &xcaps_str_notmod, NULL,
+					NULL, NULL);
+			return -2;
+		}
 
-	if((ret=xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &body))<0)
-	{
-		LM_ERR("could not fetch xcap document\n");
-		goto error;
-	}
-	if(ret==0)
-	{
-		/* doc found */
-		ctype = &xcaps_str_appxml;
-		if(xuri.type==RESOURCE_LIST)
-			ctype = &xcaps_str_apprlxml;
-		else if(xuri.type==PRES_RULES)
-			ctype = &xcaps_str_appapxml;
-		else if(xuri.type==RLS_SERVICE)
-			ctype = &xcaps_str_apprsxml;
-		else if(xuri.type==USER_PROFILE)
-			ctype = &xcaps_str_appupxml;
-		else if(xuri.type==PRES_CONTENT)
-			ctype = &xcaps_str_apppcxml;
-		else if(xuri.type==PIDF_MANIPULATION)
-			ctype = &xcaps_str_apppdxml;
-		xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag,
-				ctype, &body);
-	} else {
-		/* doc not found */
-		xcaps_send_reply(msg, 404, &xcaps_str_notfound, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
+		if((ret=xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &body))<0)
+		{
+			LM_ERR("could not fetch xcap document\n");
+			goto error;
+		}
+
+		if(ret==0)
+		{
+			/* doc found */
+			ctype = &xcaps_str_appxml;
+			if(xuri.type==RESOURCE_LIST)
+				ctype = &xcaps_str_apprlxml;
+			else if(xuri.type==PRES_RULES)
+				ctype = &xcaps_str_appapxml;
+			else if(xuri.type==RLS_SERVICE)
+				ctype = &xcaps_str_apprsxml;
+			else if(xuri.type==USER_PROFILE)
+				ctype = &xcaps_str_appupxml;
+			else if(xuri.type==PRES_CONTENT)
+				ctype = &xcaps_str_apppcxml;
+			else if(xuri.type==PIDF_MANIPULATION)
+				ctype = &xcaps_str_apppdxml;
+			xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag,
+					ctype, &body);
+		} else {
+			/* doc not found */
+			xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL,
+					NULL, NULL);
+		}
+
+		break;
 	}
+
 	return 1;
 
 error:
-	xcaps_send_reply(msg, 500, &xcaps_str_srverr, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
+	xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL,
+				NULL, NULL);
 	return -1;
 }
 
@@ -1025,6 +1203,7 @@ static int w_xcaps_del(sip_msg_t* msg, char* puri, char* ppath)
 	str etag_hdr = {0, 0};
 	str etag = {0, 0};
 	str tbuf;
+	str allow = {0, 0};
 
 	if(puri==0 || ppath==0)
 	{
@@ -1067,80 +1246,97 @@ static int w_xcaps_del(sip_msg_t* msg, char* puri, char* ppath)
 		goto error;
 	}
 
-	if(xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag)!=0)
-	{ 
-		LM_ERR("could not fetch etag for xcap document\n");
-		goto error;
-	}
-
-	if(check_preconditions(msg, etag)!=1)
-	{
-		xcaps_send_reply(msg, 412, &xcaps_str_precon, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-		return -2;
-	}
-
-	if(xuri.nss==NULL)
+	switch(xuri.type)
 	{
-		/* delete document */
-		if(xcaps_del_db(&turi.user, &turi.host, &xuri)<0)
-		{
-			LM_ERR("could not delete document\n");
-			goto error;
-		}
-		xcaps_send_reply(msg, 200, &xcaps_str_ok, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
-	} else {
-		/* delete element */
-		if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0)
-		{
-			LM_ERR("could not fetch xcap document\n");
-			goto error;
-		}
-		if(xcaps_xpath_hack(&tbuf, 0)<0)
-		{
-			LM_ERR("could not hack xcap document\n");
-			goto error;
-		}
-		if(xcaps_xpath_set(&tbuf, &xuri.node, NULL, &body)<0)
-		{
-			LM_ERR("could not update xcap document\n");
-			goto error;
-		}
-		if(body.len<=0)
-		{
-			LM_ERR("no new content\n");
-			goto error;
-		}
-		if(xcaps_xpath_hack(&body, 1)<0)
-		{
-			LM_ERR("could not hack xcap document\n");
+	case DIRECTORY:
+	case XCAP_CAPS:
+		allow.s = xcaps_hdr_buf;
+		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: GET\r\n");
+		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
+		break;
+	case SEARCH:
+		allow.s = xcaps_hdr_buf;
+		allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n");
+		xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL);
+		break;
+	default:
+		if(xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag)!=0)
+		{ 
+			LM_ERR("could not fetch etag for xcap document\n");
 			goto error;
 		}
-		if(xcaps_generate_etag_hdr(&etag_hdr)<0)
+
+		if(check_preconditions(msg, etag)!=1)
 		{
-			LM_ERR("could not generate etag\n");
-			goto error;
+			xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL,
+					NULL, NULL);
+			return -2;
 		}
-		etag.s = etag_hdr.s + 7; /* 'ETag: "' */
-		etag.len = etag_hdr.len - 10; /* 'ETag: "  "\r\n' */
-		if(xcaps_put_db(&turi.user, &turi.host,
-				&xuri, &etag, &body)<0)
+
+		if(xuri.nss==NULL)
 		{
-			LM_ERR("could not store document\n");
-			goto error;
+			/* delete document */
+			if(xcaps_del_db(&turi.user, &turi.host, &xuri)<0)
+			{
+				LM_ERR("could not delete document\n");
+				goto error;
+			}
+			xcaps_send_reply(msg, 200, &xcaps_str_ok, NULL,
+					NULL, NULL);
+		} else {
+			/* delete element */
+			if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0)
+			{
+				LM_ERR("could not fetch xcap document\n");
+				goto error;
+			}
+			if(xcaps_xpath_hack(&tbuf, 0)<0)
+			{
+				LM_ERR("could not hack xcap document\n");
+				goto error;
+			}
+			if(xcaps_xpath_set(&tbuf, &xuri.node, NULL, &body)<0)
+			{
+				LM_ERR("could not update xcap document\n");
+				goto error;
+			}
+			if(body.len<=0)
+			{
+				LM_ERR("no new content\n");
+				goto error;
+			}
+			if(xcaps_xpath_hack(&body, 1)<0)
+			{
+				LM_ERR("could not hack xcap document\n");
+				goto error;
+			}
+			if(xcaps_generate_etag_hdr(&etag_hdr)<0)
+			{
+				LM_ERR("could not generate etag\n");
+				goto error;
+			}
+			etag.s = etag_hdr.s + 7; /* 'ETag: "' */
+			etag.len = etag_hdr.len - 10; /* 'ETag: "  "\r\n' */
+			if(xcaps_put_db(&turi.user, &turi.host,
+					&xuri, &etag, &body)<0)
+			{
+				LM_ERR("could not store document\n");
+				goto error;
+			}
+			xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr,
+					NULL, NULL);
+			if(body.s!=NULL)
+				pkg_free(body.s);
 		}
-		xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr,
-				&xcaps_str_empty, &xcaps_str_empty);
-		if(body.s!=NULL)
-			pkg_free(body.s);
-		return 1;
+
+		break;
 	}
+
 	return 1;
 
 error:
-	xcaps_send_reply(msg, 500, &xcaps_str_srverr, &xcaps_str_empty,
-				&xcaps_str_empty, &xcaps_str_empty);
+	xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL,
+				NULL, NULL);
 	if(body.s!=NULL)
 		pkg_free(body.s);
 	return -1;
@@ -1246,7 +1442,7 @@ done:
  */
 int xcaps_generate_etag_hdr(str *etag)
 {
-	etag->len = snprintf(xcaps_etag_buf, XCAPS_ETAG_SIZE,
+	etag->len = snprintf(xcaps_hdr_buf, XCAPS_HDR_SIZE,
 			"ETag: \"sr-%d-%d-%d\"\r\n", xcaps_init_time, my_pid(),
 			xcaps_etag_counter++);
 	if(etag->len <0)
@@ -1254,13 +1450,13 @@ int xcaps_generate_etag_hdr(str *etag)
 		LM_ERR("error printing etag\n ");
 		return -1;
 	}
-	if(etag->len >= XCAPS_ETAG_SIZE)
+	if(etag->len >= XCAPS_HDR_SIZE)
 	{
 		LM_ERR("etag buffer overflow\n");
 		return -1;
 	}
 
-	etag->s = xcaps_etag_buf;
+	etag->s = xcaps_hdr_buf;
 	etag->s[etag->len] = '\0';
 	return 0;
 }