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. send_object_db
  7. get_type
  8. get_search_key
  9. send_and_get
  10. count_objects
  11. strip_lines
  12. take_objects
  13. take_object
  14. get_as_block
  15. get_aut_num_object
  16. get_less_specific_domain
  17. get_less_specific_set
  18. get_less_specific
  19. get_less_spec_inetnum
  20. get_exact_match_inetnum
  21. get_exact_match_routes
  22. get_less_spec_routes
  23. get_mntners
  24. get_attributes
  25. get_attribute
  26. strstr_in_list
  27. get_auths
  28. get_attr_list
  29. get_mnt_lowers
  30. get_mnt_routes
  31. get_mnt_routes_from_list
  32. get_mnt_lowers_from_list
  33. get_override
  34. check_override
  35. add_to_auth_vector
  36. get_auth_vector
  37. get_mntnfy_vector
  38. get_updto_vector
  39. filter_out_diff_origins
  40. check_auth
  41. get_old_version
  42. process_mail_header
  43. stringPack
  44. delete_delete_attrib
  45. identical
  46. find_initials
  47. get_combination_from_autonic
  48. replace_AUTO_NIC_hdl
  49. replace_refs_to_AUTO_NIC_hdl
  50. has_AUTO_NIC_hdl
  51. has_ref_to_AUTO_nic_hdl
  52. process_object
  53. find_to_address

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

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