| … | |
… | |
| 343 | |
343 | |
| 344 | my $perm_multiset = $authz->hasPermissions($userID, "download_hardcopy_multiset"); |
344 | my $perm_multiset = $authz->hasPermissions($userID, "download_hardcopy_multiset"); |
| 345 | my $perm_multiuser = $authz->hasPermissions($userID, "download_hardcopy_multiuser"); |
345 | my $perm_multiuser = $authz->hasPermissions($userID, "download_hardcopy_multiuser"); |
| 346 | my $perm_texformat = $authz->hasPermissions($userID, "download_hardcopy_format_tex"); |
346 | my $perm_texformat = $authz->hasPermissions($userID, "download_hardcopy_format_tex"); |
| 347 | my $perm_unopened = $authz->hasPermissions($userID, "view_unopened_sets"); |
347 | my $perm_unopened = $authz->hasPermissions($userID, "view_unopened_sets"); |
| 348 | my $perm_unpublished = $authz->hasPermissions($userID, "view_unpublished_sets"); |
348 | my $perm_view_hidden = $authz->hasPermissions($userID, "view_hidden_sets"); |
| 349 | |
349 | |
| 350 | # get formats |
350 | # get formats |
| 351 | my @formats; |
351 | my @formats; |
| 352 | foreach my $format (keys %HC_FORMATS) { |
352 | foreach my $format (keys %HC_FORMATS) { |
| 353 | push @formats, $format if $authz->hasPermissions($userID, "download_hardcopy_format_$format"); |
353 | push @formats, $format if $authz->hasPermissions($userID, "download_hardcopy_format_$format"); |
| … | |
… | |
| 366 | # otherwise, we get our own record only |
366 | # otherwise, we get our own record only |
| 367 | @Users = $db->getUser($eUserID); |
367 | @Users = $db->getUser($eUserID); |
| 368 | } |
368 | } |
| 369 | |
369 | |
| 370 | # get sets for selection |
370 | # get sets for selection |
| 371 | # DBFIXME should use WHERE clause to filter on open_date and published, rather then getting all |
371 | # DBFIXME should use WHERE clause to filter on open_date and visible, rather then getting all |
| 372 | my @globalSetIDs; |
372 | my @globalSetIDs; |
| 373 | my @GlobalSets; |
373 | my @GlobalSets; |
| 374 | if ($perm_multiuser) { |
374 | if ($perm_multiuser) { |
| 375 | # if we're allowed to select sets for multiple users, get all sets. |
375 | # if we're allowed to select sets for multiple users, get all sets. |
| 376 | @globalSetIDs = $db->listGlobalSets; |
376 | @globalSetIDs = $db->listGlobalSets; |
| … | |
… | |
| 412 | unless (defined $Set) { |
412 | unless (defined $Set) { |
| 413 | warn "\$GlobalSets[$i] (ID $globalSetIDs[$i]) not defined -- skipping"; |
413 | warn "\$GlobalSets[$i] (ID $globalSetIDs[$i]) not defined -- skipping"; |
| 414 | next; |
414 | next; |
| 415 | } |
415 | } |
| 416 | next unless $Set->open_date <= time or $perm_unopened; |
416 | next unless $Set->open_date <= time or $perm_unopened; |
| 417 | next unless $Set->published or $perm_unpublished; |
417 | next unless $Set->visible or $perm_view_hidden; |
| 418 | # also skip gateway sets, for which we have to have a |
418 | # also skip gateway sets, for which we have to have a |
| 419 | # version to print something |
419 | # version to print something |
| 420 | next if $Set->assignment_type =~ /gateway/; |
420 | next if $Set->assignment_type =~ /gateway/; |
| 421 | push @WantedGlobalSets, $Set; |
421 | push @WantedGlobalSets, $Set; |
| 422 | } |
422 | } |
| … | |
… | |
| 591 | } |
591 | } |
| 592 | |
592 | |
| 593 | my $tex_file_name = "hardcopy.tex"; |
593 | my $tex_file_name = "hardcopy.tex"; |
| 594 | my $tex_file_path = "$temp_dir_path/$tex_file_name"; |
594 | my $tex_file_path = "$temp_dir_path/$tex_file_name"; |
| 595 | |
595 | |
| 596 | # write TeX |
596 | ####################################### |
|
|
597 | # create TeX file (callback write_multiuser_tex, or ??) |
|
|
598 | ####################################### |
|
|
599 | |
| 597 | my $open_result = open my $FH, ">", $tex_file_path; |
600 | my $open_result = open my $FH, ">", $tex_file_path; |
| 598 | unless ($open_result) { |
601 | unless ($open_result) { |
| 599 | $self->add_errors("Failed to open file '".CGI::code(CGI::escapeHTML($tex_file_path)) |
602 | $self->add_errors("Failed to open file '".CGI::code(CGI::escapeHTML($tex_file_path)) |
| 600 | ."' for writing: ".CGI::code(CGI::escapeHTML($!))); |
603 | ."' for writing: ".CGI::code(CGI::escapeHTML($!))); |
| 601 | $self->delete_temp_dir($temp_dir_path); |
604 | $self->delete_temp_dir($temp_dir_path); |
| … | |
… | |
| 617 | .CGI::code(CGI::escapeHTML($temp_dir_path))."'. Can't continue."); |
620 | .CGI::code(CGI::escapeHTML($temp_dir_path))."'. Can't continue."); |
| 618 | $self->delete_temp_dir($temp_dir_path); |
621 | $self->delete_temp_dir($temp_dir_path); |
| 619 | return; |
622 | return; |
| 620 | } |
623 | } |
| 621 | |
624 | |
|
|
625 | ############################################## |
|
|
626 | # end creation of TeX file |
|
|
627 | ############################################## |
|
|
628 | |
| 622 | # determine base name of final file |
629 | # determine base name of final file |
| 623 | my $final_file_user = @$userIDsRef > 1 ? "multiuser" : $userIDsRef->[0]; |
630 | my $final_file_user = @$userIDsRef > 1 ? "multiuser" : $userIDsRef->[0]; |
| 624 | my $final_file_set = @$setIDsRef > 1 ? "multiset" : $setIDsRef->[0]; |
631 | my $final_file_set = @$setIDsRef > 1 ? "multiset" : $setIDsRef->[0]; |
| 625 | my $final_file_basename = "$courseID.$final_file_user.$final_file_set"; |
632 | my $final_file_basename = "$courseID.$final_file_user.$final_file_set"; |
| 626 | |
633 | |
|
|
634 | ############################################### |
| 627 | # call format subroutine |
635 | # call format subroutine (call back) |
|
|
636 | ############################################### |
| 628 | # $final_file_name is the name of final hardcopy file |
637 | # $final_file_name is the name of final hardcopy file |
| 629 | # @temp_files is a list of temporary files of interest used by the subroutine |
638 | # @temp_files is a list of temporary files of interest used by the subroutine |
| 630 | # (all are relative to $temp_dir_path) |
639 | # (all are relative to $temp_dir_path) |
| 631 | my $format_subr = $HC_FORMATS{$format}{subr}; |
640 | my $format_subr = $HC_FORMATS{$format}{subr}; |
| 632 | my ($final_file_name, @temp_files) = $self->$format_subr($temp_dir_path, $final_file_basename); |
641 | my ($final_file_name, @temp_files) = $self->$format_subr($temp_dir_path, $final_file_basename); |
| 633 | my $final_file_path = "$temp_dir_path/$final_file_name"; |
642 | my $final_file_path = "$temp_dir_path/$final_file_name"; |
| 634 | |
643 | |
| 635 | #warn "final_file_name=$final_file_name\n"; |
644 | #warn "final_file_name=$final_file_name\n"; |
| 636 | #warn "temp_files=@temp_files\n"; |
645 | #warn "temp_files=@temp_files\n"; |
| 637 | |
646 | |
|
|
647 | ################################################ |
| 638 | # calculate URLs for each temp file of interest |
648 | # calculate URLs for each temp file of interest |
|
|
649 | ################################################# |
| 639 | # makeTempDirectory's interface forces us to reverse-engineer the name of the temp dir from the path |
650 | # makeTempDirectory's interface forces us to reverse-engineer the name of the temp dir from the path |
| 640 | my $temp_dir_parent_url = $ce->{courseURLs}{html_temp} . "/hardcopy"; |
651 | my $temp_dir_parent_url = $ce->{courseURLs}{html_temp} . "/hardcopy"; |
| 641 | (my $temp_dir_url = $temp_dir_path) =~ s/^$temp_dir_parent_path/$temp_dir_parent_url/; |
652 | (my $temp_dir_url = $temp_dir_path) =~ s/^$temp_dir_parent_path/$temp_dir_parent_url/; |
| 642 | my %temp_file_map; |
653 | my %temp_file_map; |
| 643 | foreach my $temp_file_name (@temp_files) { |
654 | foreach my $temp_file_name (@temp_files) { |
| 644 | $temp_file_map{$temp_file_name} = "$temp_dir_url/$temp_file_name"; |
655 | $temp_file_map{$temp_file_name} = "$temp_dir_url/$temp_file_name"; |
| 645 | } |
656 | } |
| 646 | |
657 | |
| 647 | my $final_file_url; |
658 | my $final_file_url; |
| 648 | |
659 | |
|
|
660 | ################################################## |
| 649 | # make sure final file exists |
661 | # make sure final file exists |
|
|
662 | ################################################## |
|
|
663 | # returns undefined unless $final_file_path points to a file |
| 650 | unless (-e $final_file_path) { |
664 | unless (-e $final_file_path) { |
| 651 | $self->add_errors("Final hardcopy file '".CGI::code(CGI::escapeHTML($final_file_path)) |
665 | $self->add_errors("Final hardcopy file '".CGI::code(CGI::escapeHTML($final_file_path)) |
| 652 | ."' not found after calling '".CGI::code(CGI::escapeHTML($format_subr))."': " |
666 | ."' not found after calling '".CGI::code(CGI::escapeHTML($format_subr))."': " |
| 653 | .CGI::code(CGI::escapeHTML($!))); |
667 | .CGI::code(CGI::escapeHTML($!))); |
| 654 | return $final_file_url, %temp_file_map; |
668 | return $final_file_url, %temp_file_map; |
| 655 | } |
669 | } |
| 656 | |
670 | |
|
|
671 | ################################################## |
| 657 | # try to move the hardcopy file out of the temp directory |
672 | # try to move the hardcopy file out of the temp directory |
|
|
673 | ################################################## |
|
|
674 | |
| 658 | # set $final_file_url accordingly |
675 | # set $final_file_url accordingly |
| 659 | my $final_file_final_path = "$temp_dir_parent_path/$final_file_name"; |
676 | my $final_file_final_path = "$temp_dir_parent_path/$final_file_name"; |
| 660 | my $mv_cmd = "2>&1 " . $ce->{externalPrograms}{mv} . " " . shell_quote($final_file_path, $final_file_final_path); |
677 | my $mv_cmd = "2>&1 " . $ce->{externalPrograms}{mv} . " " . shell_quote($final_file_path, $final_file_final_path); |
| 661 | my $mv_out = readpipe $mv_cmd; |
678 | my $mv_out = readpipe $mv_cmd; |
| 662 | if ($?) { |
679 | if ($?) { |
| … | |
… | |
| 667 | $final_file_url = "$temp_dir_url/$final_file_name"; |
684 | $final_file_url = "$temp_dir_url/$final_file_name"; |
| 668 | } else { |
685 | } else { |
| 669 | $final_file_url = "$temp_dir_parent_url/$final_file_name"; |
686 | $final_file_url = "$temp_dir_parent_url/$final_file_name"; |
| 670 | } |
687 | } |
| 671 | |
688 | |
|
|
689 | ################################################## |
| 672 | # remove the temp directory if there are no errors |
690 | # remove the temp directory if there are no errors |
|
|
691 | ################################################## |
|
|
692 | |
| 673 | unless ($self->get_errors or $PreserveTempFiles) { |
693 | unless ($self->get_errors or $PreserveTempFiles) { |
| 674 | $self->delete_temp_dir($temp_dir_path); |
694 | $self->delete_temp_dir($temp_dir_path); |
| 675 | } |
695 | } |
| 676 | |
696 | |
| 677 | warn "Preserved temporary files in directory '$temp_dir_path'.\n" if $PreserveTempFiles; |
697 | warn "Preserved temporary files in directory '$temp_dir_path'.\n" if $PreserveTempFiles; |
| … | |
… | |
| 886 | $self->add_errors("Can't generate hardcopy for set '".CGI::code(CGI::escapeHTML($setID)) |
906 | $self->add_errors("Can't generate hardcopy for set '".CGI::code(CGI::escapeHTML($setID)) |
| 887 | ."' for user '".CGI::code(CGI::escapeHTML($TargetUser->user_id)) |
907 | ."' for user '".CGI::code(CGI::escapeHTML($TargetUser->user_id)) |
| 888 | ."' -- set is not yet open."); |
908 | ."' -- set is not yet open."); |
| 889 | return; |
909 | return; |
| 890 | } |
910 | } |
| 891 | if (not $MergedSet->published and not $authz->hasPermissions($userID, "view_unpublished_sets")) { |
911 | if (not $MergedSet->visible and not $authz->hasPermissions($userID, "view_hidden_sets")) { |
| 892 | $self->addbadmessage("Can't generate hardcopy for set '".CGI::code(CGI::escapeHTML($setID)) |
912 | $self->addbadmessage("Can't generate hardcopy for set '".CGI::code(CGI::escapeHTML($setID)) |
| 893 | ."' for user '".CGI::code(CGI::escapeHTML($TargetUser->user_id)) |
913 | ."' for user '".CGI::code(CGI::escapeHTML($TargetUser->user_id)) |
| 894 | ."' -- set has not been published."); |
914 | ."' -- set is not visible to students."); |
| 895 | return; |
915 | return; |
| 896 | } |
916 | } |
| 897 | |
917 | |
| 898 | # get snippets |
918 | # get snippets |
| 899 | my $header = $MergedSet->hardcopy_header |
919 | my $header = $MergedSet->hardcopy_header |