modules/up/UP_extrnl_syntax.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- up_get_dates
- up_changed_has_date
- up_get_current_date
- up_add_dates
- up_check_date_order
- up_check_changed_attr
- up_check_an_auth_attr
- up_check_auth_attr
- up_get_attribute_list
- up_reconstruct_object
- UP_check_external_syntax
1 /***************************************
2 $Revision: 1.2 $
3
4 UP external syntax checks
5
6 Status: NOT REVIEWED, NOT TESTED
7
8 Author(s): Engin Gunduz
9
10 ******************/ /******************
11 Modification History:
12 engin (15/12/2000) Created.
13 ******************/ /******************
14 Copyright (c) 2001 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34
35 #include "rpsl/object.hh"
36 #include "UP_extrnl_syntax.h"
37 #include "dbupdate.h"
38
39
40 extern int tracing;
41
42
43
44
45 /* obtains a list of dates in the given
46 list of attributes (GSList of attribute_struct) */
47 GSList * up_get_dates(GSList * attribute_list){
/* [<][>][^][v][top][bottom][index][help] */
48
49 GSList * next;
50 char * temp, * str;
51 int i;
52 //char * date;
53 GSList * list = NULL;
54
55 for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
56 /* is this a 'changed' attribute? */
57 if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
58 temp = strdup(((attribute_struct *)(next->data))->content);
59
60 /* delete the part after '#', inclusive */
61 if(index(temp,'#') != NULL){
62 temp[index(temp, '#') - temp] = '\0';
63 }
64 /* replace \n, \r & \t's with " " */
65 for(i = 0; i < strlen(temp) ;i++){
66 if(temp[i] == '\n' || temp[i] == '\r' || temp[i] == '\t' ){
67 temp[i] = ' ';
68 }
69 }
70 g_strstrip(temp);
71 /* delete multiple spaces */
72 str = (char *)malloc(strlen(temp) + 1);
73 up_string_pack(str, temp);
74 free(temp);
75
76 /* now, we have the 'changed' attribute's content in "normalized" form
77 We are sure it contains a date. So, it must be the second (and last)
78 word in the attrib. */
79 assert(index(str,' ') != NULL);
80 temp = (char *)malloc(strlen(str) - (index(str,' ') - str ));
81 temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1);
82 temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */
83 /*printf("DEBUG: up_get_dates: adding [%s] to the list of dates\n", temp);*/
84 list = g_slist_append (list, temp);
85 }
86 }
87
88 return list;
89 }
90
91
92
93
94 /* Does the 'changed' attribute we got have a date already?
95 Returns 1 if it does, 0 if not. */
96 int up_changed_has_date(char * arg){
/* [<][>][^][v][top][bottom][index][help] */
97
98 int i;
99 char * str;
100 char * temp;
101
102 /*printf("DEBUG: up_changed_has_date: [%s]\n", arg);*/
103 str = strdup(arg);
104
105 /* cut off the EOL comments */
106 if(index(str, '#')){
107 str[index(str, '#') - str - 1 ] = '\0';
108 }
109
110 /* replace \n, \r & \t's with " " */
111 for(i = 0; i < strlen(str) ;i++){
112 if(str[i] == '\n' || str[i] == '\r' || str[i] == '\t' ){
113 str[i] = ' ';
114 }
115 }
116 g_strstrip(str);
117 /* delete multiple spaces */
118 temp = (char *)malloc(strlen(str) + 1);
119 up_string_pack(temp, str);
120
121 free(str);
122 str = temp;
123
124 /* now, if there is still a white space, then we have a date in the string
125 (it has to be something like "ripe-dbm@ripe.net 20001210") */
126 if(index(str, ' ') != NULL){
127 /*printf("DEBUG: has date\n");*/
128 return 1;
129 }else{
130 /*printf("DEBUG: has NOT date\n");*/
131 return 0;
132 }
133 }
134
135
136
137
138 /* supplies the current date in YYYYMMDD format (for example 20011010) */
139 char * up_get_current_date(){
/* [<][>][^][v][top][bottom][index][help] */
140 /* We will use Glib's functions here */
141
142 char * date;
143 struct tm * time_struct;
144
145 time_t * time_loc;
146
147 time_loc = (time_t *)malloc(sizeof(time_t));
148 time(time_loc);
149
150 time_struct = localtime(time_loc);
151
152 /*printf("DEBUG: Current time is: tm_mday=[%02i], tm_mon=[%02i], tm_year=[%04i]\n",
153 time_struct->tm_mday, time_struct->tm_mon, time_struct->tm_year);*/
154
155 date = (char *)malloc(9);
156 sprintf(date, "%04i%02i%02i",
157 time_struct->tm_year + 1900,
158 time_struct->tm_mon + 1,
159 time_struct->tm_mday);
160 return date;
161 }
162
163
164
165
166
167
168
169
170 /* void add_dates: adds dates to 'changed' attributes which
171 are missing one.
172 Returns 1 if no problems encountered
173 Returns 0 if a problem encountered, and the error string is set */
174 int up_add_dates(GSList * attribute_list, char ** warning_str, char ** error_str){
/* [<][>][^][v][top][bottom][index][help] */
175
176 GSList * next;
177 char * attribute, * current_date;
178 int count_no_date = 0;
179 char * temp;
180
181 *warning_str = NULL;
182 *error_str = NULL;
183
184 /* get the current date in YYYYMMDD format (for example 20011010) */
185 current_date = up_get_current_date();
186 /*printf("DEBUG: got current_date=[%s] from up_get_current_date()\n", current_date);*/
187
188 for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
189 /* is this a 'changed' attribute? */
190 if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
191 /* if this attribute does not have a date in it, add it. Also add
192 a warning message about this */
193 if( !up_changed_has_date((char *)(((attribute_struct *)(next->data))->content))){
194 count_no_date++;
195 attribute = (char *)(((attribute_struct *)(next->data))->content);
196 temp = (char *)malloc(strlen(attribute) + strlen(current_date) + 2 );
197 if(index(attribute, '#')){/* cut off the EOL comments */
198 attribute[index(attribute, '#') - attribute - 1] = '\0';
199 }
200 sprintf(temp, "%s %s", attribute, current_date);
201 ((attribute_struct *)(next->data))->content = temp;
202 free(attribute);
203 /* add a warning message */
204 if( *warning_str == NULL){
205 *warning_str = (char *)malloc(strlen("WARNING date '' added to 'changed' attribute") + 9 );
206 sprintf(*warning_str, "WARNING date '%s' added to 'changed' attribute", current_date);
207 }else{
208 temp = (char *)malloc(strlen(*warning_str) + 1
209 + strlen("WARNING date '' added to 'changed' attribute") + 9 );
210 sprintf(temp, "%s\nWARNING date '%s' added to 'changed' attribute",
211 *warning_str, current_date);
212 free(*warning_str);
213 *warning_str = temp;
214 }
215 }
216 }
217 }
218
219 /* debugging */
220 /*for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
221 printf("DEBUG: A new changed attr is: [%s]\n", (char *)(((attribute_struct *)(next->data))->content));
222 }
223 if(*warning_str != NULL){
224 printf("DEBUG: And *warning_str is: [%s]\n", *warning_str);
225 }
226 */
227 if(count_no_date > 1){
228 *error_str = strdup("***Error: More than one 'changed' attributes without dates");
229 return 0;
230 }else{
231 return 1;
232 }
233
234
235 }
236
237
238
239
240
241
242 /* Checks the order of dates in the given list.
243 If they are in order, returns 1,
244 if not, returns 0 */
245 int up_check_date_order(GSList * list){
/* [<][>][^][v][top][bottom][index][help] */
246
247 GSList * next;
248 char * previous;
249
250 /* if list is empty, return 1 immediately */
251 if(list == NULL){
252 return 1;
253 }
254
255 /* initialize the 'previous' date */
256 previous = strdup("00000000");
257
258 for( next = list; next != NULL ; next = g_slist_next(next)){
259 assert((next->data) != NULL);
260 /* if the new date is smaller than the previous */
261 /*printf("DEBUG: up_check_date_order: will compare 'this'=[%s] and 'previous'=[%s]\n",
262 (char *)(next->data), previous);*/
263 if(strcmp((char *)(next->data), previous) < 0 ){
264 free(previous);
265 return 0;
266 }
267 free(previous);
268 previous = strdup((char *)(next->data));
269 }
270
271 free(previous);
272 /* Reached the end, without finding out-of-order date. Return 1, then */
273 /*printf("DEBUG: up_check_date_order: will return 1\n"); */
274 return 1;
275
276 }
277
278
279
280
281
282
283
284 /* void up_check_changed_attr
285 checks the order of dates in the 'changed' attributes */
286 void up_check_changed_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
/* [<][>][^][v][top][bottom][index][help] */
287
288 GSList * date_list;
289 int res;
290 char ** warning, **error;
291 char * temp;
292
293 warning = (char **)malloc(sizeof(char **));
294 error = (char **)malloc(sizeof(char **));
295
296
297 /* Now, add dates to the "changed" attributes */
298 res = up_add_dates(/*changed_list*/attribute_list, warning, error);
299 if(!res){
300 /* so, add the error string to result's error string */
301 if(result->error_str == NULL){
302 result->error_str = strdup(*error);
303 }else{
304 temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
305 sprintf(temp, "%s\n%s", result->error_str, *error);
306 free(result->error_str);
307 result->error_str = temp;
308 }
309 }
310
311 /* and get the list of dates, we must check their order */
312 date_list = up_get_dates(attribute_list);
313 /* and check the order */
314 res = up_check_date_order(date_list);
315 if(!res){
316 /* so, add the error string to result's error string */
317 if(result->error_str == NULL){
318 result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
319 }else{
320 temp = (char *)malloc(strlen(result->error_str)
321 + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
322 sprintf(temp, "%s\n%s", result->error_str,
323 "***Error: The dates in the 'changed' attributes should be in order");
324 free(result->error_str);
325 result->error_str = temp;
326 }
327 /* and here we have to change the result code of "result" here ... */
328 switch(result->result){
329 case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
330 case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
331 case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
332 case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
333 default: ;
334 }
335 }
336 /*printf("DEBUG: up_check_changed_attr: the return code is=[%i]\n", result->result); */
337 }
338
339
340
341
342
343 int up_check_an_auth_attr(const char * arg, char ** error){
/* [<][>][^][v][top][bottom][index][help] */
344
345 char * attr;
346 int ret = 1;
347 char * cryptpw, * key;
348
349
350 attr = strdup(arg);
351 /* chop the whitespace in hte beginning and end */
352 g_strstrip(attr);
353
354 /* Convert to uppercase */
355 g_strup(attr);
356
357 /* chop the EOL comment off */
358 if(index(attr, '#') != NULL){
359 attr[index(attr, '#') - attr ] = '\0';
360 }
361
362 if(strstr(attr, "MAIL-FROM ") == attr){
363 /* It must have somethings after "MAIL-FROM ", which are
364 supposed to be a regexp */
365 if(strlen(attr) <= strlen("MAIL-FROM ")){
366 /*printf("DEBUG: Error: A regular expression is missing after MAIL-FROM in 'auth' attribute\n");*/
367 ret = 0;
368 }
369 }else if(strstr(attr, "NONE") == attr){
370 /* We mustn't have anything after "NONE" */
371 if(strlen(attr) != strlen("NONE")){
372 *error = strdup("***Error: There mustn't be anything after NONE in 'auth' attribute");
373 /*printf("DEBUG: Error: There mustn't be anything after NONE in 'auth' attribute\n");*/
374 ret = 0;
375 }
376 }else if(strstr(attr, "CRYPT-PW ") == attr){
377 /* The string after CRYPT-PW must be of length 13 and must consist of certain
378 characters */
379 cryptpw = strdup(attr + strlen("CRYPT-PW "));
380 g_strstrip(cryptpw);
381 if(strlen(cryptpw) != 13){
382 *error = strdup("***Error: The crypted password must be 13-character long in 'auth' attribute");
383 /*printf("DEBUG: Error: The crypted password must be 13-character long in 'auth' attribute [%s]\n", cryptpw);*/
384 free(cryptpw);
385 ret = 0;
386 }
387 }else if(strstr(attr, "PGPKEY-") == attr){
388 /* The string after CRYPT-PW must be of length 13 and must consist of certain
389 characters */
390 key = strdup(attr + strlen("PGPKEY-"));
391 g_strchomp(key);
392 if(strlen(key) != 8){
393 *error = strdup("***Error: The PGP key must be 8-character long in 'auth' attribute");
394 /*printf("DEBUG: Error: The PGP key must be 8-character long in 'auth' attribute\n");*/
395
396 free(key);
397 ret = 0;
398 }
399
400 }else{
401 *error = strdup("***Error: 'auth' attribute must start with MAIL-FROM, NONE, PGPKEY- or CRYPT-PW");
402 /*printf("DEBUG: Error: 'auth' attribute must start with MAIL-FROM, NONE, PGPKEY- or CRYPT-PW\n");*/
403 ret = 0;
404 }
405
406 free(attr);
407 return ret;
408 }
409
410
411
412
413
414
415
416 /* void up_check_auth_attr
417 checks the syntax of 'auth' attributes */
418 void up_check_auth_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
/* [<][>][^][v][top][bottom][index][help] */
419
420 //GSList * date_list;
421 int res;
422 char /* ** warning,*/ **error;
423 char * temp;
424 GSList * next;
425
426 //warning = (char **)malloc(sizeof(char **));
427 error = (char **)malloc(sizeof(char **));
428
429 /* loop in the attribute_list, find the 'auth' attribs, and check their syntax */
430 for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
431 /* is this an 'auth' attribute? */
432 if(strcmp((char *)(((attribute_struct *)(next->data))->type), "auth") == 0){
433 /* chech its syntax */
434 res = up_check_an_auth_attr((char *)(((attribute_struct *)(next->data))->content), error);
435 if(!res){
436 /* so, add the error string to result's error string */
437 if(result->error_str == NULL){
438 result->error_str = strdup(*error);
439 }else{
440 temp = (char *)malloc(strlen(result->error_str)
441 + strlen(*error) + 2);
442 sprintf(temp, "%s\n%s", result->error_str,
443 *error);
444 free(result->error_str);
445 result->error_str = temp;
446 }
447 /* and here we have to change the result code of "result" here ... */
448 switch(result->result){
449 case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
450 case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
451 case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
452 case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
453 default: ;
454 }
455 }
456 }
457 }
458 /*printf("DEBUG: up_check_auth_attr: the return code is=[%i]\n", result->result); */
459 }
460
461
462
463
464
465
466
467
468
469
470
471 /* Constructs a list of all attributes of an object, and returns it
472 as a list of attribute_struct */
473 GSList * up_get_attribute_list(Object * o, char * text){
/* [<][>][^][v][top][bottom][index][help] */
474
475 char * value = NULL;
476 Attr *attr;
477 GSList *list_of_attributes = NULL;
478 attribute_struct * attribute;
479
480 for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
481 value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
482 strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
483 attr->len - strlen(attr->type->name()) -2 );
484 value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
485 if(tracing) {
486 cout << "TRACING: get_attributes: adding " << g_strstrip(value) << endl;
487 }
488 attribute = (attribute_struct *)malloc(sizeof(attribute_struct));
489 attribute->content = value;
490 attribute->type = strdup(attr->type->name());
491 list_of_attributes = g_slist_append(list_of_attributes, attribute);
492 }
493
494
495 return list_of_attributes;
496
497 }
498
499
500
501
502
503 void up_reconstruct_object(GSList * attr_list, external_syntax_struct *result){
/* [<][>][^][v][top][bottom][index][help] */
504
505 char * recons_obj = NULL;
506 char * temp;
507 char * content, * type;
508 GSList * next;
509
510 for( next = attr_list; next != NULL ; next = g_slist_next(next) ){
511
512 content = strdup((char *)(((attribute_struct *)(next->data))->content));
513 type = strdup((char *)(((attribute_struct *)(next->data))->type));
514
515 if(recons_obj == NULL){
516 recons_obj = (char *)malloc(12 + strlen(content) + 1 );
517 /* trim the white spaces in the beginning */
518 g_strchug(content);
519
520 /* add ':' at the end of 'type' */
521 temp = (char *)malloc(strlen(type) + 2);
522 sprintf(temp, "%s:", type);
523 free(type);
524 type = temp;
525
526 sprintf(recons_obj, "%-12s%s", type, content);
527 }else{
528 /* trim the white spaces in the beginning */
529 g_strchug(content);
530
531 /* add ':' at the end of 'type' */
532 temp = (char *)malloc(strlen(type) + 2);
533 sprintf(temp, "%s:", type);
534 free(type);
535 type = temp;
536
537 temp = (char *)malloc(strlen(recons_obj) + 12 + strlen(content) + 3 );
538 sprintf(temp, "%s\n%-12s%s", recons_obj, type, content);
539 free(recons_obj);
540 recons_obj = temp;
541 }
542
543 }
544
545 /*printf("DEBUG: The reconstructed object is=[%s]\n", recons_obj);*/
546 result->new_obj = recons_obj;
547
548 }
549
550
551
552
553
554 external_syntax_struct * UP_check_external_syntax(Object * arg, char * obj_text){
/* [<][>][^][v][top][bottom][index][help] */
555
556 external_syntax_struct *result;
557 GSList * attribute_list;
558
559
560
561 /*printf("DEBUG: check_external_syntax is running\n"); */
562
563 result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
564
565 /* initialize the struct */
566 result->result = 0;
567 result->error_str = strdup("");
568 result->warning_str = strdup("");
569
570 /* get a list of all attributes */
571 attribute_list = up_get_attribute_list(arg, obj_text);
572
573 up_check_changed_attr(arg, obj_text, attribute_list, result);
574 up_check_auth_attr (arg, obj_text, attribute_list, result);
575
576
577 up_reconstruct_object(attribute_list, result);
578 /*printf("DEBUG: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);*/
579 /*printf("DEBUG: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);*/
580 return result;
581 }