## 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_changed_attr
7. up_check_an_auth_attr
8. up_check_auth_attr
9. up_get_attribute_list
10. up_reconstruct_object
11. 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 }

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