version 1.171, 2007/10/09 17:33:57
|
version 1.176, 2008/11/18 19:14:22
|
Line 26
|
Line 26
|
# http://www.lon-capa.org/ |
# http://www.lon-capa.org/ |
# |
# |
# |
# |
############################################################### |
|
############################################################## |
=head1 NAME |
|
|
|
Apache::londropadd.pm |
|
|
|
=head1 SYNOPSIS |
|
|
|
drop & add students |
|
|
|
This is part of the LearningOnline Network with CAPA project |
|
described at http://www.lon-capa.org. |
|
|
|
=head1 SUBROUTINES |
|
|
|
=over |
|
|
|
=cut |
|
|
package Apache::londropadd; |
package Apache::londropadd; |
|
|
Line 42 use Apache::lonlocal;
|
Line 57 use Apache::lonlocal;
|
use Apache::longroup; |
use Apache::longroup; |
use LONCAPA(); |
use LONCAPA(); |
|
|
############################################################### |
|
############################################################### |
|
sub header { |
sub header { |
my ($jscript,$loaditems) = @_; |
my ($jscript,$loaditems) = @_; |
my $start_page; |
my $start_page; |
Line 59 $start_page
|
Line 72 $start_page
|
ENDHEAD |
ENDHEAD |
} |
} |
|
|
############################################################### |
=pod |
############################################################### |
|
# Drop student from all sections of a course, except optional $csec |
=item modifystudent() |
|
|
|
Drop student from all sections of a course, except optional $csec |
|
|
|
=cut |
|
|
sub modifystudent { |
sub modifystudent { |
my ($udom,$unam,$courseid,$csec,$desiredhost)=@_; |
my ($udom,$unam,$courseid,$csec,$desiredhost)=@_; |
# if $csec is undefined, drop the student from all the courses matching |
# if $csec is undefined, drop the student from all the courses matching |
Line 104 sub modifystudent {
|
Line 122 sub modifystudent {
|
return $result; |
return $result; |
} |
} |
|
|
############################################################### |
=pod |
############################################################### |
|
# build a domain and server selection form |
=item domain_form() |
|
|
|
build a domain and server selection form |
|
|
|
=cut |
|
|
sub domain_form { |
sub domain_form { |
my ($defdom) = @_; |
my ($defdom) = @_; |
# Set up domain and server selection forms |
# Set up domain and server selection forms |
Line 135 sub domain_form {
|
Line 158 sub domain_form {
|
return $result; |
return $result; |
} |
} |
|
|
############################################################### |
=pod |
############################################################### |
|
# Menu Phase One |
=item print_main_menu() |
|
|
|
Menu Phase One |
|
|
|
=cut |
|
|
sub print_main_menu { |
sub print_main_menu { |
my ($r,$permission)=@_; |
my ($r,$permission)=@_; |
# |
# |
Line 224 sub print_main_menu {
|
Line 252 sub print_main_menu {
|
return; |
return; |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
sub hidden_input { |
sub hidden_input { |
my ($name,$value) = @_; |
my ($name,$value) = @_; |
return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n"; |
return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n"; |
} |
} |
|
|
|
|
|
|
sub print_upload_manager_header { |
sub print_upload_manager_header { |
my ($r,$datatoken,$distotal,$krbdefdom)=@_; |
my ($r,$datatoken,$distotal,$krbdefdom)=@_; |
my $javascript; |
my $javascript; |
Line 291 sub print_upload_manager_header {
|
Line 321 sub print_upload_manager_header {
|
$javascript."\n".$javascript_validations.'</script>'); |
$javascript."\n".$javascript_validations.'</script>'); |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
|
|
sub javascript_validations { |
sub javascript_validations { |
my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain)=@_; |
my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain)=@_; |
my $authheader; |
my $authheader; |
Line 423 END
|
Line 455 END
|
} |
} |
END |
END |
} else { |
} else { |
$section_checks = §ion_check_js(); |
$section_checks = &Apache::lonuserutils::section_check_js(); |
$optional_checks = (<<END); |
$optional_checks = (<<END); |
var message=''; |
var message=''; |
if (foundname==0) { |
if (foundname==0) { |
Line 471 END
|
Line 503 END
|
return $result; |
return $result; |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
sub upload_manager_javascript_forward_associate { |
sub upload_manager_javascript_forward_associate { |
return(<<ENDPICK); |
return(<<ENDPICK); |
function verify(vf,sec_caller) { |
function verify(vf,sec_caller) { |
Line 564 function clearpwd(vf) {
|
Line 597 function clearpwd(vf) {
|
ENDPICK |
ENDPICK |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
sub upload_manager_javascript_reverse_associate { |
sub upload_manager_javascript_reverse_associate { |
return(<<ENDPICK); |
return(<<ENDPICK); |
function verify(vf,sec_caller) { |
function verify(vf,sec_caller) { |
Line 619 function clearpwd(vf) {
|
Line 653 function clearpwd(vf) {
|
ENDPICK |
ENDPICK |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
sub print_upload_manager_footer { |
sub print_upload_manager_footer { |
my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_; |
my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_; |
|
|
Line 673 sub print_upload_manager_footer {
|
Line 708 sub print_upload_manager_footer {
|
return; |
return; |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
sub print_upload_manager_form { |
sub print_upload_manager_form { |
my $r=shift; |
my $r=shift; |
|
|
Line 748 sub print_upload_manager_form {
|
Line 784 sub print_upload_manager_form {
|
&print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear); |
&print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear); |
} |
} |
|
|
############################################################### |
|
############################################################### |
|
|
|
|
|
sub enroll_single_student { |
sub enroll_single_student { |
my ($r,$srcharray) = @_; |
my ($r,$srcharray) = @_; |
# Remove non alphanumeric values from section |
# Remove non alphanumeric values from section |
Line 759 sub enroll_single_student {
|
Line 797 sub enroll_single_student {
|
# in the course is entirely separate from the action of enrolling the |
# in the course is entirely separate from the action of enrolling the |
# student. Also, a failure in setting the dates as default is not fatal |
# student. Also, a failure in setting the dates as default is not fatal |
# to the process of enrolling / modifying a student. |
# to the process of enrolling / modifying a student. |
my ($startdate,$enddate) = &get_dates_from_form(); |
my ($startdate,$enddate) = &Apache::lonuserutils::get_dates_from_form(); |
if ($env{'form.makedatesdefault'}) { |
if ($env{'form.makedatesdefault'}) { |
$r->print(&make_dates_default($startdate,$enddate)); |
$r->print(&Apache::lonuserutils::make_dates_default($startdate, |
|
$enddate)); |
} |
} |
|
|
$r->print('<h3>'.&mt('Enrolling Student').'</h3>'); |
$r->print('<h3>'.&mt('Enrolling Student').'</h3>'); |
Line 806 sub enroll_single_student {
|
Line 845 sub enroll_single_student {
|
$env{'form.lcdomain'}); |
$env{'form.lcdomain'}); |
if ((($amode) && ($genpwd)) || ($home ne 'no_host')) { |
if ((($amode) && ($genpwd)) || ($home ne 'no_host')) { |
# Clean out any old roles the student has in this class. |
# Clean out any old roles the student has in this class. |
&modifystudent($env{'form.lcdomain'},$env{'form.cuname'}, |
&Apache::lonuserutils::modifystudent($env{'form.lcdomain'},$env{'form.cuname'}, |
$env{'request.course.id'},$env{'form.csec'}, |
$env{'request.course.id'},$env{'form.csec'}, |
$desiredhost); |
$desiredhost); |
my $login_result = &Apache::lonnet::modifystudent |
my $login_result = &Apache::lonnet::modifystudent |
Line 960 sub make_dates_default {
|
Line 999 sub make_dates_default {
|
return $result; |
return $result; |
} |
} |
|
|
## |
=pod |
## Single student enrollment routines (some of them) |
|
## |
=item get_student_username_domain_form() |
|
|
|
Single student enrollment routines (some of them) |
|
|
|
=cut |
|
|
sub get_student_username_domain_form { |
sub get_student_username_domain_form { |
my ($r,$elements,$response,$srch,$forcenewuser) = @_; |
my ($r,$elements,$response,$srch,$forcenewuser) = @_; |
my $loaditems = { |
my $loaditems = { |
Line 1066 sub print_enroll_single_student_form {
|
Line 1110 sub print_enroll_single_student_form {
|
my ($krbdef,$krbdefdom) = |
my ($krbdef,$krbdefdom) = |
&Apache::loncommon::get_kerberos_defaults($ccdomain); |
&Apache::loncommon::get_kerberos_defaults($ccdomain); |
$javascript_validations = |
$javascript_validations = |
&javascript_validations('auth',$krbdefdom,undef,undef,$ccdomain); |
&Apache::lonuserutils::javascript_validations('auth',$krbdefdom, |
|
undef,undef,$ccdomain); |
my %param = ( formname => 'document.studentform', |
my %param = ( formname => 'document.studentform', |
kerb_def_dom => $krbdefdom, |
kerb_def_dom => $krbdefdom, |
kerb_def_auth => $krbdef |
kerb_def_auth => $krbdef |
Line 1132 END
|
Line 1177 END
|
} else { |
} else { |
# User already exists. Do not worry about authentication |
# User already exists. Do not worry about authentication |
my %uenv = &Apache::lonnet::dump('environment',$ccdomain,$ccuname); |
my %uenv = &Apache::lonnet::dump('environment',$ccdomain,$ccuname); |
$javascript_validations = &javascript_validations('noauth'); |
$javascript_validations = &Apache::lonuserutils::javascript_validations('noauth'); |
my %lt=&Apache::lonlocal::texthash( |
my %lt=&Apache::lonlocal::texthash( |
'udf' => "User Data for", |
'udf' => "User Data for", |
'fn' => "First Name", |
'fn' => "First Name", |
Line 1158 END
|
Line 1203 END
|
</table> |
</table> |
END |
END |
} |
} |
my $date_table = &date_setting_table(); |
my $date_table = &Apache::lonuserutils::date_setting_table(); |
# Print it all out |
# Print it all out |
my %lt=&Apache::lonlocal::texthash( |
my %lt=&Apache::lonlocal::texthash( |
'cd' => "Course Data", |
'cd' => "Course Data", |
Line 1247 END
|
Line 1292 END
|
return; |
return; |
} |
} |
|
|
# ========================================================= Menu Phase Two Drop |
=pod |
|
|
|
=item print_drop_menu() |
|
|
|
Menu Phase Two Drop |
|
|
|
=cut |
|
|
sub print_drop_menu { |
sub print_drop_menu { |
my $r=shift; |
my $r=shift; |
$r->print("<h3>".&mt('Drop Students')."</h3>"); |
$r->print("<h3>".&mt('Drop Students')."</h3>"); |
Line 1262 sub print_drop_menu {
|
Line 1314 sub print_drop_menu {
|
return; |
return; |
} |
} |
|
|
# ============================================== view classlist |
|
|
=pod |
|
|
|
=item print_html_classlist() |
|
|
|
view classlist |
|
|
|
=cut |
|
|
sub print_html_classlist { |
sub print_html_classlist { |
my ($r,$mode,$permission) = @_; |
my ($r,$mode,$permission) = @_; |
if (! exists($env{'form.sortby'})) { |
if (! exists($env{'form.sortby'})) { |
Line 1352 sub print_html_classlist {
|
Line 1412 sub print_html_classlist {
|
} |
} |
} |
} |
|
|
# =================================================== Show student list to drop |
|
|
=pod |
|
|
|
=item show_class_list() |
|
|
|
Show student list to drop |
|
|
|
=cut |
|
|
sub show_class_list { |
sub show_class_list { |
my ($r,$mode,$linkto,$statusmode,$classlist,$keylist)=@_; |
my ($r,$mode,$linkto,$statusmode,$classlist,$keylist)=@_; |
my $cid=$env{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
Line 1510 END
|
Line 1578 END
|
time.'_'.rand(1000000000).'.csv'; |
time.'_'.rand(1000000000).'.csv'; |
unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) { |
unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) { |
$r->log_error("Couldn't open $CSVfilename for output $!"); |
$r->log_error("Couldn't open $CSVfilename for output $!"); |
$r->print("Problems occured in writing the csv file. ". |
$r->print(&mt('Problems occurred in writing the csv file. ' |
"This error has been logged. ". |
.'This error has been logged. ' |
"Please alert your LON-CAPA administrator."); |
.'Please alert your LON-CAPA administrator.')); |
$CSVfile = undef; |
$CSVfile = undef; |
} |
} |
# |
# |
Line 1754 END
|
Line 1822 END
|
} |
} |
|
|
|
|
# |
=pod |
# print out form for modification of a single students data |
|
# |
=item print_modify_student_form() |
|
|
|
print out form for modification of a single students data |
|
|
|
=cut |
|
|
sub print_modify_student_form { |
sub print_modify_student_form { |
my $r = shift(); |
my $r = shift(); |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, |
Line 1807 sub print_modify_student_form {
|
Line 1880 sub print_modify_student_form {
|
&Apache::lonlocal::locallocaltime($endtime)).'<br />'; |
&Apache::lonlocal::locallocaltime($endtime)).'<br />'; |
|
|
} |
} |
my $date_table = &date_setting_table($starttime,$endtime); |
my $date_table = |
|
&Apache::lonuserutils::date_setting_table($starttime,$endtime); |
# |
# |
if (! exists($env{'form.Status'}) || |
if (! exists($env{'form.Status'}) || |
$env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) { |
$env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) { |
Line 1829 sub print_modify_student_form {
|
Line 1903 sub print_modify_student_form {
|
'sm' => "Submit Modifications", |
'sm' => "Submit Modifications", |
); |
); |
# Check if section name is valid |
# Check if section name is valid |
my $section_check = §ion_check_js(); |
my $section_check = &Apache::lonuserutils::section_check_js(); |
$r->print(<<"END"); |
$r->print(<<"END"); |
<script type="text/javascript"> |
<script type="text/javascript"> |
$section_check |
$section_check |
Line 1884 END
|
Line 1958 END
|
return; |
return; |
} |
} |
|
|
# |
|
# modify a single students section |
=pod |
# |
|
|
=item modify_single_student() |
|
|
|
modify a single students section |
|
|
|
=cut |
|
|
sub modify_single_student { |
sub modify_single_student { |
my ($r) = @_; |
my ($r) = @_; |
# |
# |
Line 1894 sub modify_single_student {
|
Line 1974 sub modify_single_student {
|
$env{'form.section'} =~ s/\W//g; |
$env{'form.section'} =~ s/\W//g; |
# |
# |
# Do the date defaults first |
# Do the date defaults first |
my ($starttime,$endtime) = &get_dates_from_form(); |
my ($starttime,$endtime) = &Apache::lonuserutils::get_dates_from_form(); |
if ($env{'form.makedatesdefault'}) { |
if ($env{'form.makedatesdefault'}) { |
$r->print(&make_dates_default($starttime,$endtime)); |
$r->print(&Apache::lonuserutils::make_dates_default($starttime, |
|
$endtime)); |
} |
} |
# Get the 'sortby' and 'Status' variables so the user goes back to their |
# Get the 'sortby' and 'Status' variables so the user goes back to their |
# previous screen |
# previous screen |
Line 2042 END
|
Line 2123 END
|
# |
# |
# Send request(s) to modify data (final undef is for 'desiredhost', |
# Send request(s) to modify data (final undef is for 'desiredhost', |
# which is a moot point because the student already has an account. |
# which is a moot point because the student already has an account. |
my $modify_section_results = &modifystudent($sdom,$slogin, |
my $modify_section_results = |
$env{'request.course.id'}, |
&Apache::lonuserutils::modifystudent($sdom,$slogin, |
$section,undef); |
$env{'request.course.id'}, |
|
$section,undef); |
if ($modify_section_results !~ /^ok/) { |
if ($modify_section_results !~ /^ok/) { |
$r->print(&mt('An error occured during the attempt to change the section for this student.')."<br />"); |
$r->print(&mt('An error occurred during the attempt to change the section for this student.')."<br />"); |
} |
} |
my $roleresults = &Apache::lonnet::modifystudent |
my $roleresults = &Apache::lonnet::modifystudent |
($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname, |
($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname, |
Line 2114 sub get_enrollment_data {
|
Line 2196 sub get_enrollment_data {
|
return ($start,$end,$section); |
return ($start,$end,$section); |
} |
} |
|
|
################################################# |
|
################################################# |
|
|
|
=pod |
=pod |
|
|
=item show_drop_list |
=item show_drop_list() |
|
|
Display a list of students to drop |
Display a list of students to drop |
Inputs: |
Inputs: |
Line 2139 which describes the order elements are s
|
Line 2219 which describes the order elements are s
|
|
|
=cut |
=cut |
|
|
################################################# |
|
################################################# |
|
sub show_drop_list { |
sub show_drop_list { |
my ($r,$classlist,$keylist,$nosort)=@_; |
my ($r,$classlist,$keylist,$nosort)=@_; |
my $cid=$env{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
Line 2300 END
|
Line 2378 END
|
return; |
return; |
} |
} |
|
|
# |
|
# Print out the initial form to get the courselist file |
=pod |
# |
|
|
=item print_first_courselist_upload_form() |
|
|
|
Print out the initial form to get the courselist file |
|
|
|
=cut |
|
|
sub print_first_courselist_upload_form { |
sub print_first_courselist_upload_form { |
my $r=shift; |
my $r=shift; |
my $str; |
my $str; |
Line 2327 sub print_first_courselist_upload_form {
|
Line 2411 sub print_first_courselist_upload_form {
|
return; |
return; |
} |
} |
|
|
# ================================================= Drop/Add from uploaded file |
|
|
=pod |
|
|
|
=item upfile_drop_add() |
|
|
|
Drop/Add from uploaded file |
|
|
|
=cut |
|
|
sub upfile_drop_add { |
sub upfile_drop_add { |
my $r=shift; |
my $r=shift; |
&Apache::loncommon::load_tmp_file($r); |
&Apache::loncommon::load_tmp_file($r); |
Line 2504 sub upfile_drop_add {
|
Line 2596 sub upfile_drop_add {
|
$$_ =~ s/(\s+$|^\s+)//g; |
$$_ =~ s/(\s+$|^\s+)//g; |
} |
} |
if ($password || $env{'form.login'} eq 'loc') { |
if ($password || $env{'form.login'} eq 'loc') { |
&modifystudent($domain,$username,$cid,$sec, |
&Apache::lonuserutils::modifystudent($domain, |
$desiredhost); |
$username,$cid, |
|
$sec,$desiredhost); |
my $reply=&Apache::lonnet::modifystudent |
my $reply=&Apache::lonnet::modifystudent |
($domain,$username,$id,$amode,$password, |
($domain,$username,$id,$amode,$password, |
$fname,$mname,$lname,$gen,$sec,$enddate, |
$fname,$mname,$lname,$gen,$sec,$enddate, |
Line 2572 sub drop_student_list {
|
Line 2665 sub drop_student_list {
|
foreach (@droplist) { |
foreach (@droplist) { |
my ($uname,$udom)=split(/\:/,$_); |
my ($uname,$udom)=split(/\:/,$_); |
# drop student |
# drop student |
my $result = &modifystudent($udom,$uname,$env{'request.course.id'}); |
my $result = &Apache::lonuserutils::modifystudent($udom,$uname, |
|
$env{'request.course.id'}); |
if ($result eq 'ok' || $result eq 'ok:') { |
if ($result eq 'ok' || $result eq 'ok:') { |
$r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'<br>'); |
$r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'<br>'); |
$count++; |
$count++; |
Line 2639 sub get_permission {
|
Line 2733 sub get_permission {
|
return (\%permission,$allowed); |
return (\%permission,$allowed); |
} |
} |
|
|
################################################################### |
|
################################################################### |
|
|
|
=pod |
=pod |
|
|
=item &handler |
=item &handler() |
|
|
The typical handler you see in all these modules. Takes $r, the |
The typical handler you see in all these modules. Takes $r, the |
http request, as an argument. |
http request, as an argument. |
Line 2671 The response to the request is governed
|
Line 2762 The response to the request is governed
|
|
|
=cut |
=cut |
|
|
################################################################### |
|
################################################################### |
|
sub handler { |
sub handler { |
my $r=shift; |
my $r=shift; |
if ($r->header_only) { |
if ($r->header_only) { |
Line 2757 sub handler {
|
Line 2846 sub handler {
|
my @search = ('srchterm','srchby','srchin','srchtype','srchdomain'); |
my @search = ('srchterm','srchby','srchin','srchtype','srchdomain'); |
my ($jsback,$elements) = &Apache::loncreateuser::crumb_utilities(); |
my ($jsback,$elements) = &Apache::loncreateuser::crumb_utilities(); |
my $jscript = '<script type="text/javascript">'.$jsback.'</script>'; |
my $jscript = '<script type="text/javascript">'.$jsback.'</script>'; |
|
&Apache::loncreateuser::restore_prev_selections(); |
|
my $srch; |
|
foreach my $item (@search) { |
|
$srch->{$item} = $env{'form.'.$item}; |
|
} |
|
|
if ($env{'form.state'} eq 'gotusername') { |
if ($env{'form.state'} eq 'gotusername') { |
my $srch; |
|
foreach my $item (@search) { |
|
$srch->{$item} = $env{'form.'.$item}; |
|
} |
|
if ($env{'form.phase'} eq 'get_user_info') { |
if ($env{'form.phase'} eq 'get_user_info') { |
my ($currstate,$response,$forcenewuser,$results) = |
my ($currstate,$response,$forcenewuser,$results) = |
&Apache::loncreateuser::user_search_result($srch); |
&Apache::loncreateuser::user_search_result($srch); |
Line 2811 sub handler {
|
Line 2902 sub handler {
|
&print_enroll_single_student_form($r,$jscript,$ccuname, |
&print_enroll_single_student_form($r,$jscript,$ccuname, |
$ccdomain,$srch); |
$ccdomain,$srch); |
} else { |
} else { |
&get_student_username_domain_form($r,$elements); |
&get_student_username_domain_form($r,$elements,undef,$srch); |
} |
} |
} elsif ($env{'form.state'} eq 'enrolling') { |
} elsif ($env{'form.state'} eq 'enrolling') { |
$r->print(&header($jscript)); |
$r->print(&header($jscript)); |
Line 2832 sub handler {
|
Line 2923 sub handler {
|
'Course_Add_Student')); |
'Course_Add_Student')); |
&enroll_single_student($r,\@search); |
&enroll_single_student($r,\@search); |
} else { |
} else { |
&get_student_username_domain_form($r,$elements); |
&get_student_username_domain_form($r,$elements,undef,$srch); |
} |
} |
} elsif ($env{'form.action'} eq 'classlist' && $permission->{'view'}) { |
} elsif ($env{'form.action'} eq 'classlist' && $permission->{'view'}) { |
$r->print(&header()); |
$r->print(&header()); |
Line 2881 sub handler {
|
Line 2972 sub handler {
|
return OK; |
return OK; |
} |
} |
|
|
################################################################### |
|
################################################################### |
|
|
|
1; |
1; |
__END__ |
__END__ |
|
|
|
=pod |
|
|
|
=back |
|
|
|
=cut |