#!/usr/bin/perl use POSIX qw(strftime); use lib '/etc/lilalo'; use l3config; use utf8; no warnings; our @Command_Lines; our @Command_Lines_Index; our %Commands_Description; our %Args_Description; our %Sessions; our %Uploads; our $debug_output=""; # Используйте эту переменную, если нужно передать отладочную информацию our %filter; our $filter_url; sub init_filter; our %Files; # vvv Инициализация переменных выполняется процедурой init_variables our @Day_Name; our @Month_Name; our @Of_Month_Name; our %Search_Machines; our %Elements_Visibility; # ^^^ our $First_Command=$0; our $Last_Command=40; our %Stat; our %frequency_of_command; # Сколько раз в журнале встречается какая команда our $table_number=1; our %tigra_hints; my %mywi_cache_for; # Кэш для экономии обращений к mywi sub count_frequency_of_commands; sub make_comment; sub make_new_entries_table; sub load_command_lines_from_xml; sub load_sessions_from_xml; sub load_uploads; sub sort_command_lines; sub process_command_lines; sub init_variables; sub main; sub collapse_list($); sub minutes_passed; sub print_all_txt; sub print_all_html; sub print_edit_all_html; sub print_command_lines_html; sub print_command_lines_txt; sub print_files_html; sub print_stat_html; sub print_header_html; sub print_header2_html; sub print_footer_html; sub tigra_hints_generate; #### mywi # sub mywi_init; sub load_mywitxt; sub mywi_process_query($); # sub add_to_log($$); sub parse_query; sub search_in_txt; sub add_to_log($$); sub mywi_guess($); # main(); sub main { $| = 1; init_variables(); init_config(); $Config{frontend_ico_path}=$Config{frontend_css}; $Config{frontend_ico_path}=~s@/[^/]*$@@; init_filter(); mywi_init(); load_command_lines_from_xml($Config{"backend_datafile"}); load_uploads($Config{"upload_dir"}); load_sessions_from_xml($Config{"backend_datafile"}); sort_command_lines; process_command_lines; if (defined($filter{action}) && $filter{action} eq "edit") { print_edit_all_html($Config{"output"}); } else { print_all_html($Config{"output"}); } } sub init_filter { if ($Config{filter}) { # Инициализация фильтра for (split /;;/,$Config{filter}) { my ($var, $val) = split /::/; $filter{$var} = $val || ""; } } $filter_url = join (";;", map("$_::$filter{$_}", keys %filter)); } # extract_from_cline # In: $what = commands | args # Out: return ссылка на хэш, содержащий результаты разбора # команда => позиция # Разобрать командную строку $_[1] и возвратить хэш, содержащий # номер первого появление команды в строке: # команда => первая позиция sub extract_from_cline { my $what = $_[0]; my $cline = $_[1]; my @lists = split /\;/, $cline; my @command_lines = (); for my $command_list (@lists) { push(@command_lines, split(/\|/, $command_list)); } my %position_of_command; my %position_of_arg; my $i=0; for my $command_line (@command_lines) { $command_line =~ s@^\s*@@; $command_line =~ /\s*(\S+)\s*(.*)/; if ($1 && $1 eq "sudo" ) { $position_of_command{"$1"}=$i++; $command_line =~ s/\s*sudo\s+//; } if ($command_line !~ m@^\s*\S*/etc/@) { $command_line =~ s@^\s*\S+/@@; } $command_line =~ /\s*(\S+)\s*(.*)/; my $command = $1; my $args = $2; if ($command && !defined $position_of_command{"$command"}) { $position_of_command{"$command"}=$i++; }; if ($args) { my @args = split (/\s+/, $args); for my $a (@args) { $position_of_arg{"$a"}=$i++ if !defined $position_of_arg{"$a"}; }; } } if ($what eq "commands") { return \%position_of_command; } else { return \%position_of_arg; } } sub mywrap($) { return '
$_
", split (/-\n/, $note_html))); $note_html =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@$1@g; $note_html =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@$1@g; $$cl->{"note_html"} = $note_html; } } } =cut Процедура print_command_lines выводит HTML-представление разобранного lab-скрипта. Разобранный lab-скрипт должен находиться в массиве @Command_Lines =cut sub print_command_lines_html { my @toc; # Оглавление my $note_number=0; my $result = q(); my $this_day_resut = q(); my $cl; my $last_tty=""; my $last_session=""; my $last_day=q(); my $last_wday=q(); my $first_command_of_the_day_unix_time=q(); my $human_readable_time=q(); my $in_range=0; my $current_command=0; my @known_commands; $Stat{LastCommand} ||= 0; $Stat{TotalCommands} ||= 0; $Stat{ErrorCommands} ||= 0; $Stat{MistypedCommands} ||= 0; my %new_entries_of = ( "1 1" => "программы пользователя", "2 8" => "программы администратора", "3 sh" => "команды интерпретатора", "4 script"=> "скрипты", ); COMMAND_LINE: for my $k (@Command_Lines_Index) { my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]]; next unless $cl; my $next_cl=$Command_Lines[$Command_Lines_Index[$current_command]]; next if $current_command < $Config{"start_from_command"}; last if $current_command > $Config{"start_from_command"} + $Config{"commands_to_show_at_a_go"}; next if $Config{"command_id"} && $cl->{id} ne $Config{"command_id"}; # Пропускаем строки, которые противоречат фильтру # Если у нас недостаточно информации о том, подходит строка под фильтр или нет, # мы её выводим for my $filter_key (keys %filter) { next COMMAND_LINE if defined($cl->{local_session_id}) && defined($Sessions{$cl->{local_session_id}}->{$filter_key}) && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key}; } # Набираем статистику # Хэш %Stat $Stat{FirstCommand} = $cl->{time} unless $Stat{FirstCommand}; if ($cl->{time} - $Stat{LastCommand} < $Config{stat_inactivity_interval}) { $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand} } my $seconds_since_last_command = $cl->{time} - $Stat{LastCommand}; if ($Stat{LastCommand} > $cl->{time}) { $result .= "Время идёт вспять\n \n";
$this_day_result .= " \n"; # cblock
$this_day_result .= "" . $cline ; #cline
$this_day_result .= "\n"
. "\n"
. "\n" if ($cl->{"err"} and not $cl->{tab_seq} and not $cl->{break});
$this_day_result .= "\n"
. "\n"
. "\n" if $cl->{tab_seq};
$this_day_result .= "\n"
. "\n"
. "\n" if ($cl->{break} and not $cl->{tab_seq});
$this_day_result .= " \n"; #cline
# OUTPUT
my $last_command = $cl->{"last_command"};
if (!(
$Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) ||
$Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) ||
$Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}})
)) {
$this_day_result .= "\n" . $cl->{short_output} . "\n"; } # DIFF $this_day_result .= " ".$cl->{"diff"}."" if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}); # SHOT #$this_day_result .= join(".", keys(%Uploads)); #$this_day_result .= "PRIVET"; for $t (sort { $a <=> $b } keys %{ $Uploads{$cl->{"local_session_id"}} }) { if (($t >= $cl->{"time"} and $t < $next_cl->{"time"}) or ($t >= $cl->{"time"} and not defined($next_cl))) { my @shots=split(/\s+/, $Uploads{$cl->{"local_session_id"}}{$t}); for my $shot (@shots) { $this_day_result .= " " } } } # Временно заблокировано # $this_day_result .= "" # if ( $Config{"show_screenshots"} =~ /^y/i && $cl->{"screenshot"}); #NOTES if ( $Config{"show_notes"} =~ /^y/i && $cl->{"note"}) { my $note=$cl->{"note"}; $note =~ s/\n/ \n/msg; if (not $note =~ s@(http:[a-zA-Z.0-9/_?%-]*)@$1@g) { $note =~ s@(www\.[a-zA-Z.0-9/_?%-]*)@$1@g; }; $this_day_result .= " ";
$this_day_result .= " \n";
}
# Вывод очередной команды окончен
$this_day_result .= "".$cl->{note_title}." " if $cl->{note_title};
$this_day_result .= "".$note." ";
$this_day_result .= " |
$table_caption | " . "|
Команда | Описание | " . "
Внимательно правим, потом сохраняем
" ."Строки, начинающиеся символами #l3: можно трогать, только если точно знаешь, что делаешь
" ."" .""; if ($output_filename eq "-") { print $result; } else { open(OUT, ">", $output_filename) or die "Can't open $output_filename for writing\n"; binmode ":utf8"; print OUT "$result"; close(OUT); } } ############# # print_all_txt # # Вывести страницу с текстовым представлением журнала для редактирования # # In: $_[0] output_filename # Out: sub print_all_txt { my $result; $result = print_command_lines_txt; $result =~ s/>/>/g; $result =~ s/</:utf8", $output_filename) or die "Can't open $output_filename for writing\n"; print OUT "$result"; close(OUT); } } ############# # print_all_html # # # # In: $_[0] output_filename # Out: sub print_all_html { my $output_filename=$_[0]; my $result; my ($command_lines,$toc) = print_command_lines_html; my $files_section = print_files_html; $result = $debug_output; $result .= print_header_html($toc); if ($Config{"command_id"}) { $result .= $command_lines; } else { $result .= print_header2_html($toc); $result.= "";
$result .= "Выполнил $course_student
" if $course_student;
$result .= "Проверил $course_trainer
" if $course_trainer;
$result .= "Курс " if $course_name
|| $course_code
|| $course_date;
$result .= "$course_name " if $course_name;
$result .= "($course_code)" if $course_code;
$result .= ", $course_date
" if $course_date;
$result .= "Учебный центр $course_center
" if $course_center;
$result .= "Фильтр ".join(" ", map("$filter{$_}=$_", keys %filter))."
" if %filter;
$result .= "
Содержание
|