Browse code

Merge f8a15c42bc21990966aeb47c1ac2345d199b163a into 28ce28f26ba069781ac6aee6c7ffcbd1281d7848

Tomohare authored on 28/09/2022 11:51:30 • GitHub committed on 28/09/2022 11:51:30
Showing 21 changed files
... ...
@@ -11,6 +11,7 @@
11 11
 <!ENTITY xcap_uri_len "255">
12 12
 <!ENTITY id_len "64">
13 13
 <!ENTITY table_id_len "10">
14
+<!ENTITY group_len "128">
14 15
 <!ENTITY hf_len "255">
15 16
 <!ENTITY contact_len "512">
16 17
 <!ENTITY long_hf_len "512">
... ...
@@ -9,7 +9,7 @@
9 9
 
10 10
 <table id="speed_dial" xmlns:db="http://docbook.org/ns/docbook">
11 11
     <name>speed_dial</name>
12
-    <version>2</version>
12
+    <version>3</version>
13 13
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
14 14
     <description>
15 15
 		<db:para>
... ...
@@ -100,6 +100,14 @@
100 100
         <description>Description</description>
101 101
     </column>
102 102
 
103
+    <column>
104
+        <name>group_id</name>
105
+        <type>string</type>
106
+        <size>&group_len;</size>
107
+        <default/>
108
+        <description>Group ID</description>
109
+    </column>
110
+
103 111
     <index>
104 112
         <name>speed_dial_idx</name>
105 113
         <colref linkend="username"/>
... ...
@@ -249,6 +249,41 @@ if(uri=~"sip:[0-9]{2}@.*")
249 249
 if(uri=~"sip:[0-9]{2}@.*")
250 250
 	sd_lookup("speed_dial", "sip:$au@$fd");
251 251
 ...
252
+</programlisting>
253
+		</example>
254
+	</section>
255
+	<section>
256
+		<title>
257
+		<function moreinfo="none">sd_lookup_group(table , group)</function>
258
+		</title>
259
+		<para>
260
+		The function lookups the short dial number from the group defined in the 'table' and replaces the R-URI with associated address.
261
+		</para>
262
+		<para>Meaning of the parameters is as follows:</para>
263
+		<itemizedlist>
264
+		<listitem>
265
+			<para><emphasis>table</emphasis> - The name of the table storing the
266
+			speed dial records.
267
+			</para>
268
+		</listitem>
269
+		<listitem>
270
+			<para><emphasis>group</emphasis> - The group that has the
271
+			short dialing codes.
272
+			</para>
273
+		</listitem>
274
+		</itemizedlist>
275
+		<para>
276
+		This function can be used from REQUEST_ROUTE.
277
+		</para>
278
+		<example>
279
+		<title><function>sd_lookup_group</function> usage</title>
280
+		<programlisting format="linespecific">
281
+...
282
+# 'speed_dial' is the default table name created by kamailio db script
283
+# Using 3 digits to differentiate from the simple lookup 
284
+if(uri=~"sip:[0-9]{3}@.*")
285
+	sd_lookup_group("speed_dial", "group_id");
286
+...
252 287
 </programlisting>
253 288
 		</example>
254 289
 	</section>
... ...
@@ -58,6 +58,47 @@ static inline int rewrite_ruri(struct sip_msg* _m, char* _s)
58 58
 	return 0;
59 59
 }
60 60
 
61
+/**
62
+ *
63
+ */
64
+int process_result(db1_res_t* db_res, str *ret, char *buffer)
65
+{
66
+	ret->s=buffer+4;
67
+	if (RES_ROW_N(db_res) > 1)
68
+	{
69
+		LM_WARN("too many similar results, returning first result\n");
70
+	}
71
+	switch(RES_ROWS(db_res)[0].values[0].type)
72
+	{
73
+		case DB1_STRING:
74
+			strcpy(ret->s,
75
+				(char*)RES_ROWS(db_res)[0].values[0].val.string_val);
76
+			ret->len = strlen(ret->s);
77
+		break;
78
+		case DB1_STR:
79
+			strncpy(ret->s,
80
+				(char*)RES_ROWS(db_res)[0].values[0].val.str_val.s,
81
+				RES_ROWS(db_res)[0].values[0].val.str_val.len);
82
+			ret->len = RES_ROWS(db_res)[0].values[0].val.str_val.len;
83
+			ret->s[ret->len] = '\0';
84
+		break;
85
+		case DB1_BLOB:
86
+			strncpy(ret->s,
87
+				(char*)RES_ROWS(db_res)[0].values[0].val.blob_val.s,
88
+				RES_ROWS(db_res)[0].values[0].val.blob_val.len);
89
+			ret->len = RES_ROWS(db_res)[0].values[0].val.blob_val.len;
90
+			ret->s[ret->len] = '\0';
91
+		break;
92
+		default:
93
+			LM_ERR("unknown type of DB new_uri column\n");
94
+			if (db_funcs.free_result(db_handle, db_res) < 0) {
95
+				LM_DBG("failed to free result of query\n");
96
+			}
97
+			return -1;
98
+	}
99
+	return 1;
100
+}
101
+
61 102
 /**
62 103
  *
63 104
  */
... ...
@@ -175,34 +216,129 @@ int sd_lookup_owner(sip_msg_t* _msg, str* stable, str* sowner)
175 216
 		return -1;
176 217
 	}
177 218
 
178
-	user_s.s = useruri_buf+4;
179
-	switch(RES_ROWS(db_res)[0].values[0].type)
219
+	if(process_result(db_res, &user_s, useruri_buf) < 0)
180 220
 	{
181
-		case DB1_STRING:
182
-			strcpy(user_s.s,
183
-				(char*)RES_ROWS(db_res)[0].values[0].val.string_val);
184
-			user_s.len = strlen(user_s.s);
185
-		break;
186
-		case DB1_STR:
187
-			strncpy(user_s.s,
188
-				(char*)RES_ROWS(db_res)[0].values[0].val.str_val.s,
189
-				RES_ROWS(db_res)[0].values[0].val.str_val.len);
190
-			user_s.len = RES_ROWS(db_res)[0].values[0].val.str_val.len;
191
-			user_s.s[user_s.len] = '\0';
192
-		break;
193
-		case DB1_BLOB:
194
-			strncpy(user_s.s,
195
-				(char*)RES_ROWS(db_res)[0].values[0].val.blob_val.s,
196
-				RES_ROWS(db_res)[0].values[0].val.blob_val.len);
197
-			user_s.len = RES_ROWS(db_res)[0].values[0].val.blob_val.len;
198
-			user_s.s[user_s.len] = '\0';
199
-		break;
200
-		default:
201
-			LM_ERR("unknown type of DB new_uri column\n");
202
-			if (db_funcs.free_result(db_handle, db_res) < 0) {
203
-				LM_DBG("failed to free result of query\n");
204
-			}
205
-			goto err_server;
221
+		LM_DBG("failed to process result\n");
222
+		return -1;
223
+	}
224
+
225
+	/* check 'sip:' */
226
+	if(user_s.len<4 || strncmp(user_s.s, "sip:", 4))
227
+	{
228
+		memcpy(useruri_buf, "sip:", 4);
229
+		user_s.s -= 4;
230
+		user_s.len += 4;
231
+	}
232
+
233
+	/**
234
+	 * Free the result because we don't need it anymore
235
+	 */
236
+	if (db_funcs.free_result(db_handle, db_res) < 0) {
237
+		LM_DBG("failed to free result of query\n");
238
+	}
239
+
240
+	/* set the URI */
241
+	LM_DBG("URI of sd from R-URI [%s]\n", user_s.s);
242
+	if(rewrite_ruri(_msg, user_s.s)<0)
243
+	{
244
+		LM_ERR("failed to replace the R-URI\n");
245
+		goto err_server;
246
+	}
247
+
248
+	return 1;
249
+
250
+err_server:
251
+	return -1;
252
+}
253
+
254
+/**
255
+ * 
256
+ */
257
+int sd_lookup_group(sip_msg_t* _msg, str* stable, str* sgroup)
258
+{
259
+	str user_s, table_s;
260
+	int nr_keys;
261
+	db_key_t db_keys[3];
262
+	db_val_t db_vals[3];
263
+	db_key_t db_cols[1];
264
+	db1_res_t* db_res = NULL;
265
+
266
+	if(stable==NULL || stable->s==NULL || stable->len<=0)
267
+	{
268
+		LM_ERR("invalid table parameter");
269
+		goto err_server;
270
+	}
271
+	table_s = *stable;
272
+
273
+	if(sgroup==NULL || sgroup->s==NULL || sgroup->len<=0)
274
+	{
275
+		LM_ERR("invalid group parameter");
276
+		goto err_server;
277
+	}
278
+
279
+	/* init */
280
+	nr_keys = 0;
281
+	db_cols[0]=&new_uri_column;
282
+
283
+	/* take sd from r-uri */
284
+	if (parse_sip_msg_uri(_msg) < 0)
285
+	{
286
+		LM_ERR("failed to parsing Request-URI\n");
287
+		goto err_server;
288
+	}
289
+
290
+	db_keys[nr_keys]=&sd_user_column;
291
+	db_vals[nr_keys].type = DB1_STR;
292
+	db_vals[nr_keys].nul = 0;
293
+	db_vals[nr_keys].val.str_val.s = _msg->parsed_uri.user.s;
294
+	db_vals[nr_keys].val.str_val.len = _msg->parsed_uri.user.len;
295
+	nr_keys++;
296
+
297
+	if(use_domain>=2)
298
+	{
299
+		db_keys[nr_keys]=&sd_domain_column;
300
+		db_vals[nr_keys].type = DB1_STR;
301
+		db_vals[nr_keys].nul = 0;
302
+		db_vals[nr_keys].val.str_val.s = _msg->parsed_uri.host.s;
303
+		db_vals[nr_keys].val.str_val.len = _msg->parsed_uri.host.len;
304
+
305
+		if (dstrip_s.s!=NULL && dstrip_s.len>0
306
+			&& dstrip_s.len<_msg->parsed_uri.host.len
307
+			&& strncasecmp(_msg->parsed_uri.host.s,dstrip_s.s,dstrip_s.len)==0)
308
+		{
309
+			db_vals[nr_keys].val.str_val.s   += dstrip_s.len;
310
+			db_vals[nr_keys].val.str_val.len -= dstrip_s.len;
311
+		}
312
+		nr_keys++;
313
+	}
314
+
315
+
316
+	db_keys[nr_keys]=&group_column;
317
+	db_vals[nr_keys].type = DB1_STR;
318
+	db_vals[nr_keys].nul = 0;
319
+	db_vals[nr_keys].val.str_val = *sgroup;
320
+	nr_keys++;
321
+
322
+	db_funcs.use_table(db_handle, &table_s);
323
+	if(db_funcs.query(db_handle, db_keys, NULL, db_vals, db_cols,
324
+		nr_keys /*no keys*/, 1 /*no cols*/, NULL, &db_res)!=0 || db_res==NULL)
325
+	{
326
+		LM_ERR("failed to query database\n");
327
+		goto err_server;
328
+	}
329
+
330
+	if(RES_ROW_N(db_res) <= 0 || RES_ROWS(db_res)[0].values[0].nul != 0) {
331
+		LM_DBG("no sip address found for R-URI\n");
332
+		if(db_funcs.free_result(db_handle, db_res) < 0) {
333
+			LM_DBG("failed to free result of query\n");
334
+		}
335
+		goto err_server;
336
+	}
337
+
338
+	if(process_result(db_res, &user_s, useruri_buf) < 0)
339
+	{
340
+		LM_DBG("failed to process result\n");
341
+		goto err_server;
206 342
 	}
207 343
 
208 344
 	/* check 'sip:' */
... ...
@@ -259,3 +395,24 @@ int w_sd_lookup(struct sip_msg* _msg, char* _table, char* _owner)
259 395
 
260 396
 	return sd_lookup_owner(_msg, &table_s, NULL);
261 397
 }
398
+
399
+/**
400
+ *
401
+ */
402
+int w_sd_lookup_group(struct sip_msg* _msg, char* _table, char* _group)
403
+{
404
+	str table_s, group_s;
405
+
406
+	if(_table==NULL || fixup_get_svalue(_msg, (gparam_p)_table, &table_s)!=0)
407
+	{
408
+		LM_ERR("invalid table parameter");
409
+		return -1;
410
+	}
411
+
412
+	if(_group==NULL ||fixup_get_svalue(_msg, (gparam_p)_group, &group_s)!=0)
413
+	{
414
+		LM_ERR("invalid group parameter");
415
+		return -1;
416
+	}
417
+	return sd_lookup_group(_msg, &table_s, &group_s);
418
+}
... ...
@@ -27,6 +27,8 @@
27 27
 #include "../../core/parser/msg_parser.h"
28 28
 
29 29
 int w_sd_lookup(struct sip_msg* _msg, char* _table, char* _owner);
30
+int w_sd_lookup_group(struct sip_msg* _msg, char* _table, char* _group);
30 31
 int sd_lookup_owner(struct sip_msg* _msg, str* _stable, str* _sowner);
32
+int sd_lookup_group(struct sip_msg* _msg, str* _stable, str* _sgroup);
31 33
 
32 34
 #endif /* _SDLOOKUP_H_ */
... ...
@@ -54,6 +54,7 @@ str domain_column    = str_init("domain");
54 54
 str sd_user_column   = str_init("sd_username");
55 55
 str sd_domain_column = str_init("sd_domain");
56 56
 str new_uri_column   = str_init("new_uri");
57
+str group_column     = str_init("group_id");
57 58
 int use_domain       = 0;
58 59
 static str domain_prefix    = {NULL, 0};
59 60
 
... ...
@@ -70,6 +71,8 @@ static cmd_export_t cmds[] = {
70 71
 		REQUEST_ROUTE},
71 72
 	{"sd_lookup", (cmd_function)w_sd_lookup, 2, fixup_spve_spve, 0,
72 73
 		REQUEST_ROUTE},
74
+	{"sd_lookup_group", (cmd_function)w_sd_lookup_group, 2, fixup_spve_spve, 0,
75
+		REQUEST_ROUTE},
73 76
 	{0, 0, 0, 0, 0, 0}
74 77
 };
75 78
 
... ...
@@ -180,6 +183,11 @@ static sr_kemi_t sr_kemi_speeddial_exports[] = {
180 183
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
181 184
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
182 185
 	},
186
+	{ str_init("speeddial"), str_init("lookup_group"),
187
+		SR_KEMIP_INT, sd_lookup_group,
188
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
189
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
190
+	},
183 191
 
184 192
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
185 193
 };
... ...
@@ -30,13 +30,14 @@
30 30
 
31 31
 /* Module parameters variables */
32 32
 
33
-extern str user_column;     /* 'username' column name */
34
-extern str domain_column;   /* 'domain' column name */
35
-extern str sd_user_column;     /* 'sd_username' column name */
36
-extern str sd_domain_column;   /* 'sd_domain' column name */
37
-extern str new_uri_column;   /* 'new_uri' column name */
38
-extern int   use_domain;      /* use or not the domain for sd lookup */
39
-extern str   dstrip_s;
33
+extern str user_column;       /* 'username' column name */
34
+extern str domain_column;     /* 'domain' column name */
35
+extern str sd_user_column;    /* 'sd_username' column name */
36
+extern str sd_domain_column;  /* 'sd_domain' column name */
37
+extern str new_uri_column;    /* 'new_uri' column name */
38
+extern str group_column;      /* 'group' column name */
39
+extern int use_domain;        /* use or not the domain for sd lookup */
40
+extern str dstrip_s;
40 41
 
41 42
 extern db_func_t db_funcs;    /* Database functions */
42 43
 extern db1_con_t* db_handle;   /* Database connection handle */
... ...
@@ -1,5 +1,5 @@
1 1
 METADATA_COLUMNS
2
-id(int) username(str) domain(str) sd_username(str) sd_domain(str) new_uri(str) fname(str) lname(str) description(str)
2
+id(int) username(str) domain(str) sd_username(str) sd_domain(str) new_uri(str) fname(str) lname(str) description(str) group_id(str)
3 3
 METADATA_KEY
4 4
 1 2 
5 5
 METADATA_READONLY
... ...
@@ -7,4 +7,4 @@ METADATA_READONLY
7 7
 METADATA_LOGFLAGS
8 8
 0
9 9
 METADATA_DEFAULTS
10
-NIL|''|''|''|''|''|''|''|''
10
+NIL|''|''|''|''|''|''|''|''|''
... ...
@@ -115,7 +115,7 @@ silo|8
115 115
 sip_trace|
116 116
 sip_trace|4
117 117
 speed_dial|
118
-speed_dial|2
118
+speed_dial|3
119 119
 subscriber|
120 120
 subscriber|7
121 121
 topos_d|
... ...
@@ -1,2 +1,2 @@
1
-id/int,username/string,domain/string,sd_username/string,sd_domain/string,new_uri/string,fname/string,lname/string,description/string,
2
-2
1
+id/int,username/string,domain/string,sd_username/string,sd_domain/string,new_uri/string,fname/string,lname/string,description/string,group_id/string,
2
+3
... ...
@@ -8,8 +8,9 @@ CREATE TABLE speed_dial (
8 8
     fname VARCHAR(64) DEFAULT '' NOT NULL,
9 9
     lname VARCHAR(64) DEFAULT '' NOT NULL,
10 10
     description VARCHAR(64) DEFAULT '' NOT NULL,
11
+    group_id VARCHAR(128) DEFAULT '' NOT NULL,
11 12
     CONSTRAINT speed_dial_speed_dial_idx UNIQUE (username, domain, sd_domain, sd_username)
12 13
 );
13 14
 
14
-INSERT INTO version (table_name, table_version) values ('speed_dial','2');
15
+INSERT INTO version (table_name, table_version) values ('speed_dial','3');
15 16
 
... ...
@@ -1 +1 @@
1
-id(int,auto) username(string) domain(string) sd_username(string) sd_domain(string) new_uri(string) fname(string) lname(string) description(string) 
1
+id(int,auto) username(string) domain(string) sd_username(string) sd_domain(string) new_uri(string) fname(string) lname(string) description(string) group_id(string) 
... ...
@@ -52,7 +52,7 @@ id(int,auto) table_name(string) table_version(int)
52 52
 0:secfilter:1
53 53
 0:silo:8
54 54
 0:sip_trace:4
55
-0:speed_dial:2
55
+0:speed_dial:3
56 56
 0:subscriber:7
57 57
 0:topos_d:2
58 58
 0:topos_t:2
... ...
@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "speed_dial",
3
-  "version": 2,
3
+  "version": 3,
4 4
   "columns": [
5 5
     "id": {
6 6
       "type": "int",
... ...
@@ -46,6 +46,11 @@
46 46
       "type": "string",
47 47
       "default": "",
48 48
       "null": false
49
+    },
50
+    "group_id": {
51
+      "type": "string",
52
+      "default": "",
53
+      "null": false
49 54
     }
50 55
   ]
51 56
 }
52 57
\ No newline at end of file
... ...
@@ -52,7 +52,7 @@ db.getCollection("version").insert({ table_name: "sca_subscriptions", table_vers
52 52
 db.getCollection("version").insert({ table_name: "secfilter", table_version: NumberInt(1) });
53 53
 db.getCollection("version").insert({ table_name: "silo", table_version: NumberInt(8) });
54 54
 db.getCollection("version").insert({ table_name: "sip_trace", table_version: NumberInt(4) });
55
-db.getCollection("version").insert({ table_name: "speed_dial", table_version: NumberInt(2) });
55
+db.getCollection("version").insert({ table_name: "speed_dial", table_version: NumberInt(3) });
56 56
 db.getCollection("version").insert({ table_name: "subscriber", table_version: NumberInt(7) });
57 57
 db.getCollection("version").insert({ table_name: "topos_d", table_version: NumberInt(2) });
58 58
 db.getCollection("version").insert({ table_name: "topos_t", table_version: NumberInt(2) });
... ...
@@ -8,8 +8,9 @@ CREATE TABLE `speed_dial` (
8 8
     `fname` VARCHAR(64) DEFAULT '' NOT NULL,
9 9
     `lname` VARCHAR(64) DEFAULT '' NOT NULL,
10 10
     `description` VARCHAR(64) DEFAULT '' NOT NULL,
11
+    `group_id` VARCHAR(128) DEFAULT '' NOT NULL,
11 12
     CONSTRAINT speed_dial_idx UNIQUE (`username`, `domain`, `sd_domain`, `sd_username`)
12 13
 );
13 14
 
14
-INSERT INTO version (table_name, table_version) values ('speed_dial','2');
15
+INSERT INTO version (table_name, table_version) values ('speed_dial','3');
15 16
 
... ...
@@ -8,6 +8,7 @@ CREATE TABLE speed_dial (
8 8
     fname VARCHAR2(64) DEFAULT '',
9 9
     lname VARCHAR2(64) DEFAULT '',
10 10
     description VARCHAR2(64) DEFAULT '',
11
+    group_id VARCHAR2(128) DEFAULT '',
11 12
     CONSTRAINT speed_dial_speed_dial_idx  UNIQUE (username, domain, sd_domain, sd_username)
12 13
 );
13 14
 
... ...
@@ -19,5 +20,5 @@ END speed_dial_tr;
19 20
 /
20 21
 BEGIN map2users('speed_dial'); END;
21 22
 /
22
-INSERT INTO version (table_name, table_version) values ('speed_dial','2');
23
+INSERT INTO version (table_name, table_version) values ('speed_dial','3');
23 24
 
... ...
@@ -8,8 +8,9 @@ CREATE TABLE speed_dial (
8 8
     fname VARCHAR(64) DEFAULT '' NOT NULL,
9 9
     lname VARCHAR(64) DEFAULT '' NOT NULL,
10 10
     description VARCHAR(64) DEFAULT '' NOT NULL,
11
+    group_id VARCHAR(128) DEFAULT '' NOT NULL,
11 12
     CONSTRAINT speed_dial_speed_dial_idx UNIQUE (username, domain, sd_domain, sd_username)
12 13
 );
13 14
 
14
-INSERT INTO version (table_name, table_version) values ('speed_dial','2');
15
+INSERT INTO version (table_name, table_version) values ('speed_dial','3');
15 16
 
... ...
@@ -219,6 +219,17 @@
219 219
 		<column><field>attrs</field><type>DB1_STR</type></column>
220 220
 		<column><field>description</field><type>DB1_STR</type></column>
221 221
 	</db_table>
222
+	<!-- Declaration of domainpolicy table-->
223
+	<db_table id="domainpolicy">
224
+		<table_name>domainpolicy</table_name>
225
+		<db_url_id>mysql</db_url_id>
226
+		<column><field>id</field><type>DB1_INT</type></column>
227
+		<column><field>rule</field><type>DB1_STR</type></column>
228
+		<column><field>type</field><type>DB1_STR</type></column>
229
+		<column><field>att</field><type>DB1_STR</type></column>
230
+		<column><field>val</field><type>DB1_STR</type></column>
231
+		<column><field>description</field><type>DB1_STR</type></column>
232
+	</db_table>
222 233
 	<!-- Declaration of domain table-->
223 234
 	<db_table id="domain">
224 235
 		<table_name>domain</table_name>
... ...
@@ -239,17 +250,6 @@
239 250
 		<column><field>value</field><type>DB1_STR</type></column>
240 251
 		<column><field>last_modified</field><type>DB1_DATETIME</type></column>
241 252
 	</db_table>
242
-	<!-- Declaration of domainpolicy table-->
243
-	<db_table id="domainpolicy">
244
-		<table_name>domainpolicy</table_name>
245
-		<db_url_id>mysql</db_url_id>
246
-		<column><field>id</field><type>DB1_INT</type></column>
247
-		<column><field>rule</field><type>DB1_STR</type></column>
248
-		<column><field>type</field><type>DB1_STR</type></column>
249
-		<column><field>att</field><type>DB1_STR</type></column>
250
-		<column><field>val</field><type>DB1_STR</type></column>
251
-		<column><field>description</field><type>DB1_STR</type></column>
252
-	</db_table>
253 253
 	<!-- Declaration of dr_gateways table-->
254 254
 	<db_table id="dr_gateways">
255 255
 		<table_name>dr_gateways</table_name>
... ...
@@ -753,6 +753,7 @@
753 753
 		<column><field>fname</field><type>DB1_STR</type></column>
754 754
 		<column><field>lname</field><type>DB1_STR</type></column>
755 755
 		<column><field>description</field><type>DB1_STR</type></column>
756
+		<column><field>group_id</field><type>DB1_STR</type></column>
756 757
 	</db_table>
757 758
 	<!-- Declaration of version table-->
758 759
 	<db_table id="version">
... ...
@@ -3937,6 +3938,7 @@
3937 3938
 				<col><field>fname</field></col>
3938 3939
 				<col><field>lname</field></col>
3939 3940
 				<col><field>description</field></col>
3941
+				<col><field>group_id</field></col>
3940 3942
 			</query_cols>
3941 3943
 		</cmd>
3942 3944
 		<cmd><cmd_name>add</cmd_name>
... ...
@@ -3951,6 +3953,7 @@
3951 3953
 				<col><field>fname</field></col>
3952 3954
 				<col><field>lname</field></col>
3953 3955
 				<col><field>description</field></col>
3956
+				<col><field>group_id</field></col>
3954 3957
 			</query_cols>
3955 3958
 		</cmd>
3956 3959
 		<cmd><cmd_name>update</cmd_name>
... ...
@@ -3968,6 +3971,7 @@
3968 3971
 				<col><field>fname</field></col>
3969 3972
 				<col><field>lname</field></col>
3970 3973
 				<col><field>description</field></col>
3974
+				<col><field>group_id</field></col>
3971 3975
 			</query_cols>
3972 3976
 		</cmd>
3973 3977
 		<cmd><cmd_name>delete</cmd_name>
... ...
@@ -13,6 +13,7 @@
13 13
 				<col><field>fname</field></col>
14 14
 				<col><field>lname</field></col>
15 15
 				<col><field>description</field></col>
16
+				<col><field>group_id</field></col>
16 17
 			</query_cols>
17 18
 		</cmd>
18 19
 		<cmd><cmd_name>add</cmd_name>
... ...
@@ -27,6 +28,7 @@
27 28
 				<col><field>fname</field></col>
28 29
 				<col><field>lname</field></col>
29 30
 				<col><field>description</field></col>
31
+				<col><field>group_id</field></col>
30 32
 			</query_cols>
31 33
 		</cmd>
32 34
 		<cmd><cmd_name>update</cmd_name>
... ...
@@ -44,6 +46,7 @@
44 46
 				<col><field>fname</field></col>
45 47
 				<col><field>lname</field></col>
46 48
 				<col><field>description</field></col>
49
+				<col><field>group_id</field></col>
47 50
 			</query_cols>
48 51
 		</cmd>
49 52
 		<cmd><cmd_name>delete</cmd_name>
... ...
@@ -11,4 +11,5 @@
11 11
 		<column><field>fname</field><type>DB1_STR</type></column>
12 12
 		<column><field>lname</field><type>DB1_STR</type></column>
13 13
 		<column><field>description</field><type>DB1_STR</type></column>
14
+		<column><field>group_id</field><type>DB1_STR</type></column>
14 15
 	</db_table>