## 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.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 }

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