/**************************************************************************/ // ban.cpp - code related to banning players, pretty much a rewrite by Kal /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with all the licenses * * in licenses.txt... In particular, you may not remove this copyright * * notice. * *************************************************************************** * >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. * * >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to * * you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), * * Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) * * >> Oblivion 1.2 is copyright 1996 Wes Wagner * **************************************************************************/ #include "include.h" // dawn standard includes #include "ban.h" // prototypes extern const struct flag_type ban_types[]; char *flag_string( const struct flag_type *flag_table, int bits ); char *getline( char *str, char *buf, int bufsize); // string.cpp int wild_match(register unsigned char *m, register unsigned char *n); // globals BAN_DATA *ban_list; /**************************************************************************/ // create ban_type GIO lookup table GIO_START(ban_data) GIO_STR(sitemasks) GIO_STR(intended_people) GIO_WFLAG(type, ban_types) GIO_INT(ban_date) GIO_STR(reason) GIO_STR(by) GIO_INT(expire_date) GIO_STR(custom_disconnect_message) GIO_STR(always_allowed_email_masks) GIO_STR(allowed_email_masks) GIO_STR(disallowed_email_masks) GIO_STR(disallowed_email_custom_message) GIO_SHINT(level) GIO_BOOL(enabled) GIO_FINISH_NOCLEAR /**************************************************************************/ void save_bans(void) { BAN_DATA *pban; FILE *fp; bool found = false; int count=0; fclose( fpReserve ); if ( ( fp = fopen( BAN_FILE, "w" ) ) == NULL ) { bugf("save_bans(): fopen for write '%s' - error %d (%s)", BAN_FILE, errno, strerror( errno)); fpReserve = fopen( NULL_FILE, "r" ); assert(fpReserve!=NULL); return; } logf("Saving bans to %s.", BAN_FILE); for (pban = ban_list; pban != NULL; pban = pban->next) { if (pban->permanent) { found = true; fprintf( fp, "BAN%d~\n", count++); GIO_SAVE_RECORD(ban_data, pban, fp, NULL); } } fprintf( fp, "EOF~\n" ); fclose(fp); fpReserve = fopen( NULL_FILE, "r" ); if (!found){ unlink(BAN_FILE); } } /**************************************************************************/ void load_bans(void) { FILE *fp; BAN_DATA *ban_last; char *input=&str_empty[0]; int count=0; if ( ( fp = fopen( BAN_FILE, "r" ) ) == NULL ) return; logf("Loading bans from %s...", BAN_FILE); ban_last = NULL; for ( ; ; ) { BAN_DATA *pban; if ( feof(fp) ) { fclose( fp ); logf("%d ban%s loaded.", count, count==1?"":"s"); return; } // check for end of file system free_string(input); // recycle memory input = fread_string(fp); if (!str_cmp(input, "EOF")){ fclose( fp ); logf("%d ban%s loaded.", count, count==1?"":"s"); return; } pban = new_ban(); GIO_LOAD_RECORD(ban_data, pban, fp); if(!IS_NULLSTR(pban->sitemasks)){ pban->permanent=true; count++; // check expire date - disable ban if appropriate if(pban->enabled && pban->expire_date>0 && pban->expire_date<current_time) { logf("BAN: %s set on: %.24s (lvl=%d ban, banflags=%s)\n" "was disabled due to expiring %.24s.\n", fix_string(pban->sitemasks), ((char*)ctime(&pban->ban_date)), pban->level, flag_string( ban_types, pban->type), ((char*)ctime(&pban->expire_date))); pban->enabled=false; pban->expire_date=0; }; // add to linked list if (ban_list == NULL){ ban_list = pban; }else{ ban_last->next = pban; } ban_last = pban; } } } /**************************************************************************/ // returns true if 'matchto' can be matched by any of the multiple_masks bool match_multiline_masks( char *multiple_masks, char *matchto) { char tmpb[MSL*4]; char *t; char *banmask; if(IS_NULLSTR(multiple_masks)){ return false; } while ( *multiple_masks) { multiple_masks = getline( multiple_masks, tmpb, MSL*4); // find we the ban mask starts banmask=tmpb; while(is_space(*banmask)){ banmask++; } // terminate the ban mask at the first whitespace character for (t=banmask; *t; t++){ if (is_space(*t)){ *t='\0'; break; } } if(IS_NULLSTR(banmask)) continue; if (wild_match((unsigned char*)banmask, (unsigned char*)matchto)){ return true; } } return false; } /**************************************************************************/ BAN_DATA *check_ban_for_site(char *site,int type) { BAN_DATA *pban; char host[MSL]; int i; // get hostname and make sure it is lowercase strcpy(host,site); for ( i = 0; host[i] != '\0'; i++ ){ host[i] = LOWER(host[i]); } for ( pban = ban_list; pban; pban = pban->next ) { // check ban is enabled if(!pban->enabled) continue; // check ban type if(pban->type!=type) continue; // check expire date - disable ban if appropriate if(pban->enabled && pban->expire_date>0 && pban->expire_date<current_time) { logf("BAN: %s set on: %.24s (lvl=%d ban, banflags=%s)\n" "was disabled due to expiring %.24s.\n", pban->sitemasks, ((char*)ctime(&pban->ban_date)), pban->level, flag_string( ban_types, pban->type), ((char*)ctime(&pban->expire_date))); pban->enabled=false; pban->expire_date=0; }; // do wildcard mask pattern matching if (match_multiline_masks( pban->sitemasks, host)){ return pban; } } return NULL; } /**************************************************************************/ BAN_DATA *check_ban(connection_data *c,int type) { BAN_DATA *result; result=check_ban_for_site(c->remote_hostname, type); if(!result){ result=check_ban_for_site(c->remote_ip, type); } return result; } /**************************************************************************/ bool email_descriptor_unlock_id(connection_data *d) { #ifdef unix char unlockname[MIL]; sprintf(unlockname, "emailunlockfile_%d_%d.tmp", getpid(), (int)current_time); char buf[MSL]; unlink(unlockname); sprintf(buf, "Hello %s,\n" "This email is an automated email message from %s \n" "mud... This email is only sent\n" "after someone creates a character on the game and requests for an unlock\n" "code to be sent. The ip address of the person who requested the email is\n" "%s\n" "\n" " Unlock details:\n" " Character name: %s\n" " Unlock code: %s\n" "\n", CH(d)->pcdata->email, MUD_NAME, d->remote_ip, CH(d)->name, CH(d)->pcdata->unlock_id); append_string_to_file( unlockname, buf, true); sprintf(buf,"mail %s -s \"%s dawn unlock code\" < %s ; sleep 10; rm %s &", CH(d)->pcdata->email, CH(d)->name, unlockname, unlockname); log_string(buf); system(buf); #else CH(d)->wraplnf("Unlocking codes automatically " "emailed is currently supported only by servers that run unix... your unlock " "code is %s", CH(d)->pcdata->unlock_id); #endif return true; } /**************************************************************************/ // returns NULL if the email is okay, and a text message if the email isn't char *is_invalid_email(char *email) { static char result[MSL]; unsigned char *newemail= (unsigned char*)email; char *bad_characters=";<>{}[]`'\\/$|"; if (has_whitespace(email)){ sprintf(result,"The email address you enter can not have any whitespace " "characters in it!`1reenter:`1"); return result; } if (!wild_match((unsigned char*)"*?@?*", newemail)){ sprintf(result,"The email address must have a @ in the middle somewhere...`1" "e.g. bob@aol.com`1reenter:`1"); return result; } if (!wild_match((unsigned char*)"*?@?*.?*", newemail)){ sprintf(result,"The email address must have a @ in the middle " "somewhere and at least one . in the domain name to the right of " "the @ symbol..`1" "e.g. bob@aol.com`1reenter:`1"); return result; } if (wild_match((unsigned char*)"*@*@*", newemail)){ sprintf(result,"The email address must not have more than " "one @ symbol in it." "`1e.g. bob@aol.com is valid... smith@bob@aol.com is invalid." "`1reenter:`1"); return result; } logf("check_email_ban(): Doing Badcharacter checks."); { // check for the bad characters int i; char buf[MSL]; for(i=0; bad_characters[i];i++){ sprintf(result,"*%c*", bad_characters[i]); if (wild_match((unsigned char*)buf, newemail)){ sprintf(result,"%c is not an allowed character to have in an email address.`1" "reenter:`1", bad_characters[i]); return result; } } } return NULL; } /**************************************************************************/ // ** This function explains to the user what happened, and what they ** // ** need to do... the returned values tell the calling function how ** // ** to handle the connection. ** // // 0 accepted email, and id code emailed to them. // 1 email rejected, they need another attempt. // 2 if they should be disconnected - currently not used int check_email_ban(connection_data *c, char *email_addy) { BAN_DATA *pban; char host[MSL]; char *message; unsigned char newemail[MSL]; int i; bool foundallowedemail=false; bool found_a_ban_with_an_invalid_email=false; // get hostname and make sure it is lowercase strcpy(host,c->remote_hostname); logf("Starting check_email_ban(): host='%s', email addy='%s'", host, email_addy); for ( i = 0; host[i] != '\0'; i++ ){ host[i] = LOWER(host[i]); } // get the potential email and make sure it is lowercase strcpy((char*)newemail,email_addy); for ( i = 0; newemail[i] != '\0'; i++ ){ newemail[i] = LOWER(newemail[i]); } // validate the email addy is formatted okay message=is_invalid_email((char*)&newemail[0]); if(message){ // email wasnt okay, display the message why not CH(c)->wrapln(message); return 1; } logf("check_email_ban(): Doing ban checks."); for ( pban = ban_list; pban; pban = pban->next ) { // check ban is enabled if(!pban->enabled) continue; // check ban type if(pban->type!=BAN_EMAIL_REQ) continue; // do wildcard mask pattern matching if (match_multiline_masks( pban->sitemasks, host)){ // matched... now check all email addies, start with always_allowed logf("Found match with pban->sitemasks='%s', checking always allowed.", pban->sitemasks); if(match_multiline_masks(pban->always_allowed_email_masks, (char *)newemail)){ foundallowedemail=true; }else{ // disallowed emails logf("checking disallowed."); if(match_multiline_masks(pban->disallowed_email_masks, (char *)newemail)){ if(IS_NULLSTR(pban->disallowed_email_custom_message)){ logf("check_email_ban(): disallowed email address " "'%s' from '%s'!", newemail, CH(c)->name); CH(c)->wraplnf("The email address you supplied " "'%s' is marked as a disallowed email address..." "`1try another or disconnect:", newemail); return 1; }else{ CH(c)->println(pban->disallowed_email_custom_message); } return 1; }; logf("Checking allowed."); if(match_multiline_masks(pban->allowed_email_masks, (char *)newemail)){ foundallowedemail=true; }else{ found_a_ban_with_an_invalid_email=true; } } } } logf("Found allowed = %s, found_a_ban_with_an_invalid_email=%s, %s - %s.", foundallowedemail==true?"true":"false", found_a_ban_with_an_invalid_email==true?"true":"false", host, (char*)newemail ); if(foundallowedemail && !found_a_ban_with_an_invalid_email){ if(str_cmp(CH(c)->pcdata->email, (char*)newemail)){ replace_string(CH(c)->pcdata->email, (char*)newemail); }; return 0; }else{ if(c->newbie_creating){ CH(c)->wraplnf("The email address you supplied " "'%s' was not found to be on the list of potentially " "accepted email address (e.g. *@aol.com in the case of aol.com)" "`1If dont have a valid email account, then you are unable to " "create a character sorry." "`1try another or disconnect:", newemail); }else{ CH(c)->wraplnf("The email address you supplied " "'%s' was not found to be on the list of potentially " "accepted email address (e.g. *@aol.com in the case of aol.com)" "`1try another or disconnect:", newemail); } return 1; } } /**************************************************************************/ void ban_site(char_data *ch, char *argument, bool fPerm) { char buf[MSL]; char arg1[MIL], arg2[MIL]; char *sitemask; BUFFER *buffer; BAN_DATA *pban, *prev; int type=0; int count=0; smash_tilde(argument); // must have some pcdata to use the command if(!TRUE_CH(ch)->pcdata){ do_huh(ch,""); return; } // permbans - the adding of bans by a select group if (fPerm && !IS_TRUSTED(ch,MAX_LEVEL-2) && !IS_SET(TRUE_CH(ch)->pcdata->council, COUNCIL_HEADLAW)) { do_huh(ch,""); return; } if(!fPerm){ if (ban_list == NULL) { ch->println( "No sites banned at this time." ); return; } buffer = new_buf(); add_buf(buffer,"`=t-================================== `=TBANS `=t===================================-\r\n"); count=-1; for (pban = ban_list;pban != NULL;pban = pban->next) { count++; if(!IS_NULLSTR(argument) && str_infix(argument,pban->sitemasks)) continue; sprintf(buf,"%s%d)%-2.2s%-3.3s%-2.2s=============level: %3d, duration: %s, type: %s\r\n`c", (pban->enabled?"`x":"`S"), count, ((char*)ctime(&pban->ban_date))+8, // quick hack ((char*)ctime(&pban->ban_date))+4, ((char*)ctime(&pban->ban_date))+22, pban->level, pban->permanent?"perm":"temp", flag_string( ban_types, pban->type)); add_buf(buffer,buf); add_buf(buffer,pban->sitemasks); int l=str_len(pban->sitemasks); if(pban->sitemasks[l-1]!='\r' && pban->sitemasks[l-1]!='\n'){ add_buf(buffer,"\r\n"); } add_buf(buffer,"`=t-===========================================================================-`x\r\n"); } ch->sendpage(buf_string(buffer)); free_buf(buffer); return; } argument = one_argument(argument,arg1); argument = one_argument(argument,arg2); if ( arg1[0] == '\0' ) { if (ban_list == NULL) { ch->println( "No sites banned at this time." ); return; } buffer = new_buf(); add_buf(buffer,"==- Banned sites date lvl status type\r\n"); for (pban = ban_list;pban != NULL;pban = pban->next) { sprintf(buf,"%s%2d) %-40s %-2.2s%-3.3s%-2.2s %3d %s %s\n", (pban->enabled?"`x":"`S"), count++, pban->sitemasks, ((char*)ctime(&pban->ban_date))+8, // quick hack ((char*)ctime(&pban->ban_date))+4, ((char*)ctime(&pban->ban_date))+22, pban->level, pban->permanent?"perm":"temp", flag_string( ban_types, pban->type)); add_buf(buffer,buf); } ch->sendpage(buf_string(buffer)); free_buf(buffer); return; } // find out what type of ban if (arg2[0] == '\0' || !str_prefix(arg2,"all")) type = BAN_ALL; else if (!str_prefix(arg2,"newbies")) type = BAN_NEWBIE; else if (!str_prefix(arg2,"email")) type = BAN_EMAIL_REQ; else if (!str_prefix(arg2,"permit")) type = BAN_PERMIT; else { ch->println( "Acceptable ban types are all, newbies, email and permit." ); return; } sitemask = arg1; if (str_len(sitemask) == 0) { ch->println( "You have to ban SOMETHING." ); return; } // check for a banning of themselves if(IS_UNSWITCHED_MOB(ch)){ ch->println( "Players only!" ); return; } if(!TRUE_CH(ch)->desc){ ch->println( "You can't be doing this while linkdead." ); return; } if(wild_match((unsigned char*)sitemask, (unsigned char*)TRUE_CH(ch)->desc->remote_hostname)){ ch->printlnf( "Cant use a siteban mask ('%s') that bans yourself!", sitemask); return; }; prev = NULL; for ( pban = ban_list; pban != NULL; prev = pban, pban = pban->next ) { if (!str_cmp(sitemask,pban->sitemasks)) { if (pban->level > get_trust(ch)) { ch->println( "That ban was set by a higher power." ); return; } else { if (prev == NULL) ban_list = pban->next; else prev->next = pban->next; free_ban(pban); } } } pban = new_ban(); pban->by = str_dup(TRUE_CH(ch)->name); pban->sitemasks=str_dup(sitemask); if(type){ pban->type=type; pban->enabled=true; } // a default level (97) unless atlevel is used pban->level = IS_SET(ch->dyn,DYN_USING_ATLEVEL)?get_trust(ch):MAX_LEVEL-3; // set ban type //pban->ban_flags = type; if (fPerm){ pban->permanent=true; } // add to the linked list of bans pban->next = ban_list; ban_list = pban; // save the ban file save_bans(); ch->printlnf("'%s' has been banned.",pban->sitemasks); return; } /**************************************************************************/ void do_ban(char_data *ch, char *argument) { ban_site(ch,argument,false); } /**************************************************************************/ void do_permban(char_data *ch, char *argument) { ban_site(ch,argument,true); } /**************************************************************************/ void do_allow( char_data *ch, char *argument ) { char arg[MIL]; BAN_DATA *prev; BAN_DATA *curr; one_argument( argument, arg ); if ( arg[0] == '\0' ) { ch->println( "Remove which site from the ban list?" ); return; } prev = NULL; for ( curr = ban_list; curr != NULL; prev = curr, curr = curr->next ) { if ( !str_cmp( arg, curr->sitemasks) ) { if (curr->level > get_trust(ch)){ ch->println( "You are not powerful enough to lift that ban." ); return; } if ( prev == NULL ) ban_list = ban_list->next; else prev->next = curr->next; free_ban(curr); ch->printlnf("Ban on %s lifted.",arg); save_bans(); return; } } ch->println( "Site is not banned." ); return; } /**************************************************************************/ // returns true if the connection was disconnected bool check_connection_ban(connection_data *c) { BAN_DATA *pBan; char *msg; // check unconditional bans if ( (pBan=check_ban(c,BAN_ALL)) ) { if(IS_NULLSTR(pBan->custom_disconnect_message)){ c->write_colour("`1`1`WYour site has been `Rbanned`W from this mud!!!`1",0); }else{ msg=note_format_string(str_dup(pBan->custom_disconnect_message)); c->write_colour(msg, 0); free_string(msg); } logf("%s %s (%d) dropped due to complete siteban on their site.", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); c->outtop=0;// empty output buffer connection_close(c); return true; } if ( c->newbie_creating && (pBan=check_ban(c,BAN_LOGNEWBIE)) ) { logf("Autolog turned on for newbie '%s' from '%s'", c->character->name, c->remote_hostname); SET_BIT(c->character->act,PLR_LOG); } if ( c->newbie_creating && (pBan=check_ban(c,BAN_NEWBIE)) ) { if(IS_NULLSTR(pBan->custom_disconnect_message)){ msg=note_format_string(str_dup( "`1`1Due to abuse or potential abuse of this mud, we have " "disabled newbie creation from your site. This will be in " "place to maintain some control of who creates from your " "site... If you are new here, " "you are welcome to play, we can lift this for you to create " "or maybe even permantly :) If you would like to talk with us " "regarding this matter, email the administation of " "this mud.`1`1")); }else{ msg=note_format_string(str_dup(pBan->custom_disconnect_message)); } c->write_colour(msg, 0); free_string(msg); connection_close(c); logf("%s %s (%d) dropped due to being a newbie creating and from newbie banned site.", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); return true; } // check bans with permits - only applied to those who have logged in if ( CH(c) && (pBan=check_ban(c,BAN_PERMIT)) ) { if (!IS_SET(CH(c)->act,PLR_PERMIT)) { if(IS_NULLSTR(pBan->custom_disconnect_message)){ msg=note_format_string(str_dup( "`1`1Due to abuse or potential abuse of this mud, we have " "disabled access from your site. If you are new here, " "you are welcome to play, we can lift this siteban for " "individual players... If you would like to talk with us " "regarding this matter, email the administation of " "this mud.`1`1")); }else{ msg=note_format_string(str_dup(pBan->custom_disconnect_message)); } c->write_colour(msg, 0); free_string(msg); if (IS_IRCCON(c)){ sprintf( log_buf, "NONPERMITED PLAYER DROPPED DUE TO BAN\r\n" "was %s@%s (connected via IRC). (socket = %d)", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); }else{ sprintf( log_buf, "NONPERMITED PLAYER DROPPED DUE TO BAN\r\n" "was %s@%s (socket = %d)", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); } wiznet(log_buf,NULL,NULL,WIZ_SECURE,0,get_trust(CH(c)) ); log_string(log_buf); connection_close(c); return true; } else { if (IS_IRCCON(c)){ sprintf( log_buf, "PERMITED PLAYER FROM BANNED SITE ACCEPTED\r\n" "(%s@%s connected via IRC). (socket = %d)", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); }else{ sprintf( log_buf, "PERMITED PLAYER FROM BANNED SITE ACCEPTED\r\n" "(%s@%s connected via IRC). (socket = %d)", CH(c)?CH(c)->name:"(unknown name)", c->remote_hostname, c->connected_socket); } wiznet(log_buf,NULL,NULL,WIZ_SECURE,0,get_trust(CH(c))); log_string(log_buf); } } return false; } /**************************************************************************/ bool banedit_show (char_data *ch, char *); int wild_match(register unsigned char *m, register unsigned char *n); /**************************************************************************/ void display_bans(char_data *ch, char *site,int type) { BAN_DATA *pban; char host[MSL]; int i; // get hostname and make sure it is lowercase strcpy(host,site); for ( i = 0; host[i] != '\0'; i++ ){ host[i] = LOWER(host[i]); } i=-1; for ( pban = ban_list; pban; pban = pban->next ) { i++; // check ban is enabled if(!pban->enabled) continue; // check ban type if(pban->type!=type) continue; // do wildcard mask pattern matching if (match_multiline_masks( pban->sitemasks, host)){ ch->desc->pEdit = (void *)pban; ch->printlnf("Ban #%d", i); banedit_show( ch, ""); } } } /**************************************************************************/ void do_checkban( char_data *ch, char * argument) { void * pTemp = NULL; BAN_DATA *pBan; if(IS_NULLSTR(argument)){ ch->println( "syntax: checkban <ispaddy of player>"); return; } if(str_len(argument)<4){ ch->println( "syntax: checkban <ispaddy of player>"); ch->println( "Must be longer than 4 characters"); return; } pTemp = ch->desc->pEdit; ch->printlnf( "==- CHECK BAN ON: '%s'",argument); ch->printlnf( "- Newbies: %s", (pBan=check_ban_for_site(argument,BAN_NEWBIE))?"`Rdenied`x":"`Gallowed`x"); if(pBan){ display_bans(ch, argument,BAN_NEWBIE); } ch->printlnf( "- Permit/Letgained check: %s", (pBan=check_ban_for_site(argument,BAN_PERMIT))?"`Rdenied`x":"`Gallowed`x"); if(pBan){ display_bans(ch, argument,BAN_PERMIT); } ch->printlnf( "- Email check: %s", (pBan=check_ban_for_site(argument,BAN_EMAIL_REQ))?"`Rdenied`x":"`Gallowed`x"); if(pBan){ display_bans(ch, argument,BAN_EMAIL_REQ); } ch->printlnf( "- All: %s", (pBan=check_ban_for_site(argument,BAN_ALL))?"`Rdenied`x":"`Gallowed`x"); if(pBan){ display_bans(ch, argument,BAN_ALL); } ch->desc->pEdit = pTemp; } /**************************************************************************/ void do_showban( char_data *ch, char * argument) { void * pTemp = NULL; BAN_DATA *pBan; int count; if(IS_NULLSTR(argument)){ ch->println( "syntax: showban <number of ban in the ban list>"); return; } count=atoi(argument); for ( pBan = ban_list; pBan; pBan = pBan->next ){ if(--count<0) break; } if(!pBan){ ch->println( "There aren't that many bans."); return; } pTemp = ch->desc->pEdit; ch->desc->pEdit = (void *)pBan; banedit_show( ch, ""); ch->desc->pEdit = pTemp; } /**************************************************************************/