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.4 $
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 list = g_slist_append (list, temp);
84 }
85 }
86
87 return list;
88 }
89
90
91
92
93 /* Does the 'changed' attribute we got have a date already?
94 Returns 1 if it does, 0 if not. */
95 int up_changed_has_date(char * arg){
/* [<][>][^][v][top][bottom][index][help] */
96
97 int i;
98 char * str;
99 char * temp;
100
101 str = strdup(arg);
102
103 /* cut off the EOL comments */
104 if(index(str, '#')){
105 str[index(str, '#') - str - 1 ] = '\0';
106 }
107
108 /* replace \n, \r & \t's with " " */
109 for(i = 0; i < strlen(str) ;i++){
110 if(str[i] == '\n' || str[i] == '\r' || str[i] == '\t' ){
111 str[i] = ' ';
112 }
113 }
114 g_strstrip(str);
115 /* delete multiple spaces */
116 temp = (char *)malloc(strlen(str) + 1);
117 up_string_pack(temp, str);
118
119 free(str);
120 str = temp;
121
122 /* now, if there is still a white space, then we have a date in the string
123 (it has to be something like "ripe-dbm@ripe.net 20001210") */
124 if(index(str, ' ') != NULL){
125 return 1;
126 }else{
127 return 0;
128 }
129 }
130
131
132
133
134 /* supplies the current date in YYYYMMDD format (for example 20011010) */
135 char * up_get_current_date(){
/* [<][>][^][v][top][bottom][index][help] */
136 /* We will use Glib's functions here */
137
138 char * date;
139 struct tm * time_struct;
140
141 time_t * time_loc;
142
143 time_loc = (time_t *)malloc(sizeof(time_t));
144 time(time_loc);
145
146 time_struct = localtime(time_loc);
147
148
149 date = (char *)malloc(9);
150 sprintf(date, "%04i%02i%02i",
151 time_struct->tm_year + 1900,
152 time_struct->tm_mon + 1,
153 time_struct->tm_mday);
154 return date;
155 }
156
157
158
159
160
161
162
163
164 /* void add_dates: adds dates to 'changed' attributes which
165 are missing one.
166 Returns 1 if no problems encountered
167 Returns 0 if a problem encountered, and the error string is set */
168 int up_add_dates(GSList * attribute_list, char ** warning_str, char ** error_str){
/* [<][>][^][v][top][bottom][index][help] */
169
170 GSList * next;
171 char * attribute, * current_date;
172 int count_no_date = 0;
173 char * temp;
174
175 *warning_str = NULL;
176 *error_str = NULL;
177
178 /* get the current date in YYYYMMDD format (for example 20011010) */
179 current_date = up_get_current_date();
180
181 for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
182 /* is this a 'changed' attribute? */
183 if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
184 /* if this attribute does not have a date in it, add it. Also add
185 a warning message about this */
186 if( !up_changed_has_date((char *)(((attribute_struct *)(next->data))->content))){
187 count_no_date++;
188 attribute = (char *)(((attribute_struct *)(next->data))->content);
189 temp = (char *)malloc(strlen(attribute) + strlen(current_date) + 2 );
190 if(index(attribute, '#')){/* cut off the EOL comments */
191 attribute[index(attribute, '#') - attribute - 1] = '\0';
192 }
193 sprintf(temp, "%s %s", attribute, current_date);
194 ((attribute_struct *)(next->data))->content = temp;
195 free(attribute);
196 /* add a warning message */
197 if( *warning_str == NULL){
198 *warning_str = (char *)malloc(strlen("WARNING date '' added to 'changed' attribute") + 9 );
199 sprintf(*warning_str, "WARNING date '%s' added to 'changed' attribute", current_date);
200 }else{
201 temp = (char *)malloc(strlen(*warning_str) + 1
202 + strlen("WARNING date '' added to 'changed' attribute") + 9 );
203 sprintf(temp, "%s\nWARNING date '%s' added to 'changed' attribute",
204 *warning_str, current_date);
205 free(*warning_str);
206 *warning_str = temp;
207 }
208 }
209 }
210 }
211
212 if(count_no_date > 1){
213 *error_str = strdup("***Error: More than one 'changed' attributes without dates");
214 return 0;
215 }else{
216 return 1;
217 }
218
219
220 }
221
222
223
224
225
226
227 /* Checks the order of dates in the given list.
228 If they are in order, returns 1,
229 if not, returns 0 */
230 int up_check_date_order(GSList * list){
/* [<][>][^][v][top][bottom][index][help] */
231
232 GSList * next;
233 char * previous;
234
235 /* if list is empty, return 1 immediately */
236 if(list == NULL){
237 return 1;
238 }
239
240 /* initialize the 'previous' date */
241 previous = strdup("00000000");
242
243 for( next = list; next != NULL ; next = g_slist_next(next)){
244 assert((next->data) != NULL);
245 /* if the new date is smaller than the previous */
246 if(strcmp((char *)(next->data), previous) < 0 ){
247 free(previous);
248 return 0;
249 }
250 free(previous);
251 previous = strdup((char *)(next->data));
252 }
253
254 free(previous);
255 /* Reached the end, without finding out-of-order date. Return 1, then */
256 return 1;
257
258 }
259
260
261
262
263
264
265
266 /* void up_check_changed_attr
267 checks the order of dates in the 'changed' attributes */
268 void up_check_changed_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
/* [<][>][^][v][top][bottom][index][help] */
269
270 GSList * date_list;
271 int res;
272 char ** warning, **error;
273 char * temp;
274
275 warning = (char **)malloc(sizeof(char **));
276 error = (char **)malloc(sizeof(char **));
277
278
279 /* Now, add dates to the "changed" attributes */
280 res = up_add_dates(/*changed_list*/attribute_list, warning, error);
281 if(!res){
282 /* so, add the error string to result's error string */
283 if(result->error_str == NULL){
284 result->error_str = strdup(*error);
285 }else{
286 temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
287 sprintf(temp, "%s\n%s", result->error_str, *error);
288 free(result->error_str);
289 result->error_str = temp;
290 }
291 }
292
293 /* and get the list of dates, we must check their order */
294 date_list = up_get_dates(attribute_list);
295 /* and check the order */
296 res = up_check_date_order(date_list);
297 if(!res){
298 /* so, add the error string to result's error string */
299 if(result->error_str == NULL){
300 result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
301 }else{
302 temp = (char *)malloc(strlen(result->error_str)
303 + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
304 sprintf(temp, "%s\n%s", result->error_str,
305 "***Error: The dates in the 'changed' attributes should be in order");
306 free(result->error_str);
307 result->error_str = temp;
308 }
309 /* and here we have to change the result code of "result" here ... */
310 switch(result->result){
311 case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
312 case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
313 case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
314 case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
315 default: ;
316 }
317 }
318 }
319
320
321
322
323
324 int up_check_an_auth_attr(const char * arg, char ** error){
/* [<][>][^][v][top][bottom][index][help] */
325
326 char * attr;
327 int ret = 1;
328 char * cryptpw, * key;
329
330
331 attr = strdup(arg);
332 /* chop the whitespace in hte beginning and end */
333 g_strstrip(attr);
334
335 /* Convert to uppercase */
336 g_strup(attr);
337
338 /* chop the EOL comment off */
339 if(index(attr, '#') != NULL){
340 attr[index(attr, '#') - attr ] = '\0';
341 }
342
343 if(strstr(attr, "MAIL-FROM ") == attr){
344 /* It must have somethings after "MAIL-FROM ", which are
345 supposed to be a regexp */
346 if(strlen(attr) <= strlen("MAIL-FROM ")){
347 ret = 0;
348 }
349 }else if(strstr(attr, "NONE") == attr){
350 /* We mustn't have anything after "NONE" */
351 if(strlen(attr) != strlen("NONE")){
352 *error = strdup("***Error: There mustn't be anything after NONE in 'auth' attribute");
353 ret = 0;
354 }
355 }else if(strstr(attr, "CRYPT-PW ") == attr){
356 /* The string after CRYPT-PW must be of length 13 and must consist of certain
357 characters */
358 cryptpw = strdup(attr + strlen("CRYPT-PW "));
359 g_strstrip(cryptpw);
360 if(strlen(cryptpw) != 13){
361 *error = strdup("***Error: The crypted password must be 13-character long in 'auth' attribute");
362 free(cryptpw);
363 ret = 0;
364 }
365 }else if(strstr(attr, "PGPKEY-") == attr){
366 /* The string after CRYPT-PW must be of length 13 and must consist of certain
367 characters */
368 key = strdup(attr + strlen("PGPKEY-"));
369 g_strchomp(key);
370 if(strlen(key) != 8){
371 *error = strdup("***Error: The PGP key must be 8-character long in 'auth' attribute");
372
373 free(key);
374 ret = 0;
375 }
376
377 }else{
378 *error = strdup("***Error: 'auth' attribute must start with MAIL-FROM, NONE, PGPKEY- or CRYPT-PW");
379 ret = 0;
380 }
381
382 free(attr);
383 return ret;
384 }
385
386
387
388
389
390
391
392 /* void up_check_auth_attr
393 checks the syntax of 'auth' attributes */
394 void up_check_auth_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
/* [<][>][^][v][top][bottom][index][help] */
395
396 //GSList * date_list;
397 int res;
398 char /* ** warning,*/ **error;
399 char * temp;
400 GSList * next;
401
402 //warning = (char **)malloc(sizeof(char **));
403 error = (char **)malloc(sizeof(char **));
404
405 /* loop in the attribute_list, find the 'auth' attribs, and check their syntax */
406 for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
407 /* is this an 'auth' attribute? */
408 if(strcmp((char *)(((attribute_struct *)(next->data))->type), "auth") == 0){
409 /* chech its syntax */
410 res = up_check_an_auth_attr((char *)(((attribute_struct *)(next->data))->content), error);
411 if(!res){
412 /* so, add the error string to result's error string */
413 if(result->error_str == NULL){
414 result->error_str = strdup(*error);
415 }else{
416 temp = (char *)malloc(strlen(result->error_str)
417 + strlen(*error) + 2);
418 sprintf(temp, "%s\n%s", result->error_str,
419 *error);
420 free(result->error_str);
421 result->error_str = temp;
422 }
423 /* and here we have to change the result code of "result" here ... */
424 switch(result->result){
425 case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
426 case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
427 case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
428 case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
429 default: ;
430 }
431 }
432 }
433 }
434 }
435
436
437
438
439
440
441
442
443
444
445
446 /* Constructs a list of all attributes of an object, and returns it
447 as a list of attribute_struct */
448 GSList * up_get_attribute_list(Object * o, char * text){
/* [<][>][^][v][top][bottom][index][help] */
449
450 char * value = NULL;
451 Attr *attr;
452 GSList *list_of_attributes = NULL;
453 attribute_struct * attribute;
454
455 for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
456 value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
457 strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
458 attr->len - strlen(attr->type->name()) -2 );
459 value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
460 if(tracing) {
461 cout << "TRACING: up_get_attributes: adding " << g_strstrip(value) << endl;
462 }
463 attribute = (attribute_struct *)malloc(sizeof(attribute_struct));
464 attribute->content = value;
465 attribute->type = strdup(attr->type->name());
466 list_of_attributes = g_slist_append(list_of_attributes, attribute);
467 }
468
469
470 return list_of_attributes;
471
472 }
473
474
475
476
477
478 void up_reconstruct_object(GSList * attr_list, external_syntax_struct *result){
/* [<][>][^][v][top][bottom][index][help] */
479
480 char * recons_obj = NULL;
481 char * temp;
482 char * content, * type;
483 GSList * next;
484
485
486
487
488 for( next = attr_list; next != NULL ; next = g_slist_next(next) ){
489
490 content = strdup((char *)(((attribute_struct *)(next->data))->content));
491 type = strdup((char *)(((attribute_struct *)(next->data))->type));
492
493 if(tracing){
494 printf("TRACING: up_reconstruct_object:[%s:%s]\n", type, content);
495 }
496
497 if(recons_obj == NULL){
498 recons_obj = (char *)malloc(13 + strlen(content) + 1 );
499 /* trim the white spaces in the beginning */
500 g_strchug(content);
501
502 /* add ':' at the end of 'type' */
503 temp = (char *)malloc(strlen(type) + 2);
504 sprintf(temp, "%s:", type);
505 free(type);
506 type = temp;
507
508 sprintf(recons_obj, "%-13s%s", type, content);
509 }else{
510 /* trim the white spaces in the beginning */
511 g_strchug(content);
512
513 /* add ':' at the end of 'type' */
514 temp = (char *)malloc(strlen(type) + 2);
515 sprintf(temp, "%s:", type);
516 free(type);
517 type = temp;
518
519 temp = (char *)malloc(strlen(recons_obj) + 13 + strlen(content) + 3 );
520 sprintf(temp, "%s\n%-13s%s", recons_obj, type, content);
521 free(recons_obj);
522 recons_obj = temp;
523 }
524
525 }
526
527 result->new_obj = recons_obj;
528
529 }
530
531
532
533
534
535 external_syntax_struct * UP_check_external_syntax(Object * arg, char * obj_text){
/* [<][>][^][v][top][bottom][index][help] */
536
537 external_syntax_struct *result;
538 GSList * attribute_list;
539
540
541
542
543 result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
544
545 /* initialize the struct */
546 result->result = 0;
547 result->error_str = strdup("");
548 result->warning_str = strdup("");
549
550 /* get a list of all attributes */
551 attribute_list = up_get_attribute_list(arg, obj_text);
552
553 up_check_changed_attr(arg, obj_text, attribute_list, result);
554 up_check_auth_attr (arg, obj_text, attribute_list, result);
555
556
557 up_reconstruct_object(attribute_list, result);
558
559 if(tracing){
560 printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
561 printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
562 }
563
564 return result;
565 }