Browse code

- implemented the feature described in RFC 4827 - An Extensible Markup Language (XML) Configuration Access Protocol (XCAP) Usage for Manipulating Presence Document Contents - it enables the possibility to set a permanent presence state that is independent of activeness of any particular device ( example of situations in which it is useful: setting person-related state or when in vacantion/travelling ) - the usage is configurable through 'presence_xml' new module parameter - 'pidf_manipulation' - if set to 1 the feature is enabled - thanks to Mircea Amarascu from AG Projects for an initial version and for help with the testing.

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@2296 689a6050-402a-0410-94f2-e92a70836424

Anca Vamanu authored on 25/05/2007 14:53:55
Showing 11 changed files
... ...
@@ -44,7 +44,7 @@ typedef int (publ_handling_t)(struct sip_msg*);
44 44
 
45 45
 typedef int (subs_handling_t)(struct sip_msg*);
46 46
 
47
-typedef str* (agg_nbody_t)(str** body_array, int n, int off_index);
47
+typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain, str** body_array, int n, int off_index);
48 48
 /* params for agg_body_t 
49 49
  *	body_array= an array with all the bodies stored for that resource
50 50
  *	n= the number of bodies
... ...
@@ -411,9 +411,11 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
411 411
 	db_val_t *row_vals;
412 412
 	int n_result_cols = 0;
413 413
 	int n_query_cols = 0;
414
-	int i, n;
414
+	int i, n, len;
415 415
 	int build_off_n= -1; 
416 416
 	str etags;
417
+	str* body;
418
+	int size= 0;
417 419
 
418 420
 	query_cols[n_query_cols] = "domain";
419 421
 	query_vals[n_query_cols].type = DB_STR;
... ...
@@ -464,8 +466,17 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
464 466
 		DBG("PRESENCE: get_p_notify_body: The query returned no"
465 467
 				" result\n[username]= %.*s\t[domain]= %.*s\t[event]= %.*s\n",
466 468
 				user.len, user.s, host.len, host.s, event->stored_name.len, event->stored_name.s);
467
-
469
+		
468 470
 		pa_dbf.free_result(pa_db, result);
471
+		result= NULL;
472
+
473
+		if(event->agg_nbody)
474
+		{
475
+			notify_body = event->agg_nbody(&user, &host, NULL, 0, -1);
476
+			if(notify_body)
477
+				goto done;
478
+		}	
479
+			
469 480
 		return NULL;
470 481
 	}
471 482
 	else
... ...
@@ -473,7 +484,6 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
473 484
 		n= result->n;
474 485
 		if(event->agg_nbody== NULL )
475 486
 		{
476
-			int len;
477 487
 			DBG("PRESENCE:get_p_notify_body: Event does not require aggregation\n");
478 488
 			row = &result->rows[n-1];
479 489
 			row_vals = ROW_VALUES(row);
... ...
@@ -495,7 +505,7 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
495 505
 				goto error;
496 506
 			}
497 507
 			memset(notify_body, 0, sizeof(str));
498
-			notify_body->s= (char*)malloc( len* sizeof(char));
508
+			notify_body->s= (char*)pkg_malloc( len* sizeof(char));
499 509
 			if(notify_body->s== NULL)
500 510
 			{
501 511
 				LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
... ...
@@ -504,12 +514,14 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
504 514
 			}
505 515
 			memcpy(notify_body->s, row_vals[body_col].val.string_val, len);
506 516
 			notify_body->len= len;
507
-			goto done;
517
+			pa_dbf.free_result(pa_db, result);
518
+			
519
+			return notify_body;
508 520
 		}
509 521
 		
510 522
 		DBG("PRESENCE:get_p_notify_body: Event requires aggregation\n");
511
-
512
-		body_array =(str**)pkg_malloc( (result->n)*sizeof(str*));
523
+		
524
+		body_array =(str**)pkg_malloc( (n+1) *sizeof(str*));
513 525
 		if(body_array == NULL)
514 526
 		{
515 527
 			LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR while allocating"
... ...
@@ -522,7 +534,7 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
522 534
 			DBG("PRESENCE:get_p_notify_body:searched etag = %.*s len= %d\n", 
523 535
 					etag->len, etag->s, etag->len);
524 536
 			DBG( "PRESENCE:get_p_notify_body: etag not NULL\n");
525
-			for(i= 0; i<result->n; i++)
537
+			for(i= 0; i< n; i++)
526 538
 			{
527 539
 				row = &result->rows[i];
528 540
 				row_vals = ROW_VALUES(row);
... ...
@@ -536,28 +548,76 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag,
536 548
 				{
537 549
 					DBG("PRESENCE:get_p_notify_body found etag  \n");
538 550
 					build_off_n= i;
539
-				}	
540
-				body_array[i] =&row_vals[body_col].val.str_val;
551
+				}
552
+				len= strlen(row_vals[body_col].val.string_val);
553
+				if(len== 0)
554
+				{
555
+					LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR Empty notify body record\n");
556
+					goto error;
557
+				}
558
+			
559
+				size= sizeof(str)+ len* sizeof(char);
560
+				body= (str*)pkg_malloc(size);
561
+				if(body== NULL)
562
+				{
563
+					LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
564
+					goto error;
565
+				}
566
+				memset(body, 0, size);
567
+				size= sizeof(str);
568
+				body->s= (char*)body+ size;
569
+				memcpy(body->s, row_vals[body_col].val.string_val, len);
570
+				body->len= len;
571
+
572
+				body_array[i]= body;
541 573
 			}
542 574
 		}	
543 575
 		else
544 576
 		{	
545
-			for(i=0;i<result->n;i++)
577
+			for(i=0; i< n; i++)
546 578
 			{
547 579
 				row = &result->rows[i];
548 580
 				row_vals = ROW_VALUES(row);
549
-				body_array[i] =&row_vals[body_col].val.str_val;
581
+				
582
+				len= strlen(row_vals[body_col].val.string_val);
583
+				if(len== 0)
584
+				{
585
+					LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR Empty notify body record\n");
586
+					goto error;
587
+				}
588
+				
589
+				size= sizeof(str)+ len* sizeof(char);
590
+				body= (str*)pkg_malloc(size);
591
+				if(body== NULL)
592
+				{
593
+					LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
594
+					goto error;
595
+				}
596
+				memset(body, 0, size);
597
+				size= sizeof(str);
598
+				body->s= (char*)body+ size;
599
+				memcpy(body->s, row_vals[body_col].val.string_val, len);
600
+				body->len= len;
601
+
602
+				body_array[i]= body;
550 603
 			}			
551 604
 		}
552
-	
553
-		notify_body = event->agg_nbody(body_array, result->n, build_off_n);
605
+		pa_dbf.free_result(pa_db, result);
606
+		result= NULL;
607
+
608
+		notify_body = event->agg_nbody(&user, &host, body_array, n, build_off_n);
554 609
 	}
555 610
 
556 611
 done:	
557
-	if(result!=NULL)
558
-		pa_dbf.free_result(pa_db, result);
559 612
 	if(body_array!=NULL)
613
+	{
614
+		for(i= 0; i< n; i++)
615
+		{
616
+			if(body_array[i])
617
+				pkg_free(body_array[i]);
618
+		}
560 619
 		pkg_free(body_array);
620
+	}
561 621
 	return notify_body;
562 622
 
563 623
 error:
... ...
@@ -565,7 +625,19 @@ error:
565 625
 		pa_dbf.free_result(pa_db, result);
566 626
 
567 627
 	if(body_array!=NULL)
628
+	{
629
+		for(i= 0; i< n; i++)
630
+		{
631
+			if(body_array[i])
632
+				pkg_free(body_array[i]);
633
+			else
634
+				break;
635
+
636
+		}
637
+	
568 638
 		pkg_free(body_array);
639
+	}
640
+
569 641
 	return NULL;
570 642
 }
571 643
 
... ...
@@ -340,7 +340,9 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
340 340
 		if (result->n > 0)
341 341
 		{
342 342
 			n_update_cols= 0;
343
-			
343
+			pa_dbf.free_result(pa_db, result);
344
+			result= NULL;
345
+
344 346
 			if(presentity->event->etag_not_new== 0)
345 347
 			{	
346 348
 				/* generate another etag */
... ...
@@ -410,7 +412,6 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
410 412
 							" updating presence information\n");
411 413
 					goto error;
412 414
 				}
413
-				pa_dbf.free_result(pa_db, result);
414 415
 		
415 416
 				/* send 200ok */
416 417
 				if( publ_send200ok(msg, presentity->expires, cur_etag)< 0)
... ...
@@ -424,14 +425,6 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
424 425
 					pkg_free(etag.s);
425 426
 				return 0;
426 427
 			}
427
-/*
428
-			db_row_t *row = &result->rows[0];
429
-			db_val_t *row_vals = ROW_VALUES(row);
430
-			res_body.s = row_vals[body_col].val.str_val.s;	
431
-			res_body.len = row_vals[body_col].val.str_val.len;
432
-*/			
433
-			//	update_xml( &res_body, body);
434
-			/* write the new body*/
435 428
 
436 429
 			update_keys[n_update_cols] = "body";
437 430
 			update_vals[n_update_cols].type = DB_BLOB;
... ...
@@ -448,8 +441,6 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
448 441
 				goto error;
449 442
 			}
450 443
 
451
-			pa_dbf.free_result(pa_db, result);
452
-			result= NULL;
453 444
 			
454 445
 			/* send 200OK */
455 446
 			if( publ_send200ok(msg, presentity->expires, cur_etag)< 0)
... ...
@@ -472,6 +463,8 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
472 463
 		}  
473 464
 		else  /* if there isn't no registration with those 3 values */
474 465
 		{
466
+			pa_dbf.free_result(pa_db, result);
467
+			result= NULL;
475 468
 			LOG(L_DBG, "PRESENCE:update_presentity: No E_Tag match\n");
476 469
 			if (slb.reply(msg, 412, &pu_412_rpl) == -1)
477 470
 			{
... ...
@@ -479,7 +472,6 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
479 472
 					"reply\n");
480 473
 				goto error;
481 474
 			}
482
-			pa_dbf.free_result(pa_db, result);
483 475
 		}
484 476
 	}
485 477
 	return 0;
... ...
@@ -487,10 +479,7 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
487 479
 error:
488 480
 	LOG(L_ERR, "PRESENCE:update_presentity: ERROR occured\n");
489 481
 	if(result)
490
-	{
491 482
 		pa_dbf.free_result(pa_db, result);
492
-		result= NULL;
493
-	}
494 483
 	if(etag.s)
495 484
 		pkg_free(etag.s);
496 485
 
... ...
@@ -27,8 +27,9 @@ Anca-Maria Vamanu
27 27
               1.3.2. xcap_table(str)
28 28
               1.3.3. force_active (int)
29 29
 
30
-        1.4. Exported Functions
31
-        1.5. Installation
30
+        1.4. pidf_manipulation (int)
31
+        1.5. Exported Functions
32
+        1.6. Installation
32 33
 
33 34
    2. Developer's Guide
34 35
 
... ...
@@ -40,7 +41,8 @@ Anca-Maria Vamanu
40 41
    1-1. Set db_url parameter
41 42
    1-2. Set xcap_table parameter
42 43
    1-3. Set force_active parameter
43
-   1-4. PRESECE_XML tables
44
+   1-4. Set pidf_manipulation parameter
45
+   1-5. PRESECE_XML tables
44 46
    2-1. libxml_api structure
45 47
      _________________________________________________________
46 48
 
... ...
@@ -50,7 +52,7 @@ Chapter 1. User's Guide
50 52
 
51 53
    The module does specific handling for notify-subscribe events
52 54
    using xml bodies. It is used with the general event handling
53
-   module, presence. It constructs and add 3 events to it:
55
+   module, presence. It constructs and adds 3 events to it:
54 56
    presence, presence.winfo, dialog;sla.
55 57
 
56 58
    This module uses xcap_table with permission rules to deal with
... ...
@@ -122,17 +124,37 @@ modparam("presence_xml", "force_active", 1)
122 124
 ...
123 125
      _________________________________________________________
124 126
 
125
-1.4. Exported Functions
127
+1.4. pidf_manipulation (int)
128
+
129
+   Setting this parameter to 1 enables the features described in
130
+   RFC 4827. It gives the possiblity to have a permanent state
131
+   notified to the users even in the case in which the phone is
132
+   not online. The presence document is taken from the xcap
133
+   server and aggregated together with the other presence
134
+   information, if any exist, for each Notify that is sent to the
135
+   watchers. It is also possible to have information notified
136
+   even if not issuing any Publish (useful for services such as
137
+   email, SMS, MMS).
138
+
139
+   Default value is "0". 
140
+
141
+   Example 1-4. Set pidf_manipulation parameter
142
+...
143
+modparam("presence_xml", "pidf_manipulation", 1)
144
+...
145
+     _________________________________________________________
146
+
147
+1.5. Exported Functions
126 148
 
127 149
    None to be used in configuration file.
128 150
      _________________________________________________________
129 151
 
130
-1.5. Installation
152
+1.6. Installation
131 153
 
132 154
    The module requires 1 table in OpenSER database. Next SQL
133 155
    statements shows the syntax to create it.
134 156
 
135
-   Example 1-4. PRESECE_XML tables
157
+   Example 1-5. PRESECE_XML tables
136 158
 ...
137 159
 
138 160
 use openser;
... ...
@@ -132,6 +132,30 @@ modparam("presence_xml", "force_active", 1)
132 132
 		</example>
133 133
 	</section>
134 134
 </section>
135
+	<section>
136
+		<title><varname>pidf_manipulation</varname> (int)</title>
137
+		<para>
138
+		Setting this parameter to 1 enables the features described in RFC 4827.
139
+		It gives the possiblity to have a permanent state notified to the users
140
+		even in the case in which the phone is not online. The presence document
141
+		is taken from the xcap server and aggregated together with the other
142
+		presence information, if any exist, for each Notify that is sent to the
143
+		watchers. It is also possible to have information notified even if not 
144
+		issuing any Publish (useful for services such as email, SMS, MMS).
145
+		</para>
146
+		<para>
147
+		<emphasis>Default value is <quote>0</quote>.
148
+		</emphasis>
149
+		</para>
150
+		<example>
151
+		<title>Set <varname>pidf_manipulation</varname> parameter</title>
152
+		<programlisting format="linespecific">
153
+...
154
+modparam("presence_xml", "pidf_manipulation", 1)
155
+...
156
+</programlisting>
157
+		</example>
158
+	</section>
135 159
 
136 160
 <section>
137 161
 	<title>Exported Functions</title>
... ...
@@ -36,35 +36,44 @@
36 36
 #include "presence_xml.h"
37 37
 
38 38
 str* offline_nbody(str* body);
39
-str* agregate_xmls(str** body_array, int n);
39
+str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n);
40 40
 str* get_final_notify_body( subs_t *subs, str* notify_body, xmlNodePtr rule_node);
41 41
 extern int force_active;
42
+extern int pidf_manipulation;
42 43
 
43
-str* pres_agg_nbody(str** body_array, int n, int off_index)
44
+str* pres_agg_nbody(str* pres_user, str* pres_domain, str** body_array, int n, int off_index)
44 45
 {
45 46
 	str* n_body= NULL;
47
+	str* body= NULL;
48
+
49
+	if(body_array== NULL && !pidf_manipulation)
50
+		return NULL;
46 51
 
47 52
 	if(off_index>= 0)
48 53
 	{
49
-		body_array[off_index]= offline_nbody(body_array[off_index]);
54
+		body= body_array[off_index];
55
+		body_array[off_index]= offline_nbody(body);
56
+
50 57
 		if(body_array[off_index]== NULL || body_array[off_index]->s== NULL)
51 58
 		{
52 59
 			LOG(L_ERR, "PRESENCE_XML: ERROR while constructing offline body\n");
53 60
 			return NULL;
54 61
 		}
55 62
 	}
56
-	
57
-	n_body= agregate_xmls(body_array, n);
63
+
64
+	n_body= agregate_xmls(pres_user, pres_domain, body_array, n);
58 65
 	if(n_body== NULL)
59 66
 	{
60
-		LOG(L_ERR, "PRESENCE_XML: ERROR while constructing offline body\n");
67
+		LOG(L_ERR, "PRESENCE_XML: ERROR while aggregating body\n");
61 68
 	}
62 69
 
63 70
 	if(off_index>= 0)
64 71
 	{
65 72
 		xmlFree(body_array[off_index]->s);
66 73
 		pkg_free(body_array[off_index]);
74
+		body_array[off_index]= body;
67 75
 	}
76
+
68 77
 	xmlCleanupParser();
69 78
     xmlMemoryDump();
70 79
 
... ...
@@ -81,7 +90,13 @@ int pres_apply_auth(str* notify_body, subs_t* subs, str** final_nbody)
81 90
 	if(force_active)
82 91
 		return 0;
83 92
 
84
-	doc= get_xcap_tree(subs->to_user, subs->to_domain);
93
+	if(get_xcap_tree(subs->to_user, subs->to_domain, PRES_RULES, &doc)< 0)
94
+	{
95
+		LOG(L_ERR, "PRESENCE_XML:pres_apply_auth: Error while getting xcap doc"
96
+				" for pres_rules\n");
97
+		return -1;
98
+	}
99
+
85 100
 	if(doc== NULL)
86 101
 	{
87 102
 		DBG("PRESENCE_XML:pres_apply_auth: No xcap document found\n");
... ...
@@ -434,154 +449,7 @@ error:
434 449
 	return NULL;
435 450
 }	
436 451
 
437
-/*
438
-if(strncmp(subs->status.s, "active", 6)==0 && subs->reason.s
439
-					&& strncmp(subs->reason.s, "polite-block", 12)==0)
440
-				{
441
-					if(event->polite_block_nbody== NULL)
442
-					{
443
-						LOG(L_ERR, "PRESENCE_XML:notify: ERROR no plite_bloc_nbody hadling" 
444
-								" procedure defined for this event\n");
445
-						goto error;
446
-					}	
447
-					notify_body = event->polite_block_nbody(subs->to_user,subs->to_domain);
448
-					if(notify_body == NULL)
449
-					{
450
-						LOG(L_ERR, "PRESENCE_XML:notify: ERROR while building"
451
-							" polite-block body\n");
452
-						goto error;
453
-					}	
454
-
455
-
456
-
457
-if(xcap_tree!=NULL)
458
-		xmlFreeDoc(xcap_tree);
459
-
460
-
461
-
462
-int add_event(ev_t* event)
463
-{
464
-	ev_t* ev= NULL;
465
-	int size;
466
-	str str_name;
467
-	str* str_param= NULL;
468
-	char* sep= NULL;
469
-	str wipeer_name;
470
-	char buf[50];
471
-	int ret_code= 1;
472
-
473
-	str_name.s= name;
474
-	str_name.len= strlen(name);
475
-
476
-	if(param)
477
-	{
478
-		str_param= (str*)pkg_malloc(sizeof(str));
479
-		if(str_param== NULL)
480
-		{
481
-			LOG(L_ERR, "PRESENCE_XML: add_event: ERROR No more memory\n");
482
-			return -1;
483
-		}
484
-		str_param->s= param;
485
-		str_param->len= strlen(param);
486
-	}
487
-
488
-	if(contains_event(&str_name, str_param))
489
-	{
490
-		DBG("PRESENCE_XML: add_event: Found prevoius record for event\n");
491
-		ret_code= -1;
492
-		goto done;
493
-	}	
494
-	size= sizeof(ev_t)+ (str_name.len+ strlen(content_type))
495
-		*sizeof(char);
496
-
497
-	if(param)
498
-		size+= sizeof(str)+ ( 2*strlen(param) + str_name.len+ 1)* sizeof(char);
499
-
500
-	ev= (ev_t*)shm_malloc(size);
501
-	if(ev== NULL)
502
-	{
503
-		LOG(L_ERR, "PRESENCE_XML: add_event: ERROR while allocating memory\n");
504
-		ret_code= -1;
505
-		goto done;
506
-	}
507
-	memset(ev, 0, sizeof(ev_t));
508
-
509
-	size= sizeof(ev_t);
510
-	ev->name.s= (char*)ev+ size;
511
-	ev->name.len= str_name.len;
512
-	memcpy(ev->name.s, name, str_name.len);
513
-	size+= str_name.len;
514
-
515
-	if(str_param)
516
-	{	
517
-		ev->param= (str*)((char*)ev+ size);
518
-		size+= sizeof(str);
519
-		ev->param->s= (char*)ev+ size;
520
-		memcpy(ev->param->s, str_param->s, str_param->len);
521
-		ev->param->len= str_param->len;
522
-		size+= str_param->len;
523
-
524
-		ev->stored_name.s= (char*)ev+ size;
525
-		memcpy(ev->stored_name.s, name, str_name.len);
526
-		ev->stored_name.len= str_name.len;
527
-		memcpy(ev->stored_name.s+ ev->stored_name.len, ";", 1);
528
-		ev->stored_name.len+= 1;
529
-		memcpy(ev->stored_name.s+ ev->stored_name.len, str_param->s, str_param->len);
530
-		ev->stored_name.len+= str_param->len;
531
-		size+= ev->stored_name.len;
532
-	}
533
-	else
534
-	{
535
-		ev->stored_name.s= ev->name.s;
536
-		ev->stored_name.len= ev->name.len;
537
-	}	
538
-
539
-	ev->content_type.s= (char*)ev+ size;
540
-	ev->content_type.len= strlen(content_type);
541
-	memcpy(ev->content_type.s, content_type, ev->content_type.len);
542
-	size+= ev->content_type.len;
543
-	
544
-	ev->agg_body= agg_body;
545
-	
546
-	sep= strchr(name, '.');
547
-	if(sep)
548
-	{
549
-		if(strncmp(sep+1, "winfo", 5)== 0)
550
-		{	
551
-			ev->type= WINFO_TYPE;
552
-			wipeer_name.s= name;
553
-			wipeer_name.len= sep - name;
554
-			
555
-			ev->wipeer= contains_event(&wipeer_name, ev->param );
556
-		}
557
-		else
558
-		{	
559
-			ev->type= PUBL_TYPE;
560
-			wipeer_name.s= buf;
561
-			wipeer_name.len= sprintf(wipeer_name.s, "%s", name);
562
-			memcpy(wipeer_name.s+ wipeer_name.len, ".winfo", 5);
563
-			wipeer_name.len+= 5;
564
-			ev->wipeer= contains_event(&wipeer_name, ev->param);
565
-		}
566
-
567
-	}	
568
-	else
569
-		ev->type= PUBL_TYPE;
570
-
571
-	ev->next= EvList->events;
572
-	EvList->events= ev;
573
-	EvList->ev_count++;
574
-
575
-done:
576
-	if(str_param)
577
-		pkg_free(str_param);
578
-	return ret_code; 
579
-}
580
-
581
-*/
582
-
583
-str* agregate_xmls(str** body_array, int n)
584
-
452
+str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
585 453
 {
586 454
 	int i, j= 0, append ;
587 455
 	xmlNodePtr p_root= NULL, new_p_root= NULL ;
... ...
@@ -590,19 +458,40 @@ str* agregate_xmls(str** body_array, int n)
590 458
 	xmlNodePtr add_node = NULL ;
591 459
 	str *body= NULL;
592 460
 	char* id= NULL, *tuple_id = NULL;
461
+	xmlDocPtr pidf_manip_doc= NULL;
593 462
 
594
-	xml_array = (xmlDocPtr*)pkg_malloc( (n+1)*sizeof(xmlDocPtr));
595
-
463
+	xml_array = (xmlDocPtr*)pkg_malloc( (n+2)*sizeof(xmlDocPtr));
596 464
 	if(xml_array== NULL)
597 465
 	{
598 466
 	
599 467
 		LOG(L_ERR,"PRESENCE:agregate_xmls: Error while alocating memory");
600 468
 		return NULL;
601 469
 	}
602
-	
603
-	memset(xml_array, 0, (n+1)*sizeof(xmlDocPtr)) ;
470
+	memset(xml_array, 0, (n+2)*sizeof(xmlDocPtr)) ;
604 471
 
605
-	for(i=0; i<n;i++)
472
+	/* if pidf_manipulation usage is configured */
473
+	if(pidf_manipulation)
474
+	{
475
+		if( get_xcap_tree(*pres_user, *pres_domain, PIDF_MANIPULATION, &pidf_manip_doc)< 0)
476
+		{
477
+			LOG(L_ERR, "PRESENCE:agregate_xmls: Error while getting xcap tree"
478
+					" for doc_type PIDF_MANIPULATION\n");
479
+			goto error;
480
+		}	
481
+
482
+		if(pidf_manip_doc== NULL)
483
+		{
484
+			DBG( "PRESENCE:agregate_xmls: No PIDF_MANIPULATION doc for [user]= %.*s"
485
+					" [domain]= %.*s found\n", pres_user->len, pres_user->s, pres_domain->len, pres_domain->s);
486
+		}		
487
+		else
488
+		{	
489
+			xml_array[0]= pidf_manip_doc;
490
+			j++;
491
+		}
492
+	}
493
+	
494
+	for(i=0; i<n; i++)
606 495
 	{
607 496
 		if(body_array[i] == NULL )
608 497
 			continue;
... ...
@@ -617,7 +506,14 @@ str* agregate_xmls(str** body_array, int n)
617 506
 		}
618 507
 		j++;
619 508
 
620
-	} 	
509
+	} 
510
+
511
+	if(j== 0)  /* no body */
512
+	{
513
+		if(xml_array)
514
+			pkg_free(xml_array);
515
+		return NULL;
516
+	}
621 517
 
622 518
 	j--;
623 519
 	p_root = xmlDocGetNodeByName( xml_array[j], "presence", NULL);
... ...
@@ -818,227 +714,4 @@ error:
818 714
 	return NULL;
819 715
 
820 716
 }		
821
-#if 0
822
-/* not used now*/ 
823
-str* build_off_nbody(str p_user, str p_domain, str* etag)
824
-{	
825
-	xmlDocPtr doc = NULL, new_doc = NULL; 
826
-	xmlNodePtr root_node = NULL, node = NULL, p_root= NULL;
827
-	xmlNodePtr tuple_node = NULL, status_node = NULL, basic_node = NULL;
828
-
829
-	db_key_t query_cols[4];
830
-	db_op_t  query_ops[4];
831
-	db_val_t query_vals[4];
832
-	db_key_t result_cols[4];
833
-	db_res_t *result = NULL;
834
-	int body_col;
835
-	db_row_t *row ;	
836
-	db_val_t *row_vals;
837
-	int n_result_cols = 0;
838
-	int n_query_cols = 0;
839
-	str old_body ;
840
-	char * tuple_id = NULL, * entity = NULL;
841
-	str* body;
842
-	char* status = NULL;
843
-
844
-	body = (str*)pkg_malloc(sizeof(str));
845
-	if(body == NULL)
846
-	{
847
-		LOG(L_ERR,"PRESENCE: build_off_nbody:Error while allocating memory\n");
848
-		return NULL;
849
-	}
850
-	memset(body, 0, sizeof(str));
851
-
852
-	query_cols[n_query_cols] = "domain";
853
-	query_ops[n_query_cols] = OP_EQ;
854
-	query_vals[n_query_cols].type = DB_STR;
855
-	query_vals[n_query_cols].nul = 0;
856
-	query_vals[n_query_cols].val.str_val.s = p_domain.s;
857
-	query_vals[n_query_cols].val.str_val.len = p_domain.len;
858
-	n_query_cols++;
859
-
860
-	query_cols[n_query_cols] = "username";
861
-	query_ops[n_query_cols] = OP_EQ;
862
-	query_vals[n_query_cols].type = DB_STR;
863
-	query_vals[n_query_cols].nul = 0;
864
-	query_vals[n_query_cols].val.str_val.s = p_user.s;
865
-	query_vals[n_query_cols].val.str_val.len = p_user.len;
866
-	n_query_cols++;
867
-
868
-	if(etag!= NULL)
869
-	{
870
-		query_cols[n_query_cols] = "etag";
871
-		query_ops[n_query_cols] = OP_EQ;
872
-		query_vals[n_query_cols].type = DB_STR;
873
-		query_vals[n_query_cols].nul = 0;
874
-		query_vals[n_query_cols].val.str_val.s = etag->s;
875
-		query_vals[n_query_cols].val.str_val.len = etag->len;
876
-		n_query_cols++;
877
-	}
878
-
879
-	result_cols[body_col=n_result_cols++] = "body" ;
880
-
881
-	if (pxml_dbf.use_table(pxml_db, presentity_table) < 0) 
882
-	{
883
-		LOG(L_ERR, "PRESENCE: build_off_nbody: Error in use_table\n");
884
-		goto error;
885
-	}
886
-
887
-	DBG("PRESENCE: build_off_nbody: querying presentity\n");
888
-	if (pxml_dbf.query (pxml_db, query_cols, query_ops, query_vals,
889
-		 result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
890
-	{
891
-		LOG(L_ERR, "PRESENCE: build_off_nbody: Error while querying"
892
-				" presentity\n");
893
-		goto error;
894
-	}
895
-	if(result== NULL)
896
-		goto error;
897
-
898
-	if (result && result->n <=0 )
899
-	{
900
-		LOG(L_ERR, "PRESENCE: build_off_nbody:The query returned no result\n");
901
-		goto error;
902
-	}
903
-
904
-	row = &result->rows[0];
905
-	row_vals = ROW_VALUES(row);
906
-	old_body = row_vals[body_col].val.str_val ;
907
-	DBG("PRESENCE: build_off_nbody:old-body:\n%.*s\n",old_body.len, old_body.s);
908
-
909
-	doc = xmlParseMemory( old_body.s, old_body.len );
910
-	if(doc== NULL) 
911
-	{
912
-		LOG(L_ERR,"PRESENCE: build_off_nbody: ERROR while parsing"
913
-				" the xml body message\n");
914
-		goto error;
915
-	}
916
-	
917
-	p_root = xmlDocGetNodeByName(doc,"presence", NULL);
918
-	status = xmlNodeGetNodeContentByName(p_root, "basic", NULL );
919
-	if(status == NULL)
920
-	{
921
-		LOG(L_ERR, "PRESENCE:build_off_nbody: error while getting entity"
922
-				" attribute\n");
923
-		goto error;
924
-	}
925
-
926
-	if( etag && (strncmp (status,"closed", 6) == 0) )
927
-	{
928
-		DBG( "PRESENCE:build_off_nbody:The presentity status was"
929
-				" already offline\n");
930
-		goto error;
931
-	}
932
-	entity = xmlNodeGetAttrContentByName(p_root, "entity");
933
-	if(entity == NULL)
934
-	{
935
-		LOG(L_ERR, "PRESENCE:build_off_nbody: error while getting entity"
936
-				" attribute\n");
937
-		goto error;
938
-	}
939
-	for (node = p_root->children; node!=NULL; node = node->next)
940
-	{
941
-		if(xmlStrcasecmp (node->name,(unsigned char*) "tuple") == 0)
942
-		{
943
-			tuple_id = xmlNodeGetAttrContentByName(node, "id");
944
-			if(tuple_id == NULL)
945
-			{
946
-				LOG(L_ERR, "PRESENCE:build_off_nbody: error while getting"
947
-						" entity attribute\n");
948
-				goto error;
949
-			}
950
-		}	
951
-	}
952 717
 
953
-	LIBXML_TEST_VERSION;
954
-	new_doc = xmlNewDoc(BAD_CAST "1.0");
955
-	if(new_doc==0)
956
-		goto error;
957
-    root_node = xmlNewNode(NULL, BAD_CAST "presence");
958
-	if(root_node==0)
959
-		goto error;
960
-    xmlDocSetRootElement(new_doc, root_node);
961
-
962
-    xmlNewProp(root_node, BAD_CAST "xmlns",
963
-			BAD_CAST "urn:ietf:params:xml:ns:pidf");
964
-	xmlNewProp(root_node, BAD_CAST "xmlns:dm",
965
-			BAD_CAST "urn:ietf:params:xml:ns:pidf:data-model");
966
-	xmlNewProp(root_node, BAD_CAST  "xmlns:rpid",
967
-			BAD_CAST "urn:ietf:params:xml:ns:pidf:rpid" );
968
-	xmlNewProp(root_node, BAD_CAST "xmlns:c",
969
-			BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid");
970
-	xmlNewProp(root_node, BAD_CAST "entity", BAD_CAST entity);
971
-
972
-	tuple_node =xmlNewChild(root_node, NULL, BAD_CAST "tuple", NULL) ;
973
-	if( tuple_node ==NULL)
974
-	{
975
-		LOG(L_ERR, "PRESENCE:build_off_nbody: ERROR while adding child\n");
976
-		goto error;
977
-	}
978
-	xmlNewProp(tuple_node, BAD_CAST "id", BAD_CAST tuple_id);
979
-	
980
-	status_node = xmlNewChild(tuple_node, NULL, BAD_CAST "status", NULL) ;
981
-	if( status_node ==NULL)
982
-	{
983
-		LOG(L_ERR, "PRESENCE: build_off_nbody: ERROR while adding child\n");
984
-		goto error;
985
-	}
986
-
987
-	basic_node = xmlNewChild(status_node, NULL, BAD_CAST "basic",
988
-			BAD_CAST "closed") ;
989
-	if( basic_node ==NULL)
990
-	{
991
-		LOG(L_ERR, "PRESENCE:build_off_nbody: ERROR while adding child\n");
992
-		goto error;
993
-	}
994
-	xmlDocDumpFormatMemory(new_doc,(xmlChar**)(void*)&body->s, &body->len, 1);
995
-
996
-	DBG("PRESENCE: build_off_nbody:new_body:\n%.*s\n",body->len, body->s);
997
-
998
-	if(result !=NULL)
999
-		pxml_dbf.free_result(pxml_db, result);
1000
-
1001
-    /*free the document */
1002
-    xmlFreeDoc(doc);
1003
-	xmlFreeDoc(new_doc);
1004
-
1005
-    /*
1006
-     *Free the global variables that may
1007
-     *have been allocated by the parser.
1008
-     */
1009
-    xmlCleanupParser();
1010
-
1011
-    /*
1012
-     * this is to debug memory for regression tests
1013
-     */
1014
-    xmlMemoryDump();
1015
-
1016
-	xmlFree(status);
1017
-	xmlFree(entity);
1018
-	xmlFree(tuple_id);
1019
-	
1020
-    return body;
1021
-
1022
-error:
1023
-	if(doc)
1024
-		xmlFreeDoc(doc);
1025
-	if(new_doc)
1026
-		xmlFreeDoc(new_doc);
1027
-	if(result)
1028
-		pxml_dbf.free_result(pxml_db, result);
1029
-	if(body)
1030
-	{
1031
-		if(body->s)
1032
-			xmlFree(body->s);
1033
-		pkg_free(body);
1034
-	}
1035
-	if(status)
1036
-		xmlFree(status);
1037
-	if(entity)
1038
-		xmlFree(entity);
1039
-	if(tuple_id)
1040
-		xmlFree(tuple_id);
1041
-	return NULL;
1042
-
1043
-}
1044
-#endif
... ...
@@ -29,7 +29,8 @@
29 29
 #ifndef _NBODY_H_
30 30
 #define _NBODY_H_
31 31
 
32
-str* pres_agg_nbody(str** body_array, int n, int off_index);
32
+str* pres_agg_nbody(str* pres_user, str* pres_domain, str** body_array,
33
+		int n, int off_index);
33 34
 int pres_apply_auth(str* notify_body, subs_t* subs, str** final_nbody);
34 35
 
35 36
 #endif
... ...
@@ -58,7 +58,7 @@ add_event_t pres_add_event;
58 58
 char* xcap_table="xcap_xml";  
59 59
 str db_url = {0, 0};
60 60
 int force_active= 0;
61
-
61
+int pidf_manipulation= 0;
62 62
 /* SL bind */
63 63
 struct sl_binds slb;
64 64
 
... ...
@@ -81,6 +81,7 @@ static param_export_t params[]={
81 81
 	{ "db_url",					STR_PARAM, &db_url.s},
82 82
 	{ "xcap_table",				STR_PARAM, &xcap_table},
83 83
 	{ "force_active",			INT_PARAM, &force_active },
84
+	{ "pidf_manipulation",      INT_PARAM, &pidf_manipulation}, 
84 85
 	{0,0,0}
85 86
 };
86 87
 	/** module exports */
... ...
@@ -36,7 +36,7 @@ extern add_event_t pres_add_event;
36 36
 extern db_con_t *pxml_db = NULL;
37 37
 extern db_func_t pxml_dbf;
38 38
 extern int force_active;
39
-
39
+extern int pidf_manipulation;
40 40
 /* SL bind */
41 41
 extern struct sl_binds slb;
42 42
 
... ...
@@ -55,12 +55,17 @@ int pres_watcher_allowed(subs_t* subs)
55 55
 	}
56 56
 	/* else search in xcap_table */
57 57
 
58
-	doc= get_xcap_tree(subs->to_user, subs->to_domain);
58
+	if( get_xcap_tree(subs->to_user, subs->to_domain, PRES_RULES, &doc)< 0)
59
+	{
60
+		LOG(L_ERR, "PRESENCE_XML:pres_watcher_allowed: ERROR while getting xcap_tree\n");
61
+		return -1;	
62
+	}	
59 63
 	if(doc== NULL)
60 64
 	{
61 65
 		DBG("PRESENCE_XML:pres_watcher_allowed: No xcap document found\n");
62 66
 		return 0;
63 67
 	}
68
+
64 69
 	ret_code= is_watcher_allowed(subs, doc);
65 70
 	if(ret_code==0 )
66 71
 	{
... ...
@@ -128,7 +133,6 @@ xmlNodePtr get_rule_node(subs_t* subs, xmlDocPtr xcap_tree )
128 133
 					" identity tag\n");
129 134
 			goto error;
130 135
 		}	
131
-		id = NULL;
132 136
 		
133 137
 		iden_child= xmlNodeGetChildByName(identity_node, "one");
134 138
 		if(iden_child)	
... ...
@@ -139,6 +143,12 @@ xmlNodePtr get_rule_node(subs_t* subs, xmlDocPtr xcap_tree )
139 143
 					continue;
140 144
 				
141 145
 				id = xmlNodeGetAttrContentByName(node2, "id");	
146
+				if(id== NULL)
147
+				{
148
+					LOG(L_ERR, "PRESENCE_XML:get_rule_node:Error while extracting"
149
+							" attribute\n");
150
+					goto error;
151
+				}
142 152
 				if((strlen(id)== w_uri.len && 
143 153
 							(strncmp(id, w_uri.s, w_uri.len)==0)))	
144 154
 				{
... ...
@@ -319,7 +329,7 @@ int is_watcher_allowed( subs_t* subs, xmlDocPtr xcap_tree )
319 329
 }
320 330
 
321 331
 
322
-xmlDocPtr get_xcap_tree(str user, str domain)
332
+int get_xcap_tree(str user, str domain, int doc_type, xmlDocPtr* doc )
323 333
 {
324 334
 	db_key_t query_cols[5];
325 335
 	db_val_t query_vals[5];
... ...
@@ -330,6 +340,7 @@ xmlDocPtr get_xcap_tree(str user, str domain)
330 340
 	db_val_t *row_vals ;
331 341
 	str body ;
332 342
 	xmlDocPtr xcap_tree =NULL;
343
+	int err_ret= -1;
333 344
 
334 345
 	query_cols[n_query_cols] = "username";
335 346
 	query_vals[n_query_cols].type = DB_STR;
... ...
@@ -348,15 +359,17 @@ xmlDocPtr get_xcap_tree(str user, str domain)
348 359
 	query_cols[n_query_cols] = "doc_type";
349 360
 	query_vals[n_query_cols].type = DB_INT;
350 361
 	query_vals[n_query_cols].nul = 0;
351
-	query_vals[n_query_cols].val.int_val= PRES_RULES;
362
+	query_vals[n_query_cols].val.int_val= doc_type;
352 363
 	n_query_cols++;
353 364
 
354 365
 	result_cols[0] = "xcap";
355 366
 
367
+	*doc= NULL;
368
+
356 369
 	if (pxml_dbf.use_table(pxml_db, xcap_table) < 0) 
357 370
 	{
358 371
 		LOG(L_ERR, "PRESENCE_XML:get_xcap_tree: Error in use_table\n");
359
-		return NULL;
372
+		return -1;
360 373
 	}
361 374
 
362 375
 	if( pxml_dbf.query(pxml_db, query_cols, 0 , query_vals, result_cols, 
... ...
@@ -365,21 +378,24 @@ xmlDocPtr get_xcap_tree(str user, str domain)
365 378
 		LOG(L_ERR, "PRESENCE_XML:get_xcap_tree:Error while querying table xcap for"
366 379
 		" [username]=%.*s , domain=%.*s\n",user.len, user.s, domain.len,
367 380
 		domain.s);
368
-		goto error;
381
+		if(result)
382
+			pxml_dbf.free_result(pxml_db, result);
383
+		return -1;
369 384
 	}
370 385
 	if(result== NULL)
371
-		return NULL;
386
+		return -1;
372 387
 
373 388
 	if(result && result->n<=0)
374 389
 	{
375 390
 		DBG("PRESENCE_XML:get_xcap_tree:The query in table xcap for"
376 391
 				" [username]=%.*s , domain=%.*s returned no result\n",
377 392
 				user.len, user.s, domain.len, domain.s);
393
+		err_ret= 0;
378 394
 		goto error;
379 395
 	}
380 396
 	DBG("PRESENCE_XML:get_xcap_tree:The query in table xcap for"
381
-			" [username]=%.*s , domain=%.*s returned result",user.len,
382
-			user.s, domain.len, domain.s );
397
+			" [username]=%.*s , domain=%.*s , doc_type= %d returned result\n",
398
+			user.len, user.s, domain.len, domain.s, doc_type );
383 399
 
384 400
 	row = &result->rows[0];
385 401
 	row_vals = ROW_VALUES(row);
... ...
@@ -409,12 +425,14 @@ xmlDocPtr get_xcap_tree(str user, str domain)
409 425
 	if(result!=NULL)
410 426
 		pxml_dbf.free_result(pxml_db, result);
411 427
 
412
-	return xcap_tree;
428
+	*doc= xcap_tree;
429
+
430
+	return 0;
413 431
 
414 432
 error:
415 433
 	if(result!=NULL)
416 434
 		pxml_dbf.free_result(pxml_db, result);
417
-	return NULL;
435
+	return err_ret;
418 436
 }
419 437
 
420 438
 
... ...
@@ -34,13 +34,14 @@
34 34
 #include "../../str.h"
35 35
 #include "../presence/subscribe.h"
36 36
 
37
-#define PRES_RULES 1;
38
-#define RESOURCE_LIST 2;
39
-#define RLS_SERVICE 3;
37
+#define PRES_RULES        1
38
+#define RESOURCE_LIST     2
39
+#define RLS_SERVICE       3
40
+#define PIDF_MANIPULATION 4
40 41
 
41 42
 int pres_watcher_allowed(subs_t* subs);
42 43
 
43
-xmlDocPtr get_xcap_tree(str user, str domain);
44
+int get_xcap_tree(str user, str domain, int doc_type, xmlDocPtr* doc);
44 45
 xmlNodePtr get_rule_node(subs_t* subs, xmlDocPtr xcap_tree );
45 46
 
46 47
 #endif