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