## modules/up/UP_util.cc

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

## FUNCTIONS

This source file includes following functions.

1. authorise
2. error_msg_cat
3. interpret_ripdb_result
4. get_assigned_nic
5. delete_override
6. up_get_transaction_id
7. send_object_db
8. get_class_type
9. get_search_key
10. send_and_get
11. count_objects
12. strip_lines
13. take_objects
14. take_object
15. get_as_block
16. get_aut_num_object
17. get_less_specific_domain
18. get_less_specific_set
19. get_less_specific
20. get_less_spec_inetnum
21. get_exact_match_inetnum
22. get_exact_match_routes
23. get_less_spec_routes
24. get_mntners
25. get_attributes
26. get_attribute
27. strstr_in_list
28. get_auths
29. get_attr_list
30. get_mnt_lowers
31. get_mnt_routes
32. get_mnt_routes_from_list
33. get_mnt_lowers_from_list
34. get_override
35. check_override
36. add_to_auth_vector
37. get_auth_vector
38. get_mntnfy_vector
39. get_updto_vector
40. filter_out_diff_origins
41. check_auth
42. get_old_version
43. process_mail_header
44. up_string_pack
45. delete_delete_attrib
46. identical
47. find_initials
48. get_combination_from_autonic
49. replace_AUTO_NIC_hdl
50. replace_refs_to_AUTO_NIC_hdl
51. has_AUTO_NIC_hdl
52. has_ref_to_AUTO_nic_hdl
53. find_email_address
54. replace_strings
55. replace_globals
56. get_class_type_char

       1 /***************************************
       2   $Revision: 1.47 $
       3
       4   UP module utilities
       5
       6   Status: NOT REVIEWED, NOT TESTED
       7
       8   Author(s):       Engin Gunduz
       9
      10   ******************/ /******************
      11   Modification History:
      12         engin (17/01/2000) Created.
      13   ******************/ /******************
      14   Copyright (c) 2000                              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 #include "dbupdate.h"
      35
      36 int error = 0; // a global variable to store the errors
      37 char * error_msg = NULL; // a global variable to store the error messages
      38 extern int tracing;
      39 extern char * overridecryptedpw;
      40 extern int test_mode;
      41 extern char * update_host;
      42 extern int update_port;
      43 extern char * query_host;
      44 extern int query_port;
      45 extern char * humailbox;
      46 extern char * autobox;
      47
      48 extern char *update_mail_sender;
      49 extern char *update_mail_subject;
      50 extern char *update_mail_date;
      51 extern char *update_mail_ID;
      52 extern char *update_mail_cc;
      53
      54 extern char *DBhost;
      55 extern int  DBport;
      56 extern char *DBuser;
      57 extern char *DBname;
      58 extern char *DBpasswd;
      59
      60
      61 /* authorise function takes the auth_vector, credentials struct, and 'overriden'
      62    variable. If overriden == 1, then it immediately returns UP_AUTH_OK
      63    (because this means that the update contained a valid override attribute).
      64    Else, it goes through the auth_vector and when it finds a an "auth:"
      65    attribute which passes, then it returns UP_AUTH_OK. Otherwise, it returns
      66    UP_AUF (authorisation failed) */
      67
      68 int authorise(GSList * auth_vector, credentials_struct credentials, int overriden){
         /* [<][>][^][v][top][bottom][index][help] */
      69
      70   int result = 0;
      71
      72   if(tracing){
      73     printf("TRACING: authorise started with override: %i\n", overriden);
      74   }
      75
      76   /* If 'overriden' variable is 1, then return UP_AUTH_OK immediately */
      77   if(overriden == 1){
      78     return UP_AUTH_OK;
      79   }
      80
      81   else{
      82     result = AU_authorise(auth_vector, credentials);
      83     if(tracing){
      84       printf("TRACING: authorise: AU_authorise returned %i\n", result);
      85     }
      86     if(result > 0){
      87       return UP_AUTH_OK;
      88     }
      89     else{
      90       return UP_AUF; /* authorisation failed */
      91     }
      92   }
      93 }
      94
      95 /* concatanates the string at the end of error_msg */
      96 void error_msg_cat(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
      97
      98   if(string == NULL){
      99     return;
     100   }
     101   if(error_msg == NULL){
     102     error_msg = strdup(string);
     103   }else{
     104     error_msg = (char *)realloc(error_msg, strlen(error_msg) + strlen(string) + 2);
     105     error_msg = strcat(error_msg, "\n");
     106     error_msg = strcat(error_msg, string);
     107   }
     108 }
     109
     110
     111 /* interprets the result string coming from RIPupd
     112    It is called by send_object_db.
     113    It returns the error no returned from RIPupd.  */
     114
     115 int interpret_ripdb_result(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     116    char * error_no = NULL;
     117    char ** temp = NULL, ** temp2 = NULL;
     118    int i;
     119    int err = 0;
     120
     121   /* if the string is NULL or empty, then return error */
     122   if(string == NULL || strlen(string) == 0){
     123     error = UP_INT; /* internal error, RIPupd should return something */
     124     error_msg_cat("Internal error. RIPupd didn't return anything.");
     125     return 0;
     126   }
     127
     128   /* split the string into lines */
     129   temp = g_strsplit(string , "\n", 0);
     130   for(i = 0; temp[i] != NULL; i++){
     131     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     132       temp2 = g_strsplit(temp[0], " ", 0);
     133       error_no = strdup(temp2[1]);
     134       g_strfreev(temp2);
     135       err = atoi(error_no);
     136       if(tracing){
     137         printf("TRACING: interpret_ripdb_result: error_no is [%s]\n", error_no);
     138       }
     139     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     140       error_msg_cat(temp[i]);
     141     }
     142   }
     143   g_strfreev(temp);
     144   if(error_no != NULL){
     145     free(error_no);
     146   }
     147   return err; /* 0 means no error in this context */
     148 }
     149
     150
     151
     152 /* Gets assigned NIC hdl from the string that is returned from
     153    RIPupdate */
     154 void get_assigned_nic(char * nic_hdl, const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     155    char * error_no = NULL;
     156    char ** temp = NULL, ** temp2 = NULL;
     157    int i;
     158
     159   /* if the string is NULL or empty, then return error */
     160   if(string == NULL || strlen(string) == 0){
     161     error = UP_INT; /* internal error, RIPupd should return something */
     162     error_msg_cat("Internal error. RIPupd didn't return anything.");
     163     return;
     164   }
     165
     166   /* split the string into lines */
     167   temp = g_strsplit(string , "\n", 0);
     168   for(i = 0; temp[i] != NULL; i++){
     169     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     170       temp2 = g_strsplit(temp[0], " ", 0);
     171       error_no = strdup(temp2[1]);
     172       g_strfreev(temp2);
     173       if(tracing){
     174         printf("TRACING: get_assigned_nic: error_no is [%s]\n", error_no);
     175       }
     176     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     177       error_msg_cat(temp[i]);
     178     }else if(error_no != NULL && strcmp(error_no, "0") == 0 && i == 1){/* look for assigned NIC hdl */
     179       /* in the second line RIPupdate returns for example "I[65][EK3-RIPE]" We
     180          need to extract EK3-RIPE part */
     181       //to_be_returned = (char *)malloc(128); /* 128 should be enough for a NIC hdl */
     182       nic_hdl = strncpy(nic_hdl, rindex(temp[i],'[') + 1 ,
     183                                  rindex(temp[i],']') - rindex(temp[i],'[') - 1);
     184       nic_hdl[rindex(temp[i],']') - rindex(temp[i],'[') - 1] = '\0';
     185       if(tracing && nic_hdl != NULL){
     186         printf("TRACING: get_assigned_nic will return [%s]\n", nic_hdl);
     187       }
     188       g_strfreev(temp);
     189       return;
     190     }
     191   }
     192   g_strfreev(temp);
     193   if(error_no != NULL && error_msg != NULL){
     194     printf("TRACING: interpret_ripdb_result: Error: [%s][%s]\n", error_no, error_msg);
     195   }
     196   return;
     197 }
     198
     199
     200
     201
     202
     203
     204 /* strips lines beginning with "override:" off  */
     205 char * delete_override(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     206
     207     char ** temp = NULL;
     208     char * string = NULL;
     209     int i;
     210
     211     if(arg == NULL){
     212        return NULL;
     213     }
     214
     215     /* split the string into lines */
     216     temp = g_strsplit (arg, "\n", 0);
     217
     218     for(i=0; temp[i] != NULL; i++){
     219       /* if the line begins with "override:", then do not copy it */
     220       if(strstr(temp[i], "override:") != temp[i]){
     221         if(string == NULL){
     222           string = strdup(temp[i]);
     223         }else{
     224           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
     225           string = strcat(string, "\n");
     226           string = strcat(string, temp[i]);
     227         }
     228       }
     229     }
     230     g_strfreev(temp);
     231     return string;
     232 }
     233
     234
     235
     236
     237
     238 /* Obtains a transaction ID for an object. Will be called from send_object_db */
     239 int up_get_transaction_id(){
         /* [<][>][^][v][top][bottom][index][help] */
     240
     241   SQ_connection_t * sql_connection;
     242   SQ_result_set_t *result;
     243   int error;
     244   long new_id;
     245
     246   sql_connection = SQ_get_connection(DBhost, DBport, DBname, DBuser, DBpasswd);
     247   if(!sql_connection){
     248     fprintf(stderr, "No SQL connection\n");
     249     exit(1);
     250   }
     251   error = SQ_execute_query(sql_connection, "INSERT INTO tid VALUES(NULL)", &result);
     252   if(error){
     253     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
     254     exit(1);
     255   }
     256
     257   new_id = mysql_insert_id(sql_connection);
     258
     259   return new_id;
     260 }
     261
     262
     263
     264
     265
     266
     267 /* sends the object to the database. char * operation is either 'ADD' ,'DEL' or 'UPD'
     268    assigned_NIC is filled in if this is a person/role creation with AUTO nic hdl
     269    assigned_NIC must be allocated enough memory before send_object_db is called
     270
     271    If the called do not expect a NIC hdl back, then assigned_NIC can be given NULL
     272    */
     273 int send_object_db(char * arg, char * assigned_NIC, char * operation){
         /* [<][>][^][v][top][bottom][index][help] */
     274
     275         int sockfd, numbytes;
     276         char buf[MAXDATASIZE];
     277         struct hostent *he;
     278         struct sockaddr_in their_addr; /* connector's address information */
     279         char *result_string = NULL;
     280         char *to_be_returned = NULL;
     281         int err = 0;
     282         char *to_be_sent = NULL;
     283         int tr_id;
     284         char * tr_id_str;
     285
     286         to_be_sent = delete_override(arg);
     287
     288         /* get the transaction ID, to be sent to RIPupdate*/
     289         tr_id = up_get_transaction_id();
     290
     291         /* convert it into a string */
     292         tr_id_str = (char *)malloc(64);
     293         sprintf(tr_id_str, "%d", tr_id);
     294
     295         if ((he=gethostbyname(update_host)) == NULL) {  /* get the host info */
     296             perror("gethostbyname");
     297             exit(1);
     298         }
     299
     300         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     301             perror("socket");
     302             exit(1);
     303         }
     304
     305         their_addr.sin_family = AF_INET;      /* host byte order */
     306         their_addr.sin_port = htons(update_port);    /* short, network byte order */
     307         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     308         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     309
     310
     311         if (connect(sockfd, (struct sockaddr *)&their_addr,
     312                                               sizeof(struct sockaddr)) == -1) {
     313             perror("connect");
     314             exit(1);
     315         }
     316
     317         if (send(sockfd, operation , strlen(operation), 0) == -1)
     318             perror("send");
     319         if (send(sockfd, " ", strlen(" "), 0) == -1)
     320             perror("send");
     321         if (send(sockfd, tr_id_str, strlen(tr_id_str), 0) == -1)
     322             perror("send");
     323         if (send(sockfd, "\n\n" , strlen("\n\n"), 0) == -1)
     324             perror("send");
     325         if (send(sockfd, arg , strlen(to_be_sent), 0) == -1)
     326             perror("send");
     327         if (send(sockfd, "\n\n", 2, 0)  == -1)
     328             perror("send");
     329         /* send the ACK now */
     330         if (send(sockfd, "ACK ",strlen("ACK "), 0)  == -1)
     331             perror("send");
     332         if (send(sockfd, tr_id_str, strlen(tr_id_str), 0) == -1)
     333             perror("send");
     334         if (send(sockfd, "\n\n",strlen("\n\n"), 0)  == -1)
     335             perror("send");
     336
     337
     338         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     339             buf[numbytes] = '\0';
     340             if(tracing){
     341               printf("%s",buf);
     342             }
     343             if(result_string == NULL){
     344               result_string = strdup(buf);
     345             }else{
     346               result_string = (char *)realloc(result_string,
     347                                  strlen(result_string) + strlen(buf) + 1);
     348               result_string = strcat(result_string, buf);
     349             }
     350             if(strstr(result_string,"\n\n") != NULL){/* if the result_string contains
     351                                                         an empty line at the end, we will close */
     352               break;
     353             };
     354         }
     355
     356         err = interpret_ripdb_result(result_string);
     357         if(assigned_NIC != NULL){ /* if the caller of the function expected to get a NIC handle */
     358           get_assigned_nic(assigned_NIC, result_string);
     359         }
     360         close(sockfd);
     361         free(to_be_sent);
     362         return err; /* 0 means no error in this context */
     363 }
     364
     365
     366
     367
     368
     369
     370 /* takes a pre-parsed object, and returns its type */
     371 char * get_class_type(Object *arg){
         /* [<][>][^][v][top][bottom][index][help] */
     372
     373     char * be_returned = NULL;
     374     if(arg == NULL) return NULL;
     375     be_returned = strdup(arg->type->getName());
     376     return g_strstrip(be_returned);
     377 }
     378
     379
     380
     381
     382
     383
     384 /* takes an object (pre-parsed) and returns its first attrib if it is not
     385    a person, and returns the nic-hdl if it is a person object */
     386 char * get_search_key(Object *arg, char * type, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     387
     388
     389     Attr *attr;
     390     char *primary_key = NULL, *value = NULL;
     391
     392     if(arg == NULL) return NULL;
     393
     394     for(attr = arg->attrs.head(); attr; attr = arg->attrs.next(attr)){
     395        value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     396        strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     397            attr->len - strlen(attr->type->name()) -2 );
     398            value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     399        if(strcmp(attr->type->name(),type) == 0 &&
     400               strcmp(type,"person") != 0 && strcmp(type,"role") != 0  ){
     401          primary_key = strdup(value);
     402        }
     403        if(strcmp(attr->type->name(),"nic-hdl") == 0 &&
     404             (strcmp(type,"person") == 0 || strcmp(type,"role") == 0 )){
     405          primary_key = strdup(value);
     406        }
     407        free(value);
     408     }
     409     if(primary_key != NULL){
     410       return g_strstrip(primary_key);
     411     }else{
     412       return NULL;
     413     }
     414 }
     415
     416
     417
     418
     419 /* sends char * arg to the specified host's specified port, and
     420    returns the reply as a string. This is used to query the
     421    whois host. Probably we must use WC (whois client) module here,
     422    but it must be extented */
     423 char * send_and_get(char * host, int port, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     424
     425         int sockfd, numbytes;
     426         char * result = NULL;
     427         char buf[MAXDATASIZE];
     428         struct hostent *he;
     429         struct sockaddr_in their_addr; /* connector's address information */
     430
     431         if(tracing) {
     432           printf("TRACING: send_and_get: arg : [%s]; port: [%i]; host: [%s]\n", arg, port, host);
     433         }
     434
     435         if ((he=gethostbyname(host)) == NULL) {  /* get the host info */
     436             perror("gethostbyname");
     437             exit(1);
     438         }
     439
     440         if(tracing) {
     441           printf("TRACING: send_and_get: called gethostbyname\n");
     442         }
     443
     444         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     445             perror("socket");
     446             exit(1);
     447         }
     448
     449         if(tracing) {
     450           printf("TRACING: send_and_get: called socket\n");
     451         }
     452
     453
     454         their_addr.sin_family = AF_INET;      /* host byte order */
     455         their_addr.sin_port = htons(port);    /* short, network byte order */
     456         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     457         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     458
     459         if (connect(sockfd, (struct sockaddr *)&their_addr,
     460                                               sizeof(struct sockaddr)) == -1) {
     461             perror("connect");
     462             exit(1);
     463         }
     464         if (send(sockfd, arg , strlen(arg), 0) == -1)
     465                perror("send");
     466         if (send(sockfd, "\n",1,0)  == -1)
     467                perror("send");
     468
     469
     470         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     471             buf[numbytes] = '\0';
     472             if(result == NULL){
     473               result = strdup(buf);
     474             }else{
     475               result = (char *)realloc(result, strlen(result) + strlen(buf) + 1);
     476               result = strcat(result, buf);
     477             }
     478         }
     479
     480         close(sockfd);
     481         return result;
     482
     483
     484 }
     485
     486 /* counts the number of objects in a string */
     487 int count_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     488     int count = 0;
     489     char *pos = NULL;
     490     char *temp = NULL;
     491
     492     if(tracing) {
     493       printf("TRACING: count_objects running\n");
     494     }
     495
     496     if(arg != NULL){
     497       temp = strdup(arg);
     498     }else{
     499       return 0;
     500     }
     501
     502     if(isalpha(arg[0])){
     503       count++;
     504     }else if(arg[0] == '\n' && isalpha(arg[1])){
     505       count++;
     506     }
     507     while(pos = strstr(temp,"\n\n")){
     508       pos[0] = 'a'; /* something non-EOL so that it won't be caught in the next loop */
     509       if(isalpha(pos[2])){
     510         count++;
     511       }
     512     }
     513     if(tracing) {
     514       cout << "TRACING: count_objects returning " << count << endl;
     515     }
     516     free(temp);
     517     return count;
     518 }
     519
     520
     521 /* strips lines beginning with '%' off  */
     522 char * strip_lines(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     523
     524     char ** temp = NULL;
     525     char * string = NULL;
     526     int i;
     527
     528     if(arg == NULL){
     529        return NULL;
     530     }
     531
     532     /* split the string into lines */
     533     temp = g_strsplit (arg, "\n", 0);
     534
     535     for(i=0; temp[i] != NULL; i++){
     536       if(temp[i][0] != '%'){
     537         if(string == NULL){
     538           string = strdup(temp[i]);
     539         }else{
     540           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
     541           string = strcat(string, "\n");
     542           string = strcat(string, temp[i]);
     543         }
     544       }
     545     }
     546     return string;
     547 }
     548
     549 /* Separates the objects in the given char * arg using "\n\n" as
     550    separator. Returns a linked list whose data consist of separated
     551    objects as  char *  */
     552
     553 GSList * take_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     554     char ** objects=NULL;
     555     char ** temp = NULL;
     556     GSList * tobereturned = NULL;
     557     int i;
     558
     559     arg = strip_lines(arg);
     560
     561     objects =  g_strsplit(arg, "\n\n", 1000);
     562     temp = objects;
     563     for(i=0; temp[i] != NULL; i++){
     564       /* stripe off the trailing and leading white spaces-eols*/
     565       g_strstrip(temp[i]);
     566       if(strlen(temp[i]) > 0){/* if not an empty string */
     567         tobereturned = g_slist_append(tobereturned, temp[i]);
     568       }
     569     }
     570     return tobereturned;
     571 }
     572
     573
     574
     575
     576
     577 /* takes the first object in the given char *, using empty lines as
     578    separator */
     579 char * take_object(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     580     GSList * objects;
     581     char * object;
     582
     583     objects = take_objects(arg);
     584     if(g_slist_length(objects) > 0){
     585       object = strdup((char *)(g_slist_nth_data(objects, 0)));
     586     }else{
     587       return NULL;
     588     }
     589     g_slist_free(objects);
     590     return object;
     591
     592 }
     593
     594
     595
     596
     597
     598 /* Takes an autnum_object, and returns the as-block containing this aut-num */
     599 char * get_as_block(char *autnum_object){
         /* [<][>][^][v][top][bottom][index][help] */
     600   bool code;
     601   char * search_key = NULL, * query_string = NULL;
     602   char * result = NULL;
     603   Object * o = new Object();
     604
     605   code = o->scan(autnum_object, strlen(autnum_object));
     606   search_key = get_search_key(o,"aut-num",autnum_object);
     607
     608   query_string = (char *)malloc(strlen("-Tas-block -r ")+strlen(search_key)+1);
     609   sprintf(query_string, "-Tas-block -r %s",search_key);
     610   result = send_and_get(query_host, query_port, query_string);
     611   if(count_objects(result) == 0){
     612     if(tracing){
     613       cout << "No such as-block" << endl;
     614     }
     615     return NULL;
     616   }else if(count_objects(result) > 1){
     617     if(tracing){
     618       cout << "More than one as-block returned" << endl;
     619     }
     620     return NULL;
     621   }else{ /* count_objects(result) == 1 */
     622     return take_object(result);
     623   }
     624
     625 }
     626
     627
     628 /* Takes a route_object, and returns the aut-num mentioned in origin
     629    attribute of this route */
     630 char * get_aut_num_object(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     631   bool code;
     632   char * search_key = NULL, * query_string = NULL;
     633   char * result = NULL;
     634   Object * o = new Object();
     635
     636   code = o->scan(route_object, strlen(route_object));
     637   search_key = get_search_key(o,"origin",route_object);
     638
     639   query_string = (char *)malloc(strlen("-Taut-num  -r ")+strlen(search_key)+1);
     640   sprintf(query_string, "-Taut-num -r %s",search_key);
     641   result = send_and_get(query_host, query_port, query_string);
     642   if(count_objects(result) == 0){
     643     if(tracing){
     644       cout << "No such aut-num" << endl;
     645     }
     646     return NULL;
     647   }else if(count_objects(result) > 1){
     648     if(tracing){
     649       cout << "More than one aut-num returned" << endl;
     650     }
     651     return NULL;
     652   }else{ /* count_objects(result) == 1 */
     653     return take_object(result);
     654   }
     655
     656 }
     657
     658
     659
     660
     661 /* Takes a domain_object, and returns the less specific domain of it */
     662 char * get_less_specific_domain(char *domain_object){
         /* [<][>][^][v][top][bottom][index][help] */
     663   bool code;
     664   char * search_key = NULL, * query_string = NULL;
     665   char * result = NULL, * domain = NULL;
     666   Object * o = new Object();
     667   int i,j, length;
     668   char * temp = NULL;
     669   char ** splitted;
     670
     671   code = o->scan(domain_object, strlen(domain_object));
     672   domain = get_search_key(o,"domain",domain_object);
     673
     674   /* split the domain from its dots ('50' is the max # of pieces, this number is just arbitrary) */
     675   splitted =   g_strsplit((char *)strdup(domain), ".", 50);
     676
     677   for(i=1; splitted[i] != NULL; i++){
     678     /* in the following for loop, we will construct the 'less spec' domains
     679        to be looked up in the DB */
     680     for(j=i; splitted[j] !=NULL; j++){
     681       length = 0;
     682       if(temp!=NULL){
     683         length = strlen(temp);
     684       }
     685       temp = (char *)realloc(temp, length + strlen(splitted[j]) + 2);
     686       if(j==i){
     687         temp = (char *)strdup(splitted[j]);
     688       }else{
     689         sprintf(temp, "%s.%s", temp, splitted[j]);
     690       }
     691     }
     692     query_string = (char *)malloc(strlen("-Tdomain -r -R ")+strlen(temp)+1);
     693     sprintf(query_string, "-Tdomain -r -R %s", temp);
     694     result = send_and_get(query_host, query_port, query_string);
     695     if(count_objects(result) == 0){
     696     }else if(count_objects(result) > 1){
     697       if(tracing){
     698         cout << "TRACING: get_less_specific_domain: More than one domains returned" << endl;
     699       }
     700       return NULL; /* error condition */
     701     }else{ /* count_objects(result) == 1 */
     702       return take_object(result);
     703     }
     704
     705   }
     706   /* release the memory allocated to **splitted */
     707   for(i=0; splitted[i] != NULL; i++){
     708     free(splitted[i]);
     709   }
     710   /* so, we couldn't  find any 'less specific' domain */
     711   return NULL;
     712 }
     713
     714
     715
     716
     717
     718 /* Takes a hierarchical set_object, and returns the less specific set or auth-num of it
     719    by striping down the object's name ( eg, for as35:rs-trial:rs-myset,
     720    as35:rs-trial is tried ) */
     721 char * get_less_specific_set(char *set_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     722   bool code;
     723   char * search_key = NULL, * query_string = NULL;
     724   char * result = NULL;
     725   Object * o = new Object();
     726   int i;
     727
     728   code = o->scan(set_object, strlen(set_object));
     729   search_key = get_search_key(o, type, set_object);
     730   delete(o);
     731
     732   for(i = strlen(search_key) -1; i > -1; i--){
     733     if(search_key[i] == ':'){
     734       search_key[i] = '\0'; /* truncate the string */
     735       break;
     736     }
     737     if(i == 0){/* if we've reached the beginning of the string
     738                 (this means there wasn't any ';' in the string) */
     739       free(search_key);
     740       search_key = NULL;
     741     }
     742   }
     743   if( search_key == NULL || strlen(search_key) == 0){/* this mustn't happen in fact, since
     744                                                         we make sure that the name of the
     745                                                         set_object contains a ':' in a proper place */
     746     return NULL;
     747   }
     748
     749
     750   query_string = (char *)malloc(strlen("-Taut-num,as-set,rtr-set,peering-set,filter-set -r ")+strlen(search_key)+1);
     751   sprintf(query_string, "-Taut-num,as-set,rtr-set,peering-set,filter-set -r  %s", search_key);
     752   result = send_and_get(query_host, query_port, query_string);
     753   if(count_objects(result) == 0){
     754     cout << "No such object"  << endl;
     755     return NULL;
     756   }else if(count_objects(result) > 1){
     757     cout << "More than one objects returned" << endl;
     758     return NULL;
     759   }else{ /* count_objects(result) == 1 */
     760     return take_object(result);
     761   }
     762
     763 }
     764
     765
     766
     767
     768
     769
     770
     771 /* Takes an inetnum or inet6num object and returns one less specific of it */
     772 char * get_less_specific(char *inetnum_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     773   bool code;
     774   char * search_key = NULL, * query_string = NULL;
     775   char * result = NULL;
     776   Object * o = new Object();
     777
     778   code = o->scan(inetnum_object, strlen(inetnum_object));
     779   search_key = get_search_key(o, type, inetnum_object);
     780
     781   query_string = (char *)malloc(strlen("-Tinet6num -r -l ") + strlen(search_key) + 1);
     782   sprintf(query_string, "-T%s -r -l %s",type, search_key);
     783   result = send_and_get(query_host, query_port, query_string);
     784   if(count_objects(result) == 0){
     785     cout << "No such " << type << endl;
     786     return NULL;
     787   }else if(count_objects(result) > 1){
     788     cout << "More than one " << type << " returned" << endl;
     789     return NULL;
     790   }else{ /* count_objects(result) == 1 */
     791     return take_object(result);
     792   }
     793
     794 }
     795
     796
     797
     798 /* Takes a route object and returns one less specific inetnum */
     799 char * get_less_spec_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     800   bool code;
     801   char * search_key = NULL, * query_string = NULL;
     802   char * result = NULL;
     803   Object * o = new Object();
     804
     805   code = o->scan(route_object, strlen(route_object));
     806   search_key = get_search_key(o, "route", route_object);
     807
     808   query_string = (char *)malloc(strlen("-Tinetnum -r -l ") + strlen(search_key) + 1);
     809   sprintf(query_string, "-Tinetnum -r -l %s", search_key);
     810   result = send_and_get(query_host, query_port, query_string);
     811   if(count_objects(result) == 0){
     812     cout << "No such inetnum" << endl;
     813     return NULL;
     814   }else if(count_objects(result) > 1){
     815     cout << "More than one inetnums returned" << endl;
     816     return NULL;
     817   }else{ /* count_objects(result) == 1 */
     818     return take_object(result);
     819   }
     820
     821 }
     822
     823
     824 /* Takes a route object and returns exact match inetnum */
     825 char * get_exact_match_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     826   bool code;
     827   char * search_key = NULL, * query_string = NULL;
     828   char * result = NULL;
     829   Object * o = new Object();
     830
     831   code = o->scan(route_object, strlen(route_object));
     832   search_key = get_search_key(o, "route", route_object);
     833
     834   query_string = (char *)malloc(strlen("-Tinetnum -r -x ") + strlen(search_key) + 1);
     835   sprintf(query_string, "-Tinetnum -r -x %s", search_key);
     836   result = send_and_get(query_host, query_port, query_string);
     837   if(count_objects(result) == 0){
     838     cout << "No such inetnum" << endl;
     839     return NULL;
     840   }else if(count_objects(result) > 1){
     841     cout << "More than one inetnums returned" << endl;
     842     return NULL;
     843   }else{ /* count_objects(result) == 1 */
     844     return take_object(result);
     845   }
     846
     847 }
     848
     849
     850
     851 /* Takes a route object and returns exact matches of this route */
     852 GSList * get_exact_match_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     853   bool code;
     854   char * search_key = NULL, * query_string = NULL;
     855   char * result = NULL;
     856   Object * o = new Object();
     857
     858   code = o->scan(route_object, strlen(route_object));
     859   search_key = get_search_key(o, "route", route_object);
     860
     861   query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(search_key) + 1);
     862   sprintf(query_string, "-Troute -r -x %s", search_key);
     863   result = send_and_get(query_host, query_port, query_string);
     864   if(count_objects(result) == 0){
     865     //cout << "get_exact_match_routes: No such route" << endl;
     866     return NULL;
     867   }else{ /* count_objects(result) == 1 */
     868     return take_objects(result);
     869   }
     870
     871 }
     872
     873
     874
     875 /* Takes a route object and returns (immediate) less specifics of this route */
     876 GSList * get_less_spec_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     877   bool code;
     878   char * search_key = NULL, * query_string = NULL;
     879   char * result = NULL;
     880   Object * o = new Object();
     881
     882   code = o->scan(route_object, strlen(route_object));
     883   search_key = get_search_key(o, "route", route_object);
     884
     885   query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(search_key) + 1);
     886   sprintf(query_string, "-Troute -r -l %s", search_key);
     887   result = send_and_get(query_host, query_port, query_string);
     888   if(count_objects(result) == 0){
     889     cout << "get_less_spec_routes: No such route" << endl;
     890     return NULL;
     891   }else{ /* count_objects(result) == 1 */
     892     return take_objects(result);
     893   }
     894
     895 }
     896
     897
     898
     899 /* Gets an object as a string and returns its 'mnt-by' attributes as a
     900    GSList (linked list)   */
     901 /* No need for this function any more in fact. 'get_attr_list' can be used instead.
     902    All calls to get_mntners(object) must be converted into get_attr_list(object, "mnt-by") */
     903
     904 GSList *get_mntners(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     905   bool code;
     906   Object * o;
     907   Attr *attr;
     908   char *value  = NULL;
     909   GSList *list_of_mntners = NULL;
     910   char * object;
     911
     912   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
     913    (no harm in having more than one) */
     914   object = (char *)malloc(strlen(arg) + 2);
     915   sprintf(object, "%s\n", arg);
     916
     917   if(tracing) {
     918     printf("TRACING: get_mntners is running\n");
     919   }
     920   o = new Object;
     921   code = o->scan(object,strlen(object));
     922
     923   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     924     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     925     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
     926         attr->len - strlen(attr->type->name()) -2 );
     927     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     928     if(strcmp(attr->type->name(),"mnt-by") == 0){
     929       if(tracing) {
     930         cout << "TRACING: get_mntners: adding " << g_strstrip(value) << endl;
     931       }
     932       list_of_mntners = g_slist_append(list_of_mntners, strdup(g_strstrip(value)));
     933     }
     934     free(value);
     935   }
     936
     937   free(object);
     938   return list_of_mntners;
     939 }
     940
     941
     942 /* Gets a preparsed object, its text and an attribute name. Returns a list of
     943    attribute values */
     944 GSList *get_attributes(Object * o, const char * attrib, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     945
     946   char * value = NULL;
     947   Attr *attr;
     948   GSList *list_of_attributes = NULL;
     949
     950
     951   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     952     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     953     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     954         attr->len - strlen(attr->type->name()) -2 );
     955     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     956     if(strcmp(attr->type->name(), attrib) == 0){
     957       if(tracing) {
     958         cout << "TRACING: get_attributes: adding " << g_strstrip(value) << endl;
     959       }
     960       list_of_attributes = g_slist_append(list_of_attributes, g_strstrip(value));
     961     }
     962   }
     963
     964
     965   return list_of_attributes;
     966 }
     967
     968
     969 /* Gets a preparsed object, an attribute name. Returns the value of first occurence
     970    of this attribute */
     971 char *get_attribute(Object * o, const char * attrib, char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     972
     973   char * value = NULL;
     974   Attr *attr;
     975
     976   if(tracing) {
     977     printf("TRACING: get_attributes is running\n");
     978   }
     979
     980   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     981     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     982     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     983         attr->len - strlen(attr->type->name()) -2 );
     984     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     985     if(strcmp(attr->type->name(), attrib) == 0){
     986       if(tracing) {
     987         cout << "TRACING: get_attribute: will return " << value << endl;
     988       }
     989       return value;
     990     }else{
     991       free(value);
     992     }
     993   }
     994
     995   if(tracing) {
     996     printf("TRACING: get_attribute is returning\n");
     997   }
     998
     999   return NULL;
    1000 }
    1001
    1002
    1003
    1004 /* Gets a GSList of strings and returns 1 if one of them starts with substr, 0 otherwise */
    1005 int strstr_in_list(GSList * list, const char * substr){
         /* [<][>][^][v][top][bottom][index][help] */
    1006
    1007  GSList * next = NULL;
    1008  char * word;
    1009
    1010   if(tracing) {
    1011     printf("TRACING: strstr_in_list is running\n");
    1012   }
    1013
    1014  for( next = list; next != NULL ; next = g_slist_next(next) ){
    1015    word = strdup((char *)next->data);
    1016    g_strup(word);
    1017    if(strstr(word, substr) == word){
    1018      free(word);
    1019      return 1;
    1020    }
    1021    free(word);
    1022  }
    1023  /* none of them matched, so return 0 */
    1024  return 0;
    1025 }
    1026
    1027
    1028
    1029
    1030
    1031 /* Gets a (maintainer) object as a string and returns its 'auth' attributes
    1032    as a GSList (linked list) */
    1033
    1034 GSList *get_auths(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1035   bool code;
    1036   Object * o;
    1037   Attr *attr;
    1038   char *value  = NULL;
    1039   GSList *list_of_auths = NULL;
    1040
    1041   if(tracing){
    1042     printf("TRACING: get_auths is running\n");
    1043   }
    1044   o = new Object;
    1045   code = o->scan(object,strlen(object));
    1046
    1047   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1048     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1049     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1050         attr->len - strlen(attr->type->name()) -2 );
    1051     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1052     if(strcmp(attr->type->name(),"auth") == 0){
    1053       if(tracing) {
    1054         cout << "TRACING: get_auths: adding " << g_strstrip(value) << endl;
    1055       }
    1056       list_of_auths = g_slist_append(list_of_auths, strdup(g_strstrip(value)));
    1057       if(tracing) {
    1058         cout << "TRACING: get_auths: # of nodes in list_of_auths is now " << g_slist_length(list_of_auths) << endl;
    1059       }
    1060     }
    1061   }
    1062
    1063   if(tracing) {
    1064     cout << "TRACING: get_auths: returning (with " << g_slist_length(list_of_auths) << " nodes)" << endl;
    1065   }
    1066   return list_of_auths;
    1067 }
    1068
    1069
    1070
    1071
    1072 /* Gets an object as a string an returns its 'attr_type' attributes as a
    1073    GSList (linked list) */
    1074
    1075 GSList *get_attr_list(char * arg, char * attr_type){
         /* [<][>][^][v][top][bottom][index][help] */
    1076   bool code;
    1077   Object * o;
    1078   Attr *attr;
    1079   char *value  = NULL;
    1080   GSList *list_of_attrs = NULL;
    1081   char * object;
    1082
    1083   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
    1084    (no harm in having more than one) */
    1085   object = (char *)malloc(strlen(arg) + 2);
    1086   sprintf(object, "%s\n", arg);
    1087
    1088   if(tracing) {
    1089     printf("TRACING: get_attr_list is running, object is \n#%s#\n", object);
    1090   }
    1091   o = new Object;
    1092   code = o->scan(object,strlen(object));
    1093
    1094   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1095     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1096     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1097         attr->len - strlen(attr->type->name()) -2 );
    1098     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1099     if(strcmp(attr->type->name(), attr_type) == 0){
    1100       if(tracing) {
    1101         cout << "TRACING: get_attr_list: adding " << g_strstrip(value) << endl;
    1102       }
    1103       list_of_attrs = g_slist_append(list_of_attrs, g_strstrip(value));
    1104     }
    1105   }
    1106
    1107   free(object);
    1108   return list_of_attrs;
    1109 }
    1110
    1111
    1112
    1113
    1114
    1115
    1116 /* Gets an object as a string an returns its mnt_lower attributes as a
    1117    GSList (linked list) */
    1118
    1119 GSList *get_mnt_lowers(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1120   bool code;
    1121   Object * o;
    1122   Attr *attr;
    1123   char *value  = NULL;
    1124   GSList *list_of_mnt_lowers = NULL;
    1125
    1126
    1127   if(tracing) {
    1128     printf("TRACING: get_mnt_lowers is running\n");
    1129   }
    1130   o = new Object;
    1131   code = o->scan(object,strlen(object));
    1132
    1133   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1134     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1135     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1136         attr->len - strlen(attr->type->name()) -2 );
    1137     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1138     if(strcmp(attr->type->name(),"mnt-lower") == 0){
    1139       if(tracing) {
    1140         cout << "TRACING: get_mnt_lowers: adding " << g_strstrip(value) << endl;
    1141       }
    1142       list_of_mnt_lowers = g_slist_append(list_of_mnt_lowers, strdup(g_strstrip(value)));
    1143     }
    1144   }
    1145
    1146
    1147   return list_of_mnt_lowers;
    1148 }
    1149
    1150
    1151 /* Gets an object as a string an returns its mnt_routes attributes as a
    1152    GSList (linked list) */
    1153
    1154 GSList *get_mnt_routes(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1155   bool code;
    1156   Object * o;
    1157   Attr *attr;
    1158   char *value  = NULL;
    1159   GSList *list_of_mnt_routes = NULL;
    1160
    1161   if(tracing) {
    1162   cout << "TRACING: get_mnt_routes is running" << endl;
    1163   }
    1164   o = new Object;
    1165   code = o->scan(object,strlen(object));
    1166
    1167   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1168     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1169     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1170         attr->len - strlen(attr->type->name()) -2 );
    1171     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1172     if(strcmp(attr->type->name(),"mnt-routes") == 0){
    1173       if(tracing) {
    1174         cout << "TRACING: get_mnt_routes: adding " << g_strstrip(value) << endl;
    1175       }
    1176       list_of_mnt_routes = g_slist_append(list_of_mnt_routes, strdup(g_strstrip(value)));
    1177     }
    1178   }
    1179
    1180   return list_of_mnt_routes;
    1181 }
    1182
    1183
    1184 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1185    them in a linked list */
    1186 GSList *get_mnt_routes_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1187   GSList *next = NULL;
    1188   GSList *list_of_mnt_routes = NULL;
    1189
    1190   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1191     list_of_mnt_routes = g_slist_concat(list_of_mnt_routes, get_mnt_routes((char *)next->data));
    1192   }
    1193
    1194   return list_of_mnt_routes;
    1195 }
    1196
    1197
    1198
    1199 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1200    them in a linked list */
    1201 GSList *get_mnt_lowers_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1202   GSList *next = NULL;
    1203   GSList *list_of_mnt_lowers = NULL;
    1204
    1205   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1206     list_of_mnt_lowers = g_slist_concat(list_of_mnt_lowers, get_mnt_lowers((char *)next->data));
    1207   }
    1208
    1209   return list_of_mnt_lowers;
    1210 }
    1211
    1212
    1213
    1214 /* retrieves the override password from the 'override' attribute
    1215    of the object. If none, it returns NULL   */
    1216 char *get_override(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1217   bool code;
    1218   Object * o;
    1219   Attr *attr;
    1220   char *value  = NULL;
    1221
    1222   if(tracing){
    1223     printf("TRACING: get_override is running\n");
    1224   }
    1225   o = new Object;
    1226   code = o->scan(object,strlen(object));
    1227
    1228   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1229     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1230     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1231         attr->len - strlen(attr->type->name()) -2 );
    1232     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1233     if(strcmp(attr->type->name(),"override") == 0){
    1234       if(tracing) {
    1235         cout << "TRACING: get_override: returning " << g_strstrip(value) << endl;
    1236       }
    1237       return  strdup(g_strstrip(value));
    1238     }
    1239   }
    1240   /* there was no 'override' attrib, so return NULL */
    1241   return NULL;
    1242 }
    1243
    1244
    1245
    1246
    1247
    1248
    1249 /* checks override string (password)
    1250    returns OVR_OK if it is correct password */
    1251 int check_override(char * string){
         /* [<][>][^][v][top][bottom][index][help] */
    1252    char ** temp;
    1253    int i;
    1254    char * crypted_password = strdup(overridecryptedpw);
    1255    if(string == NULL) {
    1256      if(tracing) {
    1257        printf("TRACING: check_override is returning FAILED\n");
    1258      }
    1259      return UP_OVF; /* override attempt failed */
    1260    }else{
    1261     /* split the string */
    1262      temp = g_strsplit (string, " ", 0);
    1263
    1264      for(i=0; temp[i] != NULL; i++){
    1265        if(strlen(temp[i]) != 0){
    1266          if(strcmp(AU_crypt(temp[i], crypted_password), crypted_password) == 0){
    1267            g_strfreev(temp);
    1268            if(tracing) {
    1269              printf("TRACING: check_override is returning OK\n", string);
    1270            }
    1271            return OVR_OK;
    1272          }
    1273        }
    1274      }
    1275
    1276      g_strfreev(temp);
    1277      /* we couldn't find a word matching the override password */
    1278           return UP_OVF; /* override attempt failed */
    1279    }
    1280 }
    1281
    1282
    1283
    1284
    1285
    1286
    1287
    1288
    1289
    1290
    1291
    1292
    1293 /* takes a GSList of struct auth_struct and a GSList of auths, and a mntner name,
    1294    add new elements to GSList of struct auth_struct and  returns the new
    1295    GSList of struct auth_struct  */
    1296
    1297 GSList * add_to_auth_vector(GSList * list_of_auth_struct, GSList * auths, char * mntner_name){
         /* [<][>][^][v][top][bottom][index][help] */
    1298    GSList * next;
    1299    char * auth_attrib = NULL;
    1300    char * auth_attrib_uppercase = NULL, * argument = NULL;
    1301    auth_struct * temp = NULL;
    1302    int index = 1;
    1303
    1304    for(next = auths; next != NULL; next = g_slist_next(next)){
    1305      auth_attrib = strdup((char *)next->data);
    1306      auth_attrib = g_strstrip(auth_attrib);
    1307      if(tracing) {
    1308        cout << "TRACING: add_to_auth_vector: " << auth_attrib << endl;
    1309      }
    1310      /* Take the auth attribute and convert it into uppercase for comparisons */
    1311      auth_attrib_uppercase = strdup(auth_attrib);
    1312      g_strup(auth_attrib_uppercase);
    1313
    1314      if(strstr(auth_attrib_uppercase,"CRYPT-PW") == auth_attrib_uppercase){
    1315        /* take the argument of the auth attribute */
    1316        argument = strdup(auth_attrib + strlen("CRYPT-PW"));
    1317        g_strstrip(argument);
    1318        if(tracing) {
    1319          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1320        }
    1321        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1322        temp->type = AU_CRYPT_PW;
    1323        temp->auth = argument;
    1324        temp->mntner_name = mntner_name;
    1325        temp->index = index++;
    1326        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1327      }else if(strstr(auth_attrib_uppercase,"MAIL-FROM") == auth_attrib_uppercase){
    1328        /* take the argument of the auth attribute */
    1329        argument = strdup(auth_attrib + strlen("MAIL-FROM"));
    1330        g_strstrip(argument);
    1331        if(tracing) {
    1332          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1333        }
    1334        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1335        temp->type = AU_MAIL_FROM;
    1336        temp->auth = argument;
    1337        temp->mntner_name = mntner_name;
    1338        temp->index = index++;
    1339        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1340      }else if(strstr(auth_attrib_uppercase,"NONE") == auth_attrib_uppercase){
    1341        /* take the argument of the auth attribute */
    1342        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1343        temp->type = AU_NONE;
    1344        temp->auth = NULL;
    1345        temp->mntner_name = mntner_name;
    1346        temp->index = index++;
    1347        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1348     }else if(strstr(auth_attrib_uppercase,"PGPKEY-") == auth_attrib_uppercase){
    1349        argument = strdup(auth_attrib + strlen("PGPKEY-"));
    1350        g_strstrip(argument);
    1351        if(tracing) {
    1352          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1353        }
    1354        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1355        temp->type = AU_PGP;
    1356        temp->mntner_name = mntner_name;
    1357        temp->index = index++;
    1358        temp->auth = argument;
    1359        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1360      }else{
    1361        if(tracing){
    1362          cout << "TRACING: Error: invalid auth attrib: " << auth_attrib << endl;
    1363        }
    1364        return NULL;
    1365      }
    1366    }
    1367    free(auth_attrib_uppercase);
    1368    free(auth_attrib);
    1369    return list_of_auth_struct;
    1370
    1371 }
    1372
    1373
    1374
    1375
    1376
    1377
    1378
    1379
    1380
    1381 /* Gets a list of mntner names, retrieves those mntners from
    1382    the database and extracts the 'auth' attributes, and
    1383    constructs the authorisation vector, which is a GSList of
    1384    struct auth_struct */
    1385
    1386 GSList * get_auth_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1387   GSList * list_of_auths = NULL;
    1388   GSList * next = NULL;
    1389   GSList * to_be_returned = NULL;
    1390   char * query_string = NULL, * result = NULL, * object = NULL;
    1391   GSList * temp;
    1392
    1393   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1394     if(tracing) {
    1395       cout << "=====" << endl << "Got a mntner" << endl;
    1396       cout << (char *)next->data << endl;
    1397     }
    1398     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1399     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1400     result = send_and_get(query_host, query_port, query_string);
    1401     if(count_objects(result) == 0){
    1402       /* no such maintainer */
    1403       return NULL;
    1404     }else if(count_objects(result) > 1){
    1405       if(tracing) {
    1406         cout << "More than one objects returned" << endl;
    1407       }
    1408     }else{ /* count_objects(result) == 1 */
    1409       object = take_object(result);
    1410       if(tracing) {
    1411         printf("TRACING: get_auth_vector: Calling get_auths(char *)\n");
    1412       }
    1413       temp = get_auths(object);
    1414       if(tracing) {
    1415         cout << "TRACING: get_auth_vector: get_auths(char *) returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1416       }
    1417       list_of_auths = g_slist_concat(list_of_auths, temp);
    1418       if(tracing) {
    1419         cout << "TRACING: get_auth_vector: list_of_auths has now " <<  g_slist_length(list_of_auths) << " nodes" << endl;
    1420       }
    1421       /* add this to the auth_vector. ( next->data is the name of the maintainer  ) */
    1422       if(tracing) {
    1423        cout << "TRACING: get_auth_vector: to_be_returned has now " <<  g_slist_length(to_be_returned) << " nodes" << endl;
    1424       }
    1425       to_be_returned = add_to_auth_vector(to_be_returned, list_of_auths, (char *)next->data);
    1426     }
    1427   }
    1428
    1429   if(tracing) {
    1430     printf("TRACING: get_auth_vector: to_be_returned has %i nodes\n", g_slist_length(to_be_returned));
    1431   }
    1432   return to_be_returned;
    1433 }
    1434
    1435
    1436
    1437
    1438
    1439
    1440
    1441 /* Gets a list of mntner names, retrieves those mntners from
    1442    the database and extracts the 'mnt-by' attributes, and
    1443    returns them as a GSList */
    1444
    1445 GSList * get_mntnfy_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1446   GSList * list_of_mntnfy = NULL;
    1447   GSList * next = NULL;
    1448   //GSList * to_be_returned = NULL;
    1449   char * query_string = NULL, * result = NULL, * object = NULL;
    1450   GSList * temp;
    1451
    1452   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1453     if(tracing) {
    1454       cout << "=====" << endl << "Got a mntner" << endl;
    1455       cout << (char *)next->data << endl;
    1456     }
    1457     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1458     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1459     result = send_and_get(query_host, query_port, query_string);
    1460     if(count_objects(result) == 0){
    1461       /* no such maintainer */
    1462     }else if(count_objects(result) > 1){
    1463       if(tracing) {
    1464         cout << "More than one objects returned" << endl;
    1465       }
    1466     }else{ /* count_objects(result) == 1 */
    1467       object = take_object(result);
    1468       if(tracing) {
    1469         printf("TRACING: get_mntnfy_vector: Calling get_attr_list\n");
    1470       }
    1471       temp = get_attr_list(object, "mnt-nfy");
    1472       if(tracing) {
    1473         cout << "TRACING: get_mntnfy_vector: get_attr_list returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1474       }
    1475       list_of_mntnfy = g_slist_concat(list_of_mntnfy, temp);
    1476       if(tracing) {
    1477         cout << "TRACING: get_mntnfy_vector: list_of_mntnfy has now " <<  g_slist_length(list_of_mntnfy) << " nodes" << endl;
    1478       }
    1479     }
    1480   }
    1481
    1482   if(tracing) {
    1483     printf("TRACING: get_auth_vector: list_of_mntnfy has %i nodes\n", g_slist_length(list_of_mntnfy));
    1484   }
    1485   return list_of_mntnfy;
    1486 }
    1487
    1488
    1489
    1490
    1491
    1492
    1493 /* Gets a list of mntner names, retrieves those mntners from
    1494    the database and extracts the 'upd-to' attributes, and
    1495    returns them as a GSList */
    1496
    1497 GSList * get_updto_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1498   GSList * list_of_updto = NULL;
    1499   GSList * next = NULL;
    1500   char * query_string = NULL, * result = NULL, * object = NULL;
    1501   GSList * temp;
    1502
    1503   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1504     if(tracing) {
    1505       cout << "=====" << endl << "Got a mntner" << endl;
    1506       cout << (char *)next->data << endl;
    1507     }
    1508     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1509     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1510     result = send_and_get(query_host, query_port, query_string);
    1511     if(count_objects(result) == 0){
    1512       /* no such maintainer */
    1513     }else if(count_objects(result) > 1){
    1514       if(tracing) {
    1515         cout << "More than one objects returned" << endl;
    1516       }
    1517     }else{ /* count_objects(result) == 1 */
    1518       object = take_object(result);
    1519       if(tracing) {
    1520         printf("TRACING: get_mntnfy_vector: Calling get_attr_list\n");
    1521       }
    1522       temp = get_attr_list(object, "upd-to");
    1523       if(tracing) {
    1524         cout << "TRACING: get_updto_vector: get_attr_list returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1525       }
    1526       list_of_updto = g_slist_concat(list_of_updto, temp);
    1527       if(tracing) {
    1528         cout << "TRACING: get_updto_vector: list_of_mntnfy has now " <<  g_slist_length(list_of_updto) << " nodes" << endl;
    1529       }
    1530     }
    1531   }
    1532
    1533   if(tracing) {
    1534     printf("TRACING: get_updto_vector: list_of_updto has %i nodes\n", g_slist_length(list_of_updto));
    1535   }
    1536   return list_of_updto;
    1537 }
    1538
    1539
    1540
    1541
    1542
    1543
    1544
    1545
    1546
    1547
    1548 /* gets one or more route objects filters out the ones which don't have the same
    1549    origin as 'char * origin' argument */
    1550 char * filter_out_diff_origins(char * objects, char * origin){
         /* [<][>][^][v][top][bottom][index][help] */
    1551   GSList * object_list = NULL, * next =NULL;
    1552   char * objects_to_be_returned = NULL;
    1553   bool code;
    1554   char * key = NULL;
    1555   Object * o = new Object();
    1556
    1557
    1558   if(tracing) {
    1559     printf("TRACING: filter_out_diff_origins\n");
    1560   }
    1561
    1562   /* strip the lines beginning with '%' off */
    1563   objects = strip_lines(objects);
    1564
    1565   /* separate the objects, store them in a linked list */
    1566   object_list = take_objects(objects);
    1567
    1568   for(next = object_list; next != NULL; next = g_slist_next(next)){
    1569     code = o->scan((char *)next->data, strlen((char *)next->data));
    1570     key = get_search_key(o, "origin", (char *)next->data);
    1571     if(key != NULL && strcasecmp(g_strstrip(origin), key) == 0){
    1572       if(objects_to_be_returned == NULL){
    1573         objects_to_be_returned = strdup((char *)next->data);
    1574       }else{
    1575         objects_to_be_returned = (char *)realloc(objects_to_be_returned,
    1576                       strlen(objects_to_be_returned) + strlen((char *)next->data) + 2);
    1577         objects_to_be_returned = strcat(objects_to_be_returned, "\n");
    1578         objects_to_be_returned = strcat(objects_to_be_returned, (char *)next->data);
    1579       }
    1580     }
    1581   }
    1582
    1583   delete(o);
    1584   if(tracing) {
    1585     if(objects_to_be_returned != NULL){
    1586       printf("TRACING: filter_out_diff_origins: returning:\n%s\n", objects_to_be_returned? "(NULL)":objects_to_be_returned);
    1587     }else {
    1588       printf("TRACING: filter_out_diff_origins: returning NULL\n");
    1589
    1590     }
    1591   }
    1592   return objects_to_be_returned;
    1593
    1594 }
    1595
    1596
    1597
    1598
    1599 /* Check authorisation
    1600    Applies authorisation rules according to the object type
    1601
    1602    Arguments:
    1603       char *new_object: the new object,
    1604       char *old_object: the old object, as found in the database,
    1605       char *type: type of the object
    1606       credentials_struct credentials: a struct which
    1607         contains credentials of the update, such as 'From:' field of
    1608         the e-mail header and passwords in the update   */
    1609
    1610 int check_auth(char *new_object, char *old_object, char *type, credentials_struct credentials){
         /* [<][>][^][v][top][bottom][index][help] */
    1611
    1612    GSList *old_mntners = NULL, *new_mntners = NULL;
    1613    GSList *old_auths = NULL, *new_auths = NULL;
    1614    GSList *as_block_mnt_lowers = NULL;
    1615    GSList *old_auth_vector = NULL, *new_auth_vector = NULL, *as_block_auth_vector = NULL;
    1616    GSList *less_specific_auth_vector = NULL, *less_specific_mnt_lowers = NULL;
    1617    GSList *less_specific_mntners = NULL;
    1618    GSList *aut_num_maintainers = NULL;
    1619    GSList *aut_num_auth_vector = NULL;
    1620    GSList *exact_match_routes = NULL;
    1621    GSList *exact_match_routes_maintainers = NULL;
    1622    GSList *exact_match_routes_auth_vector = NULL;
    1623    GSList *less_spec_routes = NULL;
    1624    GSList *less_spec_routes_mntners = NULL;
    1625    GSList *less_spec_routes_auth_vector = NULL;
    1626    GSList *exact_match_inetnum_mnt_routes = NULL;
    1627    GSList *exact_match_inetnum_auth_vector = NULL;
    1628    GSList *less_spec_inetnum_mntners = NULL;
    1629    GSList *less_spec_inetnum_auth_vector = NULL;
    1630    GSList *exact_match_intenum_auth_vector = NULL;
    1631    GSList *exact_match_auth_vector = NULL;
    1632
    1633    char *as_block_object = NULL, *less_specific_object = NULL;
    1634    char *less_specific_domain = NULL;
    1635    char *less_spec_inetnum = NULL;
    1636    char *exact_match_inetnum = NULL;
    1637    char *less_specific_object_type = NULL;
    1638    char *override_string = NULL;
    1639    char *set_name = NULL;
    1640    char * aut_num_object = NULL;
    1641    Object *set_object = new Object();
    1642    Object *temp_obj;
    1643    bool code;
    1644    bool aut_num_auth_OK = false;
    1645
    1646    int overriden = 0;
    1647
    1648    /* first check if it is overriden or not. if overriden, check the override
    1649       password. If it is correct, continue, setting "overriden" to 1. If not,
    1650       immediately exit returning ERR_UP_OVF                                   */
    1651    override_string = get_override((new_object == NULL) ? old_object : new_object );
    1652    if(override_string == NULL){
    1653      overriden = 0;
    1654    }else if(check_override(override_string) == OVR_OK){
    1655      overriden = 1; /* authorisation is overriden */
    1656      free(override_string);override_string = NULL;
    1657    }else if(check_override(override_string) == UP_OVS){
    1658      free(override_string);override_string = NULL;
    1659      return UP_OVS; /* override syntax error --it must have at least two words */
    1660    }else{
    1661      free(override_string);override_string = NULL;
    1662      return UP_OVF; /* override failed! */
    1663    }
    1664
    1665
    1666    /*
    1667     *  Handle the "person", "role", "limerick", "inet-rtr", "key-cert" types
    1668     */
    1669    if(strcmp(type,"person")   == 0 || strcmp(type,"role")     == 0 ||
    1670       strcmp(type,"limerick") == 0 || strcmp(type,"inet-rtr") == 0 ||
    1671       strcmp(type,"key-cert") == 0 ){
    1672      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1673        old_mntners = get_mntners(old_object);
    1674        old_auth_vector = get_auth_vector(old_mntners);
    1675        return authorise(old_auth_vector, credentials, overriden);
    1676      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1677        new_mntners = get_mntners(new_object);
    1678        new_auth_vector = get_auth_vector(new_mntners);
    1679        if(new_mntners != NULL && new_auth_vector == NULL){
    1680          /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1681          return UP_AUF; /* auth failed */
    1682        }
    1683        return authorise(new_auth_vector, credentials, overriden);
    1684      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1685        old_mntners = get_mntners(old_object);
    1686        old_auth_vector = get_auth_vector(old_mntners);
    1687        if(old_mntners != NULL && old_auth_vector == NULL){
    1688          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1689          return UP_AUF; /* auth failed */
    1690        }
    1691        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1692          return authorise(old_auth_vector, credentials, overriden);
    1693        }else{
    1694          new_mntners = get_mntners(new_object);
    1695          new_auth_vector = get_auth_vector(new_mntners);
    1696          if(new_mntners != NULL && new_auth_vector == NULL){
    1697            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1698            return UP_AUF; /* auth failed */
    1699          }
    1700          return authorise(new_auth_vector, credentials, overriden);
    1701        }
    1702      }else{ // both are NULL, mustn't happen
    1703          if(tracing){
    1704            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1705          }
    1706          return UP_INT; /* internal error */
    1707      }
    1708    }
    1709
    1710    /*
    1711     *  Handle the "auth-num" type
    1712     */
    1713    else if(strcmp(type,"aut-num")  == 0 ){
    1714      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1715        old_mntners = get_mntners(old_object);
    1716        old_auth_vector = get_auth_vector(old_mntners);
    1717        if(old_mntners != NULL && old_auth_vector == NULL){
    1718          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1719          return UP_AUF; /* auth failed */
    1720        }
    1721        return authorise(old_auth_vector, credentials, overriden);
    1722      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1723        as_block_object = get_as_block(new_object);
    1724        if(as_block_object == NULL ){
    1725          return UP_ABN; /* As-block does not exist */
    1726          }else{
    1727            as_block_mnt_lowers = get_mnt_lowers(as_block_object);
    1728            as_block_auth_vector = get_auth_vector(as_block_mnt_lowers);
    1729            if(as_block_mnt_lowers != NULL && as_block_auth_vector == NULL){
    1730              /* then, the mntners in 'as_block_mnt_lowers' do not exist. Problem. */
    1731              return UP_AUF; /* auth failed */
    1732            }
    1733          if(authorise(as_block_auth_vector, credentials, overriden) == UP_AUTH_OK ){
    1734            new_mntners = get_mntners(new_object);
    1735            new_auth_vector = get_auth_vector(new_mntners);
    1736            if(new_mntners != NULL && new_auth_vector == NULL){
    1737              /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1738              return UP_AUF; /* auth failed */
    1739            }
    1740            return authorise(new_auth_vector, credentials, overriden);
    1741          }else{
    1742            return UP_HOF; /* hierarchical auth failed */
    1743          }
    1744        }
    1745      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1746        old_mntners = get_mntners(old_object);
    1747        old_auth_vector = get_auth_vector(old_mntners);
    1748        if(old_mntners != NULL && old_auth_vector == NULL){
    1749          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1750          return UP_AUF; /* auth failed */
    1751        }
    1752        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1753          return authorise(old_auth_vector, credentials, overriden);
    1754        }else{
    1755          new_mntners = get_mntners(new_object);
    1756          new_auth_vector = get_auth_vector(new_mntners);
    1757          if(new_mntners != NULL && new_auth_vector == NULL){
    1758            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1759            return UP_AUF; /* auth failed */
    1760          }
    1761          return authorise(new_auth_vector, credentials, overriden);
    1762        }
    1763      }else{ /* both are NULL, mustn't happen */
    1764          if(tracing) {
    1765            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1766          }
    1767          return UP_INT; /* internal error */
    1768      }
    1769    }
    1770
    1771    /*
    1772     *  Handle the "mntner/as-block" types
    1773     */
    1774    else if(strcmp(type,"mntner")  == 0 || strcmp(type,"as-block")  == 0 ){
    1775      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1776        old_mntners = get_mntners(old_object);
    1777        old_auth_vector = get_auth_vector(old_mntners);
    1778        if(old_mntners != NULL && old_auth_vector == NULL){
    1779          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1780          return UP_AUF; /* auth failed */
    1781        }
    1782        return authorise(old_auth_vector, credentials, overriden);
    1783      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1784        if(overriden || test_mode){
    1785          return UP_AUTH_OK;
    1786        }else{/* If not overriden, and if not coming from ripe-dbm, must be forwarded to ripe-dbm */
    1787          if(tracing) {
    1788            cout << "TRACING: check_auth: '" << type << "' creation requested" << endl;
    1789          }
    1790          return UP_AUF; /* authorisation failed */
    1791        }
    1792      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1793        old_mntners = get_mntners(old_object);
    1794        old_auth_vector = get_auth_vector(old_mntners);
    1795        if(old_mntners != NULL && old_auth_vector == NULL){
    1796          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1797          return UP_AUF; /* auth failed */
    1798        }
    1799        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1800          return authorise(old_auth_vector, credentials, overriden);
    1801        }else{
    1802          new_mntners = get_mntners(new_object);
    1803          new_auth_vector = get_auth_vector(new_mntners);
    1804          if(new_mntners != NULL && new_auth_vector == NULL){
    1805            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1806            return UP_AUF; /* auth failed */
    1807          }
    1808          return authorise(new_auth_vector, credentials, overriden);
    1809        }
    1810      }else{ // both are NULL, mustn't happen
    1811          if(tracing){
    1812            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1813          }
    1814          return UP_INT; /* internal error */
    1815      }
    1816    }
    1817
    1818    /*
    1819     *  Handle the "inetnum/inet6num" types
    1820     */
    1821    else if(strcmp(type,"inetnum")  == 0 || strcmp(type,"inet6num")  == 0 ){
    1822      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1823        old_mntners = get_mntners(old_object);
    1824        old_auth_vector = get_auth_vector(old_mntners);
    1825        if(old_mntners != NULL && old_auth_vector == NULL){
    1826          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1827          return UP_AUF; /* auth failed */
    1828        }
    1829        return authorise(old_auth_vector, credentials, overriden);
    1830      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1831        less_specific_object = get_less_specific(new_object, type);
    1832        if(less_specific_object == NULL){
    1833          if(overriden){
    1834            return UP_AUTH_OK;
    1835          }else{
    1836            return UP_HOF; /* hierarchical authorisation failed */
    1837          }
    1838        }else{ /* if we got an inet(6)num object */
    1839          less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    1840          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    1841          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    1842            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    1843            return UP_AUF; /* auth failed */
    1844          }
    1845          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1846            new_mntners = get_mntners(new_object);
    1847            new_auth_vector = get_auth_vector(new_mntners);
    1848            if(new_mntners != NULL && new_auth_vector == NULL){
    1849              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1850              return UP_AUF; /* auth failed */
    1851            }
    1852            return authorise(new_auth_vector, credentials, overriden);
    1853          }else{
    1854            return UP_HOF; /* hierarchical authorisation failed */
    1855          }
    1856        }
    1857      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1858        old_mntners = get_mntners(old_object);
    1859        old_auth_vector = get_auth_vector(old_mntners);
    1860        if(old_mntners != NULL && old_auth_vector == NULL){
    1861          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1862          return UP_AUF; /* auth failed */
    1863        }
    1864        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1865          return authorise(old_auth_vector, credentials, overriden);
    1866        }else{
    1867          new_mntners = get_mntners(new_object);
    1868          new_auth_vector = get_auth_vector(new_mntners);
    1869          if(new_mntners != NULL && new_auth_vector == NULL){
    1870            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1871            return UP_AUF; /* auth failed */
    1872          }
    1873          return authorise(new_auth_vector, credentials, overriden);
    1874        }
    1875      }else{ /* both are NULL, mustn't happen */
    1876          if(tracing){
    1877            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1878          }
    1879          return UP_INT; /* internal error */
    1880      }
    1881    }
    1882
    1883
    1884
    1885    /*
    1886     *  Handle the "domain" type
    1887     */
    1888    else if(strcmp(type,"domain")  == 0){
    1889      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1890        old_mntners = get_mntners(old_object);
    1891        old_auth_vector = get_auth_vector(old_mntners);
    1892        if(old_mntners != NULL && old_auth_vector == NULL){
    1893          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1894          return UP_AUF; /* auth failed */
    1895        }
    1896        return authorise(old_auth_vector, credentials, overriden);
    1897      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1898        /* now, we have to find a 'less specific domain object' for this.
    1899           If there is no less specific object, then creation is possible
    1900           only with overriding. */
    1901       less_specific_domain = get_less_specific_domain(new_object);
    1902       if(less_specific_domain == NULL){
    1903         if(overriden){/* we didn't get a 'less specific' domain object */
    1904            return UP_AUTH_OK;
    1905          }else{
    1906            return UP_HOF; /* hierarchical authorisation failed */
    1907          }
    1908       }else{ /* we get a 'less specific' domain object */
    1909          less_specific_mnt_lowers = get_mnt_lowers(less_specific_domain);
    1910          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    1911          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    1912            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    1913            return UP_AUF; /* auth failed */
    1914          }
    1915          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1916            new_mntners = get_mntners(new_object);
    1917            new_auth_vector = get_auth_vector(new_mntners);
    1918            if(new_mntners != NULL && new_auth_vector == NULL){
    1919              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1920              return UP_AUF; /* auth failed */
    1921            }
    1922            return authorise(new_auth_vector, credentials, overriden);
    1923          }else{
    1924            return UP_HOF; /* hierarchical authorisation failed */
    1925          }
    1926
    1927       }
    1928      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1929        old_mntners = get_mntners(old_object);
    1930        old_auth_vector = get_auth_vector(old_mntners);
    1931        if(old_mntners != NULL && old_auth_vector == NULL){
    1932          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1933          return UP_AUF; /* auth failed */
    1934        }
    1935        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1936          return authorise(old_auth_vector, credentials, overriden);
    1937        }else{
    1938          new_mntners = get_mntners(new_object);
    1939          new_auth_vector = get_auth_vector(new_mntners);
    1940          if(new_mntners != NULL && new_auth_vector == NULL){
    1941            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1942            return UP_AUF; /* auth failed */
    1943          }
    1944          return authorise(new_auth_vector, credentials, overriden);
    1945        }
    1946      }else{ /* both are NULL, mustn't happen */
    1947          if(tracing){
    1948            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1949          }
    1950          return UP_INT; /* internal error */
    1951      }
    1952    }
    1953
    1954
    1955    /*
    1956     *  Handle the "route" type
    1957     */
    1958    else if(strcmp(type,"route")  == 0){
    1959      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1960        old_mntners = get_mntners(old_object);
    1961        old_auth_vector = get_auth_vector(old_mntners);
    1962        if(old_mntners != NULL && old_auth_vector == NULL){
    1963          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1964          return UP_AUF; /* auth failed */
    1965        }
    1966        return authorise(old_auth_vector, credentials, overriden);
    1967      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1968        /* first we have to find the aut-num object mentioned in the
    1969           origin attribute */
    1970
    1971        aut_num_object = get_aut_num_object(new_object);
    1972        if(aut_num_object == NULL){
    1973          if(overriden){
    1974            return UP_AUTH_OK;
    1975          }else{
    1976            return UP_HOF; /* hierarchical authorisation failed */
    1977          }
    1978        }else{/* there is a corresponding aut-num in the db */
    1979          if(tracing){
    1980            printf("TRACING: check_auth: will try to authorise the route using aut-num\n");
    1981          }
    1982          aut_num_maintainers = get_mnt_routes(aut_num_object);
    1983          if(aut_num_maintainers != NULL){
    1984            aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    1985            if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1986              aut_num_auth_OK = true;
    1987            }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1988              return UP_HOF;
    1989            }
    1990          }else{/* aut_num_maintainers is NULL */
    1991             aut_num_maintainers = get_mnt_lowers(aut_num_object);
    1992             if(aut_num_maintainers != NULL){
    1993               aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    1994               if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1995                 aut_num_auth_OK = TRUE;
    1996               }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1997                 return UP_HOF; /* hierarchical authorisation failed */
    1998               }
    1999             }else{/* aut_num_maintainers is NULL */
    2000               aut_num_maintainers = get_mntners(aut_num_object);
    2001               if(aut_num_maintainers != NULL){
    2002                 aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    2003                 if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2004                   aut_num_auth_OK = TRUE;
    2005                 }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2006                   return UP_HOF; /* hierarchical authorisation failed */
    2007                 }
    2008               }else{/* aut_num_maintainers is NULL */
    2009                 aut_num_auth_OK = TRUE;
    2010               }
    2011
    2012             }
    2013          }
    2014          if(aut_num_auth_OK){
    2015            /* now, we have to find an exact match for this route object.
    2016               If there is no exact match object, then we will go on to find
    2017               less specific. */
    2018            exact_match_routes = get_exact_match_routes(new_object);
    2019            if(exact_match_routes != NULL){
    2020              exact_match_routes_maintainers = get_mnt_routes_from_list(exact_match_routes);
    2021              exact_match_routes_auth_vector = get_auth_vector(exact_match_routes_maintainers);
    2022              if(exact_match_routes_maintainers != NULL && exact_match_routes_auth_vector == NULL){
    2023                /* then, the mntners in 'exact_match_routes_maintainers' do not exist. Problem. */
    2024                return UP_AUF; /* auth failed */
    2025               }
    2026              if(authorise(exact_match_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2027                /* then, check mnt_bys of the route itself */
    2028                new_mntners = get_mntners(new_object);
    2029                new_auth_vector = get_auth_vector(new_mntners);
    2030                if(new_mntners != NULL && new_auth_vector == NULL){
    2031                  /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2032                  return UP_AUF; /* auth failed */
    2033                }
    2034                return authorise(new_auth_vector, credentials, overriden);
    2035              }else{/*authorise(exact_match_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    2036                return UP_HOF; /* hierarchical authorisation failed */
    2037              }
    2038            }else{ /* exact_match_routes == NULL */
    2039              /* then we have to look for less specific route objs */
    2040              less_spec_routes = get_less_spec_routes(new_object);
    2041              if(less_spec_routes != NULL){
    2042                less_spec_routes_mntners = get_mnt_routes_from_list(less_spec_routes);
    2043                less_spec_routes_mntners = g_slist_concat(less_spec_routes_mntners,
    2044                                              get_mnt_lowers_from_list(less_spec_routes));
    2045                less_spec_routes_auth_vector = get_auth_vector(less_spec_routes_mntners);
    2046                if(less_spec_routes_mntners != NULL && less_spec_routes_auth_vector == NULL){
    2047                  /* then, the mntners in 'less_spec_routes_mntners' do not exist. Problem. */
    2048                  return UP_AUF; /* auth failed */
    2049                }
    2050                if(authorise(less_spec_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2051                  /* then, check mnt_bys of the route itself */
    2052                  new_mntners = get_mntners(new_object);
    2053                  new_auth_vector = get_auth_vector(new_mntners);
    2054                  if(new_mntners != NULL && new_auth_vector == NULL){
    2055                    /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2056                    return UP_AUF; /* auth failed */
    2057                  }
    2058                  return authorise(new_auth_vector, credentials, overriden);
    2059                }else{/*authorise(less_spec_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    2060                  return UP_HOF; /* hierarchical authorisation failed */
    2061                }
    2062             }else{/* less_spec_routes == NULL */
    2063                /* so, we have to get the exact match inetnum */
    2064                exact_match_inetnum = get_exact_match_inetnum(new_object);
    2065                if(exact_match_inetnum != NULL){
    2066                  exact_match_inetnum_mnt_routes = get_mnt_routes(exact_match_inetnum);
    2067                  exact_match_inetnum_auth_vector = get_auth_vector(exact_match_inetnum_mnt_routes);
    2068                  if(exact_match_inetnum_mnt_routes != NULL && exact_match_inetnum_auth_vector == NULL){
    2069                    /* then, the mntners in 'exact_match_inetnum_mnt_routes' do not exist. Problem. */
    2070                    return UP_AUF; /* auth failed */
    2071                  }
    2072                  if(authorise(exact_match_intenum_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2073                    /* then, check mnt_bys of the route itself */
    2074                    new_mntners = get_mntners(new_object);
    2075                    new_auth_vector = get_auth_vector(new_mntners);
    2076                    if(new_mntners != NULL && new_auth_vector == NULL){
    2077                      /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2078                      return UP_AUF; /* auth failed */
    2079                    }
    2080                    return authorise(new_auth_vector, credentials, overriden);
    2081                  }else{
    2082                    return UP_HOF; /* hierarchical authorisation failed */
    2083                  }
    2084                }else{/* exact_match_inetnum == NULL */
    2085                  /* then, we will try to find less spec inetnums */
    2086                  less_spec_inetnum = get_less_spec_inetnum(new_object);
    2087                  if(less_spec_inetnum != NULL){
    2088                    less_spec_inetnum_mntners = get_mnt_routes(less_spec_inetnum);
    2089                    less_spec_inetnum_mntners = g_slist_concat(less_spec_inetnum_mntners,
    2090                                   get_mnt_lowers(less_spec_inetnum));
    2091                    less_spec_inetnum_auth_vector = get_auth_vector(less_spec_inetnum_mntners);
    2092                    if(less_spec_inetnum_mntners != NULL && less_spec_inetnum_auth_vector == NULL){
    2093                      /* then, the mntners in 'less_spec_inetnum_mntners' do not exist. Problem. */
    2094                      return UP_AUF; /* auth failed */
    2095                    }
    2096                    if(authorise(exact_match_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2097                      /* then, check mnt_bys of the route itself */
    2098                      new_mntners = get_mntners(new_object);
    2099                      new_auth_vector = get_auth_vector(new_mntners);
    2100                      if(new_mntners != NULL && new_auth_vector == NULL){
    2101                        /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2102                        return UP_AUF; /* auth failed */
    2103                      }
    2104                      return authorise(new_auth_vector, credentials, overriden);
    2105                    }else{/* authorise(exact_match_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2106                      return UP_HOF; /* hierarchical authorisation failed */
    2107                    }
    2108                  }else{/* less_spec_inetnum == NULL */
    2109                    /* now that we couldn't find any route or inetnum object
    2110                       to be used in authentication. So, only if the auth is
    2111                       overriden the object will be created. */
    2112                    if(overriden){
    2113                      return UP_AUTH_OK;
    2114                    }else{
    2115                      return UP_HOF; /* hierarchical authorisation failed */
    2116                    }
    2117                  }
    2118                }
    2119              }
    2120            }
    2121          }else{/* ! aut_num_auth_OK */
    2122            return UP_HOF; /* hierarchical auth failed */
    2123          }
    2124
    2125        }
    2126
    2127      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2128        old_mntners = get_mntners(old_object);
    2129        old_auth_vector = get_auth_vector(old_mntners);
    2130        if(old_mntners != NULL && old_auth_vector == NULL){
    2131          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2132          return UP_AUF; /* auth failed */
    2133        }
    2134        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2135          return authorise(old_auth_vector, credentials, overriden);
    2136        }else{
    2137          new_mntners = get_mntners(new_object);
    2138          new_auth_vector = get_auth_vector(new_mntners);
    2139          if(new_mntners != NULL && new_auth_vector == NULL){
    2140            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2141            return UP_AUF; /* auth failed */
    2142          }
    2143          return authorise(new_auth_vector, credentials, overriden);
    2144        }
    2145      }else{ /* both are NULL, mustn't happen */
    2146          if(tracing){
    2147            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2148          }
    2149          return UP_INT; /* internal error */
    2150      }
    2151    }
    2152
    2153
    2154    /*
    2155     *  Handle the set objects ("as-set","rtr-set", "peering-set", "route-set" and "filter-set" types
    2156     */
    2157    else if(strcmp(type,"as-set")       == 0 || strcmp(type,"rtr-set")     == 0 ||
    2158            strcmp(type,"peering-set")  == 0 || strcmp(type,"filter-set")  == 0 ||
    2159            strcmp(type,"route-set")    == 0 ){
    2160      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    2161        old_mntners = get_mntners(old_object);
    2162        old_auth_vector = get_auth_vector(old_mntners);
    2163        if(old_mntners != NULL && old_auth_vector == NULL){
    2164          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2165          return UP_AUF; /* auth failed */
    2166        }
    2167        return authorise(old_auth_vector, credentials, overriden);
    2168      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    2169         code = set_object->scan(new_object, strlen(new_object));
    2170         set_name = get_search_key(set_object, type, new_object);
    2171        if(strstr(set_name,":") == NULL ){/* if the name is _not_ hierarchical */
    2172          new_mntners = get_mntners(new_object);
    2173          new_auth_vector = get_auth_vector(new_mntners);
    2174          if(new_mntners != NULL && new_auth_vector == NULL){
    2175            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2176            return UP_AUF; /* auth failed */
    2177          }
    2178          return authorise(new_auth_vector, credentials, overriden);
    2179        }else{/* the name is hierarchical */
    2180          less_specific_object = get_less_specific_set(new_object, type);
    2181          if(less_specific_object != NULL){/* such an object exists */
    2182            temp_obj = new Object();
    2183            code = temp_obj->scan(less_specific_object, strlen(less_specific_object));
    2184            less_specific_object_type = get_class_type(temp_obj);
    2185            delete(temp_obj);
    2186            if(strcmp(less_specific_object_type, "aut-num") == 0){/* if this is an aut-num object */
    2187              less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    2188              less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    2189              if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    2190                /* then, the mntners in 'less_specific_auth_vector' do not exist. Problem. */
    2191               return UP_AUF; /* auth failed */
    2192              }
    2193              if(less_specific_auth_vector != NULL){
    2194                return authorise(less_specific_auth_vector, credentials, overriden);
    2195              }else{/* the less specific object doesn't contain any mnt-lower */
    2196                less_specific_mntners = get_mntners(less_specific_object);
    2197                less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    2198                if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    2199                  /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    2200                  return UP_AUF; /* auth failed */
    2201                }
    2202                if(less_specific_auth_vector != NULL){/* less spec object has some mnt-by attribs,
    2203                                                         use them  */
    2204                    return authorise(less_specific_auth_vector, credentials, overriden);
    2205                }else{/* the less specific object doesn't contain any mnt-by either */
    2206                  if(overriden){
    2207                    return UP_AUTH_OK;
    2208                  }else{
    2209                    return UP_HOF; /* hierarchical authorisation failed */
    2210                  }
    2211                }
    2212              }
    2213            }else{ /* this is _not_ an aut-num object*/
    2214              less_specific_mntners = get_mntners(less_specific_object);
    2215              less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    2216              if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    2217                /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    2218                return UP_AUF; /* auth failed */
    2219              }
    2220              if(less_specific_auth_vector != NULL ){/* the set obj has some mnt-by attribs */
    2221                return authorise(less_specific_auth_vector, credentials, overriden);
    2222              }else{
    2223                if(overriden){
    2224                  return UP_AUTH_OK;
    2225                }else{
    2226                  return UP_HOF; /* hierarchical authorisation failed */
    2227                }
    2228              }
    2229            }
    2230
    2231          }else{/* we don't have a less specific of this set object in the DB  */
    2232            return UP_HOF; /* hierarchical authorisation failed */
    2233          }
    2234        }
    2235      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2236        old_mntners = get_mntners(old_object);
    2237        old_auth_vector = get_auth_vector(old_mntners);
    2238        if(old_mntners != NULL && old_auth_vector == NULL){
    2239          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2240          return UP_AUF; /* auth failed */
    2241        }
    2242        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2243          return authorise(old_auth_vector, credentials, overriden);
    2244        }else{
    2245          new_mntners = get_mntners(new_object);
    2246          new_auth_vector = get_auth_vector(new_mntners);
    2247          if(new_mntners != NULL && new_auth_vector == NULL){
    2248            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2249            return UP_AUF; /* auth failed */
    2250          }
    2251          return authorise(new_auth_vector, credentials, overriden);
    2252        }
    2253      }else{ /* both are NULL, mustn't happen */
    2254          if(tracing){
    2255            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2256          }
    2257          return UP_INT; /* internal error */
    2258      }
    2259
    2260
    2261
    2262
    2263
    2264    }else{ /* We exhausted all object classes. If we are here, then there is a problem */
    2265      cout << "check_auth: This type '" << type << "' is unknown" << endl;
    2266      return UP_NIY; /* not implemented yet */
    2267    }
    2268    return UP_AUF; /* if we come to this point, then auth failed */
    2269 }
    2270
    2271
    2272
    2273
    2274
    2275
    2276 /* Gets the old version of the given "arg" object, which is in char * format
    2277    and returns the old version again in char * format */
    2278
    2279 char * get_old_version(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2280
    2281     bool code = true;
    2282     char *type=NULL, *primary_search_key = NULL, *search_string = NULL;
    2283     Object *o;
    2284     o = new Object;
    2285     char *result = NULL, *origin = NULL;
    2286
    2287     error = 0;
    2288     code = o->scan(arg,strlen(arg));
    2289     type = get_class_type(o);
    2290     primary_search_key = get_search_key(o, type, arg);
    2291     if(tracing) {
    2292       cout << "type=" << type << endl;
    2293       cout << "primary_search_key=" << primary_search_key << endl;
    2294     }
    2295     /* if the object is a pn ro a ro object, then get all pn/ro's with the
    2296        same NIC hdl */
    2297     if(strcmp(type,"person") == 0 || strcmp(type,"role") == 0){
    2298       /* prepare the search string */
    2299       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2300                                           + strlen("person,role") + 2);
    2301       sprintf(search_string, "-x -R -r -Tperson,role %s", primary_search_key);
    2302     }else{
    2303       /* prepare the search string */
    2304       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2305                                           + strlen(type) + 2);
    2306       sprintf(search_string, "-x -R -r -T%s %s",type, primary_search_key);
    2307     }
    2308     result = send_and_get(query_host, query_port, search_string);
    2309     if(tracing) {
    2310       cout << "TRACING: send_and_get has returned" << endl;
    2311       cout << "TRACING: send_and_get returned (with search '"<< search_string <<"'): " << endl
    2312            << result << endl;
    2313     }
    2314     /* Attention: here we must also check these:
    2315          for ro/pn objects: The name must also the same. When the NIC hdl is the
    2316                same but names are different, we must somehow return an error.
    2317                Also, when we search for a person, we must also look for role objects
    2318                (and vice versa) since the RIPupdate does not distinguish between
    2319                role & person objects. We have to check it here.
    2320          for rt objects: We also have to check the identicalness of origin
    2321                attributes.
    2322
    2323           These are not yet implemented.
    2324                */
    2325
    2326     if(strcmp(type,"route") == 0){
    2327       if(tracing) {
    2328         printf("TRACING: This is a route\n");
    2329       }
    2330       /* if this is a route, then we must filter out the routes with different
    2331          origin attributes */
    2332       origin = get_search_key(o, "origin", arg);
    2333       if(tracing) {
    2334         printf("TRACING: Got origin of route: %s\n", origin);
    2335       }
    2336       result = filter_out_diff_origins(result, origin);
    2337       if(tracing) {
    2338         printf("TRACING: Filtered routes\n");
    2339       }
    2340     }
    2341     // count the objects
    2342     if(count_objects(result) == 0){
    2343       result = NULL; /* we don't have such an object */
    2344     }else if(count_objects(result) == 1){
    2345       result = take_object(result);
    2346       if(tracing) {
    2347       cout << "TRACING: Take_object returned ***\n" << result << "***" << endl;
    2348       }
    2349     }else{ /* we have more than one objects, error! */
    2350       error = UP_MOR;
    2351       return NULL;
    2352     }
    2353     return result;
    2354 }
    2355
    2356
    2357
    2358
    2359 /* Gets a credentials_struct whose 'from' field will be filled in and
    2360    the mail header. Finds the 'From:' line in the header and sets
    2361    the 'from' field to this line (all line, including the 'From:' string,
    2362    since some users have put regexps which match the whole line in their
    2363    'auth' attributes.) */
    2364 void process_mail_header(credentials_struct * credentials_ptr, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2365   char * header = strdup(arg);
    2366   char * temp = (char *)malloc(strlen(header));
    2367   while(index(header, '\n') != NULL){
    2368     temp = strdup(header);
    2369     temp[index(temp, '\n') - temp] = '\0';
    2370     if(strstr(temp, "From:") == temp){
    2371       if(tracing) {
    2372         printf("TRACING: process_mail_header: Assigning %s\n", temp);
    2373       }
    2374       credentials_ptr->from = strdup(temp);
    2375       free(temp);
    2376       return;
    2377     }
    2378     header = header + (index(header, '\n') - header + 1);
    2379   }
    2380   free(temp);
    2381 }
    2382
    2383
    2384
    2385
    2386
    2387
    2388 void up_string_pack(char *dest, const char *source){
         /* [<][>][^][v][top][bottom][index][help] */
    2389
    2390   if(tracing) {
    2391     printf("TRACING: up_string_pack running\n");
    2392   }
    2393
    2394
    2395
    2396 /*----------------------------------------------------------------------*\
    2397
    2398 *  Function to rewrite a line of text with only one blankspace between  *
    2399 *  each word.
    2400 *
    2401
    2402 \*----------------------------------------------------------------------*/
    2403
    2404
    2405 /*
    2406  * This while loop continues until the NULL character is copied into
    2407  * the destination string.  If a tab character is copied into the
    2408  * destination string, it is replaced with a blank-space character.
    2409  *
    2410  * Multiple blank-space and/or tab characters are skipped in the source
    2411  * string until any other character is found.
    2412  */
    2413
    2414         while (1)
    2415                 {
    2416                 *dest = *source;
    2417
    2418                 if (*dest == '\t')
    2419                         (*dest = ' ');
    2420
    2421                 /* Exit if have copied the end of the string. */
    2422                 if (*dest == '\0')
    2423                         return;
    2424
    2425 /*
    2426  * If the source character was a blank-space or a tab, move to the next
    2427  * source character.  While the source character is a blank-space or a
    2428  * tab, move to the next character (i.e. ignore these characters).  When
    2429  * any other character is found in the source string, move to the next
    2430  * element of the destination string.
    2431  *
    2432  * Otherwise, simultaneously, move to the next elements of the destination
    2433  * and the source strings.
    2434  */
    2435
    2436
    2437
    2438                 if ( (*source == ' ') || (*source == '\t') )
    2439                         {
    2440                         ++source;
    2441                         while ( (*source == ' ') || (*source == '\t') )
    2442                                 {
    2443                                 ++source;
    2444                                 }
    2445
    2446                         ++dest;
    2447                         }
    2448                 else
    2449                         {
    2450                         ++dest;
    2451                         ++source;
    2452                         }
    2453                 }
    2454 }
    2455
    2456
    2457
    2458
    2459
    2460
    2461
    2462
    2463 /* strips lines beginning with "delete:" off  */
    2464 char * delete_delete_attrib(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2465
    2466     char ** temp = NULL;
    2467     char * string = NULL;
    2468     int i;
    2469
    2470     if(arg == NULL){
    2471        return NULL;
    2472     }
    2473
    2474     /* split the string into lines */
    2475     temp = g_strsplit (arg, "\n", 0);
    2476
    2477     for(i=0; temp[i] != NULL; i++){
    2478       /* if the line begins with "delete:", then do not copy it */
    2479       if(strstr(temp[i], "delete:") != temp[i]){
    2480         if(string == NULL){
    2481           string = strdup(temp[i]);
    2482         }else{
    2483           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
    2484           string = strcat(string, "\n");
    2485           string = strcat(string, temp[i]);
    2486         }
    2487       }
    2488     }
    2489     g_strfreev(temp);
    2490     return string;
    2491 }
    2492
    2493
    2494
    2495
    2496
    2497 /* looks if two objects are identical or not.
    2498     Takes two objects as char *, and returns 1 if
    2499     they are identical, returns 0 if not.
    2500
    2501     Algorithm is very simple: All strings of tabs and
    2502     white spaces are collapsed into a single white space,
    2503     and then the strings are compared (strcmp) */
    2504 int identical(const char * old_version, const char * new_version){
         /* [<][>][^][v][top][bottom][index][help] */
    2505   char * arg1 = strdup(old_version);
    2506   char * arg2 = strdup(new_version);
    2507   int result = 0;
    2508   char *temp1, *temp2;
    2509
    2510
    2511   arg1 = g_strstrip(arg1);
    2512   arg2 = g_strstrip(arg2);
    2513
    2514   /* delete the 'delete:' attrib */
    2515   arg2 = delete_delete_attrib(arg2);
    2516   /* convert tabs to white spaces */
    2517   arg1 = g_strdelimit(arg1, "\t", ' ');
    2518   arg2 = g_strdelimit(arg2, "\t", ' ');
    2519
    2520   temp1 = (char *)malloc(strlen(arg1) + 1);
    2521   temp2 = (char *)malloc(strlen(arg2) + 1);
    2522   up_string_pack(temp1, arg1);
    2523   up_string_pack(temp2, arg2);
    2524
    2525   /* if there is still \r's at the end of strings, remove them */
    2526   if((temp1[strlen(temp1) - 1]) == '\r'){
    2527     temp1[strlen(temp1) - 1] = '\0';
    2528   }
    2529   if((temp2[strlen(temp2) - 1]) == '\r'){
    2530     temp2[strlen(temp2) - 1] = '\0';
    2531   }
    2532
    2533   result = strcmp(temp1, temp2);
    2534   if(tracing){
    2535     printf("TRACING: identical: the objects are:\n[%s]\n[%s]\n", temp1, temp2);
    2536     printf("TRACING: identical: the lengths are:\n[%i]\n[%i]\n", strlen(temp1), strlen(temp2));
    2537   }
    2538   free(arg1);
    2539   free(arg2);
    2540   free(temp1);
    2541   free(temp2);
    2542   if(result  == 0){
    2543     if(tracing) {
    2544       printf("TRACING: identical returning 1\n");
    2545     }
    2546     return 1;
    2547   }else{
    2548     if(tracing) {
    2549       printf("TRACING: identical returning 0\n");
    2550     }
    2551     return 0;
    2552   }
    2553 }
    2554
    2555
    2556
    2557
    2558
    2559
    2560 /* constructs an initials string from a given name (for NIC hdl generation) */
    2561 char * find_initials(const char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2562
    2563    char * temp, * temp2;
    2564    char * initials = NULL;
    2565    int len, i;
    2566    char ** vector;
    2567
    2568    temp = strdup(arg);
    2569    g_strstrip(temp);
    2570    temp2 = (char *)malloc(strlen(temp) + 1);
    2571    up_string_pack(temp2, temp);
    2572    vector = g_strsplit(temp2, " ", 0);
    2573    for(i = 0; vector[i] != NULL && i < 4; i++){
    2574      if(strlen(vector[i]) > 0){
    2575        if(initials == NULL){
    2576          initials = (char *)malloc(2);
    2577          initials[0] = vector[i][0]; initials[1] = '\0';
    2578        }else{
    2579          len = strlen(initials);
    2580          initials = (char *)realloc(initials, len + 2 );
    2581          initials[len] = vector[i][0];
    2582          initials[len + 1] = '\0';
    2583        }
    2584      }
    2585    }
    2586    free(temp);free(temp2);g_strfreev(vector);
    2587    return initials;
    2588 }
    2589
    2590
    2591
    2592
    2593
    2594 /*  Gets the letter combination to be used in the automatically
    2595     generated NIc handle. It the letter combination is specified
    2596     in the AUTO NIC handle, return that. If not, return NULL
    2597     (in which case the initials of the name must be used) */
    2598 char * get_combination_from_autonic(const char * autonic){
         /* [<][>][^][v][top][bottom][index][help] */
    2599
    2600   GString * temp;
    2601   char * str = NULL;
    2602
    2603   temp = g_string_new(autonic);
    2604   temp = g_string_up(temp);
    2605   temp = g_string_erase(temp, 0, strlen("AUTO-"));
    2606   /* delete all digits from the beginning of the string */
    2607   while(temp->len > 0 && ((temp->str)[0] >= '0' && (temp->str)[0] <= '9')){
    2608     temp = g_string_erase(temp, 0, 1);
    2609   }
    2610   if(temp->len == 0){
    2611     g_string_free(temp, TRUE);
    2612     return NULL;
    2613   }else{
    2614     str = temp->str;
    2615     g_string_free(temp, FALSE);
    2616     return str;
    2617   }
    2618
    2619 }
    2620
    2621
    2622
    2623
    2624
    2625
    2626 /* Gets an object whose NIC hdl is AUTO and to be modified (to be sent to RIPupdate)
    2627    and  modifies the nic-hdl: attribute, returns the new object.
    2628    For example, "nic-hdl: AUTO-1" becomes "nic-hdl: HG*-RIPE . Also,
    2629    auto_nic is set to "AUTO-1"
    2630    auto_nic must be allocated enough memory before replace_AUTO_NIC_hdl called */
    2631 char * replace_AUTO_NIC_hdl(char * arg, char * auto_nic_hdl){
         /* [<][>][^][v][top][bottom][index][help] */
    2632
    2633   GString* temp_string;
    2634   char * to_be_returned = NULL;
    2635   char * person_role_name= NULL;
    2636   char * initials = NULL;
    2637   char ** temp = NULL;
    2638   int i, pos;
    2639   Object * o = new Object;
    2640
    2641   temp = g_strsplit(arg, "\n", 0);
    2642
    2643   for(i = 0; temp[i] != NULL; i++){
    2644     if(strstr(temp[i], "nic-hdl:") == temp[i]){/* if it starts with nic-hdl */
    2645       temp_string = g_string_new(temp[i]);
    2646       temp_string = g_string_down(temp_string);
    2647       if(strstr(temp_string->str, "auto-") != NULL){
    2648         auto_nic_hdl = strncpy(auto_nic_hdl, strstr(temp_string->str, "auto-"),
    2649             temp_string->len + temp_string->str - strstr(temp_string->str, "auto-") );
    2650         auto_nic_hdl[temp_string->len + temp_string->str - strstr(temp_string->str, "auto-")] = '\0';
    2651         g_strstrip(auto_nic_hdl);
    2652         if(tracing){
    2653           printf("TRACING: auto_nic is [%s]\n", auto_nic_hdl);
    2654         }
    2655         pos = strstr(temp_string->str, "auto-") - temp_string->str;
    2656         temp_string = g_string_erase(temp_string,
    2657             strstr(temp_string->str, "auto-") - temp_string->str, strlen(auto_nic_hdl)/*strlen("AUTO-")*/);
    2658         /* as the suffix to the AUTO nic handle we use the first updatable
    2659            source. Since currently we don't support multiple sources,
    2660            this is not a problem but when we support it, we must change this */
    2661         temp_string = g_string_insert(temp_string, pos, sources[0]);
    2662         temp_string = g_string_insert(temp_string, pos, "*-");
    2663         o->scan(arg, strlen(arg));
    2664         person_role_name = get_attribute(o, get_class_type(o), arg);
    2665         delete(o);
    2666         /* if the letter combination is already specified, get it */
    2667         initials = get_combination_from_autonic(auto_nic_hdl);
    2668         /* if the letter combination is not in the AUTO nichdl, obtain it from the name */
    2669         if(initials == NULL){
    2670           initials = find_initials(person_role_name);
    2671         }
    2672         free(person_role_name);
    2673         temp_string = g_string_insert(temp_string, pos, initials);
    2674         free(initials);
    2675
    2676         if(to_be_returned == NULL){
    2677           to_be_returned = strdup(temp_string->str);
    2678           g_string_free(temp_string, TRUE);
    2679         }else{
    2680           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    2681           to_be_returned = strcat(to_be_returned, "\n");
    2682           to_be_returned = strcat(to_be_returned, temp_string->str);
    2683           g_string_free(temp_string, TRUE);
    2684         }
    2685       }else{
    2686         if(to_be_returned == NULL){
    2687           to_be_returned = strdup(temp[i]);
    2688         }else{
    2689           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2690           to_be_returned = strcat(to_be_returned, "\n");
    2691           to_be_returned = strcat(to_be_returned, temp[i]);
    2692         }
    2693       }
    2694     }else{/* if it doesn't begin with nic-hdl */
    2695         if(to_be_returned == NULL){
    2696           to_be_returned = strdup(temp[i]);
    2697         }else{
    2698           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2699           strcat(to_be_returned, "\n");
    2700           strcat(to_be_returned, temp[i]);
    2701         }
    2702
    2703     }
    2704
    2705   }
    2706   g_strfreev (temp);
    2707   return to_be_returned;
    2708 }
    2709
    2710
    2711
    2712 /* replaces the refs to AUTO NIC hdls with the assigned one */
    2713
    2714 char * replace_refs_to_AUTO_NIC_hdl(char * changed_obj, char * arg, GHashTable * auto_nic_hash){
         /* [<][>][^][v][top][bottom][index][help] */
    2715
    2716   char * auto_nic = NULL;
    2717   GString* temp_string;
    2718   char * to_be_returned = NULL;
    2719   char ** temp = NULL;
    2720   int i, pos;
    2721
    2722
    2723   temp = g_strsplit(arg, "\n", 0);
    2724
    2725   for(i = 0; temp[i] != NULL; i++){
    2726     if(   strstr(temp[i], "admin-c:") == temp[i]    /*    if it starts with admin-c */
    2727        || strstr(temp[i], "tech-c:" ) == temp[i]    /* or if it starts with tech-c */
    2728        || strstr(temp[i], "zone-c:" ) == temp[i]    /* or if it starts with zone-c */
    2729        || strstr(temp[i], "author:" ) == temp[i]){  /* or if it starts with author */
    2730       temp_string = g_string_new(temp[i]);
    2731       temp_string = g_string_down(temp_string);
    2732       if(strstr(temp_string->str, "auto-") != NULL){
    2733         auto_nic = (char *)malloc(temp_string->len + temp_string->str - strstr(temp_string->str, "auto-")  + 1);
    2734         auto_nic = strncpy(auto_nic, strstr(temp_string->str, "auto-"),
    2735             temp_string->len + temp_string->str - strstr(temp_string->str, "auto-") );
    2736         auto_nic[temp_string->str + temp_string->len - strstr(temp_string->str, "auto-")] = '\0';
    2737         g_strstrip(auto_nic);
    2738         if(tracing){
    2739           printf("TRACING: auto_nic is [%s]\n", auto_nic);
    2740         }
    2741         pos = strstr(temp_string->str, "auto-") - temp_string->str;
    2742         temp_string = g_string_erase(temp_string,
    2743             strstr(temp_string->str, "auto-") - temp_string->str, strlen(auto_nic)/*strlen("AUTO-")*/);
    2744
    2745         /* if we have this AUTO NIC hdl in the hash, put it. */
    2746         if(g_hash_table_lookup(auto_nic_hash, auto_nic)){
    2747           temp_string = g_string_insert(temp_string, pos, (char *)g_hash_table_lookup(auto_nic_hash, auto_nic));
    2748         }else{/* else, return 0 immediately */
    2749           g_strfreev (temp);
    2750           return NULL;
    2751         }
    2752
    2753         if(to_be_returned == NULL){
    2754           to_be_returned = strdup(temp_string->str);
    2755           g_string_free(temp_string, TRUE);
    2756         }else{
    2757           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    2758           to_be_returned = strcat(to_be_returned, "\n");
    2759           to_be_returned = strcat(to_be_returned, temp_string->str);
    2760           g_string_free(temp_string, TRUE);
    2761         }
    2762       }else{
    2763         if(to_be_returned == NULL){
    2764           to_be_returned = strdup(temp[i]);
    2765         }else{
    2766           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2767           to_be_returned = strcat(to_be_returned, "\n");
    2768           to_be_returned = strcat(to_be_returned, temp[i]);
    2769         }
    2770       }
    2771     }else{/* if it doesn't begin with ac,tc,ac or author */
    2772         if(to_be_returned == NULL){
    2773           to_be_returned = strdup(temp[i]);
    2774         }else{
    2775           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2776           strcat(to_be_returned, "\n");
    2777           strcat(to_be_returned, temp[i]);
    2778         }
    2779
    2780     }
    2781
    2782   }
    2783   g_strfreev (temp);
    2784   if(tracing){
    2785     printf("TRACING: replace_first_ref_to_AUTO_NIC_hdl is returning,\nto_be_returned=[%s]\n", to_be_returned);
    2786   }
    2787   return to_be_returned;
    2788 }
    2789
    2790
    2791
    2792
    2793
    2794
    2795
    2796
    2797 /* Takes an object in a char * , and returns 1 if this object has
    2798    an AUTO NIC handle. Otherwise, returns 0 */
    2799 int has_AUTO_NIC_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    2800
    2801   Object * o = new Object();
    2802   GSList * attributes = NULL;
    2803   bool code;
    2804
    2805   code = o->scan(object, strlen(object));
    2806
    2807   if(code && !(o->isDeleted)){
    2808     attributes = get_attributes(o, "nic-hdl", object);
    2809     if(attributes != NULL){
    2810       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2811         g_slist_free(attributes);
    2812         delete(o);
    2813         return 1;
    2814       }
    2815     }
    2816     /* if control reaches here, then we will return 0 */
    2817     g_slist_free(attributes);
    2818     delete(o);
    2819     return 0;
    2820   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    2821            it contains refs to AUTO NIC hdls. */
    2822     delete(o);
    2823     return 0;
    2824   }
    2825
    2826 }
    2827
    2828
    2829 /* Takes an object in a char * , and returns 1 if this object contains
    2830    a reference to an AUTO NIC handle. Otherwise, returns 0 */
    2831 int has_ref_to_AUTO_nic_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    2832
    2833   Object * o = new Object();
    2834   GSList * attributes = NULL;
    2835   bool code;
    2836
    2837   code = o->scan(object, strlen(object));
    2838
    2839   if(code && !(o->isDeleted)){
    2840     attributes = get_attributes(o, "admin-c", object);
    2841     if(attributes != NULL){
    2842       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2843         g_slist_free(attributes);
    2844         delete(o);
    2845         return 1;
    2846       }
    2847     }
    2848     g_slist_free(attributes);
    2849     attributes = get_attributes(o, "tech-c", object);
    2850     if(attributes != NULL){
    2851       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2852         g_slist_free(attributes);
    2853         delete(o);
    2854         return 1;
    2855       }
    2856     }
    2857
    2858     g_slist_free(attributes);
    2859     attributes = get_attributes(o, "zone-c", object);
    2860     if(attributes != NULL){
    2861       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2862         g_slist_free(attributes);
    2863         delete(o);
    2864         return 1;
    2865       }
    2866     }
    2867     g_slist_free(attributes);
    2868     attributes = get_attributes(o, "author", object);
    2869     if(attributes != NULL){
    2870       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2871         g_slist_free(attributes);
    2872         delete(o);
    2873         return 1;
    2874       }
    2875     }
    2876     /* if control reaches here, then we will return 0 */
    2877     delete(o);
    2878     return 0;
    2879   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    2880            it contains refs to AUTO NIC hdls. */
    2881     delete(o);
    2882     return 0;
    2883   }
    2884
    2885 }
    2886
    2887
    2888
    2889
    2890
    2891
    2892
    2893
    2894
    2895 /* Gets the "From" line of the incoming mail message and finds out an
    2896    address to send the acknowledgement */
    2897 char * find_email_address(const char * from_line){
         /* [<][>][^][v][top][bottom][index][help] */
    2898   char * pos1 = NULL, * pos2 = NULL;
    2899   char * temp = NULL;
    2900
    2901   if(from_line == NULL){
    2902     return NULL;
    2903   }
    2904   if(strstr(from_line, "From:") != from_line){
    2905     temp = strdup(from_line);
    2906   }else{
    2907     temp = strdup(from_line + strlen("From:"));
    2908   }
    2909   g_strstrip(temp);
    2910   if(index(temp, '<')){/* then the line is something like '"John White" <john@inter.net>' */
    2911     pos1 = index(temp, '<');
    2912     pos2 = index(temp, '>');
    2913     temp = strncpy(temp, pos1 + 1, pos2 - pos1 -1);
    2914     temp[pos2 - pos1 - 1] = '\0';
    2915     if(tracing) {
    2916      printf("TRACING: find_email_address temp=[%s]\n", temp);
    2917     }
    2918
    2919     return temp;
    2920   }else{/* the line contains only the address, then */
    2921    return temp;
    2922   }
    2923 }
    2924
    2925
    2926
    2927 /* replaces the erase_str occurences with insert_str in g_str */
    2928 GString * replace_strings(GString * g_str, const char * erase_str, const char * insert_str){
         /* [<][>][^][v][top][bottom][index][help] */
    2929
    2930   int pos;
    2931
    2932   if(insert_str == NULL){/* then don't do anything */
    2933     return g_str;
    2934   }
    2935
    2936   /* replace erase_str with insert_str */
    2937   while(strstr(g_str->str, erase_str) != NULL){
    2938     pos = strstr(g_str->str, erase_str) - g_str->str;
    2939     g_str = g_string_erase(g_str, pos, strlen(erase_str));
    2940     if(insert_str != NULL){
    2941       g_str = g_string_insert(g_str, pos, insert_str);
    2942     }
    2943   }
    2944   return g_str;
    2945
    2946 }
    2947
    2948
    2949 /* Duplicates the given arg, and replaces
    2950     $FROM,
    2951     $SUBJECT,
    2952     $MDATE,
    2953     $MSGID,
    2954     $CC,
    2955     $HUMAILBOX
    2956     $AUTOBOX
    2957
    2958     and $TIME & $DATE
    2959
    2960     strings with the corresponding variables.
    2961
    2962 */
    2963 char * replace_globals(const char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2964
    2965   GString * g_str;
    2966   int pos;
    2967   char * to_be_returned;
    2968   time_t cur_time;
    2969   char * temp, * time_str, * date_str;
    2970
    2971
    2972   /* get time */
    2973   cur_time = time(NULL);
    2974   temp = strdup(ctime(&cur_time));
    2975   /* temp is now something like "Fri Sep 13 00:00:00 1986\n\0", fields are const width */
    2976
    2977   time_str = (char *)malloc(9);
    2978   time_str = strncpy(time_str, temp + 11, 8);
    2979   time_str[8] = '\0';
    2980
    2981   date_str = (char *)malloc(16);
    2982   date_str = strncpy(date_str, temp, 11);
    2983   date_str[11] = '\0';
    2984   date_str = strncat(date_str, temp + 20, 4);
    2985
    2986
    2987   free(temp);
    2988
    2989   g_str = g_string_new(arg);
    2990
    2991   g_str = replace_strings(g_str, "$TIME", time_str);
    2992
    2993   g_str = replace_strings(g_str, "$DATE", date_str);
    2994
    2995   g_str = replace_strings(g_str, "$SUBJECT", update_mail_subject);
    2996
    2997   g_str = replace_strings(g_str, "$FROM", update_mail_sender);
    2998
    2999   g_str = replace_strings(g_str, "$MDATE", update_mail_date);
    3000
    3001   g_str = replace_strings(g_str, "$MSGID", update_mail_ID);
    3002
    3003   g_str = replace_strings(g_str, "$CC", update_mail_cc);
    3004
    3005   g_str = replace_strings(g_str, "$HUMAILBOX", humailbox);
    3006
    3007   g_str = replace_strings(g_str, "$AUTOBOX", autobox);
    3008
    3009   free(time_str);
    3010   free(date_str);
    3011
    3012   to_be_returned = strdup(g_str->str);
    3013   g_string_free(g_str, 1);
    3014   return to_be_returned;
    3015 }
    3016
    3017 /* Get the type of the object, which is represented as a char * */
    3018 char * get_class_type_char(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    3019   bool code;
    3020   Object * o;
    3021   char * type;
    3022   char * temp;
    3023
    3024   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
    3025    (no harm in having more than one) */
    3026   temp = (char *)malloc(strlen(object) + 2);
    3027   sprintf(temp, "%s\n", object);
    3028
    3029   if(tracing) {
    3030     printf("TRACING: get_class_type_char is running, object is \n[%s]\n", object);
    3031   }
    3032   o = new Object;
    3033   code = o->scan(temp,strlen(temp));
    3034
    3035   type = get_class_type(o);
    3036
    3037   free(temp);
    3038   delete(o);
    3039   return type;
    3040
    3041 }

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