modules/up/UP_extrnl_syntax.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. up_get_dates
  2. up_changed_has_date
  3. UP_get_current_date
  4. up_add_dates
  5. up_check_date_order
  6. up_check_date
  7. up_check_dates_syntax
  8. up_check_changed_attr
  9. up_check_an_auth_attr
  10. up_check_auth_attr
  11. up_check_an_inetnum_attr
  12. up_check_inetnum_attr
  13. up_add_keycert_attrs
  14. up_get_attribute_list
  15. up_reconstruct_object
  16. UP_check_external_syntax
  17. UP_generate_kc_attrs

   1 /***************************************
   2   $Revision: 1.10 $
   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 #define UP_DATE_OK      0
  40 #define UP_DATE_SYNERR  1
  41 #define UP_DATE_FUTURE  2
  42 #define UP_DATE_TOOSMALL        3
  43 #define UP_DATE_INVMONTH        4
  44 #define UP_DATE_INVDAY  5
  45 #define UP_DATE_WRONGFORMAT 6
  46 #define UP_DATE_NOK    7
  47 
  48 
  49 
  50 char * up_date_errmsgs[]={
  51 
  52   "OK",
  53   "Syntax error in date of 'changed' attribute",
  54   "Date in the future in 'changed' attribute",
  55   "Date is older than the database itself in 'changed' attribute",
  56   "Invalid month in date in 'changed' attribute",
  57   "Invalid day in date in 'changed' attribute",
  58   "Date must be in YYYYMMDD format in 'change' attribute",
  59   "Syntax error in date of 'changed' attribute"
  60 };
  61 
  62 
  63 extern int tracing;
  64 
  65 extern char * fingerprint;
  66 extern char * keyowner;
  67 
  68 
  69 
  70 /* obtains a list of dates in the given 
  71    list of attributes (GSList of attribute_struct) */
  72 GSList * up_get_dates(GSList * attribute_list){
     /* [<][>][^][v][top][bottom][index][help] */
  73 
  74   GSList * next;
  75   char * temp, * str; 
  76   int i;
  77   GSList * list = NULL;
  78 
  79   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
  80     /* is this a 'changed' attribute? */
  81     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
  82       temp = strdup(((attribute_struct *)(next->data))->content);
  83 
  84       /* delete the part after '#', inclusive */
  85       if(index(temp,'#') != NULL){
  86         temp[index(temp, '#') - temp] = '\0';
  87       }
  88       /* replace \n, \r & \t's with " " */
  89       for(i = 0; i < strlen(temp) ;i++){
  90         if(temp[i] == '\n' || temp[i] == '\r' || temp[i] == '\t' ){
  91           temp[i] = ' ';
  92         }
  93       }
  94       g_strstrip(temp);
  95       /* delete multiple spaces */
  96       str = (char *)malloc(strlen(temp) + 1);
  97       up_string_pack(str, temp);
  98       free(temp); 
  99 
 100       /* now, we have the 'changed' attribute's content in "normalized" form 
 101          We are sure it contains a date. So, it must be the second (and last)
 102          word in the attrib. */
 103       assert(index(str,' ') != NULL);
 104       temp = (char *)malloc(strlen(str) - (index(str,' ') - str ));
 105       temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1);
 106       temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */
 107       list = g_slist_append (list, temp);   
 108     }
 109   }
 110   
 111   return list;
 112 }
 113 
 114 
 115 
 116 
 117 /* Does the 'changed' attribute we got have a date already?
 118    Returns 1 if it does, 0 if not. */
 119 int up_changed_has_date(char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 120   
 121   int i;
 122   char * str;
 123   char * temp;
 124   
 125   str = strdup(arg);
 126 
 127   /* cut off the EOL comments */
 128   if(index(str, '#')){
 129     str[index(str, '#') - str - 1 ] = '\0';
 130   }
 131   
 132   /* replace \n, \r & \t's with " " */
 133   for(i = 0; i < strlen(str) ;i++){
 134     if(str[i] == '\n' || str[i] == '\r' || str[i] == '\t' ){
 135       str[i] = ' ';
 136     }
 137   }
 138   g_strstrip(str);
 139   /* delete multiple spaces */
 140   temp = (char *)malloc(strlen(str) + 1);
 141   up_string_pack(temp, str);
 142   
 143   free(str);
 144   str = temp;
 145   
 146   /* now, if there is still a white space, then we have a date in the string
 147      (it has to be something like "ripe-dbm@ripe.net 20001210") */
 148   if(index(str, ' ') != NULL){
 149     return 1; 
 150   }else{
 151     return 0;
 152   }
 153 }
 154 
 155 
 156 
 157 
 158 /* supplies the current date in YYYYMMDD format (for example 20011010) */
 159 char * UP_get_current_date(){
     /* [<][>][^][v][top][bottom][index][help] */
 160   /* We will use Glib's functions here */
 161 
 162   char * date;
 163   struct tm * time_struct;
 164   
 165   time_t * time_loc;
 166 
 167   time_loc = (time_t *)malloc(sizeof(time_t));
 168   time(time_loc);
 169   
 170   time_struct = localtime(time_loc);
 171 
 172 
 173   date = (char *)malloc(9);
 174   sprintf(date, "%04i%02i%02i", 
 175           time_struct->tm_year + 1900, 
 176           time_struct->tm_mon + 1,
 177           time_struct->tm_mday);
 178   return date;
 179 }
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 /* int up_add_dates: adds dates to 'changed' attributes which 
 189      are missing one.
 190      Returns 1 if no problems encountered
 191      Returns 0 if a problem encountered, and the error string is set */
 192 int up_add_dates(GSList * attribute_list, char ** warning_str, char ** error_str){
     /* [<][>][^][v][top][bottom][index][help] */
 193   
 194   GSList * next;
 195   char * attribute, * current_date;
 196   int count_no_date = 0; 
 197   char * temp;
 198   
 199   *warning_str = NULL;
 200   *error_str   = NULL;
 201 
 202   /* get the current date in YYYYMMDD format (for example 20011010) */
 203   current_date = UP_get_current_date();
 204   
 205   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 206     /* is this a 'changed' attribute? */
 207     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
 208       /* if this attribute does not have a date in it, add it. Also add 
 209           a warning message about this */
 210       if( !up_changed_has_date((char *)(((attribute_struct *)(next->data))->content))){
 211         count_no_date++;
 212         attribute = (char *)(((attribute_struct *)(next->data))->content);
 213         temp = (char *)malloc(strlen(attribute) + strlen(current_date) + 2 );
 214         if(index(attribute, '#')){/* cut off the EOL comments */
 215           attribute[index(attribute, '#') - attribute - 1] = '\0';
 216         }
 217         sprintf(temp, "%s %s", attribute, current_date);
 218         ((attribute_struct *)(next->data))->content = temp;
 219         free(attribute);
 220         /* add a warning message */
 221         if( *warning_str == NULL){
 222           *warning_str = (char *)malloc(strlen("WARNING  date '' added to 'changed' attribute") + 9 );
 223           sprintf(*warning_str, "WARNING  date '%s' added to 'changed' attribute", current_date);
 224         }else{
 225           temp = (char *)malloc(strlen(*warning_str) + 1 
 226                                        + strlen("WARNING  date '' added to 'changed' attribute") + 9 );
 227           sprintf(temp, "%s\nWARNING  date '%s' added to 'changed' attribute", 
 228                               *warning_str, current_date);
 229           free(*warning_str);
 230           *warning_str = temp; 
 231         }
 232       }
 233     }
 234   }
 235   
 236   if(count_no_date > 1){ 
 237     *error_str = strdup("***Error: More than one 'changed' attributes without dates");
 238     return 0;
 239   }else{
 240     return 1;
 241   }
 242   
 243 
 244 }
 245 
 246 
 247 
 248 
 249 
 250 
 251 /* Checks the order of dates in the given list. 
 252    If they are in order, returns 1, 
 253    if not, returns 0 */
 254 int up_check_date_order(GSList * list){
     /* [<][>][^][v][top][bottom][index][help] */
 255    
 256   GSList * next;
 257   char * previous;
 258 
 259   /* if list is empty, return 1 immediately */
 260   if(list == NULL){
 261     return 1;
 262   }
 263 
 264   /* initialize the 'previous' date */
 265   previous = strdup("00000000");
 266    
 267   for( next = list; next != NULL ; next = g_slist_next(next)){
 268     assert((next->data) != NULL);
 269     /* if the new date is smaller than the previous */
 270     if(strcmp((char *)(next->data), previous) < 0 ){
 271       free(previous);
 272       return 0;
 273     }
 274     free(previous);
 275     previous = strdup((char *)(next->data));
 276   }
 277    
 278   free(previous);
 279   /* Reached the end, without finding out-of-order date. Return 1, then */
 280   return 1; 
 281    
 282 }
 283 
 284 
 285 
 286 
 287 
 288 /* up_check_date: checks the syntax of the date, given as the only
 289    argument (char *). The argument is checked if it is in YYYYMMDD
 290    format, and returns an error code accordingly */
 291 int up_check_date(const char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 292 
 293   int date_int; /* integer representation of the date (arg) */
 294   char * current_date;
 295   int year, month, day; /* integers for the components of the date */
 296 
 297 
 298   errno = 0;
 299   date_int = atoi(arg);
 300 
 301       
 302   if(errno != 0){/* there was an error in the conversion, syntax error */
 303     return UP_DATE_SYNERR;
 304   }
 305     
 306   /* wrong format */
 307   if(date_int <= 10000000 ){ /* the date is not in YYYYMMDD format */
 308     return UP_DATE_WRONGFORMAT;
 309   }
 310 
 311 
 312   /* check if it is too small */  
 313   if(date_int <= 19880000 ){ /* the date is older than the DB itself! */
 314     return UP_DATE_TOOSMALL;
 315   }
 316 
 317   /* check if it is too big */
 318   if(date_int >= 100000000 ){/* too big: syntax error */
 319     return UP_DATE_SYNERR;
 320   }
 321 
 322   /* and now check year, month and day components */
 323   year = date_int / 10000;
 324   month = (date_int - (year * 10000) ) / 100;
 325   day = (date_int % 100);
 326   
 327   /* check year */
 328   if(year < 1988 ){
 329     return UP_DATE_TOOSMALL;
 330   }
 331 
 332   /* check month */
 333   if(month < 1 || month > 12){
 334     return UP_DATE_INVMONTH;
 335   }
 336 
 337   /* check day */
 338   if(day < 1 || day > 31){
 339     return UP_DATE_INVDAY;
 340   }
 341 
 342   switch( month ){
 343     case 1: case 3: case 5: case 7:
 344     case 8: case 10: case 12:
 345          if (day > 31){
 346            return UP_DATE_INVDAY;
 347          };
 348          break;
 349     case 2: 
 350          if ( (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && (day > 29 )){ /* leap year */
 351            return UP_DATE_INVDAY;
 352          }else if( (!(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) && (day > 28) ){/* non-leap year */
 353            return UP_DATE_INVDAY;
 354          };
 355          break;
 356     case 4: case 6: case 9: case 11:
 357          if (day > 30){
 358            return UP_DATE_INVDAY;
 359          };
 360          break;
 361     default: return UP_DATE_INVMONTH;
 362 
 363   }
 364 
 365   /* check if the arg is in the future or not */
 366   current_date = UP_get_current_date();
 367   if(strcmp(current_date, arg) < 0 ){/* arg is in the future */
 368     free(current_date);
 369     return UP_DATE_FUTURE;
 370   }
 371   free(current_date);
 372   
 373     
 374   return UP_DATE_OK;
 375   
 376 }
 377 
 378 
 379 
 380 
 381 
 382 
 383 
 384 
 385 
 386 
 387 /* Checks the syntax of the dates in the list */
 388 date_syntax_struct * up_check_dates_syntax(GSList * list){
     /* [<][>][^][v][top][bottom][index][help] */
 389    
 390   GSList * next;
 391   char * previous;
 392   date_syntax_struct * result;
 393   int res;
 394 
 395   /* initialize the result struct */
 396   result = (date_syntax_struct *)malloc(sizeof(date_syntax_struct));
 397   result->result = UP_DATE_OK;
 398   result->error_str = NULL;
 399 
 400   /* if list is empty, return immediately */
 401   if(list == NULL){
 402     return result;
 403   }
 404 
 405   /* loop through the members of the list, check each of them */
 406   for( next = list; next != NULL ; next = g_slist_next(next)){
 407     assert((next->data) != NULL);
 408     
 409     /* check the date */
 410     res = up_check_date((char *)next->data);
 411     switch (res){
 412       case UP_DATE_OK: break;
 413       
 414       case UP_DATE_FUTURE:
 415       case UP_DATE_TOOSMALL:
 416       case UP_DATE_INVDAY:
 417       case UP_DATE_INVMONTH:
 418       case UP_DATE_WRONGFORMAT:
 419 
 420              if(result->error_str == NULL){
 421                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[res]) 
 422                                                   + strlen(": ") + strlen((char *)next->data) + 1);
 423                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[res],
 424                        (char *)next->data);
 425              }else{
 426                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 
 427                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[res]) 
 428                                                    + strlen(": ") + strlen((char *)next->data) + 1);
 429                sprintf(result->error_str, "%s\n***Error: %s: %s",
 430                        result->error_str, up_date_errmsgs[res], (char *)next->data);
 431              }
 432              result->result = UP_DATE_NOK; /* Not OK */
 433 
 434              break;
 435              
 436              
 437       case UP_DATE_SYNERR: /* syntax error in the date */
 438 
 439       default:
 440              if(result->error_str == NULL){
 441                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 
 442                                                   + strlen(": ") + strlen((char *)next->data) + 1);
 443                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[UP_DATE_SYNERR],
 444                        (char *)next->data);
 445              }else{
 446                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 
 447                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 
 448                                                    + strlen(": ") + strlen((char *)next->data) + 1);
 449                sprintf(result->error_str, "%s\n***Error: %s: %s",
 450                        result->error_str, up_date_errmsgs[UP_DATE_SYNERR], (char *)next->data);
 451              }
 452              result->result = UP_DATE_NOK; /* Not OK */
 453              break;
 454     }
 455 
 456   }
 457   
 458   
 459   return result;
 460    
 461 }
 462 
 463 
 464 
 465 
 466 
 467 
 468 
 469 
 470 
 471 
 472 /* void up_check_changed_attr 
 473    checks the order of dates in the 'changed' attributes */
 474 void up_check_changed_attr(Object * obj, char * obj_text, GSList * attribute_list, 
     /* [<][>][^][v][top][bottom][index][help] */
 475                            external_syntax_struct * result){
 476 
 477   GSList * date_list;
 478   int res;
 479   char ** warning, **error;
 480   char * temp;
 481   date_syntax_struct * date_check_res;
 482 
 483 
 484   warning = (char **)malloc(sizeof(char **));
 485   error   = (char **)malloc(sizeof(char **));
 486    
 487 
 488   /* Now, add dates to the "changed" attributes */
 489   res = up_add_dates(/*changed_list*/attribute_list, warning, error);
 490   if(!res){
 491     /* so, add the error string to result's error string */
 492     if(result->error_str == NULL){
 493       result->error_str = strdup(*error);
 494     }else{
 495       temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
 496       sprintf(temp, "%s\n%s", result->error_str, *error);
 497       free(result->error_str);
 498       result->error_str = temp;
 499     }
 500   }
 501 
 502   /* and get the list of dates, we must check their order */
 503   date_list = up_get_dates(attribute_list);
 504   /* and check the order */ 
 505   res = up_check_date_order(date_list);
 506   if(!res){
 507     /* so, add the error string to result's error string */
 508     if(result->error_str == NULL){
 509       result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
 510     }else{
 511       temp = (char *)malloc(strlen(result->error_str) 
 512               + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
 513       sprintf(temp, "%s\n%s", result->error_str, 
 514               "***Error: The dates in the 'changed' attributes should be in order");
 515       free(result->error_str);
 516       result->error_str = temp;
 517     }
 518     /* and here we have to change the result code of "result" here ... */
 519     switch(result->result){
 520       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 521       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 522       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 523       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 524       default: ;
 525     }
 526   }
 527 
 528   /* check the syntax of dates */
 529   date_check_res = up_check_dates_syntax(date_list);
 530   if(date_check_res->result != UP_DATE_OK){
 531     /* so, add the error string to result's error string */
 532     if(result->error_str == NULL){
 533       result->error_str = strdup(date_check_res->error_str);
 534     }else{
 535       temp = (char *)malloc(strlen(result->error_str) 
 536               + strlen(date_check_res->error_str) + 2);
 537       sprintf(temp, "%s\n%s", result->error_str, 
 538               date_check_res->error_str);
 539       free(result->error_str);
 540       result->error_str = temp;
 541     }
 542     /* and here we have to change the result code of "result" here ... */
 543     switch(result->result){
 544       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 545       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 546       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 547       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 548       default: ;
 549     }
 550     
 551   }
 552   
 553 }
 554 
 555 
 556 
 557 
 558 
 559 int up_check_an_auth_attr(const char * arg, char ** error){
     /* [<][>][^][v][top][bottom][index][help] */
 560 
 561   char * attr;
 562   int ret = 1;
 563   char * cryptpw, * key;
 564 
 565 
 566   attr = strdup(arg);
 567   /*  chop the whitespace in hte beginning and end */
 568   g_strstrip(attr);
 569 
 570   /* Convert to uppercase  */
 571   g_strup(attr);
 572 
 573   /* chop the EOL comment off */
 574   if(index(attr, '#') != NULL){
 575     attr[index(attr, '#') - attr ] = '\0';
 576   }
 577 
 578   if(strstr(attr, "MAIL-FROM ") == attr){
 579     /* It must have somethings after "MAIL-FROM ", which are
 580       supposed to be a regexp */
 581     if(strlen(attr) <= strlen("MAIL-FROM ")){
 582       ret = 0;
 583     }
 584   }else if(strstr(attr, "NONE") == attr){
 585     /* We mustn't have anything after "NONE"  */
 586     if(strlen(attr) != strlen("NONE")){
 587       *error = strdup("***Error: There mustn't be anything after NONE in 'auth' attribute");
 588       ret = 0;
 589     }
 590   }else if(strstr(attr, "CRYPT-PW ") == attr){
 591     /* The string after CRYPT-PW must be of length 13 and must consist of certain
 592        characters */
 593     cryptpw = strdup(attr + strlen("CRYPT-PW "));
 594     g_strstrip(cryptpw);
 595     if(strlen(cryptpw) != 13){
 596       *error = strdup("***Error: The crypted password must be 13-character long in 'auth' attribute");
 597       free(cryptpw);
 598       ret = 0;
 599     }
 600   }else if(strstr(attr, "PGPKEY-") == attr){
 601     /* The string after CRYPT-PW must be of length 13 and must consist of certain
 602        characters */
 603     key = strdup(attr + strlen("PGPKEY-"));
 604     g_strchomp(key);
 605     if(strlen(key) != 8){
 606       *error = strdup("***Error: The PGP key must be 8-character long in 'auth' attribute");
 607       
 608       free(key);
 609       ret = 0;
 610     }
 611 
 612   }else{
 613     *error = strdup("***Error: 'auth' attribute must start with MAIL-FROM, NONE, PGPKEY- or CRYPT-PW");
 614     ret = 0;
 615   }
 616 
 617   free(attr);
 618   return ret;
 619 }
 620 
 621 
 622 
 623 
 624 
 625 
 626 
 627 /* void up_check_auth_attr 
 628    checks the syntax of 'auth' attributes */
 629 void up_check_auth_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 630 
 631   int res;
 632   char **error;
 633   char * temp;
 634   GSList * next;
 635 
 636   error   = (char **)malloc(sizeof(char **));
 637 
 638   /* loop in the attribute_list, find the 'auth' attribs, and check their syntax */
 639   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 640     /* is this an 'auth' attribute? */
 641     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "auth") == 0){
 642       /* chech its syntax */
 643       res = up_check_an_auth_attr((char *)(((attribute_struct *)(next->data))->content), error);
 644       if(!res){
 645         /* so, add the error string to result's error string */
 646         if(result->error_str == NULL){
 647           result->error_str = strdup(*error);
 648         }else{
 649           temp = (char *)malloc(strlen(result->error_str) 
 650                   + strlen(*error) + 2);
 651           sprintf(temp, "%s\n%s", result->error_str, 
 652                   *error);
 653           free(result->error_str);
 654           result->error_str = temp;
 655         }
 656         /* and here we have to change the result code of "result" here ... */
 657         switch(result->result){
 658           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 659           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 660           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 661           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 662           default: ;
 663         }
 664       }
 665     }
 666   }
 667 }
 668 
 669 
 670 /* performs a simple check on a inetnum attribute. Assumes that
 671    the RPSL parser has already checked it. Tries to see if the attr
 672    is a range or not  */
 673 int up_check_an_inetnum_attr(const char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 674   
 675 
 676   char * str;
 677   char * pos;
 678 
 679   str = strdup(arg);
 680 
 681   while((pos = index(str, '\n')) != NULL){
 682     *pos = ' ';
 683   }
 684 
 685   /* strip off the comment */
 686   if((pos = index(str, '#')) != NULL){
 687     *pos = '\0';
 688   }
 689    
 690    
 691   /* Most of the syntax check is done by RPSL parser. We only need to check
 692      that the argument is a _range_ of IPv4 addresses. So it suffices to
 693      check the existence of '-' in the arg */
 694   if(index(str, '-') != NULL){
 695     
 696     free(str);
 697     return 1;
 698     
 699   }else{
 700 
 701     free(str);
 702     return 0;
 703 
 704   }
 705 }
 706 
 707 
 708 
 709 /* void up_check_inetnum_attr 
 710    checks the syntax of 'inetnum' attributes 
 711    (this is required to reject inetnums in the form of 
 712    "inetnum: 23.23.23.23". RPSL parser unfortunately
 713    passes them although we define them as a range of ipv4 addreses.) */
 714 void up_check_inetnum_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 715 
 716   int res;
 717   char * temp;
 718   GSList * next;
 719 
 720 
 721   /* loop in the attribute_list, find the 'inetnum' attribs, and check their syntax */
 722   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 723     /* is this an 'inetnum' attribute? */
 724     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "inetnum") == 0){
 725       /* chech its syntax */
 726       res = up_check_an_inetnum_attr((char *)(((attribute_struct *)(next->data))->content));
 727       if(!res){
 728         /* so, add the error string to result's error string */
 729         if(result->error_str == NULL){
 730           result->error_str = strdup("***Error: inetnum must be a range of IPv4 address\n");
 731         }else{
 732           temp = (char *)malloc(strlen(result->error_str) 
 733                   + strlen("***Error: inetnum must be a range of IPv4 address\n") + 2);
 734           sprintf(temp, "%s\n%s", result->error_str, 
 735                   "***Error: inetnum must be a range of IPv4 address\n");
 736           free(result->error_str);
 737           result->error_str = temp;
 738         }
 739         /* and here we have to change the result code of "result" here ... */
 740         switch(result->result){
 741           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 742           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 743           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 744           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 745           default: ;
 746         }
 747       }
 748     }
 749   }
 750 }
 751 
 752 
 753 
 754 
 755 
 756 
 757 
 758 /* GSList * up_add_keycert_attrs
 759    adds the generated attrs of key-cert objects */
 760 GSList * up_add_keycert_attrs(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 761 
 762   int res;
 763   char * type, * content;
 764   char **error;
 765   char * temp;
 766   GSList * new_list;
 767   attribute_struct * attribute;
 768   
 769   new_list = attribute_list;
 770 
 771 
 772   /* if this is a key-cert object */
 773   if(strcmp(obj->type->getName(), "key-cert") == 0){
 774       content = strdup("PGP");
 775       type = strdup("method");
 776       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 777       attribute->content = content;
 778       attribute->type = type;
 779       new_list = g_slist_insert(new_list, attribute, 1);
 780 
 781       content = strdup(keyowner);
 782       type = strdup("owner");
 783       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 784       attribute->content = content;
 785       attribute->type = type;
 786       new_list = g_slist_insert(new_list, attribute, 2);
 787 
 788       content = strdup(fingerprint);
 789       type = strdup("fingerpr");
 790       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 791       attribute->content = content;
 792       attribute->type = type;
 793       new_list = g_slist_insert(new_list, attribute, 3);
 794       
 795   }
 796 
 797   return new_list;
 798 
 799 }
 800 
 801 
 802 
 803 
 804 
 805 
 806 
 807 
 808 
 809 
 810 /* Constructs a list of all attributes of an object, and returns it
 811    as a list of attribute_struct */
 812 GSList * up_get_attribute_list(Object * o, char * text){
     /* [<][>][^][v][top][bottom][index][help] */
 813 
 814   char * value = NULL;
 815   char * type = NULL;
 816   Attr *attr;
 817   GSList *list_of_attributes = NULL;
 818   attribute_struct * attribute;
 819   
 820   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
 821     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
 822     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
 823         attr->len - strlen(attr->type->name()) -2 );
 824     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
 825       if(tracing) {
 826         cout << "TRACING: up_get_attributes: adding " << g_strstrip(value) << endl;
 827       }
 828       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 829       attribute->content = value;
 830       type = strdup(attr->type->name());
 831       g_strdown(type);
 832       attribute->type = type;
 833       list_of_attributes = g_slist_append(list_of_attributes, attribute);
 834   }
 835 
 836   
 837   return list_of_attributes; 
 838 
 839 }
 840 
 841 
 842 
 843 
 844 /* up_reconstruct_object: Reconstructs the object's text representation
 845      using the attribute list */
 846 void up_reconstruct_object(GSList * attr_list, external_syntax_struct *result){
     /* [<][>][^][v][top][bottom][index][help] */
 847 
 848   char * recons_obj = NULL;
 849   char * temp;
 850   char * content, * type;
 851   GSList * next;
 852 
 853 
 854 
 855 
 856   for( next = attr_list; next != NULL ; next = g_slist_next(next) ){
 857 
 858     content = strdup((char *)(((attribute_struct *)(next->data))->content));
 859     type = strdup((char *)(((attribute_struct *)(next->data))->type));
 860 
 861     if(tracing){
 862       printf("TRACING: up_reconstruct_object:[%s:%s]\n", type, content);
 863     }
 864     
 865     if(recons_obj == NULL){
 866       recons_obj = (char *)malloc(14 + strlen(content) + 1 );
 867       /* trim the white spaces in the beginning */
 868       g_strchug(content);
 869 
 870       /* add ':' at the end of 'type' */
 871       temp = (char *)malloc(strlen(type) + 2);
 872       sprintf(temp, "%s:", type);
 873       free(type);
 874       type = temp;
 875 
 876       sprintf(recons_obj, "%-14s%s", type, content);
 877     }else{
 878       /* trim the white spaces in the beginning */
 879       g_strchug(content);
 880 
 881       /* add ':' at the end of 'type' */
 882       temp = (char *)malloc(strlen(type) + 2);
 883       sprintf(temp, "%s:", type);
 884       free(type);
 885       type = temp;
 886       
 887       temp = (char *)malloc(strlen(recons_obj) + 14 + strlen(content) + 3 );
 888       sprintf(temp, "%s\n%-14s%s", recons_obj, type, content);
 889       free(recons_obj);
 890       recons_obj = temp;
 891     }
 892     
 893   }
 894   
 895   result->new_obj = recons_obj;
 896   
 897 }
 898 
 899 
 900 
 901 
 902 /*  UP_check_external_syntax: Checks the syntax of attributes which are not checked
 903        by RAToolSet syntax checker. */
 904 external_syntax_struct * UP_check_external_syntax(Object * arg, char * obj_text){
     /* [<][>][^][v][top][bottom][index][help] */
 905   
 906   external_syntax_struct *result;
 907   GSList * attribute_list;
 908   
 909  
 910 
 911 
 912   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
 913 
 914   /* initialize the struct */
 915   result->result = 0;
 916   result->error_str = strdup(""); 
 917   result->warning_str = strdup("");
 918 
 919   /* get a list of all attributes */
 920   attribute_list = up_get_attribute_list(arg, obj_text);
 921 
 922   up_check_changed_attr(arg, obj_text, attribute_list, result);
 923   up_check_auth_attr   (arg, obj_text, attribute_list, result);  
 924   up_check_inetnum_attr(arg, obj_text, attribute_list, result);
 925   
 926   up_reconstruct_object(attribute_list, result);
 927 
 928   if(tracing){
 929     printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
 930     printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
 931   }
 932 
 933   return result;  
 934 }
 935 
 936 
 937 
 938 
 939 
 940 /* generates the "generated" attributes of a key-cert object. Returns the 
 941    new object as a char * */
 942 char * UP_generate_kc_attrs(Object * arg, char * obj_text){
     /* [<][>][^][v][top][bottom][index][help] */
 943   
 944   external_syntax_struct *result;
 945   GSList * attribute_list;
 946   
 947  
 948 
 949 
 950   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
 951 
 952   /* initialize the struct */
 953   result->result = 0;
 954   result->error_str = strdup(""); 
 955   result->warning_str = strdup("");
 956 
 957   /* get a list of all attributes */
 958   attribute_list = up_get_attribute_list(arg, obj_text);
 959 
 960   up_check_changed_attr(arg, obj_text, attribute_list, result);
 961   //up_check_auth_attr   (arg, obj_text, attribute_list, result);  
 962   attribute_list = up_add_keycert_attrs (arg, obj_text, attribute_list, result); 
 963 
 964   
 965   up_reconstruct_object(attribute_list, result);
 966 
 967   if(tracing){
 968     printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
 969     printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
 970   }
 971 
 972   return result->new_obj;  
 973 }
 974 

/* [<][>][^][v][top][bottom][index][help] */