Browse code

*** empty log message ***

Bogdan-Andrei Iancu authored on 14/08/2002 16:24:37
Showing 15 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,146 @@
1
+#ifndef _CPL_TREE_DEFINITION_H
2
+#define _CPL_TREE_DEFINITION_H
3
+
4
+
5
+
6
+#define              CPL_NODE   1
7
+#define         INCOMING_NODE   2
8
+#define         OUTGOING_NODE   3
9
+#define        ANCILLARY_NODE   4
10
+#define        SUBACTION_NODE   5
11
+#define   ADDRESS_SWITCH_NODE   6
12
+#define          ADDRESS_NODE   7
13
+#define             BUSY_NODE   8
14
+#define          DEFAULT_NODE   9
15
+#define          FAILURE_NODE  10
16
+#define              LOG_NODE  11
17
+#define           LOOKUP_NODE  12
18
+#define         LOCATION_NODE  13
19
+#define         LANGUAGE_NODE  14
20
+#define  LANGUAGE_SWITCH_NODE  15
21
+#define             MAIL_NODE  16
22
+#define         NOTFOUND_NODE  17
23
+#define         NOANSWER_NODE  18
24
+#define            PROXY_NODE  19
25
+#define         PRIORITY_NODE  20
26
+#define  PRIORITY_SWITCH_NODE  21
27
+#define           REJECT_NODE  22
28
+#define         REDIRECT_NODE  23
29
+#define      REDIRECTION_NODE  24
30
+#define  REMOVE_LOCATION_NODE  25
31
+#define              SUB_NODE  26
32
+#define          SUCCESS_NODE  27
33
+#define           STRING_NODE  28
34
+#define    STRING_SWITCH_NODE  29
35
+#define             TIME_NODE  30
36
+#define      TIME_SWITCH_NODE  31
37
+#define        OTHERWISE_NODE  32
38
+
39
+
40
+
41
+/* attributs and values fro ADDRESS-SWITCH node */
42
+#define  FIELD_ATTR                  0       /*shared with STRING_SWITCH*/
43
+#define  SUBFIELD_ATTR               1
44
+#define  ORIGIN_VAL                  0
45
+#define  DESTINATION_VAL             1
46
+#define  ORIGINAL_DESTINATION_VAL    2
47
+#define  ADDRESS_TYPE_VAL            0
48
+#define  USER_VAL                    1
49
+#define  HOST_VAL                    2
50
+#define  PORT_VAL                    3
51
+#define  TEL_VAL                     4
52
+#define  DISPLAY_VAL                 5
53
+
54
+/* attributs and values for ADDRESS node */
55
+#define  IS_ATTR                     0    /*shared with STRING*/
56
+#define  CONTAINS_ATTR               1    /*shared with STRING*/
57
+#define  SUBDOMAIN_OF_ATTR           2
58
+
59
+/* attributs and values for STRING-SWITCH node */
60
+#define  SUBJECT_VAL                 0
61
+#define  ORGANIZATION_VAL            1
62
+#define  USER_AGENT_VAL              2
63
+#define  DISPALY_VAL                 3
64
+
65
+/* attributs and values for LANGUAGE node */
66
+#define  MATCHES_ATTR                0
67
+
68
+/* attributs and values for TIME-SWITCH node */
69
+#define  TZID_ATTR                   0
70
+#define  TZURL_ATTR                  1
71
+
72
+/* attributs and values for TIME node */
73
+#define  DTSTART_ATTR                0
74
+#define  DTEND_ATTR                  1
75
+#define  DURATION_ATTR               2
76
+#define  FREQ_ATTR                   3
77
+#define  INTERVAL_ATTR               4
78
+#define  UNTIL_ATTR                  5
79
+#define  COUNT_ATTR                  6
80
+#define  BYSECOND_ATTR               7
81
+#define  BYMINUTE_ATTR               8
82
+#define  BYHOUR_ATTR                 9
83
+#define  BYDAY_ATTR                 10
84
+#define  BYMONTHDAY_ATTR            11
85
+#define  BYYEARDAY_ATTR             12
86
+#define  BYWEEKNO_ATTR              13
87
+#define  BYMONTH_ATTR               14
88
+#define  WKST_ATTR                  15
89
+#define  BYSETPOS_ATTR              16
90
+
91
+/* attributs and values for PRIORITY node */
92
+#define  LESS_ATTR                   0
93
+#define  GREATER_ATTR                1
94
+#define  EQUAL_ATTR                  2
95
+#define  EMERGENCY_VAL               0
96
+#define  URGENT_VAL                  1
97
+#define  NORMAL_VAL                  2
98
+#define  NON_URGENT_VAL              3
99
+
100
+/* attributs and values for LOCATION node */
101
+#define  URL_ATTR                    0
102
+#define  PRIORITY_ATTR               1
103
+#define  CLEAR_ATTR                  2    /*shared with LOOKUP node*/
104
+#define  NO_VAL                      0    /*shared with LOOKUP node*/
105
+#define  YES_VAL                     1    /*shared with LOOKUP node*/
106
+
107
+/* attributs and values for LOOKUP node */
108
+#define  SOURCE_ATTR                 0
109
+#define  TIMEOUT_ATTR                1
110
+#define  USE_ATTR                    2
111
+#define  IGNORE_ATTR                 3
112
+
113
+/* attributs and values for REMOVE_LOCATION node */
114
+#define  LOCATION_ATTR               0
115
+#define  PARAM_ATTR                  1
116
+#define  VALUE_ATTR                  2
117
+
118
+/* attributs and values for PROXY node */
119
+#define  RECURSE_ATTR                0
120
+#define  ORDERING_ATTR               1
121
+#define  PARALLEL_VAL                0
122
+#define  SEQUENTIAL_VAL              1
123
+#define  FIRSTONLY_VAL               2
124
+
125
+/* attributs and values for REDIRECT node */
126
+#define  PERMANENT_ATTR              0
127
+
128
+/* attributs and values for REJECT node */
129
+#define  STATUS_ATTR                 0
130
+#define  REASON_ATTR                 1
131
+
132
+/* attributs and values for LOG node */
133
+#define  NAME_ATTR                   0
134
+#define  COMMENT_ATTR                1
135
+
136
+
137
+
138
+
139
+#define      NODE_TYPE(_buf)        ( *(_buf) )
140
+#define      NR_OF_KIDS(_buf)       ( *((_buf)+1) )
141
+#define      KID_OFFSET(_buf,_nr)   ( *((unsigned short*)((_buf)+2+2*(_nr))) )
142
+#define      ATTR_PTR(_buf)         ( (_buf)+2+2*NR_OF_KIDS(_buf)+1 )
143
+#define      NR_OF_ATTR(_buf)       ( *((_buf)+2+2*NR_OF_KIDS(_buf)) )
144
+
145
+
146
+#endif
0 147
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+# $Id$
2
+#
3
+# example module makefile
4
+#
5
+# 
6
+# WARNING: do not run this directly, it should be run by the master Makefile
7
+
8
+auto_gen=
9
+NAME=cpl-c.so
10
+LIBS= -L/usr/lib -lxml
11
+
12
+include ../../Makefile.modules
0 13
new file mode 100644
... ...
@@ -0,0 +1,185 @@
1
+/*
2
+ * $Id$
3
+ */
4
+
5
+#include <stdio.h>
6
+#include <string.h>
7
+
8
+#include "../../sr_module.h"
9
+#include "../../str.h"
10
+#include "../../msg_translator.h"
11
+#include "../../data_lump_rpl.h"
12
+#include "../../dprint.h"
13
+#include "../../error.h"
14
+#include "../../ut.h"
15
+#include "../../globals.h"
16
+#include "cpl_parser.h"
17
+
18
+
19
+//char           *resp_buf;
20
+//char           *cpl_server = "127.0.0.1";
21
+//unsigned int   cpl_port = 18011;
22
+//unsigned int   resp_len;
23
+//unsigned int   resp_code;
24
+
25
+char *DB_URL       = 0;
26
+char *DB_TABLE     = 0;
27
+int  cache_timeout = 5;
28
+
29
+
30
+
31
+
32
+static int cpl_run_script(struct sip_msg* msg, char* str, char* str2);
33
+static int cpl_is_response_accept(struct sip_msg* msg, char* str, char* str2);
34
+static int cpl_is_response_reject(struct sip_msg* msg, char* str, char* str2);
35
+static int cpl_is_response_redirect(struct sip_msg* msg, char* str, char* str2);
36
+static int cpl_update_contact(struct sip_msg* msg, char* str, char* str2);
37
+static int mod_init(void);
38
+
39
+struct module_exports exports = {
40
+	"cpl_module",
41
+	(char*[]){		"cpl_run_script",
42
+				"cpl_is_response_accept",
43
+				"cpl_is_response_reject",
44
+				"cpl_is_response_redirect",
45
+				"cpl_update_contact"
46
+			},
47
+	(cmd_function[]){
48
+				cpl_run_script,
49
+				cpl_is_response_accept,
50
+				cpl_is_response_reject,
51
+				cpl_is_response_redirect,
52
+				cpl_update_contact
53
+				},
54
+	(int[]){
55
+				0,
56
+				0,
57
+				0,
58
+				0,
59
+				0
60
+			},
61
+	(fixup_function[]){
62
+				0,
63
+				0,
64
+				0,
65
+				0,
66
+				0
67
+		},
68
+	5,
69
+
70
+	(char*[]) {   /* Module parameter names */
71
+		"cpl_db",
72
+		"cpl_table"
73
+		"cache_timeout"
74
+	},
75
+	(modparam_t[]) {   /* Module parameter types */
76
+		STR_PARAM,
77
+		STR_PARAM,
78
+		INT_PARAM
79
+	},
80
+	(void*[]) {   /* Module parameter variable pointers */
81
+		&DB_URL,
82
+		&DB_TABLE,
83
+		&cache_timeout
84
+	},
85
+	2,      /* Number of module paramers */
86
+
87
+
88
+	mod_init, /* Module initialization function */
89
+	(response_function) 0,
90
+	(destroy_function) 0,
91
+	0,
92
+	0 /* per-child init function */
93
+};
94
+
95
+
96
+static int mod_init(void)
97
+{
98
+	fprintf(stderr, "cpl - initializing\n");
99
+	return 0;
100
+}
101
+
102
+
103
+static int cpl_run_script(struct sip_msg* msg, char* str1, char* str2)
104
+{
105
+	return 1;
106
+}
107
+
108
+
109
+
110
+static int cpl_is_response_accept(struct sip_msg* msg, char* str1, char* str2)
111
+{
112
+	return 1;
113
+}
114
+
115
+
116
+static int cpl_is_response_reject(struct sip_msg* msg, char* str1, char* str2)
117
+{
118
+	return 1;
119
+}
120
+
121
+
122
+static int cpl_is_response_redirect(struct sip_msg* msg, char* str1,char* str2)
123
+{
124
+	return 1;
125
+}
126
+
127
+
128
+static int cpl_update_contact(struct sip_msg* msg, char* str1, char* str2)
129
+{
130
+#ifdef cucu
131
+	TRedirectMessage  *redirect;
132
+	struct lump_rpl *lump;
133
+	char *buf, *p;
134
+	int len;
135
+	int i;
136
+
137
+	if (resp_code!=REDIRECT_CALL || !resp_buf || !resp_len)
138
+		return -1;
139
+
140
+	redirect = parseRedirectResponse( resp_buf , resp_len );
141
+	printRedirectMessage( redirect );
142
+
143
+	len = 9 /*"Contact: "*/;
144
+	/* locations*/
145
+	for( i=0 ; i<redirect->numberOfLocations; i++)
146
+		len += 2/*"<>"*/ + redirect->locations[i].urlLength;
147
+	len += redirect->numberOfLocations -1 /*","*/;
148
+	len += CRLF_LEN;
149
+
150
+	buf = pkg_malloc( len );
151
+	if(!buf)
152
+	{
153
+		LOG(L_ERR,"ERROR:cpl_update_contact: out of memory! \n");
154
+		return -1;
155
+	}
156
+
157
+	p = buf;
158
+	memcpy( p , "Contact: " , 9);
159
+	p += 9;
160
+	for( i=0 ; i<redirect->numberOfLocations; i++)
161
+	{
162
+		if (i) *(p++)=',';
163
+		*(p++) = '<';
164
+		memcpy(p,redirect->locations[i].URL,redirect->locations[i].urlLength);
165
+		p += redirect->locations[i].urlLength;
166
+		*(p++) = '>';
167
+	}
168
+	memcpy(p,CRLF,CRLF_LEN);
169
+
170
+	lump = build_lump_rpl( buf , len );
171
+	if(!buf)
172
+	{
173
+		LOG(L_ERR,"ERROR:cpl_update_contact: unable to build lump_rpl! \n");
174
+		pkg_free( buf );
175
+		return -1;
176
+	}
177
+	add_lump_rpl( msg , lump );
178
+
179
+	freeRedirectMessage( redirect );
180
+	pkg_free(buf);
181
+#endif
182
+	return 1;
183
+}
184
+
185
+
0 186
new file mode 100644
... ...
@@ -0,0 +1,82 @@
1
+#include "../mysql/dbase.h"
2
+#include "../../dprint.h"
3
+#include "cpl_db.h"
4
+
5
+
6
+char *DB_URL;
7
+char *DB_TABLE;
8
+
9
+int write_to_db( char *usr, char *bin_s, int bin_len, char *xml_s, int xml_len)
10
+{
11
+	db_key_t   keys[] = {"username","cpl","status","cpl_bin"};
12
+	db_val_t   vals[4];
13
+	db_con_t   *db_con;
14
+	db_res_t   *res;
15
+
16
+
17
+	/* open connexion to db */
18
+	db_con = db_init(DB_URL);
19
+	if (!db_con) {
20
+		LOG(L_ERR,"ERROR:cpl:write_to_db: cannot connect to mysql db.\n");
21
+		goto error;
22
+	}
23
+
24
+	/* set the table */
25
+	if (use_table(db_con, DB_TABLE)<0) {
26
+		LOG(L_ERR,"ERROR:cpl:write_to_db: db_use_table failed\n");
27
+		goto error;
28
+	}
29
+
30
+	/* lets see if the user is already in database */
31
+	vals[0].type = DB_STRING;
32
+	vals[0].nul  = 0;
33
+	vals[0].val.string_val = usr;
34
+	if (db_query(db_con, keys, vals, keys, 1, 1, NULL, &res) < 0) {
35
+		LOG(L_ERR,"ERROR:cpl:write_to_db: db_query failed\n");
36
+		goto error;
37
+	}
38
+	if (res->n>1) {
39
+		LOG(L_ERR,"ERROR:cpl:write_to_db: Incosistent CPL database:"
40
+			" %d records for user %s\n",res->n,usr);
41
+		goto error;
42
+	}
43
+
44
+	/* username */
45
+	vals[0].type = DB_STRING;
46
+	vals[0].nul  = 0;
47
+	vals[0].val.string_val = usr;
48
+	/* cpl text */
49
+	vals[1].type = DB_BLOB;
50
+	vals[1].nul  = 0;
51
+	vals[1].val.blob_val.s = xml_s;
52
+	vals[1].val.blob_val.len = xml_len;
53
+	/* status */
54
+	vals[2].type = DB_INT;
55
+	vals[2].nul  = 0;
56
+	vals[2].val.int_val = 1;
57
+	/* cpl bin */
58
+	vals[3].type = DB_BLOB;
59
+	vals[3].nul  = 0;
60
+	vals[3].val.blob_val.s = bin_s;
61
+	vals[3].val.blob_val.len = bin_len;
62
+	/* insert or update ? */
63
+	if (res->n==0) {
64
+		DBG("DEBUG:cpl:write_to_db:No user %s in CPL databse->insert\n",usr);
65
+		if (db_insert(db_con, keys, vals, 4) < 0) {
66
+			LOG(L_ERR,"ERROR:cpl:write_to_db: insert failed !\n");
67
+			goto error;
68
+		}
69
+	} else {
70
+		DBG("DEBUG:cpl:write_to_db:User %s already in CPL database ->"
71
+			" update\n",usr);
72
+		if (db_update(db_con, keys, vals, keys+1, vals+1, 1, 3) < 0) {
73
+			LOG(L_ERR,"ERROR:cpl:write_to_db: updare failed !\n");
74
+			goto error;
75
+		}
76
+	}
77
+
78
+	return 0;
79
+error:
80
+	return -1;
81
+}
82
+
0 83
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+#ifndef _CPL_DB_H
2
+#define _CPL_DB_H
3
+
4
+int write_to_db(char *usr, char *bin_s, int bin_len, char *xml_s, int xml_len);
5
+
6
+extern char* DB_URL;
7
+extern char* DB_TABLE;
8
+
9
+#endif
0 10
new file mode 100644
... ...
@@ -0,0 +1,739 @@
1
+#include <stdio.h>
2
+#include <string.h>
3
+#include <stdlib.h>
4
+#include <sys/types.h>
5
+#include <sys/stat.h>
6
+#include <fcntl.h>
7
+#include <errno.h>
8
+#include <unistd.h>
9
+#include <gnome-xml/libxml/xmlmemory.h>
10
+#include <gnome-xml/libxml/parser.h>
11
+#include "CPL_tree.h"
12
+#include "sub_list.h"
13
+#include "../../dprint.h"
14
+
15
+
16
+
17
+struct node *list = 0;
18
+
19
+
20
+#define FOR_ALL_ATTR(_node,_attr) \
21
+	for( (_attr)=(_node)->properties ; (_attr) ; (_attr)=(_attr)->next)
22
+
23
+
24
+
25
+unsigned char encode_node_name(char *node_name)
26
+{
27
+	switch (node_name[0]) {
28
+		case 'a':
29
+		case 'A':
30
+			switch (node_name[7]) {
31
+				case 0:
32
+					return ADDRESS_NODE;
33
+				case '-':
34
+					return ADDRESS_SWITCH_NODE;
35
+				default:
36
+					return ANCILLARY_NODE;
37
+			}
38
+		case 'B':
39
+		case 'b':
40
+			return BUSY_NODE;
41
+		case 'c':
42
+		case 'C':
43
+			return CPL_NODE;
44
+		case 'd':
45
+		case 'D':
46
+			return DEFAULT_NODE;
47
+		case 'f':
48
+		case 'F':
49
+			return FAILURE_NODE;
50
+		case 'i':
51
+		case 'I':
52
+			return INCOMING_NODE;
53
+		case 'l':
54
+		case 'L':
55
+			switch (node_name[2]) {
56
+				case 'g':
57
+				case 'G':
58
+					return LOG_NODE;
59
+				case 'o':
60
+				case 'O':
61
+					return LOOKUP_NODE;
62
+				case 'c':
63
+				case 'C':
64
+					return LOCATION_NODE;
65
+				default:
66
+					if (node_name[8])
67
+						return LANGUAGE_SWITCH_NODE;
68
+					else
69
+						return LANGUAGE_NODE;
70
+			}
71
+		case 'm':
72
+		case 'M':
73
+			return MAIL_NODE;
74
+		case 'n':
75
+		case 'N':
76
+			if (node_name[2]=='T' || node_name[2]=='t')
77
+				return NOTFOUND_NODE;
78
+			else
79
+				return NOANSWER_NODE;
80
+		case 'o':
81
+		case 'O':
82
+			if (node_name[1]=='t' || node_name[1]=='T')
83
+				return OTHERWISE_NODE;
84
+			else
85
+				return OUTGOING_NODE;
86
+		case 'p':
87
+		case 'P':
88
+			if (node_name[2]=='o' || node_name[2]=='O')
89
+				return PROXY_NODE;
90
+			if (node_name[8])
91
+				return PRIORITY_SWITCH_NODE;
92
+			else
93
+				return PRIORITY_NODE;
94
+		case 'r':
95
+		case 'R':
96
+			switch (node_name[2]) {
97
+				case 'j':
98
+				case 'J':
99
+					return REJECT_NODE;
100
+				case 'm':
101
+				case 'M':
102
+					return REMOVE_LOCATION_NODE;
103
+				default:
104
+					if (node_name[8])
105
+						return REDIRECTION_NODE;
106
+					else
107
+						return REDIRECT_NODE;
108
+			}
109
+		case 's':
110
+		case 'S':
111
+			switch (node_name[3]) {
112
+				case 0:
113
+					return SUB_NODE;
114
+				case 'c':
115
+				case 'C':
116
+					return SUCCESS_NODE;
117
+				case 'a':
118
+				case 'A':
119
+					return SUBACTION_NODE;
120
+				default:
121
+					if (node_name[6])
122
+						return STRING_SWITCH_NODE;
123
+					else
124
+						return STRING_NODE;
125
+			}
126
+		case 't':
127
+		case 'T':
128
+			if (node_name[4])
129
+				return TIME_SWITCH_NODE;
130
+			else
131
+				return TIME_NODE;
132
+	}
133
+	return 0;
134
+}
135
+
136
+
137
+
138
+
139
+int encript_node_attr( xmlNodePtr node, unsigned char *node_ptr,
140
+					unsigned int type, unsigned char *ptr,int *nr_of_attr)
141
+{
142
+	xmlAttrPtr    attr;
143
+	char          *val;
144
+	unsigned char *p;
145
+	unsigned char *offset;
146
+	int           nr_attr;
147
+	int           foo;
148
+
149
+	nr_attr = 0;
150
+	p = ptr;
151
+
152
+	switch (type) {
153
+		case CPL_NODE:
154
+		case INCOMING_NODE:
155
+		case OUTGOING_NODE:
156
+		case OTHERWISE_NODE:
157
+		case LANGUAGE_SWITCH_NODE:
158
+		case PRIORITY_SWITCH_NODE:
159
+		case SUCCESS_NODE:
160
+		case FAILURE_NODE:
161
+		case NOTFOUND_NODE:
162
+		case BUSY_NODE:
163
+		case NOANSWER_NODE:
164
+		case REDIRECTION_NODE:
165
+		case DEFAULT_NODE:
166
+		case ANCILLARY_NODE:
167
+			break;
168
+		/* enconding attributes and values fro ADDRESS-SWITCH node */
169
+		case ADDRESS_SWITCH_NODE:
170
+			FOR_ALL_ATTR(node,attr) {
171
+				nr_attr++;
172
+				val = (char*)xmlGetProp(node,attr->name);
173
+				switch(attr->name[0]) {
174
+					case 'F': case 'f':
175
+						*(p++) = FIELD_ATTR;
176
+						if (val[0]=='D' || val[0]=='d')
177
+							*(p++) = DESTINATION_VAL;
178
+						else if (val[6]=='-')
179
+							*(p++) = ORIGINAL_DESTINATION_VAL;
180
+						else if (!val[6])
181
+							*(p++) = ORIGIN_VAL;
182
+						else goto error;
183
+						break;
184
+					case 'S': case 's':
185
+						*(p++) = SUBFIELD_ATTR;
186
+						switch (val[0]) {
187
+							case 'a': case 'A':
188
+								*(p++)=ADDRESS_TYPE_VAL;break;
189
+							case 'u': case 'U':
190
+								*(p++)=USER_VAL;break;
191
+							case 'h': case 'H':
192
+								*(p++)=HOST_VAL;break;
193
+							case 'p': case 'P':
194
+								*(p++)=PORT_VAL;break;
195
+							case 't': case 'T':
196
+								*(p++)=TEL_VAL;break;
197
+							case 'd': case 'D':
198
+								*(p++)=DISPLAY_VAL;break;
199
+							default: goto error;
200
+						}
201
+						break;
202
+					default: goto error;
203
+				}
204
+			}
205
+			break;
206
+		/* enconding attributes and values fro ADDRESS node */
207
+		case ADDRESS_NODE:
208
+			FOR_ALL_ATTR(node,attr) {
209
+				nr_attr++;
210
+				val = (char*)xmlGetProp(node,attr->name);
211
+				switch (attr->name[0]) {
212
+					case 'i': case 'I':
213
+						*(p++) = IS_ATTR; break;
214
+					case 'c': case 'C':
215
+						*(p++) = CONTAINS_ATTR; break;
216
+					case 's': case 'S':
217
+						*(p++) = SUBDOMAIN_OF_ATTR; break;
218
+					default: goto error;
219
+				}
220
+				foo = strlen(val);
221
+				*((unsigned short*)(p)) = (unsigned short)foo;
222
+				p += 2;
223
+				memcpy(p,val,foo);
224
+				p += foo;
225
+			}
226
+			break;
227
+		/* enconding attributes and values for STRING-SWITCH node */
228
+		case STRING_SWITCH_NODE:
229
+			FOR_ALL_ATTR(node,attr) {
230
+				nr_attr++;
231
+				val = (char*)xmlGetProp(node,attr->name);
232
+				if (attr->name[0]=='F' || attr->name[0]=='f') {
233
+					*(p++) = FIELD_ATTR;
234
+					switch (val[0]) {
235
+						case 'S': case 's':
236
+							*(p++) = SUBJECT_VAL; break;
237
+						case 'O': case 'o':
238
+							*(p++) = ORGANIZATION_VAL; break;
239
+						case 'U': case 'u':
240
+							*(p++) = USER_AGENT_VAL; break;
241
+						case 'D': case 'd':
242
+							*(p++) = DISPLAY_VAL; break;
243
+						default: goto error;
244
+					}
245
+				} else goto error;
246
+			}
247
+			break;
248
+		/* enconding attributes and values for STRING node */
249
+		case STRING_NODE:
250
+			FOR_ALL_ATTR(node,attr) {
251
+				nr_attr++;
252
+				val = (char*)xmlGetProp(node,attr->name);
253
+				switch (attr->name[0]) {
254
+					case 'i': case 'I':
255
+						*(p++) = IS_ATTR; break;
256
+					case 'c': case 'C':
257
+						*(p++) = CONTAINS_ATTR; break;
258
+					default: goto error;
259
+				}
260
+				foo = strlen(val);
261
+				*((unsigned short*)(p)) = (unsigned short)foo;
262
+				p += 2;
263
+				memcpy(p,val,foo);
264
+				p += foo;
265
+			}
266
+			break;
267
+		/* enconding attributes and values for LANGUAGE node */
268
+		case LANGUAGE_NODE:
269
+			FOR_ALL_ATTR(node,attr) {
270
+				nr_attr++;
271
+				val = (char*)xmlGetProp(node,attr->name);
272
+				if (attr->name[0]=='M' || attr->name[0]=='m') {
273
+					*(p++) = MATCHES_ATTR;
274
+				} else goto error;
275
+				foo = strlen(val);
276
+				*((unsigned short*)(p)) = (unsigned short)foo;
277
+				p += 2;
278
+				memcpy(p,val,foo);
279
+				p += foo;
280
+			}
281
+			break;
282
+		/* enconding attributes and values for TIME-SWITCH node */
283
+		case TIME_SWITCH_NODE:
284
+			FOR_ALL_ATTR(node,attr) {
285
+				nr_attr++;
286
+				val = (char*)xmlGetProp(node,attr->name);
287
+				switch(attr->name[2]) {
288
+					case 'I': case 'i':
289
+						*(p++) = TZID_ATTR;break;
290
+					case 'U': case 'u':
291
+						*(p++) = TZURL_ATTR;break;
292
+					default: goto error;
293
+				}
294
+				foo = strlen(val);
295
+				*((unsigned short*)(p)) = (unsigned short)foo;
296
+				p += 2;
297
+				memcpy(p,val,foo);
298
+				p += foo;
299
+			}
300
+			break;
301
+		/* enconding attributes and values for TIME node */
302
+		case TIME_NODE:
303
+			FOR_ALL_ATTR(node,attr) {
304
+				nr_attr++;
305
+				val = (char*)xmlGetProp(node,attr->name);
306
+				switch (attr->name[4]) {
307
+					case 0:
308
+						if (attr->name[0]=='F' || attr->name[0]=='f')
309
+							*(p++) = FREQ_ATTR;
310
+						else if (attr->name[0]=='W' || attr->name[0]=='w')
311
+							*(p++) = WKST_ATTR;
312
+						break;
313
+					case 'a': case 'A':
314
+						if (attr->name[0]=='D' || attr->name[0]=='d')
315
+							*(p++) = DTSTART_ATTR;
316
+						else if (attr->name[0]=='B' || attr->name[0]=='b')
317
+							*(p++) = BYYEARDAY_ATTR;
318
+						break;
319
+					case 't': case 'T':
320
+						if (attr->name[0]=='D' || attr->name[0]=='d')
321
+							*(p++) = DURATION_ATTR;
322
+						else if (attr->name[0]=='C' || attr->name[0]=='c')
323
+							*(p++) = COUNT_ATTR;
324
+						else if (attr->name[0]=='B' || attr->name[0]=='b')
325
+							*(p++) = BYSETPOS_ATTR;
326
+						break;
327
+					case 'n': case 'N':
328
+						if (!attr->name[0])
329
+							*(p++) = BYMONTH_ATTR;
330
+						else if (attr->name[0]=='D' || attr->name[0]=='d')
331
+							*(p++) = BYMONTHDAY_ATTR;
332
+						else if (attr->name[0]=='e' || attr->name[0]=='E')
333
+							*(p++) = BYMINUTE_ATTR;
334
+						break;
335
+					case 'd': case 'D':
336
+						*(p++) = DTEND_ATTR; break;
337
+					case 'r': case 'R':
338
+						*(p++) = INTERVAL_ATTR; break;
339
+					case 'l': case 'L':
340
+						*(p++) = UNTIL_ATTR; break;
341
+					case 'c': case 'C':
342
+						*(p++) = BYSECOND_ATTR; break;
343
+					case 'u': case 'U':
344
+						*(p++) = BYHOUR_ATTR; break;
345
+					case 'y': case 'Y':
346
+						*(p++) = BYDAY_ATTR; break;
347
+					case 'e': case 'E':
348
+						*(p++) = BYWEEKNO_ATTR; break;
349
+					default: goto error;
350
+				}
351
+				foo = strlen(val);
352
+				*((unsigned short*)(p)) = (unsigned short)foo;
353
+				p += 2;
354
+				memcpy(p,val,foo);
355
+				p += foo;
356
+			}
357
+			break;
358
+		/* enconding attributes and values for PRIORITY node */
359
+		case PRIORITY_NODE:
360
+			FOR_ALL_ATTR(node,attr) {
361
+				nr_attr++;
362
+				val = (char*)xmlGetProp(node,attr->name);
363
+				switch(attr->name[0]) {
364
+					case 'L': case 'l':
365
+						*(p++) = LESS_ATTR;break;
366
+					case 'G': case 'g':
367
+						*(p++) = GREATER_ATTR;break;
368
+					case 'E': case 'e':
369
+						*(p++) = EQUAL_ATTR;break;
370
+					default: goto error;
371
+				}
372
+				switch (val[0]) {
373
+					case 'e': case 'E':
374
+						*(p++) = EMERGENCY_VAL; break;
375
+					case 'g': case 'G':
376
+						*(p++) = URGENT_VAL;break;
377
+					case 'r': case 'R':
378
+						*(p++) = NORMAL_VAL;break;
379
+					case 'n': case 'N':
380
+						*(p++) = NON_URGENT_VAL;break;
381
+					default: goto error;
382
+				}
383
+			}
384
+			break;
385
+		/* enconding attributes and values for LOCATION node */
386
+		case LOCATION_NODE:
387
+			FOR_ALL_ATTR(node,attr) {
388
+				nr_attr++;
389
+				val = (char*)xmlGetProp(node,attr->name);
390
+				switch(attr->name[0]) {
391
+					case 'U': case 'u':
392
+						*(p++) = URL_ATTR;
393
+						foo = strlen(val);
394
+						*((unsigned short*)(p)) = (unsigned short)foo;
395
+						p += 2;
396
+						memcpy(p,val,foo);
397
+						p += foo;
398
+						break;
399
+					case 'P': case 'p':
400
+						*(p++) = PRIORITY_ATTR;
401
+						if (val[0]=='0') foo=0;
402
+						else if (val[0]=='1') foo=10;
403
+						else goto error;
404
+						if (val[1]!='.') goto error;
405
+						if (val[2]<'0' || val[2]>'9')
406
+							goto error;
407
+						foo += val[2] - '0';
408
+						if (foo<0 || foo>10)
409
+							goto error;
410
+						*(p++) = (unsigned char)foo;
411
+						break;
412
+					case 'C': case 'c':
413
+						*(p++) = CLEAR_ATTR;
414
+						if (val[0]=='y' || val[0]=='Y')
415
+							*(p++) = YES_VAL;
416
+						else
417
+							*(p++) = NO_VAL;
418
+						break;
419
+					default: goto error;
420
+				}
421
+			}
422
+			break;
423
+		/* enconding attributes and values for LOOKUP node */
424
+		case LOOKUP_NODE:
425
+			FOR_ALL_ATTR(node,attr) {
426
+				nr_attr++;
427
+				val = (char*)xmlGetProp(node,attr->name);
428
+				foo = 0;
429
+				switch(attr->name[0]) {
430
+					case 'S': case 's':
431
+						*(p++) = SOURCE_ATTR;
432
+						foo = 1;
433
+						break;
434
+					case 'T': case 't':
435
+						*(p++) = TIMEOUT_ATTR;
436
+						foo = strtol(val,0,10);
437
+						if (errno||foo<0||foo>255)
438
+							goto error;
439
+						*(p++) = (unsigned char)foo;
440
+						foo = 0;
441
+						break;
442
+					case 'C': case 'c':
443
+						*(p++) = CLEAR_ATTR;
444
+						if (val[0]=='y' || val[0]=='Y')
445
+							*(p++) = YES_VAL;
446
+						else
447
+							*(p++) = NO_VAL;
448
+						foo = 0;
449
+						break;
450
+					case 'U': case 'u':
451
+						*(p++) = USE_ATTR;
452
+						foo = 1;
453
+						break;
454
+					case 'I': case 'i':
455
+						*(p++) = IGNORE_ATTR;
456
+						foo = 1;
457
+						break;
458
+					default: goto error;
459
+				}
460
+				if (foo) {
461
+					foo = strlen(val);
462
+					*((unsigned short*)(p)) = (unsigned short)foo;
463
+					p += 2;
464
+					memcpy(p,val,foo);
465
+					p += foo;
466
+				}
467
+			}
468
+			break;
469
+		/* enconding attributes and values for REMOVE_LOCATION node */
470
+		case REMOVE_LOCATION_NODE:
471
+			FOR_ALL_ATTR(node,attr) {
472
+				nr_attr++;
473
+				val = (char*)xmlGetProp(node,attr->name);
474
+				switch(attr->name[0]) {
475
+					case 'L': case 'l':
476
+						*(p++) = LOCATION_ATTR;break;
477
+					case 'P': case 'p':
478
+						*(p++) = PARAM_ATTR;break;
479
+					case 'V': case 'v':
480
+						*(p++) = VALUE_ATTR;break;
481
+					default: goto error;
482
+				}
483
+				foo = strlen(val);
484
+				*((unsigned short*)(p)) = (unsigned short)foo;
485
+				p += 2;
486
+				memcpy(p,val,foo);
487
+				p += foo;
488
+			}
489
+			break;
490
+		/* enconding attributes and values for REMOVE_LOCATION node */
491
+		case PROXY_NODE:
492
+			FOR_ALL_ATTR(node,attr) {
493
+				nr_attr++;
494
+				val = (char*)xmlGetProp(node,attr->name);
495
+				switch(attr->name[0]) {
496
+					case 'R': case 'r':
497
+						*(p++) = RECURSE_ATTR;
498
+						if (val[0]=='y' || val[0]=='Y')
499
+							*(p++) = YES_VAL;
500
+						else if (val[0]=='n' || val[0]=='N')
501
+							*(p++) = NO_VAL;
502
+						else goto error;
503
+						break;
504
+					case 'T': case 't':
505
+						*(p++) = TIMEOUT_ATTR;
506
+						foo = strtol(val,0,10);
507
+						if (errno||foo<0||foo>255)
508
+							goto error;
509
+						*(p++) = (unsigned char)foo;
510
+						foo = 0;
511
+						break;
512
+					case 'O': case 'o':
513
+						*(p++) = ORDERING_ATTR;
514
+						switch (val[0]) {
515
+							case 'p': case'P':
516
+								*(p++) = PARALLEL_VAL; break;
517
+							case 'S': case 's':
518
+								*(p++) = SEQUENTIAL_VAL; break;
519
+							case 'F': case 'f':
520
+								*(p++) = FIRSTONLY_VAL; break;
521
+							default: goto error;
522
+						}
523
+						break;
524
+					default: goto error;
525
+				}
526
+			}
527
+			break;
528
+		/* enconding attributes and values for REDIRECT node */
529
+		case REDIRECT_NODE:
530
+			FOR_ALL_ATTR(node,attr) {
531
+				nr_attr++;
532
+				val = (char*)xmlGetProp(node,attr->name);
533
+				if (attr->name[0]=='p' || attr->name[0]=='P') {
534
+					*(p++) = PERMANENT_ATTR;
535
+					if (val[0]=='y' || val[0]=='Y')
536
+						*(p++) = YES_VAL;
537
+					else if (val[0]=='n' || val[0]=='N')
538
+						*(p++) = NO_VAL;
539
+					else goto error;
540
+				} else goto error;
541
+			}
542
+			break;
543
+		/* enconding attributes and values for REJECT node */
544
+		case REJECT_NODE:
545
+			FOR_ALL_ATTR(node,attr) {
546
+				nr_attr++;
547
+				val = (char*)xmlGetProp(node,attr->name);
548
+				switch(attr->name[0]) {
549
+					case 'R': case 'r':
550
+						*(p++) = REASON_ATTR;
551
+						foo = strlen(val);
552
+						*((unsigned short*)(p)) = (unsigned short)foo;
553
+						p += 2;
554
+						memcpy(p,val,foo);
555
+						p += foo;
556
+						break;
557
+					case 'S': case 's':
558
+						*(p++) = STATUS_ATTR;
559
+						foo = strtol(val,0,10);
560
+						if (errno||foo<0||foo>1000)
561
+							goto error;
562
+						*((unsigned short*)p) = (unsigned short)foo;
563
+						p +=2;
564
+						break;
565
+					default: goto error;
566
+				}
567
+			}
568
+			break;
569
+		/* enconding attributes and values for MAIL node */
570
+		case MAIL_NODE:
571
+			FOR_ALL_ATTR(node,attr) {
572
+				nr_attr++;
573
+				val = (char*)xmlGetProp(node,attr->name);
574
+				if (attr->name[0]=='u' || attr->name[0]=='U') {
575
+					*(p++) = URL_ATTR;
576
+					foo = strlen(val);
577
+					*((unsigned short*)(p)) = (unsigned short)foo;
578
+					p += 2;
579
+					memcpy(p,val,foo);
580
+					p += foo;
581
+				} else goto error;
582
+			}
583
+			break;
584
+		/* enconding attributes and values for LOG node */
585
+		case LOG_NODE:
586
+			FOR_ALL_ATTR(node,attr) {
587
+				nr_attr++;
588
+				val = (char*)xmlGetProp(node,attr->name);
589
+				switch (attr->name[0] ) {
590
+					case 'n': case 'N':
591
+						*(p++) = NAME_ATTR; break;
592
+					case 'c': case 'C':
593
+						*(p++) = COMMENT_ATTR;break;
594
+					default: goto error;
595
+				}
596
+				foo = strlen(val);
597
+				*((unsigned short*)(p)) = (unsigned short)foo;
598
+				p += 2;
599
+				memcpy(p,val,foo);
600
+				p += foo;
601
+			}
602
+			break;
603
+		/* enconding attributes and values for SUBACTION node */
604
+		case SUBACTION_NODE:
605
+			FOR_ALL_ATTR(node,attr) {
606
+				nr_attr++;
607
+				val = (char*)xmlGetProp(node,attr->name);
608
+				if (strcasecmp("id",attr->name)==0 ) {
609
+					if ((list = append_to_list(list, node_ptr,val))==0)
610
+						goto error;
611
+				} else goto error;
612
+			}
613
+			break;
614
+		/* enconding attributes and values for SUB node */
615
+		case SUB_NODE:
616
+			FOR_ALL_ATTR(node,attr) {
617
+				nr_attr++;
618
+				val = (char*)xmlGetProp(node,attr->name);
619
+				if (strcasecmp("ref",attr->name)==0 ) {
620
+					if (( offset = search_the_list(list, val))==0)
621
+						goto error;
622
+					*((unsigned short*)p) = (unsigned short)(node_ptr-offset);
623
+					p += 2;
624
+				} else goto error;
625
+			}
626
+			break;
627
+
628
+	}
629
+
630
+	*nr_of_attr = nr_attr;
631
+	return (p-ptr);
632
+error:
633
+	LOG(L_ERR,"ERROR:cpl:encript_node_attr: error enconding attributes\n");
634
+	return -1;
635
+}
636
+
637
+
638
+
639
+
640
+int encrypt_node( xmlNodePtr node, unsigned char *p)
641
+{
642
+	xmlNodePtr kid;
643
+	int sub_tree_size;
644
+	int attr_size;
645
+	int len;
646
+	int foo;
647
+	int nr;
648
+
649
+	/* get node's type (on one byte) */
650
+	NODE_TYPE(p) = encode_node_name((char*)node->name);
651
+
652
+	/* counting the kids */
653
+	NR_OF_KIDS(p) = 0;
654
+	for( kid=node->xmlChildrenNode;kid;kid=kid->next)
655
+		NR_OF_KIDS(p)++;
656
+
657
+	/* setting the attributes */
658
+	attr_size = encript_node_attr( node, p, NODE_TYPE(p), ATTR_PTR(p), &nr);
659
+	if (attr_size<0) return -1;
660
+	NR_OF_ATTR(p) = (unsigned char)nr;
661
+
662
+	sub_tree_size = 2 + 2*(NR_OF_KIDS(p)) + 1 + attr_size;
663
+
664
+	/* encrypt all the kids */
665
+	for(kid = node->xmlChildrenNode,foo=0;kid;kid=kid->next,foo++) {
666
+		KID_OFFSET(p,foo) = sub_tree_size;
667
+		len = encrypt_node(kid,p+sub_tree_size);
668
+		if (len<=0) return -1;
669
+		sub_tree_size += len;
670
+	}
671
+
672
+	return sub_tree_size;
673
+}
674
+
675
+
676
+
677
+
678
+char* encryptXML( char* xml_s, int xml_len, char* DTD_filename, int *bin_len)
679
+{
680
+	static unsigned char buf[2048];
681
+	unsigned int  len;
682
+	xmlValidCtxt  cvp;
683
+	xmlDocPtr  doc;
684
+	xmlNodePtr cur;
685
+	xmlDtdPtr  dtd;
686
+
687
+	doc  = 0;
688
+	list = 0;
689
+	dtd  = 0;
690
+
691
+	/* parse the xml */
692
+	xml_s[xml_len] = 0;
693
+	doc = xmlParseDoc( xml_s );
694
+	if (!doc) {
695
+		LOG(L_ERR,"ERROR:cpl:encryptXML:CPL script not parsed successfully\n");
696
+		goto error;
697
+	}
698
+
699
+	/* parse the dtd file - if any! */
700
+	if (DTD_filename) {
701
+		dtd = xmlParseDTD( NULL, DTD_filename);
702
+		if (!dtd) {
703
+			LOG(L_ERR,"ERROR:cpl:encryptXML: DTD not parsed successfully. \n");
704
+			goto error;
705
+		}
706
+		cvp.userData = (void *) stderr;
707
+		cvp.error    = (xmlValidityErrorFunc) fprintf;
708
+		cvp.warning  = (xmlValidityWarningFunc) fprintf;
709
+		if (xmlValidateDtd(&cvp, doc, dtd)!=1) {
710
+			LOG(L_ERR,"ERROR:cpl:encryptXML: CPL script do not matche DTD\n");
711
+			goto error;
712
+		}
713
+	}
714
+
715
+
716
+	cur = xmlDocGetRootElement(doc);
717
+	if (!cur) {
718
+		LOG(L_ERR,"ERROR:cpl:encryptXML: empty CPL script!\n");
719
+		goto error;
720
+	}
721
+
722
+	len = encrypt_node( cur, buf);
723
+	if (len<0) {
724
+		LOG(L_ERR,"ERROR:cpl:encryptXML: zero lenght return by encripting"
725
+			" function\n");
726
+		goto error;
727
+	}
728
+
729
+
730
+	if (doc) xmlFreeDoc(doc);
731
+	if (list) delete_list(list);
732
+	if (bin_len) *bin_len = len;
733
+	return buf;
734
+error:
735
+	if (doc) xmlFreeDoc(doc);
736
+	if (list) delete_list(list);
737
+	return 0;
738
+}
739
+
0 740
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+#ifndef _CPL_PARSER_H
2
+#define _CPL_PARSER_H
3
+
4
+char* encryptXML(char* xml, int xml_len, char* DTD_filename, int *bin_len);
5
+
6
+
7
+#endif
0 8
new file mode 100644
... ...
@@ -0,0 +1,57 @@
1
+#include <stdlib.h>
2
+#include <string.h>
3
+#include "sub_list.h"
4
+
5
+struct node*   append_to_list(struct node *head, unsigned char *offset,
6
+																char *name)
7
+{
8
+	struct node *n;
9
+	struct node *new_node;
10
+
11
+	new_node = malloc(sizeof(struct node));
12
+	if (!new_node)
13
+		return 0;
14
+	new_node->offset = offset;
15
+	new_node->name = name;
16
+	new_node->next = 0;
17
+	if (head) {
18
+		n = head;
19
+		while (n->next)
20
+			n = n->next;
21
+		n->next = new_node;
22
+	}
23
+
24
+	return new_node;
25
+}
26
+
27
+
28
+
29
+
30
+unsigned char* search_the_list(struct node *head, char *name)
31
+{
32
+	struct node *n;
33
+
34
+	n = head;
35
+	while (n) {
36
+		if (strcasecmp(n->name,name)==0)
37
+			return n->offset;
38
+		n = n->next;
39
+	}
40
+	return 0;
41
+}
42
+
43
+
44
+
45
+
46
+void delete_list(struct node* head)
47
+{
48
+	struct node *n;
49
+;
50
+	while (head) {
51
+		n=head->next;
52
+		free(head);
53
+		head = n;
54
+	}
55
+}
56
+
57
+
0 58
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+#ifndef _CPL_SUB_LIST_H
2
+#define _CPL_SUB_LIST_H
3
+
4
+struct node {
5
+	unsigned char  *offset;
6
+	char           *name;
7
+	struct node    *next;
8
+};
9
+
10
+
11
+struct node*   append_to_list(struct node *head, unsigned char *offdet,
12
+																char *name);
13
+unsigned char* search_the_list(struct node *head, char *name);
14
+void           delete_list(struct node *head );
15
+
16
+#endif
0 17
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+BIN=encrypt
2
+CC=gcc
3
+OPT=-Wall -O9
4
+EXT_OBJ=../../mysql/mysql.so ../cpl_parser.o ../cpl_db.o ../sub_list.o
5
+LIBS=-lxml
6
+
7
+
8
+
9
+
10
+all: $(BIN)
11
+
12
+$(BIN): $(EXT_OBJ) encrypt.o wraper.o
13
+	$(CC) $(LIBS) $(EXT_OBJ) encrypt.o wraper.o -o $(BIN)
14
+
15
+encrypt.o: encrypt.c ../cpl_db.h ../cpl_parser.h Makefile
16
+	$(CC) -c $(OPT) -o encrypt.o encrypt.c
17
+	
18
+wraper.o: wraper.c Makefile
19
+	$(CC) -c $(OPT) -o wraper.o wraper.c
20
+
21
+clean:
22
+	rm -f *.o
23
+	rm -f $(BIN)
0 24
new file mode 100644
... ...
@@ -0,0 +1,266 @@
1
+<?xml version="1.0" encoding="US-ASCII" ?>
2
+
3
+   <!--
4
+       Draft DTD for CPL, corresponding to
5
+       draft-ietf-iptel-cpl-06.
6
+   -->
7
+
8
+   <!-- Nodes. -->
9
+   <!-- Switch nodes -->
10
+   <!ENTITY % Switch 'address-switch|string-switch|language-switch|
11
+                      time-switch|priority-switch' >
12
+
13
+   <!-- Location nodes -->
14
+   <!ENTITY % Location 'location|lookup|remove-location' >
15
+
16
+   <!-- Signalling action nodes -->
17
+   <!ENTITY % SignallingAction 'proxy|redirect|reject' >
18
+
19
+   <!-- Other actions -->
20
+   <!ENTITY % OtherAction 'mail|log' >
21
+
22
+   <!-- Links to subactions -->
23
+   <!ENTITY % Sub 'sub' >
24
+
25
+   <!-- Nodes are one of the above four categories, or a subaction.
26
+        This entity (macro) describes the contents of an output.
27
+        Note that a node can be empty, implying default action. -->
28
+   <!ENTITY % Node     '(%Location;|%Switch;|%SignallingAction;|
29
+                        %OtherAction;|%Sub;)?' >
30
+
31
+
32
+   <!-- Switches: choices a CPL script can make. -->
33
+
34
+   <!-- All switches can have an 'otherwise' output. -->
35
+   <!ELEMENT otherwise ( %Node; ) >
36
+
37
+   <!-- All switches can have a 'not-present' output. -->
38
+   <!ELEMENT not-present ( %Node; ) >
39
+
40
+   <!-- Address-switch makes choices based on addresses. -->
41
+   <!ELEMENT address-switch ( address*, (not-present, address*)?,
42
+                              otherwise? ) >
43
+   <!-- <not-present> must appear at most once -->
44
+   <!ATTLIST address-switch
45
+      field         CDATA    #REQUIRED
46
+      subfield      CDATA    #IMPLIED
47
+   >
48
+
49
+   <!ELEMENT address ( %Node; ) >
50
+
51
+   <!ATTLIST address
52
+      is            CDATA    #IMPLIED
53
+      contains      CDATA    #IMPLIED
54
+      subdomain-of  CDATA    #IMPLIED
55
+   > <!-- Exactly one of these three attributes must appear -->
56
+
57
+
58
+   <!-- String-switch makes choices based on strings. -->
59
+
60
+   <!ELEMENT string-switch ( string*, (not-present, string*)?,
61
+                             otherwise? ) >
62
+   <!-- <not-present> must appear at most once -->
63
+   <!ATTLIST string-switch
64
+      field         CDATA    #REQUIRED
65
+   >
66
+
67
+   <!ELEMENT string ( %Node; ) >
68
+   <!ATTLIST string
69
+      is            CDATA    #IMPLIED
70
+      contains      CDATA    #IMPLIED
71
+   >  <!-- Exactly one of these two attributes must appear -->
72
+
73
+
74
+   <!-- Language-switch makes choices based on the originator's preferred
75
+        languages. -->
76
+
77
+   <!ELEMENT language-switch ( language*, (not-present, language*)?,
78
+                               otherwise? ) >
79
+   <!-- <not-present> must appear at most once -->
80
+
81
+   <!ELEMENT language ( %Node; ) >
82
+   <!ATTLIST language
83
+      matches      CDATA     #REQUIRED
84
+   >
85
+
86
+
87
+   <!-- Time-switch makes choices based on the current time. -->
88
+
89
+   <!ELEMENT time-switch ( time*, (not-present, time*)?, otherwise? ) >
90
+   <!ATTLIST time-switch
91
+      tzid          CDATA    #IMPLIED
92
+      tzurl         CDATA    #IMPLIED
93
+   >
94
+
95
+   <!ELEMENT time ( %Node; ) >
96
+
97
+   <!-- Exactly one of the two attributes "dtend" and "duration"
98
+        must occur. -->
99
+   <!-- The value of "freq" is (daily|weekly|monthly|yearly).  It is
100
+           case-insensitive, so it is not given as a DTD switch. -->
101
+   <!-- None of the attributes following freq are meaningful unless freq
102
+            appears. -->
103
+   <!-- The value of "wkst" is (MO|TU|WE|TH|FR|SA|SU).  It is
104
+           case-insensitive, so it is not given as a DTD switch. -->
105
+   <!ATTLIST time
106
+      dtstart       CDATA  #REQUIRED
107
+      dtend         CDATA  #IMPLIED
108
+      duration      CDATA  #IMPLIED
109
+      freq          CDATA  #IMPLIED
110
+      until         CDATA  #IMPLIED
111
+      count         CDATA  #IMPLIED
112
+      interval      CDATA  "1"
113
+      bysecond      CDATA  #IMPLIED
114
+      byminute      CDATA  #IMPLIED
115
+      byhour        CDATA  #IMPLIED
116
+      byday         CDATA  #IMPLIED
117
+      bymonthday    CDATA  #IMPLIED
118
+      byyearday     CDATA  #IMPLIED
119
+      byweekno      CDATA  #IMPLIED