![]() ![]() | ![]() |
- lots of \w -> probper regexp replacements
1: # The LearningOnline Network with CAPA 2: # Routines for messaging 3: # 4: # $Id: lonmsg.pm,v 1.187 2006/12/05 02:55:53 albertel Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: # 28: 29: package Apache::lonmsg; 30: 31: use strict; 32: use Apache::lonnet; 33: use HTML::TokeParser(); 34: use Apache::lonlocal; 35: use Mail::Send; 36: use LONCAPA qw(:DEFAULT :match); 37: 38: { 39: my $uniq; 40: sub get_uniq { 41: $uniq++; 42: return $uniq; 43: } 44: } 45: 46: # ===================================================================== Package 47: 48: sub packagemsg { 49: my ($subject,$message,$citation,$baseurl,$attachmenturl, 50: $recuser,$recdomain,$msgid,$type,$crsmsgid)=@_; 51: $message =&HTML::Entities::encode($message,'<>&"'); 52: $citation=&HTML::Entities::encode($citation,'<>&"'); 53: $subject =&HTML::Entities::encode($subject,'<>&"'); 54: #remove machine specification 55: $baseurl =~ s|^http://[^/]+/|/|; 56: $baseurl =&HTML::Entities::encode($baseurl,'<>&"'); 57: #remove machine specification 58: $attachmenturl =~ s|^http://[^/]+/|/|; 59: $attachmenturl =&HTML::Entities::encode($attachmenturl,'<>&"'); 60: my $course_context; 61: if (defined($env{'form.replyid'})) { 62: my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$origcid)= 63: split(/\:/,&unescape($env{'form.replyid'})); 64: $course_context = $origcid; 65: } 66: foreach my $key (keys(%env)) { 67: if ($key=~/^form\.(rep)?rec\_(.*)$/) { 68: my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$origcid) = 69: split(/\:/,&unescape($2)); 70: $course_context = $origcid; 71: last; 72: } 73: } 74: unless(defined($course_context)) { 75: $course_context = $env{'request.course.id'}; 76: } 77: my $now=time; 78: my $msgcount = &get_uniq(); 79: unless(defined($msgid)) { 80: $msgid = &buildmsgid($now,$subject,$env{'user.name'},$env{'user.domain'}, 81: $msgcount,$course_context,$$); 82: } 83: my $result = '<sendername>'.$env{'user.name'}.'</sendername>'. 84: '<senderdomain>'.$env{'user.domain'}.'</senderdomain>'. 85: '<subject>'.$subject.'</subject>'. 86: '<time>'.&Apache::lonlocal::locallocaltime($now).'</time>'; 87: if (defined($crsmsgid)) { 88: $result.= '<courseid>'.$course_context.'</courseid>'. 89: '<coursesec>'.$env{'request.course.sec'}.'</coursesec>'. 90: '<msgid>'.$msgid.'</msgid>'. 91: '<coursemsgid>'.$crsmsgid.'</coursemsgid>'. 92: '<message>'.$message.'</message>'; 93: return ($msgid,$result); 94: } 95: $result .= '<servername>'.$ENV{'SERVER_NAME'}.'</servername>'. 96: '<host>'.$ENV{'HTTP_HOST'}.'</host>'. 97: '<client>'.$ENV{'REMOTE_ADDR'}.'</client>'. 98: '<browsertype>'.$env{'browser.type'}.'</browsertype>'. 99: '<browseros>'.$env{'browser.os'}.'</browseros>'. 100: '<browserversion>'.$env{'browser.version'}.'</browserversion>'. 101: '<browsermathml>'.$env{'browser.mathml'}.'</browsermathml>'. 102: '<browserraw>'.$ENV{'HTTP_USER_AGENT'}.'</browserraw>'. 103: '<courseid>'.$course_context.'</courseid>'. 104: '<coursesec>'.$env{'request.course.sec'}.'</coursesec>'. 105: '<role>'.$env{'request.role'}.'</role>'. 106: '<resource>'.$env{'request.filename'}.'</resource>'. 107: '<msgid>'.$msgid.'</msgid>'; 108: if (ref($recuser) eq 'ARRAY') { 109: for (my $i=0; $i<@{$recuser}; $i++) { 110: if ($type eq 'dcmail') { 111: my ($username,$email) = split(/:/,$$recuser[$i]); 112: $username = &unescape($username); 113: $email = &unescape($email); 114: $username = &HTML::Entities::encode($username,'<>&"'); 115: $email = &HTML::Entities::encode($email,'<>&"'); 116: $result .= '<recipient username="'.$username.'">'. 117: $email.'</recipient>'; 118: } else { 119: $result .= '<recuser>'.$$recuser[$i].'</recuser>'. 120: '<recdomain>'.$$recdomain[$i].'</recdomain>'; 121: } 122: } 123: } else { 124: $result .= '<recuser>'.$recuser.'</recuser>'. 125: '<recdomain>'.$recdomain.'</recdomain>'; 126: } 127: $result .= '<message>'.$message.'</message>'; 128: if (defined($citation)) { 129: $result.='<citation>'.$citation.'</citation>'; 130: } 131: if (defined($baseurl)) { 132: $result.= '<baseurl>'.$baseurl.'</baseurl>'; 133: } 134: if (defined($attachmenturl)) { 135: $result.= '<attachmenturl>'.$attachmenturl.'</attachmenturl>'; 136: } 137: return $msgid,$result; 138: } 139: 140: # ================================================== Unpack message into a hash 141: 142: sub unpackagemsg { 143: my ($message,$notoken)=@_; 144: my %content=(); 145: my $parser=HTML::TokeParser->new(\$message); 146: my $token; 147: while ($token=$parser->get_token) { 148: if ($token->[0] eq 'S') { 149: my $entry=$token->[1]; 150: my $value=$parser->get_text('/'.$entry); 151: if (($entry eq 'recuser') || ($entry eq 'recdomain')) { 152: push(@{$content{$entry}},$value); 153: } elsif ($entry eq 'recipient') { 154: my $username = $token->[2]{'username'}; 155: $username = &HTML::Entities::decode($username,'<>&"'); 156: $content{$entry}{$username} = $value; 157: } else { 158: $content{$entry}=$value; 159: } 160: } 161: } 162: if (!exists($content{'recuser'})) { $content{'recuser'} = []; } 163: if ($content{'attachmenturl'}) { 164: my ($fname)=($content{'attachmenturl'}=~m|/([^/]+)$|); 165: if ($notoken) { 166: $content{'message'}.='<p>'.&mt('Attachment').': <tt>'.$fname.'</tt>'; 167: } else { 168: &Apache::lonnet::allowuploaded('/adm/msg', 169: $content{'attachmenturl'}); 170: $content{'message'}.='<p>'.&mt('Attachment'). 171: ': <a href="'.$content{'attachmenturl'}.'"><tt>'. 172: $fname.'</tt></a>'; 173: } 174: } 175: return %content; 176: } 177: 178: # ======================================================= Get info out of msgid 179: 180: sub buildmsgid { 181: my ($now,$subject,$uname,$udom,$msgcount,$course_context,$pid) = @_; 182: $subject=&escape($subject); 183: return(&escape($now.':'.$subject.':'.$uname.':'. 184: $udom.':'.$msgcount.':'.$course_context.':'.$pid)); 185: } 186: 187: sub unpackmsgid { 188: my ($msgid,$folder,$skipstatus,$status_cache)=@_; 189: $msgid=&unescape($msgid); 190: my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$fromcid, 191: $processid)=split(/\:/,&unescape($msgid)); 192: $shortsubj = &unescape($shortsubj); 193: $shortsubj = &HTML::Entities::decode($shortsubj); 194: if (!defined($processid)) { $fromcid = ''; } 195: my %status=(); 196: unless ($skipstatus) { 197: if (ref($status_cache)) { 198: $status{$msgid} = $status_cache->{$msgid}; 199: } else { 200: my $suffix=&foldersuffix($folder); 201: %status=&Apache::lonnet::get('email_status'.$suffix,[$msgid]); 202: } 203: if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } 204: unless ($status{$msgid}) { $status{$msgid}='new'; } 205: } 206: return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid},$fromcid); 207: } 208: 209: 210: sub sendemail { 211: my ($to,$subject,$body)=@_; 212: my %senderemails=&Apache::loncommon::getemails(); 213: my $senderaddress=''; 214: foreach my $type ('notification','permanentemail','critnotification') { 215: if ($senderemails{$type}) { 216: $senderaddress=$senderemails{$type}; 217: } 218: } 219: $body= 220: "*** ".&mt('This is an automatic message generated by the LON-CAPA system.')."\n". 221: "*** ".($senderaddress?&mt('You can reply to this message'):&mt('Please do not reply to this address.')."\n*** ". 222: &mt('A reply will not be received by the recipient!'))."\n\n".$body; 223: my $msg = new Mail::Send; 224: $msg->to($to); 225: $msg->subject('[LON-CAPA] '.$subject); 226: if ($senderaddress) { $msg->add('Reply-to',$senderaddress); } 227: if (my $fh = $msg->open()) { 228: print $fh $body; 229: $fh->close; 230: } 231: } 232: 233: # ==================================================== Send notification emails 234: 235: sub sendnotification { 236: my ($to,$touname,$toudom,$subj,$crit,$text)=@_; 237: my $sender=$env{'environment.firstname'}.' '.$env{'environment.lastname'}; 238: unless ($sender=~/\w/) { 239: $sender=$env{'user.name'}.'@'.$env{'user.domain'}; 240: } 241: my $critical=($crit?' critical':''); 242: $text=~s/\<\;/\</gs; 243: $text=~s/\>\;/\>/gs; 244: $text=~s/\<\/*[^\>]+\>//gs; 245: my $url='http://'. 246: $Apache::lonnet::hostname{&Apache::lonnet::homeserver($touname,$toudom)}. 247: '/adm/email?username='.$touname.'&domain='.$toudom; 248: my $body=(<<ENDMSG); 249: You received a$critical message from $sender in LON-CAPA. The subject is 250: 251: $subj 252: 253: === Excerpt ============================================================ 254: $text 255: ======================================================================== 256: 257: Use 258: 259: $url 260: 261: to access the full message. 262: ENDMSG 263: &sendemail($to,'New'.$critical.' message from '.$sender,$body); 264: } 265: # ============================================================= Check for email 266: 267: sub newmail { 268: if ((time-$env{'user.mailcheck.time'})>300) { 269: my %what=&Apache::lonnet::get('email_status',['recnewemail']); 270: &Apache::lonnet::appenv('user.mailcheck.time'=>time); 271: if ($what{'recnewemail'}>0) { return 1; } 272: } 273: return 0; 274: } 275: 276: # =============================== Automated message to the author of a resource 277: 278: =pod 279: 280: =item * B<author_res_msg($filename, $message)>: Sends message $message to the owner 281: of the resource with the URI $filename. 282: 283: =cut 284: 285: sub author_res_msg { 286: my ($filename,$message)=@_; 287: unless ($message) { return 'empty'; } 288: $filename=&Apache::lonnet::declutter($filename); 289: my ($domain,$author,@dummy)=split(/\//,$filename); 290: my $homeserver=&Apache::lonnet::homeserver($author,$domain); 291: if ($homeserver ne 'no_host') { 292: my $id=unpack("%32C*",$message); 293: $message .= " <p>This error occurred on machine ". 294: $Apache::lonnet::perlvar{'lonHostID'}."</p>"; 295: my $msgid; 296: ($msgid,$message)=&packagemsg($filename,$message); 297: return &Apache::lonnet::reply('put:'.$domain.':'.$author. 298: ':nohist_res_msgs:'. 299: &escape($filename.'_'.$id).'='. 300: &escape($message),$homeserver); 301: } 302: return 'no_host'; 303: } 304: 305: # =========================================== Retrieve author resource messages 306: 307: sub retrieve_author_res_msg { 308: my $url=shift; 309: $url=&Apache::lonnet::declutter($url); 310: my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); 311: my %errormsgs=&Apache::lonnet::dump('nohist_res_msgs',$domain,$author); 312: my $msgs=''; 313: foreach (keys %errormsgs) { 314: if ($_=~/^\Q$url\E\_\d+$/) { 315: my %content=&unpackagemsg($errormsgs{$_}); 316: $msgs.='<p><img src="/adm/lonMisc/bomb.gif" /><b>'. 317: $content{'time'}.'</b>: '.$content{'message'}. 318: '<br /></p>'; 319: } 320: } 321: return $msgs; 322: } 323: 324: 325: # =============================== Delete all author messages related to one URL 326: 327: sub del_url_author_res_msg { 328: my $url=shift; 329: $url=&Apache::lonnet::declutter($url); 330: my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); 331: my @delmsgs=(); 332: foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { 333: if ($_=~/^\Q$url\E\_\d+$/) { 334: push (@delmsgs,$_); 335: } 336: } 337: return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author); 338: } 339: # =================================== Clear out all author messages in URL path 340: 341: sub clear_author_res_msg { 342: my $url=shift; 343: $url=&Apache::lonnet::declutter($url); 344: my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); 345: my @delmsgs=(); 346: foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { 347: if ($_=~/^\Q$url\E/) { 348: push (@delmsgs,$_); 349: } 350: } 351: return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author); 352: } 353: # ================= Return hash with URLs for which there is a resource message 354: 355: sub all_url_author_res_msg { 356: my ($author,$domain)=@_; 357: my %returnhash=(); 358: foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { 359: $_=~/^(.+)\_\d+/; 360: $returnhash{$1}=1; 361: } 362: return %returnhash; 363: } 364: 365: # ====================================== Add a comment to the User Notes screen 366: 367: sub store_instructor_comment { 368: my ($msg,$uname,$udom) = @_; 369: my $cid = $env{'request.course.id'}; 370: my $cnum = $env{'course.'.$cid.'.num'}; 371: my $cdom = $env{'course.'.$cid.'.domain'}; 372: my $subject= &mt('Record').' ['.$uname.':'.$udom.']'; 373: my $result = &user_normal_msg_raw($cnum,$cdom,$subject,$msg); 374: return $result; 375: } 376: 377: # ================================================== Critical message to a user 378: 379: sub user_crit_msg_raw { 380: my ($user,$domain,$subject,$message,$sendback,$toperm,$sentmessage)=@_; 381: # Check if allowed missing 382: my $status=''; 383: my $msgid='undefined'; 384: unless (($message)&&($user)&&($domain)) { $status='empty'; }; 385: my $text=$message; 386: my $homeserver=&Apache::lonnet::homeserver($user,$domain); 387: if ($homeserver ne 'no_host') { 388: ($msgid,$message)=&packagemsg($subject,$message); 389: if ($sendback) { $message.='<sendback>true</sendback>'; } 390: $status=&Apache::lonnet::critical( 391: 'put:'.$domain.':'.$user.':critical:'. 392: &escape($msgid).'='. 393: &escape($message),$homeserver); 394: if (defined($sentmessage)) { 395: $$sentmessage = $message; 396: } 397: } else { 398: $status='no_host'; 399: } 400: # Notifications 401: my %userenv = &Apache::loncommon::getemails($user,$domain); 402: if ($userenv{'critnotification'}) { 403: &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1, 404: $text); 405: } 406: if ($toperm && $userenv{'permanentemail'}) { 407: &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,1, 408: $text); 409: } 410: # Log this 411: &Apache::lonnet::logthis( 412: 'Sending critical email '.$msgid. 413: ', log status: '. 414: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 415: $env{'user.home'}, 416: 'Sending critical '.$msgid.' to '.$user.' at '.$domain.' with status: ' 417: .$status)); 418: return $status; 419: } 420: 421: # New routine that respects "forward" and calls old routine 422: 423: =pod 424: 425: =item * B<user_crit_msg($user, $domain, $subject, $message, $sendback)>: Sends 426: a critical message $message to the $user at $domain. If $sendback is true, 427: a reciept will be sent to the current user when $user recieves the message. 428: 429: Additionally it will check if the user has a Forwarding address 430: set, and send the message to that address instead 431: 432: returns 433: - in array context a list of results for each message that was sent 434: - in scalar context a space seperated list of results for each 435: message sent 436: 437: =cut 438: 439: sub user_crit_msg { 440: my ($user,$domain,$subject,$message,$sendback,$toperm,$sentmessage)=@_; 441: my @status; 442: my %userenv = &Apache::lonnet::get('environment',['msgforward'], 443: $domain,$user); 444: my $msgforward=$userenv{'msgforward'}; 445: if ($msgforward) { 446: foreach my $addr (split(/\,/,$msgforward)) { 447: my ($forwuser,$forwdomain)=split(/\:/,$addr); 448: push(@status, 449: &user_crit_msg_raw($forwuser,$forwdomain,$subject,$message, 450: $sendback,$toperm,$sentmessage)); 451: } 452: } else { 453: push(@status, 454: &user_crit_msg_raw($user,$domain,$subject,$message,$sendback, 455: $toperm,$sentmessage)); 456: } 457: if (wantarray) { 458: return @status; 459: } 460: return join(' ',@status); 461: } 462: 463: # =================================================== Critical message received 464: 465: sub user_crit_received { 466: my $msgid=shift; 467: my %message=&Apache::lonnet::get('critical',[$msgid]); 468: my %contents=&unpackagemsg($message{$msgid},1); 469: my $status='rec: '.($contents{'sendback'}? 470: &user_normal_msg($contents{'sendername'},$contents{'senderdomain'}, 471: &mt('Receipt').': '.$env{'user.name'}.' '.&mt('at').' '.$env{'user.domain'}.', '.$contents{'subject'}, 472: &mt('User').' '.$env{'user.name'}.' '.&mt('at').' '.$env{'user.domain'}. 473: ' acknowledged receipt of message'."\n".' "'. 474: $contents{'subject'}.'"'."\n".&mt('dated').' '. 475: $contents{'time'}.".\n" 476: ):'no msg req'); 477: $status.=' trans: '. 478: &Apache::lonnet::put( 479: 'nohist_email',{$contents{'msgid'} => $message{$msgid}}); 480: $status.=' del: '. 481: &Apache::lonnet::del('critical',[$contents{'msgid'}]); 482: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 483: $env{'user.home'},'Received critical message '. 484: $contents{'msgid'}. 485: ', '.$status); 486: return $status; 487: } 488: 489: # ======================================================== Normal communication 490: 491: sub user_normal_msg_raw { 492: my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, 493: $toperm,$currid,$newid,$sentmessage,$crsmsgid)=@_; 494: # Check if allowed missing 495: my ($status,$packed_message); 496: my $msgid='undefined'; 497: my $text=$message; 498: unless (($message)&&($user)&&($domain)) { $status='empty'; }; 499: my $homeserver=&Apache::lonnet::homeserver($user,$domain); 500: if ($homeserver ne 'no_host') { 501: ($msgid,$packed_message)= 502: &packagemsg($subject,$message,$citation,$baseurl, 503: $attachmenturl,$user,$domain,$currid, 504: undef,$crsmsgid); 505: 506: # Store in user folder 507: $status=&Apache::lonnet::critical( 508: 'put:'.$domain.':'.$user.':nohist_email:'. 509: &escape($msgid).'='. 510: &escape($packed_message),$homeserver); 511: # Save new message received time 512: &Apache::lonnet::put 513: ('email_status',{'recnewemail'=>time},$domain,$user); 514: # Into sent-mail folder unless a broadcast message or critical message 515: unless (($env{'request.course.id'}) && 516: (($env{'form.sendmode'} eq 'group') || 517: (($env{'form.critmsg'}) || ($env{'form.sendbck'})) && 518: (&Apache::lonnet::allowed('srm',$env{'request.course.id'}) 519: || &Apache::lonnet::allowed('srm',$env{'request.course.id'}. 520: '/'.$env{'request.course.sec'})))) { 521: (undef, my $packed_message_no_citation)= 522: &packagemsg($subject,$message,undef ,$baseurl, 523: $attachmenturl,$user,$domain,$currid, 524: undef,$crsmsgid); 525: 526: $status .= &store_sent_mail($msgid,$packed_message_no_citation); 527: } 528: } else { 529: $status='no_host'; 530: } 531: if (defined($newid)) { 532: $$newid = $msgid; 533: } 534: if (defined($sentmessage)) { 535: $$sentmessage = $packed_message; 536: } 537: 538: # Notifications 539: my %userenv = &Apache::lonnet::get('environment',['notification', 540: 'permanentemail'], 541: $domain,$user); 542: if ($userenv{'notification'}) { 543: &sendnotification($userenv{'notification'},$user,$domain,$subject,0, 544: $text); 545: } 546: if ($toperm && $userenv{'permanentemail'}) { 547: &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,0, 548: $text); 549: } 550: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 551: $env{'user.home'}, 552: 'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status); 553: return $status; 554: } 555: 556: # New routine that respects "forward" and calls old routine 557: 558: =pod 559: 560: =item * B<user_normal_msg($user, $domain, $subject, $message, 561: $citation, $baseurl, $attachmenturl)>: Sends a message to the 562: $user at $domain, with subject $subject and message $message. 563: 564: =cut 565: 566: sub user_normal_msg { 567: my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, 568: $toperm,$sentmessage)=@_; 569: my $status=''; 570: my %userenv = &Apache::lonnet::get('environment',['msgforward'], 571: $domain,$user); 572: my $msgforward=$userenv{'msgforward'}; 573: if ($msgforward) { 574: foreach (split(/\,/,$msgforward)) { 575: my ($forwuser,$forwdomain)=split(/\:/,$_); 576: $status.= 577: &user_normal_msg_raw($forwuser,$forwdomain,$subject,$message, 578: $citation,$baseurl,$attachmenturl,$toperm, 579: undef,undef,$sentmessage).' '; 580: } 581: } else { 582: $status=&user_normal_msg_raw($user,$domain,$subject,$message, 583: $citation,$baseurl,$attachmenturl,$toperm, 584: undef,undef,$sentmessage); 585: } 586: return $status; 587: } 588: 589: sub store_sent_mail { 590: my ($msgid,$message) = @_; 591: my $status =' '.&Apache::lonnet::critical( 592: 'put:'.$env{'user.domain'}.':'.$env{'user.name'}. 593: ':nohist_email_sent:'. 594: &escape($msgid).'='. 595: &escape($message),$env{'user.home'}); 596: return $status; 597: } 598: 599: # =============================================================== Folder suffix 600: 601: sub foldersuffix { 602: my $folder=shift; 603: unless ($folder) { return ''; } 604: return '_'.&escape($folder); 605: } 606: 607: 1; 608: __END__ 609: