#!/usr/bin/perl # gitweb - simple web interface to track changes in git repositories # # (C) 2005-2006, Kay Sievers # (C) 2005, Christian Gierke # # This program is licensed under the GPLv2 use strict; use warnings; use CGI qw(:standard :escapeHTML -nosticky); use CGI::Util qw(unescape); use CGI::Carp qw(fatalsToBrowser); use Encode; use Fcntl ':mode'; binmode STDOUT, ':utf8'; my $cgi = new CGI; my $version = "266"; my $my_url = $cgi->url(); my $my_uri = $cgi->url(-absolute => 1); my $rss_link = ""; # absolute fs-path which will be prepended to the project path my $projectroot = "/data/polvi/git/"; # location of the git-core binaries my $gitbin = "/usr/bin"; # location for temporary files needed for diffs my $git_temp = "/tmp/gitweb"; # target of the home link on top of all pages my $home_link = $my_uri; # html text to include at home page my $home_text = "indextext.html"; # source of projects list #my $projects_list = $projectroot; my $projects_list = "index/index.aux"; # input validation and dispatch my $action = $cgi->param('a'); if (defined $action) { if ($action =~ m/[^0-9a-zA-Z\.\-_]/) { undef $action; die_error(undef, "Invalid action parameter."); } if ($action eq "git-logo.png") { # git_logo(); alex_logo(); exit; } elsif ($action eq "opml") { git_opml(); exit; } } my $order = $cgi->param('o'); if (defined $order) { if ($order =~ m/[^0-9a-zA-Z_]/) { undef $order; die_error(undef, "Invalid order parameter."); } } my $project = $cgi->param('p'); if (defined $project) { $project = validate_input($project); if (!defined($project)) { die_error(undef, "Invalid project parameter."); } if (!(-d "$projectroot/$project")) { undef $project; die_error(undef, "No such directory."); } if (!(-e "$projectroot/$project/HEAD")) { undef $project; die_error(undef, "No such project."); } $rss_link = ""; $ENV{'GIT_DIR'} = "$projectroot/$project"; } else { git_project_list(); exit; } my $file_name = $cgi->param('f'); if (defined $file_name) { $file_name = validate_input($file_name); if (!defined($file_name)) { die_error(undef, "Invalid file parameter."); } } my $hash = $cgi->param('h'); if (defined $hash) { $hash = validate_input($hash); if (!defined($hash)) { die_error(undef, "Invalid hash parameter."); } } my $hash_parent = $cgi->param('hp'); if (defined $hash_parent) { $hash_parent = validate_input($hash_parent); if (!defined($hash_parent)) { die_error(undef, "Invalid hash parent parameter."); } } my $hash_base = $cgi->param('hb'); if (defined $hash_base) { $hash_base = validate_input($hash_base); if (!defined($hash_base)) { die_error(undef, "Invalid hash base parameter."); } } my $page = $cgi->param('pg'); if (defined $page) { if ($page =~ m/[^0-9]$/) { undef $page; die_error(undef, "Invalid page parameter."); } } my $searchtext = $cgi->param('s'); if (defined $searchtext) { if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { undef $searchtext; die_error(undef, "Invalid search parameter."); } $searchtext = quotemeta $searchtext; } sub validate_input { my $input = shift; if ($input =~ m/^[0-9a-fA-F]{40}$/) { return $input; } if ($input =~ m/(^|\/)(|\.|\.\.)($|\/)/) { return undef; } if ($input =~ m/[^a-zA-Z0-9_\x80-\xff\ \t\.\/\-\+\#\~\%]/) { return undef; } return $input; } if (!defined $action || $action eq "summary") { git_summary(); exit; } elsif ($action eq "heads") { git_heads(); exit; } elsif ($action eq "tags") { git_tags(); exit; } elsif ($action eq "blob") { git_blob(); exit; } elsif ($action eq "blob_plain") { git_blob_plain(); exit; } elsif ($action eq "tree") { git_tree(); exit; } elsif ($action eq "rss") { git_rss(); exit; } elsif ($action eq "commit") { git_commit(); exit; } elsif ($action eq "log") { git_log(); exit; } elsif ($action eq "blobdiff") { git_blobdiff(); exit; } elsif ($action eq "blobdiff_plain") { git_blobdiff_plain(); exit; } elsif ($action eq "commitdiff") { git_commitdiff(); exit; } elsif ($action eq "commitdiff_plain") { git_commitdiff_plain(); exit; } elsif ($action eq "history") { git_history(); exit; } elsif ($action eq "search") { git_search(); exit; } elsif ($action eq "shortlog") { git_shortlog(); exit; } elsif ($action eq "tag") { git_tag(); exit; } else { undef $action; die_error(undef, "Unknown action."); exit; } # quote unsafe chars, but keep the slash, even when it's not # correct, but quoted slashes look too horrible in bookmarks sub esc_param { my $str = shift; $str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&=])/sprintf("%%%02X", ord($1))/eg; $str =~ s/\+/%2B/g; $str =~ s/ /\+/g; return $str; } # replace invalid utf8 character with SUBSTITUTION sequence sub esc_html { my $str = shift; $str = decode("utf8", $str, Encode::FB_DEFAULT); $str = escapeHTML($str); return $str; } # git may return quoted and escaped filenames sub unquote { my $str = shift; if ($str =~ m/^"(.*)"$/) { $str = $1; $str =~ s/\\([0-7]{1,3})/chr(oct($1))/eg; } return $str; } sub git_header_html { my $status = shift || "200 OK"; my $expires = shift; my $title = "git"; if (defined $project) { $title .= " - $project"; if (defined $action) { $title .= "/$action"; } } print $cgi->header(-type=>'text/html', -charset => 'utf-8', -status=> $status, -expires => $expires); print < $title $rss_link EOF print "
\n" . "" . "\"git\"" . "\n"; print $cgi->a({-href => esc_param($home_link)}, "git") . " / "; if (defined $project) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, esc_html($project)); if (defined $action) { print " / $action"; } print "\n"; if (!defined $searchtext) { $searchtext = ""; } my $search_hash; if (defined $hash) { $search_hash = $hash; } else { $search_hash = "HEAD"; } $cgi->param("a", "search"); $cgi->param("h", $search_hash); print $cgi->startform(-method => "get", -action => $my_uri) . "
\n" . $cgi->hidden(-name => "p") . "\n" . $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . "
" . $cgi->end_form() . "\n"; } print "
\n"; } sub git_footer_html { print "
\n"; if (defined $project) { my $descr = git_read_description($project); if (defined $descr) { print "\n"; } print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=rss"), -class => "rss_logo"}, "RSS") . "\n"; } else { print $cgi->a({-href => "$my_uri?" . esc_param("a=opml"), -class => "rss_logo"}, "OPML") . "\n"; } print "
\n" . "\n" . ""; } sub die_error { my $status = shift || "403 Forbidden"; my $error = shift || "Malformed query, file missing or permission denied"; git_header_html($status); print "
\n" . "

\n" . "$status - $error\n" . "
\n" . "
\n"; git_footer_html(); exit; } sub git_get_type { my $hash = shift; open my $fd, "-|", "$gitbin/git-cat-file -t $hash" or return; my $type = <$fd>; close $fd or return; chomp $type; return $type; } sub git_read_head { my $project = shift; my $oENV = $ENV{'GIT_DIR'}; my $retval = undef; $ENV{'GIT_DIR'} = "$projectroot/$project"; if (open my $fd, "-|", "$gitbin/git-rev-parse", "--verify", "HEAD") { my $head = <$fd>; close $fd; if (defined $head && $head =~ /^([0-9a-fA-F]{40})$/) { $retval = $1; } } if (defined $oENV) { $ENV{'GIT_DIR'} = $oENV; } return $retval; } sub git_read_hash { my $path = shift; open my $fd, "$projectroot/$path" or return undef; my $head = <$fd>; close $fd; chomp $head; if ($head =~ m/^[0-9a-fA-F]{40}$/) { return $head; } } sub git_read_description { my $path = shift; open my $fd, "$projectroot/$path/description" or return undef; my $descr = <$fd>; close $fd; chomp $descr; return $descr; } sub git_read_tag { my $tag_id = shift; my %tag; my @comment; open my $fd, "-|", "$gitbin/git-cat-file tag $tag_id" or return; $tag{'id'} = $tag_id; while (my $line = <$fd>) { chomp $line; if ($line =~ m/^object ([0-9a-fA-F]{40})$/) { $tag{'object'} = $1; } elsif ($line =~ m/^type (.+)$/) { $tag{'type'} = $1; } elsif ($line =~ m/^tag (.+)$/) { $tag{'name'} = $1; } elsif ($line =~ m/^tagger (.*) ([0-9]+) (.*)$/) { $tag{'author'} = $1; $tag{'epoch'} = $2; $tag{'tz'} = $3; } elsif ($line =~ m/--BEGIN/) { push @comment, $line; last; } elsif ($line eq "") { last; } } push @comment, <$fd>; $tag{'comment'} = \@comment; close $fd or return; if (!defined $tag{'name'}) { return }; return %tag } sub age_string { my $age = shift; my $age_str; if ($age > 60*60*24*365*2) { $age_str = (int $age/60/60/24/365); $age_str .= " years ago"; } elsif ($age > 60*60*24*(365/12)*2) { $age_str = int $age/60/60/24/(365/12); $age_str .= " months ago"; } elsif ($age > 60*60*24*7*2) { $age_str = int $age/60/60/24/7; $age_str .= " weeks ago"; } elsif ($age > 60*60*24*2) { $age_str = int $age/60/60/24; $age_str .= " days ago"; } elsif ($age > 60*60*2) { $age_str = int $age/60/60; $age_str .= " hours ago"; } elsif ($age > 60*2) { $age_str = int $age/60; $age_str .= " min ago"; } elsif ($age > 2) { $age_str = int $age; $age_str .= " sec ago"; } else { $age_str .= " right now"; } return $age_str; } sub git_read_commit { my $commit_id = shift; my $commit_text = shift; my @commit_lines; my %co; if (defined $commit_text) { @commit_lines = @$commit_text; } else { $/ = "\0"; open my $fd, "-|", "$gitbin/git-rev-list --header --parents --max-count=1 $commit_id" or return; @commit_lines = split '\n', <$fd>; close $fd or return; $/ = "\n"; pop @commit_lines; } my $header = shift @commit_lines; if (!($header =~ m/^[0-9a-fA-F]{40}/)) { return; } ($co{'id'}, my @parents) = split ' ', $header; $co{'parents'} = \@parents; $co{'parent'} = $parents[0]; while (my $line = shift @commit_lines) { last if $line eq "\n"; if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) { $co{'tree'} = $1; } elsif ($line =~ m/^author (.*) ([0-9]+) (.*)$/) { $co{'author'} = $1; $co{'author_epoch'} = $2; $co{'author_tz'} = $3; if ($co{'author'} =~ m/^([^<]+) 50) { $title =~ s/^Automatic //; $title =~ s/^merge (of|with) /Merge ... /i; if (length($title) > 50) { $title =~ s/(http|rsync):\/\///; } if (length($title) > 50) { $title =~ s/(master|www|rsync)\.//; } if (length($title) > 50) { $title =~ s/kernel.org:?//; } if (length($title) > 50) { $title =~ s/\/pub\/scm//; } } $co{'title_short'} = chop_str($title, 50, 5); last; } } # remove added spaces foreach my $line (@commit_lines) { $line =~ s/^ //; } $co{'comment'} = \@commit_lines; my $age = time - $co{'committer_epoch'}; $co{'age'} = $age; $co{'age_string'} = age_string($age); my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($co{'committer_epoch'}); if ($age > 60*60*24*7*2) { $co{'age_string_date'} = sprintf "%4i-%02u-%02i", 1900 + $year, $mon+1, $mday; $co{'age_string_age'} = $co{'age_string'}; } else { $co{'age_string_date'} = $co{'age_string'}; $co{'age_string_age'} = sprintf "%4i-%02u-%02i", 1900 + $year, $mon+1, $mday; } return %co; } sub git_diff_print { my $from = shift; my $from_name = shift; my $to = shift; my $to_name = shift; my $format = shift || "html"; my $from_tmp = "/dev/null"; my $to_tmp = "/dev/null"; my $pid = $$; # create tmp from-file if (defined $from) { $from_tmp = "$git_temp/gitweb_" . $$ . "_from"; open my $fd2, "> $from_tmp"; open my $fd, "-|", "$gitbin/git-cat-file blob $from"; my @file = <$fd>; print $fd2 @file; close $fd2; close $fd; } # create tmp to-file if (defined $to) { $to_tmp = "$git_temp/gitweb_" . $$ . "_to"; open my $fd2, "> $to_tmp"; open my $fd, "-|", "$gitbin/git-cat-file blob $to"; my @file = <$fd>; print $fd2 @file; close $fd2; close $fd; } open my $fd, "-|", "/usr/bin/diff -u -p -L \'$from_name\' -L \'$to_name\' $from_tmp $to_tmp"; if ($format eq "plain") { undef $/; print <$fd>; $/ = "\n"; } else { while (my $line = <$fd>) { chomp($line); my $char = substr($line, 0, 1); my $color = ""; if ($char eq '+') { $color = " style=\"color:#008800;\""; } elsif ($char eq "-") { $color = " style=\"color:#cc0000;\""; } elsif ($char eq "@") { $color = " style=\"color:#990099;\""; } elsif ($char eq "\\") { # skip errors next; } while ((my $pos = index($line, "\t")) != -1) { if (my $count = (8 - (($pos-1) % 8))) { my $spaces = ' ' x $count; $line =~ s/\t/$spaces/; } } print "
" . esc_html($line) . "
\n"; } } close $fd; if (defined $from) { unlink($from_tmp); } if (defined $to) { unlink($to_tmp); } } sub mode_str { my $mode = oct shift; if (S_ISDIR($mode & S_IFMT)) { return 'drwxr-xr-x'; } elsif (S_ISLNK($mode)) { return 'lrwxrwxrwx'; } elsif (S_ISREG($mode)) { # git cares only about the executable bit if ($mode & S_IXUSR) { return '-rwxr-xr-x'; } else { return '-rw-r--r--'; }; } else { return '----------'; } } sub chop_str { my $str = shift; my $len = shift; my $add_len = shift || 10; # allow only $len chars, but don't cut a word if it would fit in $add_len # if it doesn't fit, cut it if it's still longer than the dots we would add $str =~ m/^(.{0,$len}[^ \/\-_:\.@]{0,$add_len})(.*)/; my $body = $1; my $tail = $2; if (length($tail) > 4) { $tail = " ..."; } return "$body$tail"; } sub file_type { my $mode = oct shift; if (S_ISDIR($mode & S_IFMT)) { return "directory"; } elsif (S_ISLNK($mode)) { return "symlink"; } elsif (S_ISREG($mode)) { return "file"; } else { return "unknown"; } } sub format_log_line_html { my $line = shift; $line = esc_html($line); $line =~ s/ / /g; if ($line =~ m/([0-9a-fA-F]{40})/) { my $hash_text = $1; if (git_get_type($hash_text) eq "commit") { my $link = $cgi->a({-class => "text", -href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_text")}, $hash_text); $line =~ s/$hash_text/$link/; } } return $line; } sub date_str { my $epoch = shift; my $tz = shift || "-0000"; my %date; my @months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); my @days = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch); $date{'hour'} = $hour; $date{'minute'} = $min; $date{'mday'} = $mday; $date{'day'} = $days[$wday]; $date{'month'} = $months[$mon]; $date{'rfc2822'} = sprintf "%s, %d %s %4d %02d:%02d:%02d +0000", $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec; $date{'mday-time'} = sprintf "%d %s %02d:%02d", $mday, $months[$mon], $hour ,$min; $tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/; my $local = $epoch + ((int $1 + ($2/60)) * 3600); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local); $date{'hour_local'} = $hour; $date{'minute_local'} = $min; $date{'tz_local'} = $tz; return %date; } # git-logo (cached in browser for one day) sub git_logo { binmode STDOUT, ':raw'; print $cgi->header(-type => 'image/png', -expires => '+1d'); # cat git-logo.png | hexdump -e '16/1 " %02x" "\n"' | sed 's/ /\\x/g' print "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" . "\x00\x00\x00\x48\x00\x00\x00\x1b\x04\x03\x00\x00\x00\x2d\xd9\xd4" . "\x2d\x00\x00\x00\x18\x50\x4c\x54\x45\xff\xff\xff\x60\x60\x5d\xb0" . "\xaf\xaa\x00\x80\x00\xce\xcd\xc7\xc0\x00\x00\xe8\xe8\xe6\xf7\xf7" . "\xf6\x95\x0c\xa7\x47\x00\x00\x00\x73\x49\x44\x41\x54\x28\xcf\x63" . "\x48\x67\x20\x04\x4a\x5c\x18\x0a\x08\x2a\x62\x53\x61\x20\x02\x08" . "\x0d\x69\x45\xac\xa1\xa1\x01\x30\x0c\x93\x60\x36\x26\x52\x91\xb1" . "\x01\x11\xd6\xe1\x55\x64\x6c\x6c\xcc\x6c\x6c\x0c\xa2\x0c\x70\x2a" . "\x62\x06\x2a\xc1\x62\x1d\xb3\x01\x02\x53\xa4\x08\xe8\x00\x03\x18" . "\x26\x56\x11\xd4\xe1\x20\x97\x1b\xe0\xb4\x0e\x35\x24\x71\x29\x82" . "\x99\x30\xb8\x93\x0a\x11\xb9\x45\x88\xc1\x8d\xa0\xa2\x44\x21\x06" . "\x27\x41\x82\x40\x85\xc1\x45\x89\x20\x70\x01\x00\xa4\x3d\x21\xc5" . "\x12\x1c\x9a\xfe\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82"; } sub alex_logo { binmode STDOUT, ':raw'; print $cgi->header(-type => 'image/png', -expires => '+1d'); # cat git-logo.png | hexdump -e '16/1 " %02x" "\n"' | sed 's/ /\\x/g' print "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" . "\x00\x00\x00\x5f\x00\x00\x00\x6e\x08\x06\x00\x00\x00\x41\x6a\xcf" . "\xfd\x00\x00\x00\x06\x62\x4b\x47\x44\x00\x00\x00\x00\x00\x00\xf9" . "\x43\xbb\x7f\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00" . "\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45" . "\x07\xd6\x08\x18\x13\x26\x1d\x13\xd6\x93\xf7\x00\x00\x20\x00\x49" . "\x44\x41\x54\x78\xda\xec\xbd\x79\xb8\xa5\xd9\x55\xde\xf7\x5b\x7b" . "\xf8\x86\x33\xdd\xb9\xe6\xae\xea\xea\xea\x79\x56\x77\xab\x5b\xea" . "\xd6\xd0\x42\x13\x08\x21\x05\x49\xc6\x24\xf8\x81\x80\x45\x08\xc4" . "\x61\x88\x9d\x10\x9b\xd8\xb2\x1f\x06\x87\x90\x98\x29\x18\x6c\x0b" . "\x30\x90\x04\x43\xac\x78\x08\x60\xd0\xdc\x48\x08\x4d\x2d\x24\xb5" . "\x7a\x54\x0f\xd5\xd5\xd5\x35\xde\xba\xd3\xb9\xe7\x9c\xef\xfb\xf6" . "\x94\x3f\xf6\xa9\x6a\x04\xb2\x6c\x1e\x8c\xd4\x4a\xb3\x9f\xe7\xfe" . "\xd1\x55\xd5\x75\x6f\xad\xbd\xf7\xda\xef\x7a\xd7\xbb\xde\x23\x3c" . "\x8f\xd6\xd9\xb3\xe7\x07\x7b\xf7\xae\xed\x7e\xcf\x77\x7f\xef\x0f" . "\x15\xbd\xea\x47\x86\x0b\x0b\x8c\x77\x27\xdc\x7d\xcf\x2b\xf8\xd8" . "\xc7\x3e\x4e\x70\x8e\x4f\xdf\xff\x71\x48\x8e\xaa\x5f\xb1\x7f\xe5" . "\x10\x4f\x3e\xfd\x14\xaf\xfb\xba\xaf\xe7\x95\xaf\x7e\x1d\xef\xfb" . "\x9d\xf7\x32\xac\x8b\xdf\x38\x72\xf4\xc0\x7f\xf3\xd6\xb7\xbd\xe9" . "\x02\xcf\xf3\xa5\x9f\x4f\x3f\x4c\xdb\xb8\xeb\x5e\xf7\xda\xaf\xfd" . "\xf1\xb3\x67\xcf\x7e\xff\xc9\x67\x9f\x95\x04\x58\x6b\xf8\xa3\x3f" . "\xfa\x14\x0f\x3d\xfc\x10\xdb\x5b\xdb\xd4\x65\x41\x08\x81\x59\xd3" . "\x52\xd8\x82\xb5\x3d\x7b\xf8\xec\xe7\x1e\xe4\xc0\xc1\x23\x5c\x7f" . "\xe3\x8d\x5c\x73\xdd\xd5\x37\x2e\x2d\x2e\x7c\xeb\x4b\xee\xba\xdb" . "\xbe\xf4\xae\x97\x7d\xe6\xbd\xef\xff\xbd\xee\x2f\x83\xff\x25\xd6" . "\x77\xbe\xfd\x7b\xae\xba\xf5\x45\xb7\xff\x54\x4c\xf1\x27\xd7\xd7" . "\xcf\xdf\x71\xfe\xc2\xba\x9c\x39\x7d\x9a\xad\xad\x6d\x3e\xf9\xc9" . "\x8f\x73\xfa\xcc\x49\x96\x97\x16\x08\x21\x70\xe1\xfc\x39\x56\x56" . "\x96\x78\xfc\xc9\xc7\xd9\x1e\xef\xb0\x77\xff\x5e\xca\xba\x62\xcf" . "\x9e\x7d\x0c\x16\x86\x28\x6b\x38\x7f\xee\xc2\xe0\x86\xeb\xae\x7f" . "\xcd\xf6\x78\xeb\xad\x2f\xba\xfd\xc5\x0f\x7c\xf0\x03\xef\x7b\xfa" . "\xf9\x18\x7c\xf9\x4a\x7e\xf3\x9f\xf9\x99\x9f\xab\x7e\xfe\x1f\xff" . "\x93\x1f\x2c\xcb\xf2\x1d\xb7\xbc\xe8\x16\x09\xc1\x73\x7e\xfd\x1c" . "\xdb\xdb\x9b\x2c\x2e\xac\x72\xf6\xec\x39\xce\x5d\x38\xc3\xf6\xce" . "\x05\xfa\xc3\x01\x60\x08\x6d\x4b\xbf\xd7\x23\xa4\xc8\x55\xd7\x5c" . "\xcf\xb4\x99\xf2\xec\xa9\x93\xec\xdf\x7f\x88\x6f\x7c\xeb\x37\xb3" . "\xbc\xbc\xc6\xe2\x68\x81\x6b\xae\x3c\xca\xf2\xd2\x90\xf1\x78\xfa" . "\x98\x51\xfa\xd5\xd7\x5e\x75\xf9\xc9\xbf\x0c\xfe\x7c\xbd\xf9\xcd" . "\x6f\xbb\xe3\xc4\x89\x93\xff\xf4\xc0\xc1\x83\x2f\x9a\xb5\x33\x56" . "\xf7\xad\x71\xfc\xf1\xc7\xd8\xdd\xde\xa0\x75\x53\x9a\x59\x47\xaf" . "\xb7\x40\x4a\x30\x6b\x27\xa0\x22\xdb\xdb\xdb\x48\x04\xa3\x0b\x92" . "\xd2\xd8\xa2\xc6\xd8\x84\xf3\x0d\xfb\xf6\x1e\xe2\xf0\x91\x2b\x79" . "\xcd\xeb\xbf\x8e\xd3\xa7\x4f\x73\xef\x2b\x5f\xce\x53\x4f\x3e\xc9" . "\x15\x97\x5f\xc5\x9e\xbd\x6b\x8f\x2d\x8e\x86\xaf\xb9\xf2\xc8\xc1" . "\x67\x5e\xf0\xc1\xff\xae\xef\xfa\x9e\xeb\x3e\xfc\xe1\x8f\x7c\x54" . "\x6b\x3d\xda\xb3\x6f\x0f\x5b\xe3\x0d\x26\xed\x94\x33\x27\x9f\x41" . "\xc5\x88\x56\xe0\x7d\x44\xd0\x24\x34\x4a\x0b\xa2\x12\x9d\x6b\x21" . "\x80\x31\x25\x3e\x26\x94\xb1\x28\x1d\x28\x4b\xcb\xea\xca\x3e\x12" . "\x16\x31\x9a\xde\x60\xc8\x75\xd7\x5c\xc7\xed\x2f\xba\x1d\xd1\x86" . "\x5b\x6f\xbd\x85\xb5\xe5\xc5\x5f\xb8\xfa\xe8\xa1\xef\x7e\xc1\x07" . "\xff\xa6\x5b\x6e\x7d\x97\xb5\xe5\x5b\x9c\x9b\xd1\xb6\x53\xa6\xcd" . "\x94\x9d\xe9\x0e\x12\x13\x56\x0c\xa1\xf3\x44\x1f\x50\x4a\x11\x81" . "\x90\x22\x22\x10\x53\xa2\xd0\x16\x6b\x0b\x7c\x4a\x20\x1a\xad\x61" . "\x61\x61\x84\x88\x66\x30\x5c\xa0\xf1\x9e\x63\x57\x5d\xcb\xb9\x53" . "\xe7\x39\x74\xf0\x32\xae\xbb\xf9\x06\x62\x80\xff\xec\x8d\x6f\x78" . "\xaa\xaa\x8b\xbf\x7a\xcb\xf5\x57\x7d\xe2\x05\x1b\xfc\x37\xbe\xe9" . "\x1b\x7a\xe3\xf1\xee\x78\xda\x34\xea\xcc\xe9\x67\x98\x4e\x26\x04" . "\x1f\xe8\x82\x23\xc4\x84\x11\x41\x07\x90\x98\x40\x25\x44\x41\x4c" . "\xe0\x43\x42\x6b\x8d\x15\x4d\x4c\x11\x31\x1a\x31\x1a\x10\x62\x8c" . "\xd4\x75\x4d\xaf\x3f\xc0\x94\x05\x4b\xcb\xab\x2c\x0c\x47\xf8\x00" . "\xaf\xfb\xfa\x37\xd3\xaf\xfa\x8c\x46\x03\xae\xb9\xf6\xaa\x4f\x23" . "\xf1\xee\xbb\x6e\xbe\x61\xf6\x82\x44\x3b\x91\x64\xa7\xb3\xe9\xff" . "\x54\x56\x25\x1b\x1b\xeb\xb8\xc6\xe1\xba\x44\x8a\x10\x42\x44\x29" . "\x41\x62\xc2\xa4\x44\x55\x18\x8c\x51\xc4\x98\x10\xa0\xd4\x9a\xc2" . "\x18\xb4\x08\x21\x04\x8c\xb5\x74\x9d\x23\x46\x88\x21\xa2\x44\xe8" . "\x9c\xe3\xc2\x85\xf3\x74\xed\x94\xc5\xc5\x05\x5a\x17\x59\x5d\x59" . "\xe5\xcc\xd9\x73\x2c\x2c\x2e\xee\xfb\xd4\x47\xfe\xd0\xbf\xfb\xdd" . "\xff\xee\x83\xcf\x87\xe0\xab\x2f\xfb\x55\x53\xbc\x44\x5b\xcd\xb9" . "\x73\x67\x08\x3e\xe2\x7d\x24\x04\x47\x70\x2d\x4a\x22\x31\x38\x90" . "\x44\x65\x85\xc5\xca\x32\x2a\x4b\x06\x65\xc1\xa0\xd4\x2c\x54\x9a" . "\x81\x81\x9e\x12\x6a\xa5\x90\xe0\xd1\x3a\x91\x52\x80\x04\x92\x04" . "\xdf\xb6\x10\x3d\xc6\x58\x66\xd3\x19\xcf\x1e\x7f\x9c\xc7\x1f\x7b" . "\x90\x85\xe1\x00\xad\x2c\x21\xea\xef\x3e\x79\x7e\xf6\xb2\x17\x64" . "\xf0\x47\xc3\xd1\xb7\x6d\xac\xaf\xd3\x4e\x67\x74\x4d\x8b\x73\x8e" . "\x18\x02\x29\xe5\xd3\xad\x80\xca\x6a\x86\xbd\x92\x52\x41\xdf\x28" . "\x96\x2a\xc3\x4a\x5d\xd2\xd3\x42\xa9\x12\x75\x21\xd4\x05\x98\xe8" . "\xa9\x80\xbe\xd1\xa8\xe8\x21\x78\x8c\xc0\xd2\x60\x48\x6a\x5b\x4a" . "\xa0\xd6\xc2\xe3\x8f\x3c\x44\xbf\x2e\xd0\x12\xb8\xfd\xae\xbb\xf6" . "\x3c\x7e\x62\xe3\xff\xf9\xb9\x5f\xfd\xc0\xf5\x2f\xa8\xe0\xdf\xfd" . "\xca\x7b\xf6\xee\xec\xec\xbc\x95\x10\x99\xee\x4e\xf0\x9d\x83\x98" . "\x48\x24\x44\x14\x02\x18\x25\x58\x25\x94\x46\x53\x28\x41\xc7\x40" . "\x2d\xd0\xd7\x8a\x9e\x36\xf4\x8c\xa6\x5f\x18\x2a\x2b\x54\x0a\x6a" . "\x12\x7d\xad\xa9\xb4\x22\xba\x06\x2b\xa0\xbd\x87\xb6\xa5\xdb\x19" . "\xa3\x7c\x64\x69\x30\xe4\xd3\x9f\xfc\x24\xcf\x9e\x38\xc1\x78\x7b" . "\x0b\x53\xf6\xd6\xea\xba\xfc\xbe\xaf\x74\xf0\xcd\x97\xf3\x9b\x6d" . "\x6e\x6d\x7d\x4d\x22\xf5\x95\x52\x04\xef\x09\x21\x90\x00\x51\x82" . "\x20\x28\x01\x45\xa2\x34\x1a\x25\x42\x8c\x79\x33\xb4\x40\x0a\x11" . "\x83\x41\x6b\x8b\x57\x89\x48\x42\x25\x4d\xf4\x11\x4f\x22\x29\x30" . "\x55\xc5\x70\xd8\x67\x34\xe8\x53\xd9\x8a\xc1\x60\x91\x9b\x6e\xb8" . "\x85\xd1\xf2\x32\xb6\x37\x60\x67\x73\x87\x61\xd9\xc3\x48\xc7\x70" . "\xb1\xb7\xfe\x82\x0a\x7e\x59\xd6\x7d\xd7\x75\x74\xbe\x21\x49\x24" . "\xa6\x7c\xea\x21\xa2\x92\x22\x62\x40\x2b\x4c\x8c\x28\x17\xd1\xca" . "\x90\x42\x42\x04\x20\x91\x92\xcf\x8f\x72\xd4\xf4\xa5\xa0\x34\x8e" . "\x4e\x29\x3c\x1a\x7c\x44\x69\xc5\xc2\xa0\x66\x75\x71\xc4\xa0\xb7" . "\xc4\xbe\x03\xc7\xb8\xfd\xae\x97\xd3\xcc\xc6\x9c\xdb\x3c\xc7\xe6" . "\xf6\x0e\x75\x6d\x88\x0f\x7d\x92\x03\x97\x1d\xfe\xd4\x0b\x2a\xf8" . "\x93\xf1\x2e\xae\xeb\x20\x41\x8a\xf3\x54\xa3\x04\x08\x48\x12\xb4" . "\xd1\x28\x81\x34\x4f\x88\x49\x12\x85\x32\x58\x49\x88\x4a\x97\x60" . "\x25\xc1\xa3\x94\x02\x12\x4a\x0b\x41\x84\xd2\x96\x24\x2d\x18\x1f" . "\x70\xb3\x86\x58\x46\x2e\xbf\xe2\x18\xab\x7b\xf7\xd1\x4e\x6a\x1e" . "\x78\xe0\xd3\xf9\x96\xad\x04\xf0\x2e\xb8\xd9\xf4\xf7\x5f\x50\xc1" . "\x8f\x31\xe2\x9d\xc3\x3b\x4f\x42\x10\x51\x20\x42\x8c\x01\x01\x42" . "\xe7\x10\xab\xd1\xca\x80\x22\xa7\x1e\xc0\xc5\x84\x35\x16\xa5\x34" . "\x3a\x86\x8c\x8f\x63\xc2\x28\x3d\xdf\x28\x43\xd2\x1a\x6b\x0b\x6a" . "\x53\xb2\x3c\xda\x83\x2a\x47\x14\xbd\x21\xa6\xac\xb1\x1a\x86\x83" . "\x21\x6d\xd7\x52\x1a\xcb\xb1\xcb\x0f\xbf\xef\x8e\x97\xde\x76\xfe" . "\x05\xf5\xe0\x1e\x3b\x7a\xf4\x43\xc1\x87\x59\xf0\x1e\x92\x42\x44" . "\x88\x31\x9f\x68\x42\x44\x47\xa8\xc5\x52\xdb\x12\x4d\x3e\xf9\x5e" . "\x12\x3b\x5d\xcb\x46\x33\x65\xbb\xed\x70\xca\x40\x51\x51\xf4\xfb" . "\x54\x65\x8f\xd2\xd6\x94\x45\x45\x65\x0b\x4a\x6d\x18\xd6\x43\x2e" . "\x3f\x72\x35\x57\x5d\x77\x2b\xe5\x60\x91\xa6\xe9\x50\xc6\xb2\xe7" . "\xe0\x7e\x54\x55\x30\x5a\x58\xa0\x2c\x8a\x9f\x7d\x3e\x40\xcd\x2f" . "\xeb\xc9\x7f\xf7\xef\xfe\xde\xa3\xfb\x0e\xef\x7f\x26\x91\xae\x86" . "\x84\x12\x85\xa4\x44\x12\xc1\x18\x4b\x25\xc2\x42\x5d\x53\x68\x85" . "\x4a\xe0\x7c\xa0\x8b\x91\x20\x06\x1f\x13\xbb\x6d\xc3\xa4\x73\x0c" . "\xcb\x92\xa5\xde\x80\xda\x56\xa8\x98\x40\x04\x31\xa0\xb4\x26\x7a" . "\x87\x22\x72\xf4\x8a\xcb\xb9\xfa\x96\x5b\x28\xea\x3e\x31\x35\x14" . "\xc3\x11\xfb\x44\x66\x47\x8e\x5d\xfe\xf6\xa5\xc5\xa5\xdf\x7e\x41" . "\xe2\xfc\x5e\x5d\xa1\x01\xab\xc0\x10\x51\x04\x62\xf2\x44\x01\x31" . "\x8a\x20\x89\x8e\x48\x10\x45\x4c\x82\xb5\x25\xb6\xa8\xb1\xb6\xa2" . "\xe8\xf5\xf1\xa2\x98\xb9\xc8\xac\xf3\xb8\x98\xd0\xb6\x40\x44\x50" . "\xca\x20\xa2\xe8\xbc\xe3\xe9\x13\x4f\x72\xea\xd9\xe3\xf8\x6e\x82" . "\xb5\x89\xa2\x32\x88\x82\x44\xfc\xad\xad\x9d\xad\x7f\x71\xe8\xd8" . "\xc1\xf4\x82\x3b\xf9\x00\x56\x34\x0b\x65\x8d\x88\xa6\x69\x1a\x66" . "\xae\x25\x20\x28\x05\xc6\x5a\xda\xe0\x49\x4a\xd1\x29\x21\xa8\x44" . "\xd7\x35\xf8\x98\xd3\x93\x88\x20\x02\xca\x08\x63\x1f\xb0\x49\xd0" . "\x92\x50\x56\x13\x95\x42\x69\x83\x43\x38\xbf\xb9\xc5\xa7\xee\xff" . "\x38\x9d\x24\xae\xbd\xe5\x45\x5c\x73\xcd\x95\xac\x9f\x3d\xc5\x85" . "\x8d\xf3\x4f\xff\xf5\xb7\x7f\x7b\x7c\xbe\x10\x6b\x5f\xf6\xe0\xf7" . "\x8b\x0a\x44\x43\x8c\x94\x45\x81\x56\x89\x89\xef\x30\x08\xa3\xba" . "\xc6\x08\x38\xdf\xb2\xd3\xcc\xe8\x62\x42\xeb\x92\xc1\x70\x94\x69" . "\x88\x94\x50\x02\x3e\x25\x76\xba\x8e\x66\x6b\x93\xa5\x51\xcd\xa8" . "\x5f\x51\x98\x1e\x0e\x43\x42\x11\x7c\xe2\xfc\xf1\xa7\x38\xb5\x7e" . "\x8e\x13\x27\x9e\xc1\x8d\x5f\xc9\xa9\x27\x9f\xa6\x1e\xd6\xcf\x27" . "\x46\xf9\xcb\x1f\xfc\xd9\xee\xee\x03\x7d\x5b\x5c\x2d\xde\x91\x8c" . "\x42\x0c\x48\x50\xc4\x26\x52\x8a\x60\x04\xaa\xb2\x24\x85\x40\xf2" . "\x8e\xd1\xb0\x8f\x24\x08\x21\x61\xcb\x8a\xc2\x2a\x7c\xd7\x51\xf5" . "\xfa\x4c\x76\xa7\x3c\xb3\x7e\x8e\x3d\x71\x89\xa5\xa5\x8a\xa4\xa1" . "\xe9\x3c\x2a\x69\x94\x29\x29\x6d\x45\xbb\xdb\x32\xd9\x9a\xd2\x35" . "\x8e\xd7\xbc\xf6\xb5\x0f\x3c\x9f\x82\xff\x65\xcf\xf9\x47\x8f\x1c" . "\xfe\x28\x24\x2c\x11\x1d\x3d\xc9\x77\xa8\x24\x58\x6b\x30\x0a\x74" . "\x0a\x98\xe8\xe9\x5b\xcd\xa0\x30\x48\x70\x90\x02\xfd\xba\x62\xa8" . "\x0a\x98\xec\x32\xd0\xb0\x38\x1a\x32\x1c\x2d\xe0\xbd\x67\x73\x7b" . "\xc2\x13\x27\x4e\x71\x7a\xe7\x02\xe3\xd4\x32\xf6\x1d\xc9\x94\x54" . "\xe5\x90\x42\x97\x14\x75\x9f\x3b\x5e\x72\xf7\xfa\xbe\xfd\x07\x3f" . "\x3e\xde\xdc\x92\x17\x6c\xf0\x3f\xff\xf9\x27\x7e\x3d\x28\x8d\x88" . "\x10\xda\x8e\xbe\x29\xe9\x17\x15\x85\x35\xf9\xe1\x44\x48\x11\x6a" . "\xa5\x19\x15\x16\xba\x8e\xba\x28\xe9\x57\x25\x85\x76\xf4\x6b\x45" . "\xe8\x26\x4c\x2f\x9c\xc7\x6d\x5d\x60\xdf\xa0\xcf\x2d\x57\x5d\xcb" . "\xd1\xcb\xae\xa0\xa6\xa4\x6f\x4b\x54\xa1\x59\x5e\x59\x41\x8b\xa1" . "\x69\xa7\xd8\xca\xf0\xc9\xcf\xdc\xbf\x1d\x8a\x74\x7a\xb8\xb4\x98" . "\x5e\xb0\xc1\x7f\xd9\x2b\xee\x3d\x17\x44\xfe\xa8\x4b\x99\x7f\x2f" . "\x8d\xc5\x88\xc2\x68\x85\x02\xb4\xd6\xb9\xda\x45\x51\x24\xc5\xb0" . "\x28\x71\xe3\x6d\x76\xd6\xcf\x32\x99\x6d\x93\x74\x24\x44\xc7\x64" . "\xbc\x8d\xee\x26\xac\xf6\x6a\xf6\x2e\xac\xf0\xea\x7b\x5f\xcf\x62" . "\x6f\x01\xb6\xa7\x0c\x82\x70\x70\x65\x3f\x2f\xba\xfd\x4e\x8e\x5e" . "\x7d\x15\xe3\xa6\xe1\xe1\x47\x1f\x3d\xf6\x2b\xbf\xf2\xab\x77\xbd" . "\xa0\xd3\xce\x3f\xfa\x85\x9f\x4f\xab\x6b\x2b\x3f\xaa\xaa\x32\x99" . "\xa2\xa4\xeb\x3a\xbc\x77\xa4\x14\x08\x31\xe0\x7d\x00\x20\xf8\x84" . "\x42\xa3\x63\xa4\xa7\x60\x60\x04\xeb\x23\x6e\x67\x82\xb4\x9e\x81" . "\x58\x16\x06\x35\x86\x48\x5d\x94\x5c\x73\xed\x0d\x5c\x76\xe5\x55" . "\x2c\x2c\x2e\xb1\xd8\x1f\xa2\x0a\xcb\xc2\x65\x07\x79\xc9\xbd\xaf" . "\x62\x7d\x73\x8b\xb3\x67\xce\xf9\x8f\xfd\xe1\xc7\x3e\xfc\x82\x0e" . "\xfe\xd2\x68\xe4\x3f\xf8\xa9\xcf\xbc\xeb\xe0\x15\x57\xff\x70\x3d" . "\x5c\x68\xca\xa2\x20\xf9\x8e\xe0\x3c\x21\x02\x62\x10\xa5\xd0\x06" . "\x8c\x49\x54\x46\x51\x2b\xa1\x44\xe8\x63\x19\x49\x8f\x45\xd3\xa7" . "\xa7\x0d\x46\x1b\x88\xc2\x6c\xba\xcd\x55\xd7\x1c\xe3\x1b\xde\xf8" . "\x56\xf6\x5d\x76\x39\xe5\x70\xc8\x60\x38\x60\xcf\xca\x0a\x3e\x86" . "\x69\xaf\x34\x0f\x5d\x75\xf4\xf2\x9f\xf8\xd0\x87\xee\x9b\xbe\xa0" . "\x83\x7f\x71\xfd\xeb\x0f\xfe\xfe\x3b\xfa\x4b\x4b\xd7\xeb\xe1\xe8" . "\x2c\xba\x40\x1b\x8d\x28\xc9\xfd\x59\x04\xd1\x99\x74\xd3\x4a\x51" . "\x14\x05\x55\x61\xa9\xab\xdc\x56\x14\x2d\xe8\xd2\x92\x94\x21\x59" . "\xcb\xf6\x78\x87\x67\x9f\x78\x14\xba\x19\x77\xde\x76\x27\xd7\x5f" . "\x7b\x23\x0b\x83\x05\x06\x65\xc5\xb1\xa3\x97\x3f\x30\x99\x8e\x7f" . "\xcb\x39\xf7\x3f\xf3\x3c\x5b\x5f\x51\xc5\xda\x63\xcf\x9e\xda\xd2" . "\x5a\x7f\x93\x12\x0e\x1a\xa3\x50\x08\x5a\x04\x89\x01\x51\x09\xa3" . "\x35\x46\x69\x14\x2a\xd3\xca\x29\x12\x42\x20\x0a\xb8\x14\xd8\x9d" . "\xcc\x28\xca\x9a\xe1\xc2\x22\x29\x09\xc1\x79\x06\xfd\x3e\xc3\xc1" . "\x02\x29\x45\x7c\xd7\x50\x0f\xaa\xcf\x5e\x76\xe4\xd0\x4f\xff\xcd" . "\x1f\xfc\xef\x9e\x77\xaa\x35\xf5\x95\xfe\x01\xa6\x4d\x83\x29\x4c" . "\x7e\x68\x05\x84\x34\xe7\xee\xe7\x4c\x7f\xcc\x2d\x46\x42\x84\xe0" . "\x10\x89\xcc\x9a\x29\x4d\xdb\x62\xb5\xa5\xac\xfa\xf8\xa8\xf9\xdc" . "\x03\x8f\xf0\xe4\x63\x8f\x70\xfa\x99\xe3\x18\x9d\x28\x35\x14\x12" . "\x71\xed\xec\xf1\xbb\x5f\xf6\x92\x4f\xf3\x3c\x5c\xe6\x2b\xf9\xcd" . "\x47\xbd\x6a\x10\x53\xbc\xc6\xa0\x91\x18\x80\x44\x94\x88\x2e\x20" . "\x86\x40\x8c\x8a\xa4\x34\x3e\x45\x7c\xf4\x90\x12\x11\xa1\x2e\x6b" . "\x94\xd6\x94\xa6\xa6\x57\xd4\xdc\xf1\xe2\xbb\x79\xc9\xbd\xaf\xe1" . "\xb1\x47\x1e\xe1\xb1\x87\x1e\xe0\xb2\xa3\x47\xd0\xa3\x3e\xe5\x70" . "\xc0\xea\x9e\x95\xfb\x79\x9e\xae\xaf\xe8\xc9\x7f\xd5\xab\x5f\xbd" . "\x32\x1c\x0e\x47\x4a\x69\x20\x4b\x44\x12\x89\x98\x12\x22\x9a\x98" . "\x84\x18\x05\x1f\x04\x87\xa2\xd3\x96\x20\x06\x25\x16\x95\x34\x75" . "\x69\x01\x58\x5d\xdb\x43\x9b\xe0\xaa\x1b\x6e\xe6\xd0\xe5\x47\x09" . "\xd1\x53\xd5\x96\xc5\xe5\x05\x06\xa3\xe1\x7d\xcf\xd7\xe0\x7f\x45" . "\x4f\xfe\x53\xc7\x8f\xbf\x5a\x29\x45\x8c\x91\x38\x57\xa4\x69\xd1" . "\x24\x84\x94\x20\x24\xd0\x4a\x11\x49\x38\x9f\x68\x93\xc3\x8a\xc1" . "\x64\x3d\x15\xbb\xe3\x29\x6b\xfd\x65\xce\x9e\x3a\xcd\xc2\xfe\xcb" . "\x68\x9a\x8e\xbd\xfb\xf7\x53\x16\x42\xd1\x2b\x58\x5c\x1a\xac\xef" . "\xec\x6c\x9f\x79\xbe\x06\xff\x2b\xfa\xe0\x4e\xa6\x93\xef\x1e\xd4" . "\xf5\xed\x56\xc0\xa5\xbc\x01\x5a\x34\x2a\x29\x94\xca\x0d\xf5\xdc" . "\xad\x4a\x8c\x27\xbb\x74\x6d\x4b\x0a\x81\xe8\xb3\xba\x2d\x78\x68" . "\x1b\xc7\xfa\xf9\x0b\x4c\x77\x27\x5c\x58\x3f\x43\x8c\x9e\x85\xc5" . "\x45\x06\xcb\x8b\x6d\x59\x97\x2f\xbb\xf5\xce\x17\x9f\xfa\xcb\x93" . "\xff\x45\x56\x8a\xe1\x90\x56\x90\x7c\x20\xa6\x40\x8c\x89\x2e\x46" . "\x50\x8a\x94\x65\x0d\xb8\xe0\x49\x29\xd1\xef\xf5\xf0\xae\x23\xa6" . "\x84\x51\x16\x2b\x96\xd2\xf4\x58\x5d\xda\xcf\xe1\xa3\xc7\x38\x75" . "\xe2\x69\xb6\x26\x5b\xdc\x76\xc7\xed\x1c\x3e\x7a\x19\xb6\xaa\xfe" . "\xd9\x1d\x2f\xbb\xe7\x01\x9e\xc7\xeb\x2b\x96\xf3\x3f\xf3\x99\x3f" . "\xea\xad\xad\xac\xdc\x56\x1a\x8d\x24\x9f\x15\x0b\x29\x4b\x42\xa2" . "\x24\x42\x4a\x59\x06\x98\x12\x31\x45\x90\x84\xb6\x9a\xa2\x57\x62" . "\xab\x92\xb2\xea\x63\xad\x46\x69\xcd\xd1\x2b\xae\xe6\xc5\x2f\xb9" . "\x8b\xa5\xc5\x05\x82\x73\x28\xa3\x48\xc4\x7f\xc5\xf3\x7c\x7d\xc5" . "\x82\xff\x8a\x97\xdd\x73\xa0\x2a\x6c\x69\x24\xeb\x76\x54\x8a\x19" . "\xdf\xc7\x44\x0c\x81\x90\x3c\x59\x91\x13\x20\x45\xb4\x08\x5a\x54" . "\xe6\x81\x8c\x26\xe8\x08\xa5\xc2\x9b\xc0\xc3\x4f\x3c\xc8\x78\x67" . "\x93\x43\x97\x1d\x62\xb8\xb2\x84\x94\xe6\xc1\xfe\x60\xf0\x91\xbf" . "\x0c\xfe\x17\x59\xcb\x8b\xa3\x2b\xeb\xa2\x78\xff\xd0\xda\x45\xed" . "\x3d\xca\x3b\x94\x44\xb4\x16\x42\x8c\x74\xc1\xe3\x62\xc4\x49\xa2" . "\xf3\x1e\x94\x26\x26\x30\xc6\xa2\x53\x42\xbc\xc7\x48\xc2\x16\x25" . "\xb6\x57\xa2\x2b\xc3\xd6\x78\x4c\xe3\x1c\xc3\x95\x25\xea\x41\xff" . "\x1f\xde\x71\xf7\x4b\x9a\xe7\x7b\xf0\xbf\xac\x39\xff\xca\xab\xae" . "\xd7\xbe\x9b\xbe\x65\x65\x71\xf4\xce\x30\xdd\x1d\x49\xd7\x41\xd7" . "\x51\x28\xa1\x21\x77\xf7\x44\xc0\xfb\xdc\x54\x4f\x21\x60\x93\x42" . "\x92\x60\x94\x21\x04\x4f\x21\x50\x6a\x45\xaf\xac\xd9\x7f\xd9\xe5" . "\xdc\x7c\xc7\x5d\x78\xa5\xd8\xdc\xd8\x44\x97\x3a\xf5\x47\xc3\x1f" . "\x9b\x4e\xa7\xff\x17\x5f\x05\xeb\x2f\x34\xf8\x1b\x9b\xdb\x1a\x48" . "\xcb\x4b\x0b\xf1\x8e\x3b\x5f\xfe\x35\xa2\xf4\x77\x1b\x3f\x7b\x5b" . "\x39\xdd\x66\xd2\x4e\x70\x12\x11\xe5\x29\x62\x42\x03\x51\x3c\x82" . "\xc2\x48\x41\xf2\x90\x54\xc4\x8b\x30\x0b\x9e\x52\x14\x16\x8b\xd6" . "\x82\x14\x15\x3e\x0a\x17\xb6\x37\xd9\x99\x4d\x58\xde\x77\x80\x95" . "\xba\x68\xfa\x8b\xc3\x1f\xf9\xd6\xef\x7a\xfb\x8f\xf2\x55\xb2\xfe" . "\x42\xba\x3a\xbf\xf8\x9b\xff\xd6\x3c\xf9\xd4\xf1\x1b\x9f\x78\xf2" . "\xc4\x6d\x8f\x3e\xfa\xc8\x37\x37\xb3\x9d\x7b\x37\xcf\x9e\xb5\xdd" . "\x74\xc2\x65\x8b\x15\xbd\xe9\x16\x42\xc0\x11\x49\x31\xa1\x23\x60" . "\x34\x5d\x0c\x44\xb1\xa4\xa0\x11\x04\xb4\xa2\x4b\x11\x94\x41\x12" . "\x14\xb6\xa0\x2e\x2c\xbd\xaa\x87\x4a\x8a\xba\xee\x71\xe8\xca\x2b" . "\x39\x74\xec\x8a\xf7\xde\xfa\xa2\x5b\xff\xe1\x1b\xde\xf2\xa6\xf7" . "\xf3\x55\xb4\xfe\x5c\x27\xff\x42\x13\xf5\x4a\xa5\xc2\x37\xfc\xd5" . "\xff\x72\xe5\xa6\x9b\xae\xb9\x6d\x65\xed\xc0\x2b\xc7\x13\x77\xe3" . "\xef\xbc\xe7\xbe\x97\x9d\x38\x71\x72\xe5\xe9\x93\xcf\xa2\x6d\xc1" . "\x85\x33\xa7\xf0\x3b\x17\x90\xd4\x61\x1d\x1c\xe9\x97\x14\x24\x4c" . "\x92\x4b\x42\x59\x62\xc4\xa0\x49\x62\x88\x4a\x90\x04\x11\xd0\xda" . "\x90\x44\x53\x14\x15\x88\x22\x68\xcd\x2c\x09\x22\x06\x10\xc6\xdd" . "\xec\x99\x8d\xed\x8d\x37\xbc\xe1\x2d\x6f\x72\x7c\x95\xad\x3f\xd3" . "\xc9\x7f\xcb\xb7\x7c\xa7\xba\xe6\xc6\x5b\xcb\xa7\x4f\x3c\x7b\x4f" . "\x35\x5a\x3a\x7a\x7e\x6b\xfc\xb2\xf1\x64\x76\xe5\xee\xf6\xc6\x4d" . "\xd3\xed\x53\xc3\x8d\x33\x27\x69\x76\x5b\xa2\x08\x65\x5d\xb1\xb9" . "\xbe\x9e\x1f\xd1\x66\x4c\x74\x0d\x49\x25\x0a\x02\xc7\x16\x97\x19" . "\x1a\x20\x78\xf4\x5c\x6f\xa9\x49\x04\x0a\x3c\x86\x98\x40\xa9\x48" . "\x00\x82\x36\x28\x55\x60\x75\x81\x2d\x4b\x8a\xc2\x62\xab\x3e\xcb" . "\x2b\xfb\x78\xd1\x9d\x77\xb0\xb6\x7f\xf5\x7b\xbe\xed\xed\xdf\xfe" . "\xf3\x7c\x15\xae\x7f\xef\xc9\xdf\x1c\x4f\xd5\xd2\xb0\x17\x01\x5e" . "\xff\xb6\xef\x1c\x1d\x38\x7a\xcd\xf7\x9f\x38\x73\xee\x3f\xff\xc0" . "\xa7\x1e\xbf\x76\x3c\x75\x4c\x9b\x0b\xb4\xce\xd3\xb6\x0d\xbe\x9d" . "\xd0\xac\x3f\x8b\xbb\x70\x12\x1d\x3a\x54\x61\x99\x6c\x78\x84\x94" . "\x87\xd9\xd2\x3c\xa7\x07\x08\xa2\x39\xbd\xdb\x50\x8e\x06\x0c\x52" . "\x24\x49\x40\x94\x06\x12\x2a\x09\x0a\x90\x42\x41\x02\xed\x13\x1a" . "\x8d\xd1\x06\x6d\x0b\xca\xb2\x60\x50\xd7\xec\x3b\x78\x88\xeb\x6f" . "\xbd\x83\xc1\x9e\xa5\xa7\x4e\x9c\x3c\xf9\xab\x7c\x95\xae\x2f\x79" . "\xf2\x3f\xf1\xe8\xc9\xde\xcf\xfe\xe3\x5f\x7e\xe3\x89\x67\x4e\xfd" . "\xf4\xc9\xf5\xf1\xbe\xb1\x87\xb6\x6d\x51\xa2\xd0\x4a\x41\xf4\xb8" . "\x6e\x46\xea\x3a\xda\xcd\x67\x71\xdb\x67\x51\x61\x4a\xd2\x82\xb6" . "\x86\xe0\xba\x3c\x71\x92\xd2\x5c\x7a\x7c\x11\xdf\x26\xf6\xf5\x2a" . "\x0e\xf4\x4b\x8c\xce\x7c\x0e\x44\xb4\xb2\x20\x96\x60\xf2\xcc\x15" . "\x49\x40\x19\x94\x29\xd1\xa6\xa0\xdf\xef\xb1\x77\x75\x8d\xa3\x57" . "\x5f\xcb\xb1\x1b\x6e\xa4\x5a\x1e\xfe\xd3\x57\xdc\xfb\x8a\xef\x5d" . "\x59\x59\x69\xff\x7f\x75\xf2\x7f\xe2\x7f\xff\xc5\x9b\x7e\xf1\x97" . "\x7e\xf5\x57\x1f\xf8\xec\x43\xb7\x3e\xfd\xcc\x49\xc4\x5a\x74\x51" . "\x52\x69\x8d\xeb\x3c\x4d\xd3\x92\x82\x23\xfa\x96\x7e\x3d\xa4\x1c" . "\x0c\xd9\x9e\x6e\xe1\x43\x4b\x0c\x8e\x94\x22\x5a\x2b\xa2\xf3\xe4" . "\xc8\x3f\xb7\xcf\x11\xe1\xfc\x74\x82\xd5\xc2\xf2\xa8\x47\x15\x85" . "\xfc\xc4\xe6\xa6\x89\x12\x83\xd2\x26\xe3\x4e\x6d\x11\x6d\x40\x65" . "\x3d\x67\xbf\x3f\x62\x69\x69\x15\x5b\x94\xcf\xb6\xb3\xe6\xef\x3c" . "\xdf\x03\xff\x91\x3f\xfc\x44\xb1\xb4\xb8\xb0\x76\xdd\x75\x57\x3f" . "\xfb\x1f\x0c\xfe\xb9\x8d\xed\x85\x1f\xff\xd9\x5f\x7a\xd5\x27\x3e" . "\xfd\xf0\xaf\xdd\x77\xdf\x7d\x83\xad\xf5\x4d\x44\x02\xde\x37\xc4" . "\x10\x29\xeb\x01\xbd\xc1\x22\x26\x09\xce\x7b\x7a\x75\x49\x3b\xdd" . "\xc6\xfb\x8e\xde\xc2\x12\x53\x3c\xae\x1d\xcf\x75\xf4\x0e\xad\x35" . "\x29\xc5\xcc\xd5\x5c\xba\x6f\x82\x4b\x8a\x33\xe3\x29\xde\x6a\xf6" . "\xd7\x3d\x94\x28\x50\x0a\x94\xa0\xb5\x45\x94\x26\xc4\x84\x68\x83" . "\xad\x0a\xb4\x31\x54\xbd\x1e\x4b\xab\x7b\xa8\x47\x0b\x34\xd1\xff" . "\xfa\x5f\xfb\xb6\x6f\xf9\xb2\x38\x8b\xa4\x94\x7a\x7f\xf0\x91\x8f" . "\xde\x7c\xee\xc2\xc6\x35\x47\x8e\x1e\xe1\xe8\x91\x23\x27\x96\x86" . "\x83\xf3\xce\xfb\xea\xf4\xe9\x33\x37\x3d\xfe\xf8\x13\xc3\x3b\x5e" . "\x7c\xfb\x33\xa3\xc1\x60\x13\xb8\xa1\xf1\xfe\x6b\x62\x8a\x97\x57" . "\xc6\x7e\xe6\x73\x0f\x3e\xf6\xf9\xed\xf1\xf4\x26\xe0\xbf\xf8\x0f" . "\x06\xff\x67\xff\xd9\xaf\xdd\x79\xfc\xc4\xa9\x7f\xf9\x9e\x77\xbf" . "\x4f\x4f\xb6\x4f\x81\x8f\x79\x68\x81\x44\xc4\xd3\xec\x9e\xc7\x4f" . "\x36\xa9\xfb\x8b\x38\x97\x20\xd4\x24\x63\xd0\x55\xc5\x78\x7b\x03" . "\x6b\x4b\x4a\x71\x74\xcd\x2c\x37\x3f\x42\x98\x0f\x40\x90\x25\xe1" . "\xf3\x5d\x10\x34\x8e\xc8\xf9\xad\x31\x12\x22\xfb\x86\x23\xb4\x52" . "\x68\x95\xf9\x1a\x94\x41\xb4\x80\x12\x10\x45\x51\xd6\x2c\xad\xae" . "\xb0\xb8\x67\x95\x49\xf0\xfc\xf2\x3b\xdf\xf9\x17\x42\x9a\xbd\xfc" . "\x95\x5f\x7b\xcd\xeb\xbf\xee\x0d\xaf\x7f\xc3\x5b\xde\x54\xac\x6f" . "\x6c\x1d\xdc\xdd\xd8\xbe\xed\x83\x1f\xfb\xec\x4b\x8f\x1c\xbd\xc6" . "\x5c\x79\x53\x2d\x21\x79\x5a\x49\xb4\xc1\x27\x17\x03\x87\x0e\x1d" . "\x4c\x87\x0e\x1d\xcc\x2c\xad\x73\x32\xe9\x9c\x4c\xba\x8e\x14\x03" . "\x6b\xc3\xd1\x6d\x97\x1f\xbb\xfc\x03\x67\xcf\x6f\x5d\xb1\x31\x76" . "\x76\x79\x68\xdd\x97\xa4\x17\x9e\x78\xf2\xf1\xbf\xff\xfb\xef\xff" . "\x5d\xbd\xbb\xf9\x2c\x46\x3c\x4a\x39\x7c\xd7\x22\xa2\xe6\xd3\x20" . "\x91\x18\x1a\x9a\xf1\x06\x86\x8e\x66\x67\x83\xd8\xb5\xb8\xb6\x65" . "\xb8\xbc\x4c\xcc\x52\x7b\x8c\xb5\x88\xce\xc3\x0f\x24\x99\xff\xbf" . "\x39\x8d\x3f\xd7\x26\x14\x5c\x48\x9c\xde\x9e\x70\x7c\xfd\x02\x63" . "\x17\x89\x2a\x37\xc6\x8b\xb2\xa2\x2c\x4b\xca\xb2\xa2\xd0\x05\xbd" . "\x7a\xc0\xca\xea\x7e\x42\x3d\xe4\xc1\x73\x13\x1e\x3a\x39\x7e\xe7" . "\x70\xf9\xd0\xff\xfa\x3f\xfc\x9d\x7f\xb0\xf6\x9f\x2a\xf0\x17\x76" . "\x26\xea\xc8\x95\x57\xfc\x64\x3d\x1c\xfd\xf4\xca\x9e\xb5\x9f\x38" . "\xbb\x7e\xe1\xfb\xcf\x6d\x4e\x5f\xb1\xd9\x38\x7b\x76\x6b\x47\x84" . "\x84\x11\x28\xb4\x21\x81\x14\xc6\x8a\x80\x52\x22\x2a\xa6\xa4\x12" . "\x48\xa1\x0d\xc3\xde\x80\x41\xaf\x47\x13\x12\x13\x1f\x5f\x35\x5a" . "\x1c\xa8\xa5\x81\xf1\x5f\xf2\xc1\xfd\x5b\x3f\xf4\xc3\x6f\xff\xbf" . "\xff\xcd\xbf\xfe\x85\x67\x8e\x3f\xa2\x25\x25\x24\x64\x14\x92\x10" . "\x94\x36\x28\xa3\x89\xde\x13\x9d\x83\x94\xc0\x28\x6c\x51\x91\x5a" . "\x85\x19\x0c\x49\xa5\xc5\xfb\x86\x30\xd9\x41\x42\x47\x8a\x1e\x8d" . "\x22\x45\x48\x44\x98\xab\x12\x12\x09\x52\x22\xc5\x48\x4a\x32\x97" . "\x78\x47\xfa\xc6\xb2\x7f\x61\x99\xfd\x7b\xf6\x31\xe8\xd5\x18\x2d" . "\x28\x34\x22\x9a\xb5\xd5\x55\x2e\xbb\xea\x28\xb3\xd1\x65\x7c\xf8" . "\xe9\x5d\x76\x9b\xc8\x03\x1f\xfa\x6d\x96\xea\xf8\x99\x8d\xf3\x67" . "\xbe\xa6\x39\xff\xf9\x8d\xff\x14\x1b\xf0\x53\xef\xfc\xb5\xdf\x5d" . "\x3d\x70\xe8\xf5\xaf\xbd\xf7\xa5\xae\x48\x41\x59\x65\xb4\xd6\x2a" . "\x93\x7a\x3a\xff\xac\x5f\x6a\x75\x31\x32\xf3\x01\x9f\x22\x4d\xe7" . "\x29\x8d\x61\x64\xcd\xd4\x6a\x75\x87\x52\xea\xe1\x2f\x9a\x76\xfe" . "\xf9\xff\xf9\x1b\x37\xff\xbb\xdf\x7b\xef\xff\x72\xea\xf8\x71\x2d" . "\xde\x67\xa5\x40\x0a\x28\x14\x31\x7a\x52\xd4\x04\xaf\x29\xca\x0a" . "\x89\x10\x7c\x07\x24\x62\x72\x68\xad\x98\xed\xae\x53\xa9\x45\x52" . "\x8a\x18\x53\xe0\x42\x87\x52\x9a\x18\xc9\x1b\x25\x17\x83\xac\x88" . "\x29\x53\xc6\x17\x73\x7c\x24\x11\x10\xc6\x3e\xd1\x6e\x6c\xb1\xd3" . "\x05\xae\xb8\xfc\x30\x0b\xc3\x11\xa5\x2e\x29\x8c\xa5\x1e\x2d\x62" . "\x7b\x23\x1e\x3e\xbb\xc5\x4c\x2d\x42\xbf\xe4\x55\x7f\xed\x6f\xe1" . "\x76\xd7\x6f\x99\x9d\x7d\xf4\xa9\x0b\xcf\x3c\xf5\x4d\x1f\xfb\xad" . "\x5f\x78\xcf\x68\x61\xe9\xcf\x25\x01\x7f\xf9\x6b\x5e\xf3\x29\x53" . "\xd7\xaf\x1f\x58\x63\x7b\xa6\xa4\x0b\x9e\x42\x3f\x97\x9d\x63\xcc" . "\x7f\xfd\xc5\x9b\xfc\x27\xde\x86\x3c\xe2\x24\x81\x10\x22\x21\x46" . "\x76\x76\xa7\x54\xa3\x41\xd5\xb4\xcd\x15\xc0\x9f\x0e\x7e\x35\x18" . "\xea\x77\xfc\xbd\xbf\xf7\x33\x67\xce\xad\x2f\xe1\x5a\x54\xcc\x33" . "\x51\x51\x7b\x24\x26\xb4\x82\x84\x27\xc6\x44\x3b\x9d\x62\x8c\xc5" . "\x98\x82\x2e\xf8\xac\xf6\xd6\x1e\x11\x68\x76\xb7\x30\x45\x3f\xff" . "\x70\xc6\x90\xbc\xc7\xe8\xec\x95\x90\x2e\x7d\x81\x56\x96\x98\xf2" . "\xd8\x0f\x3a\x22\x92\x48\xde\x13\x45\xe1\x80\x0b\x93\x31\x3b\x8f" . "\x3d\xc6\xea\xca\x5e\x0e\xac\xed\x63\xdf\xea\x5e\x3a\xd3\x67\xc7" . "\x2e\x71\x7c\xeb\x0c\x93\xd2\xe0\xba\x8e\x70\xf6\x2c\xe5\xe2\x1a" . "\x69\xef\x6d\xa3\xbd\xbd\x7d\xbf\x73\xe7\x9b\xbe\xf7\xbf\x07\xfe" . "\xd1\x9f\x27\xf8\xe3\xf1\x36\x8b\x75\x19\x00\x9d\x52\xca\x90\xfa" . "\x8f\xad\x2f\x15\x7c\x11\xa1\x32\x96\x32\x19\x44\x42\x8e\x61\x11" . "\x99\x39\x37\xd9\xdc\xd8\x58\xfb\xa2\x69\x67\xff\x65\x87\x0f\xee" . "\xee\xee\x9e\x6c\xda\x16\x7c\xce\xc7\x97\x1e\x05\xc9\x69\x22\x5d" . "\x4a\x1c\x90\x52\x44\x69\x0b\xa2\xf0\x21\x50\x14\x9a\x18\x22\x31" . "\x26\x94\xd6\xe8\x7a\x98\xf5\x35\xae\xa3\x14\x85\x4a\x42\x08\x0e" . "\x17\x66\x24\x11\x8a\xa2\x44\x4c\x81\x0b\xf3\xdb\x20\x81\x24\x79" . "\x63\x52\x48\x48\x12\x94\x18\x24\x69\xaa\xaa\xc7\xa0\x3f\x62\x71" . "\x75\x0f\x7e\xb8\x07\x37\x3a\xcc\x60\xef\x95\x14\x45\x4d\x54\x91" . "\x28\x09\x95\x12\x61\x36\x65\x68\xdb\xb4\xaf\x18\xff\xf8\x5d\x37" . "\x5d\xfd\x8e\xef\x78\xeb\xab\xec\xf2\xf2\xca\xe4\xcf\x12\xf8\xcd" . "\xf1\xae\x7a\xd7\xff\xfb\xee\x1f\xa9\x97\x56\xfe\xf6\xe1\xcb\xf6" . "\xb1\x77\x65\x81\xa5\x7e\x8f\x61\xaf\xa6\x50\xfa\x4f\x05\xfa\x8b" . "\x9d\x7c\xe6\xc0\x7a\x96\x60\xb3\xf5\xc4\x10\x58\xaa\x4c\x1a\x1a" . "\x73\x8f\x88\xfc\xe1\x9f\x3a\xf9\xab\xab\xab\x0b\xdb\xdb\xdb\x97" . "\x46\xf0\xf3\xa0\xda\xfc\xf6\x4a\x42\xa9\xbc\x01\x31\x46\x52\x1e" . "\x0d\x21\x78\x8f\x35\x96\x42\x29\x62\x88\xa4\x94\xff\x5c\xf0\x01" . "\x9d\x12\xc6\x5a\x02\xb9\x58\x52\x4a\xd0\x4a\x13\x93\x25\x46\x4f" . "\x70\x81\xb2\xa8\x11\x5d\x10\x05\x8c\x8e\xb8\x18\x21\xe5\xa9\x93" . "\x14\x41\x29\x4d\x8a\x30\x8b\x8a\x66\xd2\xb2\xde\x9d\xc7\x2c\x57" . "\xec\x59\xc8\x30\xb4\x3f\x5c\x60\x63\xbc\x01\x92\x65\x25\xae\x6b" . "\x99\x35\x5e\xf4\x68\xf0\x3f\x7e\xee\xc4\xc6\x1b\xee\x7d\xf3\x77" . "\xbc\xeb\x6b\xbf\xfe\x4d\x3f\xfb\xbb\xbf\xfd\x6f\x37\xff\x63\x83" . "\xbf\x34\x1c\xc4\xbf\xfd\x43\x3f\x7c\x74\x69\xcf\x1a\x3b\xcf\x7c" . "\x9e\x93\xa3\x3e\x8b\xa3\x05\x16\xd7\x56\x18\x2d\x2e\xe5\x11\x24" . "\x6d\x50\x4a\xd1\x2f\x4b\x4a\x6b\x11\xad\x11\xa5\x08\x21\x31\xeb" . "\x3a\xa6\xbe\x43\x94\x26\x26\x8d\xeb\x3a\xac\x16\x86\xaa\x2f\x49" . "\xeb\x7b\x81\x3f\x1d\xfc\xe1\x70\x78\x67\x08\xe1\x8b\xee\xac\x88" . "\xe4\x5c\x36\xdf\xd5\xec\x81\x23\x18\xab\xf0\xde\x65\xbd\xe4\xfc" . "\x7a\xa6\x98\xe1\x53\xf4\x0e\x6b\x2b\x28\x4a\x7c\x3b\xa5\x4b\x1e" . "\x6b\x0a\x04\x05\xae\x25\xc4\x40\xd7\x39\x06\x4b\xab\x74\x51\x40" . "\x25\x2a\xad\xf1\x21\x12\x42\xcc\x69\x4d\x1b\x04\xc1\x27\xc1\xc5" . "\x88\x29\x07\xf4\x17\xf7\x60\x6d\x85\xd5\x0a\xa5\x12\x55\x59\x83" . "\x44\x9a\xe9\x0e\x21\x78\x9c\x4b\x9c\x5c\x77\xf8\x54\xdc\x5c\x2c" . "\x1f\xb9\xf9\x13\x9f\x78\xcf\x1e\xe0\x6f\xfc\x59\x4e\xff\x93\x8f" . "\x3d\x7c\xe5\x95\xed\x26\x5b\xd3\x75\x4e\xb9\x29\x95\x29\x19\x0c" . "\x46\xf4\x86\x0b\xa8\xaa\xc6\xd4\x3d\x8a\xba\xa6\x1e\x0c\x11\x5b" . "\x62\xab\x3e\x68\x4b\xc4\xe2\x82\x47\xb4\xa6\xea\xd7\x14\x45\x8f" . "\x5e\x7f\xc0\xc1\x03\xfb\x18\x54\x25\x22\xb2\xfa\x45\x71\xfe\xe7" . "\x1e\xf8\xec\x75\x7f\xf2\xea\x5c\xcc\x6f\xea\xe2\xa0\xf2\xc5\x2b" . "\x15\x13\x1a\xc1\x58\x9d\x47\x35\x63\xc8\x72\x8f\x94\x88\x31\x61" . "\x8c\xc1\xb9\x8e\xa2\x56\x28\x53\x20\x29\x10\xbd\xd0\xa1\xa8\xeb" . "\x3e\xde\x34\xb4\xcd\x0e\xce\x4d\x70\xd1\x51\xf6\x57\xe9\x7c\x22" . "\x49\xa4\xaa\x2d\x2e\xc4\xec\xaf\x13\x13\x5a\x5b\xb4\x2d\x50\xda" . "\xd0\x1f\x2c\xd2\x1f\x2d\x53\x97\x05\xcd\x64\x07\xa5\x04\x63\x7b" . "\x68\x63\x19\xcf\x5a\x7c\xdb\x90\xda\xcc\x35\x6d\x89\x67\xb4\x74" . "\x19\x4b\x87\xae\xfb\xeb\xa5\xa4\x5f\x7e\xe0\x81\x8f\x7f\x7a\x65" . "\x79\x14\xfe\x63\x82\x7f\xfa\xc4\x71\xaa\xee\x34\xe5\xf4\x34\xb5" . "\xdf\x61\xbb\xed\x38\x13\x14\x45\xdd\xa7\x8b\x42\x10\x85\xb2\x15" . "\xbd\xd1\x02\x65\x7f\x11\x53\x0f\xe8\x0d\x16\xe8\x55\x7d\x44\x6b" . "\x8a\xba\x62\x61\x69\x89\xfe\xd2\x2a\xc5\xca\x1e\x3a\xeb\x9a\x69" . "\x5a\x6d\xab\xba\xfe\xe8\x17\x0d\xbe\xd2\xfa\x95\xde\xcf\xf2\x60" . "\x02\x71\xbe\x01\x92\xd1\x4c\x74\x90\x32\xdc\x13\x89\x90\x1c\x51" . "\x84\x24\x15\xf3\xf9\x4b\x62\x70\x28\x04\x63\x4c\x46\x30\x9d\x27" . "\x74\x33\xf4\x68\x84\x55\x25\x4a\xcd\x68\xbd\xa3\x15\xa1\x1e\x2e" . "\x13\xd1\xf8\x66\x9d\x66\x72\x9e\xde\xc2\x3e\x52\x39\xa0\xeb\x76" . "\x68\xbc\x43\x2b\x4b\x55\x0d\xd0\x45\x49\x14\x8d\x0b\x19\x21\x25" . "\x29\x88\x5a\x70\xb1\x23\x79\xd8\xd9\x0e\x54\xb6\xc5\x87\x40\x68" . "\x5b\xe8\x66\x84\x66\x42\x12\x43\xd3\x4c\xd9\x38\x7b\x9e\x03\x87" . "\xaf\xa9\x36\xcf\x9f\x78\xf3\xca\xf2\xe8\x4f\xa9\xd6\x5e\xf5\xe2" . "\xbb\x6e\xbe\xe1\xc8\x91\xbf\x71\xcb\x75\x37\xdc\x78\xfb\x4b\x5f" . "\x36\x1b\xac\xae\xfe\xc6\xfd\x9f\xfa\xd4\x87\x7f\xf3\x37\x7f\xfd" . "\xba\xeb\x2e\x3b\xca\xce\x19\x8f\x9d\x8e\xa9\x95\xc7\x79\x21\xa5" . "\x29\x98\x82\x2e\x44\x52\x37\xa3\x3b\x7d\x8e\x9d\x00\x7e\xae\x64" . "\x8c\x73\xaf\x20\xa5\x72\x3d\x24\x83\x21\x83\xa5\x3d\x94\x8b\x2b" . "\x55\xb5\xba\x54\x5d\x77\xeb\xed\xef\xdc\x38\xf3\xf9\x07\x97\xf7" . "\x5d\xf5\xd0\x17\x04\x7f\x32\x9d\x5c\x71\x51\x1b\x79\x31\xb5\xa4" . "\x34\x9f\xfe\x23\x41\xae\x24\xb2\x8a\x2c\x66\xcf\x84\x10\x22\x45" . "\xd9\xa3\xed\x3a\xb4\xb1\x84\xce\x51\x96\xc5\x3c\x80\x0a\xd7\x4e" . "\x29\x94\x26\xa0\xd1\x28\xea\x2a\x31\x69\x76\x09\x28\x7a\xfd\x25" . "\xb6\x67\x1b\xf8\x76\x4a\x3b\x19\x33\xd8\xbb\x87\xa0\x23\x6e\x36" . "\x25\x01\xae\xeb\x28\xeb\x21\xba\xee\x53\x9b\x0a\x91\x3c\x69\x2e" . "\xc6\xd0\xb4\x2d\xe8\x48\x51\xe5\x4d\x4f\x51\x30\x5a\xd3\xc6\x48" . "\xdb\x4e\x31\x55\x1f\xd7\x4d\x98\x6c\x9f\x67\xb7\x4a\x2c\xad\xac" . "\x2d\x5c\x78\xea\xb9\xa0\xf7\x0a\xbb\x77\xff\xea\xda\xcf\xac\x8d" . "\x86\x6f\xdb\x7c\xe6\x84\x7a\xdf\xa3\x0f\xf2\xc9\x0f\x7f\x90\xa5" . "\x3d\xfb\x5f\x35\xec\x8d\xe2\x4d\xab\xfb\xf4\xd3\x0f\x3c\x89\x9f" . "\x9c\xe3\xe0\xa0\x63\xb1\x48\xb4\xed\x2e\x2e\x28\x5a\x0f\x26\x24" . "\x42\x4c\xd8\x08\x6a\x4e\xfc\x45\xa5\xe9\x2e\x4e\x4a\x92\x1b\xfd" . "\xb4\x2d\xc5\x24\x12\xc3\x2e\x93\xe6\x1c\x3b\x7b\x97\x47\xcd\xee" . "\xd6\x1d\xc0\x73\xc1\x7f\xed\xeb\x5f\x77\xf8\xc3\x1f\xf9\xc3\x61" . "\x0c\xb9\x70\xba\x98\xe3\x2f\xe5\xfd\x94\x2e\xc1\x44\xa5\x0b\x52" . "\x4c\x90\x02\x31\x42\x4a\x73\x87\x1c\xc9\x06\x74\x6e\x6e\x4a\x67" . "\x4b\x43\x33\xdb\x45\x82\xa3\xa8\x16\x88\xce\x21\x3a\x52\xda\x02" . "\xd7\x74\x54\x45\x85\x98\x12\x42\x4b\xb3\xbb\x45\xb5\x34\xc1\x56" . "\x7d\xb4\x2a\x89\xcd\x0c\xef\x5b\x76\x27\x63\x6a\x5d\xa0\x55\x4d" . "\x59\xd5\x24\x81\xd6\x85\xcc\xfd\x2b\x8d\xf3\x2d\xa6\x2a\xb1\x45" . "\x41\xf0\x09\xe6\x90\xb6\x2c\x34\x61\xb6\x83\x9f\x6e\xd2\xed\x0a" . "\x9b\x67\x4e\x3f\x17\x78\x53\xde\xb3\x50\x57\xef\xba\xe7\xd6\x5b" . "\xf6\xca\xce\x36\xcd\xf6\x05\x14\x9e\xd9\xc6\x19\xa6\xe7\xce\x4b" . "\xea\x92\x8e\xde\xd1\x4a\x87\x4e\x1b\x5c\xb9\xa8\xe9\xdb\x0e\x6d" . "\x23\x4d\x8c\x20\x0a\x21\xe2\x93\x60\x44\x93\x94\xc6\xcd\xf1\x7c" . "\xa9\xf2\xc9\xd7\x26\x0b\xbe\xa4\x54\x18\xb3\x8b\x97\x44\xbf\x37" . "\xa0\x2e\x14\xb3\xc9\xee\x65\x5f\x90\x76\x1e\x7c\xf0\xc1\x65\xef" . "\x7d\x75\x11\xe9\xfc\xf1\xc0\xa7\x94\x20\x45\x44\xe7\x42\x8b\x68" . "\xb1\xa6\x26\xba\x96\x18\x20\xc6\x84\x36\x06\xdf\xb5\xd4\x55\x9f" . "\xae\xed\xd0\x65\x91\x75\x36\x21\xd0\xcd\xa6\x98\x42\xa3\x8b\x8a" . "\x40\x8b\xd6\x05\x29\x28\x50\x16\x31\x15\x84\x86\xe8\x5b\x9a\xe9" . "\x98\xa2\xee\x53\xd6\x03\x82\x2e\x99\x4c\x77\x88\x31\xd2\xcd\xa6" . "\x14\xba\xc2\x29\x4b\x51\xd5\x20\x82\xb6\x36\x53\x13\xc1\xa3\xb4" . "\xa0\x6c\x76\x20\xb4\x45\x89\x88\x62\xb6\x3b\x21\x35\x13\xc4\xb7" . "\x34\x3b\xdb\x14\x46\x2d\x03\xdc\x7a\xdd\x4d\x6f\xd8\xdd\xd8\xfe" . "\x17\x5f\xf3\x92\x5b\x87\xd3\xf3\xa7\xe9\xb6\xb6\x70\xbe\xa3\x8d" . "\x81\x4a\x15\xf4\xfb\x7d\x52\x15\xb1\xa6\x64\x58\x82\xc2\x20\x83" . "\x09\x21\x35\x58\x2d\x04\x05\x41\x29\x82\x12\x64\x7e\x18\xc3\x9c" . "\xa0\xb1\x80\x32\x11\x5d\x28\x94\x0d\x28\xab\xa0\x10\x92\x09\xd8" . "\x7e\x4d\xbd\xb8\xc6\xd4\x6b\x9e\x3c\x71\xea\x4f\xe4\x7c\xad\x5e" . "\x4b\x22\xef\xe4\x1f\xc3\xf1\x29\xe6\x74\x83\x32\xc4\x14\x2e\x61" . "\x70\x6b\x35\x85\xe9\xd3\xce\x66\xb8\xb6\x61\xd0\x5f\x60\x57\x1c" . "\xad\x6b\x28\x8b\x92\xa0\x0b\x48\x0d\x4a\x2b\x42\xd3\x51\xaf\x14" . "\x78\x11\x52\x54\x54\x45\x81\x8e\x92\x21\x58\x51\xe2\x3a\x81\xd8" . "\x92\x7c\x4b\x37\x6b\x30\xfd\x92\x72\x30\xc0\x1b\x45\x70\x0d\xc4" . "\x84\xef\x9a\xdc\x32\x14\x85\xaa\xcb\x2f\x2c\x78\x82\x03\x6a\x6c" . "\x59\x63\xab\x1a\xad\x0b\x24\x44\x42\xd7\x90\x7c\x47\x4c\x05\xdd" . "\x6c\xf6\xba\xbb\x6e\xbc\xf5\xef\xdf\x70\xdd\x75\xef\x38\xb0\xb0" . "\xc2\xa3\xf7\x7f\x18\x9a\x31\xae\x9b\xd1\x88\xe6\x8a\xeb\x6e\xe2" . "\x2d\xdf\xf4\xcd\x54\xfd\x01\xeb\x3b\x3b\x7c\xe0\x83\xf7\xa1\xa7" . "\xe7\x68\x37\x77\x09\xf5\x12\xd1\xb5\x54\xaa\x21\x69\xc1\xbb\xcc" . "\x8b\x89\x9e\x57\xe5\x31\x66\x03\x0f\xad\x33\x01\xa8\xf2\x06\x98" . "\x92\xac\x37\x32\x05\x76\xb4\x97\xde\xd2\x61\xa2\xe9\x33\x69\x7d" . "\xf5\x05\xc4\x5a\xd9\xef\x1f\x98\xc3\xf9\xec\x7f\x93\x32\xfb\x75" . "\xa9\x88\x10\x21\x65\x0b\x10\x52\xf4\x04\x02\x62\x0b\x6c\xaf\x26" . "\x25\x8f\xef\x3a\x7a\x83\x21\x21\xe6\xce\x95\x68\x4d\x88\x11\x6d" . "\x0b\x82\xf3\xd9\xac\xc8\x18\x94\x40\x70\x9e\xaa\xaa\x49\x22\x73" . "\xbe\x5e\x13\x93\x03\xdf\xa1\x42\xa2\x6d\x1a\x82\x12\xca\xe1\x08" . "\x3b\x58\xc0\xd4\x7d\x8a\xa2\xa4\x2a\x4b\x62\x08\xa8\x98\x50\x17" . "\x21\x70\x4a\x10\x23\xc1\x7b\x5c\x08\x14\x45\x8d\xd2\x25\xc6\x5a" . "\xa2\x6f\x89\x61\x46\x4c\x9e\xd2\x98\x3d\x26\x86\x77\x4c\x4e\x3d" . "\xc3\xa3\xf7\x7f\x88\x38\x1b\x33\x9b\x4d\x99\x86\xc4\xeb\xbe\xf1" . "\x9b\xf8\xa6\x6f\xff\xaf\xb8\xef\x23\x9f\xa0\x1c\xad\x70\x6e\xcb" . "\x31\xdc\x73\x05\x2b\x97\x5f\xc1\x60\x79\x85\x7a\xe5\x10\xa6\x10" . "\xaa\x42\x63\x8c\x50\x58\x45\x65\x34\x5a\x09\x46\x29\x54\xca\x6e" . "\x88\x46\x12\x85\x11\x4a\x2b\x14\x2a\xa1\x25\x50\x18\x85\xb5\x25" . "\xa3\xc5\x7d\xf4\x17\xf7\x31\x5a\x3e\xc0\x68\x61\xe5\x0b\xbc\xdd" . "\x54\x42\x6e\x88\x4a\x40\xc8\x5a\x99\x5c\xd6\x5e\xc2\xf5\xd9\x9a" . "\x45\x80\x48\x52\x0d\xce\x37\x68\x6d\x49\x5a\x93\xac\xa2\x09\x1d" . "\x85\xad\xd1\x65\x8f\x69\xd3\xa2\x89\x08\x0a\xab\x7b\xa4\xe8\x08" . "\xbe\xa5\xb4\x15\xc6\x16\xf8\x98\x70\x31\x61\xaa\x1e\x49\x95\x28" . "\x53\x92\x52\x22\xf8\x0e\x9d\x02\xf8\x8e\x6e\x3a\x41\x01\x45\xd1" . "\x07\x4a\xda\xc6\xd3\x4c\xa7\x0c\x07\xfd\x0c\x63\x3b\x97\xd1\x84" . "\x08\x6d\xd7\x12\x42\x07\xc1\x93\x92\x42\x17\x25\xaa\xb4\x04\x89" . "\x24\xef\xa0\x99\xb1\xd0\xb3\xf4\x75\x62\xb2\x79\x8e\x34\xdb\x61" . "\xda\x8c\x99\x06\xcf\x8b\xee\x7e\x15\x4b\xfb\x8e\xf1\xc1\x0f\x7d" . "\x92\x3d\xfb\x0e\xf3\xc4\xe3\x4f\xd3\x2f\x2b\x5e\x7a\xe7\x8b\x19" . "\xae\xed\x65\xe5\xc8\xd5\x8c\x86\x7d\x06\x36\x51\x68\x28\x8d\x50" . "\x68\xb0\x3a\x51\x28\xc1\x4a\xfe\x35\xad\x22\x4a\x22\x4a\x12\x12" . "\xe7\x5f\x7e\x5e\xa9\x93\x20\x79\xd6\x56\x56\x58\x18\x2c\xa2\x8c" . "\xba\xeb\xec\xf9\xa7\xec\xa5\xb4\x13\x7c\x22\x85\x98\xbd\x6f\x52" . "\x20\x89\xc9\x9c\xcb\xc5\x0d\x48\xf1\x12\xfb\x2c\x92\x88\xbe\xa1" . "\x9b\x4d\xa8\xfa\x03\x62\x6c\x09\x6d\x64\x36\xeb\xa8\x87\x8b\x4c" . "\x66\xe7\x09\xcd\x14\x65\x04\x82\x22\xa5\x31\x5d\xb3\x45\x35\xdc" . "\x83\x28\x8b\xa8\x80\x4b\xe4\x53\x6a\x07\xa0\x36\x50\x0a\x24\x7a" . "\xa2\x78\xd0\x9a\xae\x6d\x88\x4a\x51\xd6\x23\x7a\x83\x01\xcd\x78" . "\x42\x0c\x81\xe9\xee\x2e\x76\x30\x9c\xf3\x44\x99\xa8\x0b\xa1\x23" . "\x05\x47\x08\xb9\x3f\x50\xd6\x03\x52\xda\x45\xb4\x90\x82\xc3\x06" . "\xc7\x81\xd5\x45\xd8\x3d\x87\xae\x46\x28\x63\xf1\x61\x9d\xe5\x7d" . "\xab\xac\x1d\xbc\x9c\xe3\x4f\x3d\x8d\x24\xe1\xd4\x89\xe3\x3c\xfc" . "\xd9\xfb\x69\xa6\x53\x0e\x1e\x3e\xcc\x91\x2b\x96\xb8\xfb\xce\xc3" . "\xb4\xcf\x7c\x82\xed\x33\x1d\xc6\x80\x53\x91\xd2\x08\x2e\x25\x54" . "\x8c\xc4\x94\x0b\xcd\xd6\x07\x22\x09\x62\xf6\x8f\x10\x9f\x6f\xa5" . "\xa8\x48\x6c\xb7\xd8\x38\xf5\x00\x33\x3c\x83\x83\xd7\x53\xae\x1c" . "\xae\xcf\x2c\xed\xbd\x17\x78\x0f\x80\xe9\x66\x4d\x4e\x39\x31\xd3" . "\x00\xe9\x12\xe3\x93\x4f\x3b\x44\x44\xec\xfc\xbf\x25\x07\xb0\xdd" . "\x25\x46\xe8\x8f\x16\xe8\x54\xa0\x6d\x3a\x4c\xaf\xc4\x54\x25\xbe" . "\x99\xa0\x6d\x35\x1f\xf1\xe9\x70\xcd\x18\x91\x44\x51\xd5\x84\x26" . "\xd0\xb9\x0e\xa5\x41\x17\x3d\x12\x96\x94\x3a\xbc\xef\x50\xca\xe3" . "\xbd\x50\x58\x43\x70\x9e\x56\x66\x44\xe3\xb0\x46\xd1\xb6\x9e\xae" . "\xeb\x90\x18\x32\xa5\x6d\x3c\x98\x9a\xe0\x3b\x7c\xd7\x62\x4d\x7e" . "\xc4\x11\x95\xa1\xaa\x77\xa8\x94\x38\xb2\x7f\x2f\xc7\x0e\xef\x65" . "\xcf\xe0\x1a\x6e\xbb\xeb\x95\xb4\x1e\x1e\x7f\xe8\x73\x74\xed\x94" . "\x27\x1f\x3f\xce\x74\xbc\x45\xdb\x34\x90\x3c\x84\x16\xdf\x34\x3c" . "\x74\xea\x29\xf6\xf5\x6e\xe5\x89\xb3\x1f\x65\xc1\x3d\x8b\x9d\xe3" . "\x6f\xa3\xc0\x48\x02\x49\x18\xa3\x70\x3e\x8b\x7a\x0b\x23\x84\x9c" . "\x17\x48\x81\x3c\xcc\x07\xa8\x14\xd0\x32\x23\xf9\xb3\x6c\x9e\xca" . "\x8e\xb9\xa3\x26\xf1\x07\x1f\x7d\xf8\xa7\x80\x1b\x00\x54\xdb\x36" . "\xa4\x04\x11\x85\x44\x81\x18\x88\x31\x8b\x54\x45\xcd\xb9\x1c\x12" . "\x5a\x69\x50\x05\x51\x2c\x44\x47\x68\xc6\x4c\x77\x1b\xaa\x85\x25" . "\xea\xa5\x65\x2b\xbd\x5c\x7d\x00\x00\x1b\x08\x49\x44\x41\x54\xa6" . "\x93\x8e\xaa\x37\xc2\x23\x80\x25\xa5\x80\x12\x83\x9b\x8d\x09\x7e" . "\x42\x10\x4b\x51\x8e\x30\xda\x92\x94\x46\x54\x45\x61\x17\x31\xca" . "\x12\xa3\x43\x7b\x8f\x0e\x40\xdb\x61\x8d\x25\xc4\x44\xf4\xd9\x0a" . "\xac\xac\x0a\x42\x72\x28\x63\x88\xdd\x14\x37\xdd\xc5\x27\x70\xde" . "\xe3\x5d\x47\xd7\x35\x24\x95\xd3\x91\x11\x85\x25\x72\x64\x6d\x2f" . "\x77\x5c\x7b\x35\xb5\x52\x98\x62\x48\xf4\xb9\x02\x5f\x5c\xd9\x0f" . "\xa2\xd8\xdd\xbe\x40\xb3\xb3\x81\x9f\x6e\xe3\xda\x1d\x62\x0c\x19" . "\x74\x48\xc3\x60\xcf\x12\xb8\x09\xb6\x8d\x04\xd7\xd1\xc5\x6c\xba" . "\x5a\x8a\xa6\xd4\x92\x47\x54\x4b\x4d\x65\x35\xb5\x16\x6a\x95\x28" . "\x44\xa1\x94\x21\x29\x9d\xdf\x49\x91\xcc\x8b\x49\xc0\x48\xa4\x69" . "\xc7\xb8\xa6\x61\x58\xf7\x46\x3f\xf9\xbf\xfd\x4c\x0d\x60\x5c\xd7" . "\x65\x77\xbf\x3c\x87\x86\xd6\x42\x92\x79\xd7\x29\xe6\x2b\x9e\xdf" . "\xf4\x40\x51\xf7\x08\xb1\x26\xa4\x19\x29\xb5\x38\x37\x26\xfa\x55" . "\xfa\xfd\xfd\xe8\xc2\xe1\xba\x1d\xec\x28\x4b\x49\xb4\x18\x94\xd6" . "\x78\x3f\x63\xb6\xbd\xce\xa0\xbf\x42\x50\x16\x5b\x06\xda\x98\xb0" . "\xb6\xc0\xd6\x43\xa2\xdf\xcc\x9c\x69\xeb\xb1\xb5\xa6\x6b\x5b\xf4" . "\x74\x42\x39\x5c\x26\x89\xc2\x89\x64\xa3\x3b\xe7\xd0\xbe\x63\xd8" . "\xef\xb3\xbe\xb9\x85\xb2\x65\x16\x54\xa5\x84\x73\x1d\x36\x94\xe8" . "\xa2\xc0\x4d\x13\x03\x81\x6b\x0f\xec\xe1\xf3\x9f\xf9\x38\xfd\x52" . "\x71\x81\x27\xb8\xf0\xe4\x63\xf4\xfa\x43\x36\xb7\xb7\xe8\xba\x09" . "\x6d\xb3\x43\xdb\x4e\xd1\x2a\xa7\xd3\x94\x04\x2f\xc2\xb1\xeb\x6f" . "\xc2\x98\x35\x92\x5e\x64\xe6\xb7\x90\x10\xf1\x41\xe6\x35\x0d\x28" . "\x6b\x30\x29\xe6\x99\xe1\x08\xe8\x6c\x49\x19\x42\x42\x13\xf1\x00" . "\x46\x10\x95\xd9\xdc\xe8\x02\x89\x40\xbf\xaa\x20\x45\x46\xa3\xe1" . "\xa1\x07\x1e\xf8\xcc\x32\xf0\xac\x11\x92\xce\xc0\x28\x3f\x10\x12" . "\x65\xde\xfe\x53\xb9\x83\xa5\x12\x32\x2f\x9f\x5d\xdb\xd1\x1b\x2d" . "\xe3\xad\xa5\x6d\x76\x20\xc0\x64\x73\x83\xb2\xdc\x83\x2e\x87\xc4" . "\xb2\xc4\xf4\x2c\x93\x67\x1f\xc1\x29\x9d\x77\xdf\x4d\x71\xbb\x1b" . "\xe0\x3a\x82\xae\x29\xea\x05\x82\xef\x32\x7a\x29\x6a\xb0\x25\xca" . "\x37\xd0\x79\x54\x4f\xf0\xa1\x25\x6c\x5f\x60\x54\x54\x48\xd5\x23" . "\x49\x22\xcd\x1d\xa9\xa6\x3b\x5b\xf4\x17\x96\x50\x4a\xe3\x67\xbb" . "\x2c\xaf\xed\xa7\xf1\x9e\x24\x91\xae\x9b\x02\x86\x9e\x8e\xac\x0d" . "\x2d\xd3\xf3\x4f\x13\xdd\x2e\xbb\xb3\x44\x8d\x21\x8e\x37\x38\xe7" . "\x3d\x49\x41\x54\x91\xa4\xf2\xf0\x05\x4a\x41\x72\x74\xd3\x29\xce" . "\x79\x1e\x79\xe8\x73\x5c\x7e\xe8\x0a\xd6\x8a\x01\x33\xa7\xb0\x3e" . "\x7b\x39\x67\x4b\xe1\x8b\xed\xcf\x9c\xf3\xc3\x45\xc5\x9d\x96\xec" . "\x0f\x1a\xe7\x13\x94\x4a\x43\x52\xc4\xa0\x71\x68\xda\xe0\x29\x3b" . "\xc7\xde\xd5\x45\x9e\x5c\x9f\xd1\xef\x5b\x01\x50\xde\x75\xed\xc5" . "\x9e\x2a\x17\xe1\x65\xca\x3c\xbe\x92\x2c\xe8\x90\x39\xe4\x0f\xde" . "\x31\x9d\xee\xa0\x6c\x45\xdd\xdb\x4f\x59\x8c\x48\x7e\xc6\xce\xd6" . "\xb3\xd8\xca\x20\x45\x8f\x7a\x61\x1f\xca\x28\x42\x0c\x88\xd1\xa8" . "\xd4\xe5\x6a\x73\x36\x26\xc4\x00\xc6\x50\xf5\xfb\x98\xb2\x26\x99" . "\x22\x4b\x43\x94\xca\xe4\x9c\x08\x62\x73\x30\xda\xf1\x16\x2a\x3a" . "\x5c\x37\x83\xe0\x29\x8d\xce\xce\xb3\xca\x62\x8a\xde\x1c\x6a\xe6" . "\x8a\x3c\xcc\x29\x65\x71\x53\x46\xd2\x51\xba\x5d\x5c\xb3\x45\x1b" . "\x66\xcc\x9a\x96\xce\x77\x34\x6e\x4a\x14\x07\x26\x12\xc8\x86\x4a" . "\x21\x69\xb6\xc6\x53\x76\xc7\x13\x0a\x11\x96\x07\x35\xb5\x72\xfc" . "\xc1\x7b\x7f\x07\xd7\x75\x74\x01\x42\x34\xb8\x39\x87\xe3\x43\x24" . "\xc4\x40\x08\xe0\x03\x84\x28\xf8\x90\x2b\xfb\x0c\x49\x74\x1e\xde" . "\x8b\x6a\x1e\x74\x8d\xf3\x86\xb6\x4b\x5c\xb8\xb0\xce\xf2\xd2\x80" . "\x43\x87\xd6\x38\x73\xf6\xe4\xcb\x01\x94\xeb\xda\x0f\x28\xb2\x89" . "\x50\x4a\x69\x2e\x72\xca\xb8\x5f\x6b\x0d\x62\xe6\x69\x28\x01\x1e" . "\xef\x66\x34\xd3\x29\x2e\x65\x92\x6c\xb8\xb4\x87\xa8\x61\x36\xdd" . "\xc9\x86\x43\xb1\x40\xd9\x9a\x14\x5a\x4a\x5b\x03\x86\x14\x77\x71" . "\xd3\x2d\x0c\x11\xe7\x1a\x4a\x53\xd3\x1f\xad\xa0\xea\x21\xba\x1c" . "\x12\x22\xb4\x6e\x42\x24\x62\xeb\x05\xb4\x32\xb8\xd9\x2e\xae\x9d" . "\xa0\x53\x24\x38\x47\x4a\x8a\xe0\x02\xc9\x75\x18\x6d\x09\x21\xd0" . "\xb9\x90\x0d\x32\x44\xa3\x81\x5e\x4a\xd8\x9d\x73\xcc\xb6\x9e\xa1" . "\x4b\x8e\x14\xf2\x03\x3c\x0b\x8e\x59\x74\x4c\x7c\xcb\xcc\x75\x73" . "\x39\x62\xa6\xa5\x87\xbd\x82\xe1\x70\x88\xae\x0c\x62\x02\x92\x3c" . "\x3e\xce\xf0\xb1\x47\x8a\x31\xa3\x98\x24\xa8\x94\x8d\xb6\x9d\x17" . "\x42\xc8\x99\x20\xc5\x90\x53\x73\x80\xe0\x21\xc5\x5c\x4c\x0a\x15" . "\xc9\xd4\x44\xdd\x47\x74\x4d\x8a\x91\x30\x9b\xf0\xf4\x53\x0f\x72" . "\xcd\x55\xc7\xe8\x95\x0b\x25\x80\x5a\x59\x59\xc9\x01\x57\x73\xab" . "\xc5\x39\x6d\x1c\x42\x16\x3b\x69\x63\xe6\x9c\x46\xfe\x01\x54\x02" . "\x91\x48\x51\x68\xc6\xbb\x13\x66\x9d\xcf\x8d\x92\x76\x86\x09\x91" . "\xd2\x18\x8a\xde\x30\x43\xd4\x79\xad\x10\x7d\xcb\x74\xfb\x3c\xca" . "\xb5\x74\xbb\x63\x62\xd7\x90\xca\x82\x6a\x79\x19\xdd\x5f\xc8\x10" . "\xd0\x8f\x89\x6d\x4b\x65\x86\xd4\xf5\x08\x63\x35\xbe\x99\x11\xbb" . "\x19\xd1\x35\xb8\xae\xa5\xeb\x5a\x7c\x3b\xc3\x58\x43\x4c\x8a\x66" . "\xb2\xc3\xb0\xd2\x5c\x7b\xc5\x7e\x96\xea\xc8\x50\xc6\xec\x9e\x79" . "\x9c\xd0\xee\x66\x63\x3c\x72\xe1\xe8\x82\xc7\x79\x9f\xcd\xae\x63" . "\x6e\xfa\x28\x84\xba\xb0\x14\x73\x1b\x78\xe7\x23\x3e\x28\x94\xea" . "\xb3\xef\xe8\xb5\x94\xcb\x7b\xf0\x5a\x32\x10\x99\xfb\xc8\x2b\x14" . "\x78\xf0\x5d\x22\xf8\x94\xe5\x8f\xfe\x62\xe0\x33\x2c\xb7\x4a\x90" . "\x18\xe7\x4a\xeb\x02\xad\x7b\x28\xa9\x91\xa4\x78\xec\xd1\x87\x38" . "\x7e\xfc\x38\x8f\x3d\xfe\x64\xbe\x29\x21\x84\xfb\x2e\x06\x3c\xa5" . "\xdc\x4f\xcd\xed\xc9\x94\xab\xd6\x04\xb6\x28\x50\x26\xcf\xbf\x4a" . "\x4a\xf8\x6e\x4a\xf4\x2d\x83\xd1\x08\x74\x49\x0c\x91\x76\x32\x66" . "\xba\xbd\x89\x46\x50\xb6\x4f\xc2\xe6\x16\xa4\x64\x97\x52\x3f\xdb" . "\x84\x6e\x8c\x0d\x81\xc9\xd6\x19\x9a\x66\x17\x53\xf7\xa8\x17\xd7" . "\x50\xf5\x22\x29\x3a\x62\xd7\xe4\x0d\x2e\x7b\xa8\xb2\x42\x24\x4f" . "\xa1\x48\x70\xc4\x30\x43\xab\x8e\xc9\xce\x3a\x56\x04\x5b\xd4\x24" . "\x1c\xb7\xdd\x71\x3d\xdf\xf8\xa6\x57\xf0\x9d\xdf\xfa\x0d\xac\x16" . "\x3b\xa4\x9d\x93\x14\x3a\xbf\x57\x3e\x05\xd0\x82\xb1\x26\x3f\xac" . "\x29\x51\x16\x25\x8b\x83\x21\xa3\xfe\x00\xa3\x34\x24\x08\x01\x8c" . "\xa9\x48\xd1\x30\xdd\x6d\x90\xae\x65\x63\x73\x03\x51\x91\x52\x07" . "\xb4\x64\x2b\x02\x95\x84\xe4\xb3\x7c\x3a\x06\x21\x06\x48\x49\x65" . "\x05\x06\x99\x84\x54\xc9\x43\x68\x08\xb3\x2d\x24\x8c\x71\x6e\x07" . "\x24\x30\x1a\x0d\xb1\xda\xf0\xc8\x23\x8f\xd0\xef\xcf\xfb\xdc\x4d" . "\xd3\x74\x40\x26\xc3\xe6\x93\x21\x79\xce\x9b\xec\x75\xec\x03\xa2" . "\x14\xc9\x5a\xa2\xb5\x24\x25\x10\x3d\xcd\x64\x9c\x3b\xfb\xc3\x05" . "\xec\x60\x81\xe1\xe2\x12\x51\x81\x03\xaa\xe1\x1e\x94\xed\x03\x9a" . "\x44\x96\x72\xc7\x38\x61\x36\xd9\xc4\x8a\xe0\xc6\xeb\xa4\xcd\x75" . "\x52\xeb\xa9\x06\xab\xf4\x56\x0e\x21\x7a\x40\xd7\x4e\x88\x69\x82" . "\xf4\x7a\xc4\xb2\x9f\x85\x53\x08\x29\x45\x9c\x6b\xe9\x26\x17\x70" . "\xbb\xeb\xc4\x76\x92\x1b\x3a\x08\xdb\xe7\xce\xf2\xe8\xfd\x9f\x60" . "\x3f\x1d\xbb\x27\x1e\xc6\x86\x29\xf8\x98\x7d\x3b\x49\xf8\x10\xf2" . "\x7c\xaf\xd2\x14\xa6\xa0\xd0\x06\xab\x2d\xa4\x84\x35\x86\x14\xc1" . "\xda\xfc\xf1\x4f\x9b\x5b\x17\x30\xe2\x38\x7b\xfc\x09\xce\x9d\x99" . "\x12\x18\x11\x35\x68\x1d\xd1\x3a\x51\x1a\xa1\xd4\x79\x13\x2f\x36" . "\x9b\x64\xde\x66\x55\x73\x69\x49\x69\x15\xb5\x85\x5a\x39\xd2\x6c" . "\x8b\xd4\xed\x50\x19\xc9\x7d\x66\xef\xd9\xdc\xda\x62\xff\x81\x03" . "\xab\x00\xea\xfb\xbe\xef\xfb\x1e\xd7\x46\x6f\x29\x91\xb9\x82\x4a" . "\xcd\x45\x4d\x71\x2e\x90\xf2\x73\x4a\x58\x30\xbd\x1a\x5d\xd6\xf3" . "\xb7\xc0\xd3\xcd\x26\xa4\x10\x10\x53\xe0\x55\x41\x3d\x5a\x20\xa0" . "\x50\xd5\x88\xaa\xae\x11\x65\xc9\x60\x2a\x42\xec\x68\x67\x9b\x68" . "\x15\x70\xbb\xbb\xb8\xcd\x33\xec\x9e\x39\x81\xc6\x50\x8c\xf6\x51" . "\x2d\x1c\x20\x12\x70\x6e\x4c\x90\x94\x49\xa9\xa2\x4f\x42\x93\x62" . "\x22\xba\x0e\x71\x0d\xbe\xd9\x61\x77\xf3\x54\xbe\x79\x46\x73\xdd" . "\x9e\x05\xa6\x9f\x7f\x90\x7f\xfe\x63\xff\x80\xed\x93\xc7\x73\xbf" . "\x01\x41\x91\x53\xa9\x8f\x81\xd6\xfb\x2c\x37\x4f\xd0\x3a\xc7\x78" . "\x3c\x66\x36\x9d\xd1\x39\x47\x12\xc1\x07\xcf\x6c\xb6\xcb\xa0\x5f" . "\x31\x18\xd4\x78\x31\x98\xd1\x31\x42\xef\x10\xad\xd1\xe8\xca\x50" . "\x14\x0a\x5b\x28\xaa\x4a\x53\x5a\x85\xd1\xa0\x2f\x76\xf8\x2e\x72" . "\x62\x73\xbb\xe1\x14\x03\xb5\x32\x54\x3a\x7b\xc6\x89\x14\xb4\xae" . "\xa3\x69\x27\x6c\x5c\xd8\xe4\xec\xd9\xcd\x17\x01\x98\x1f\xfb\x91" . "\x1f\xdd\x55\xa5\x76\x5a\x54\xbe\x4e\x31\x32\xef\x0a\x64\xec\x4f" . "\xc0\xbb\x00\xc9\x62\xfa\x05\xba\xe8\xd3\xc5\xf9\xef\x85\x16\x3f" . "\x1d\x53\xd8\x12\x65\x4b\x42\x02\xab\x2d\x89\x40\xd7\xed\x66\x54" . "\x32\x2f\xd2\x54\x08\xb8\xe9\x18\xad\x22\x22\x9a\xae\xd9\x42\xa7" . "\x8e\x5d\x5b\xd3\x5f\xd9\x47\x58\xde\x4f\x93\x1a\xba\x36\x50\x25" . "\x95\x27\x54\x52\xcc\xd2\x14\x37\x45\x42\x03\x49\x08\x29\xa2\xdc" . "\x84\x15\x35\xe4\xda\x3d\x3d\xce\x7d\xee\xc3\x9c\x7d\xe8\x63\x6c" . "\x9d\x3e\x89\x0a\x8e\x36\x65\x15\x34\xd1\xa1\x44\x13\xe7\xfc\xfb" . "\xb4\xeb\x10\x53\xd2\xfa\x19\x75\x55\x61\x52\xa2\x73\x4d\x2e\x1e" . "\x53\xa4\xd7\x2f\x51\xde\xe3\x9c\xa7\x1e\xae\xd2\x5f\x39\xc6\x6c" . "\x77\x83\x44\x0f\x61\x4a\x4f\x3c\x01\x4f\x14\x41\x9b\xfc\xe9\x16" . "\xe4\x99\x0e\x52\xa6\xfa\x09\x31\xcd\xe3\x26\x44\x09\x58\x23\x28" . "\x11\x74\xd9\xc7\x18\xcb\xb0\xb7\xc0\x6c\x5a\xb3\x77\xb1\xfa\x62" . "\x72\xc1\xf4\x9c\xae\x12\x95\x91\x8e\xce\x50\x98\x18\xf1\x4d\x87" . "\xc6\x50\x56\x23\x94\xae\x28\x6c\x09\x29\xe0\x9c\xcb\xa6\xd4\xf3" . "\x40\x27\xd7\x10\xba\x19\x71\xde\x50\x8e\xcc\xb5\x3f\xdd\x8c\xd9" . "\x74\x17\x53\x95\x74\xdd\x14\x3f\xdb\x62\xf7\xec\x09\x9a\x0b\x67" . "\x30\x55\x8f\xd1\xca\x01\x12\x55\x4e\x1b\x21\xe0\x63\xc4\x25\x47" . "\x14\x8f\xd6\x91\x10\x3a\x0a\x11\x0e\xd4\xc2\xcd\x8b\x91\xf8\xec" . "\x67\x39\x7e\xff\x7d\x6c\x9e\x7e\x9a\x84\x43\x74\xca\xff\xa0\xf9" . "\x4c\x40\x8a\x59\xec\x92\x44\x70\x31\xe1\x53\xc2\x45\xcf\xac\x9b" . "\xd1\x74\x33\x82\x77\xb8\xae\xcd\x77\x3d\x45\x22\x30\x19\x4f\x61" . "\xd6\xf1\xe1\xf7\x7d\x90\xd6\x29\x36\xba\x8a\x9d\xa8\x69\xc8\x9a" . "\x22\x07\x04\x11\xd0\x42\x52\xf3\x2f\x9e\x93\x8c\x30\xff\x48\x11" . "\x17\xf3\x07\xed\x90\x72\x41\xd9\x5b\x3a\x42\x34\x97\x51\x2f\xec" . "\xe3\xe6\xdb\x6e\x7e\xae\x8d\xa8\xb5\x46\xe2\x9c\x3e\x96\xdc\x8d" . "\xca\x36\xde\x90\x44\xcd\x0d\x88\x22\xd1\x35\xb4\x13\x45\x6f\xb4" . "\x4c\x2a\x2d\xa2\x0a\x94\xb2\xb8\x90\x21\x97\x35\x26\xdf\x1c\xd7" . "\x41\x0c\x99\x62\xd0\xd9\xe7\x92\xe8\x91\xd8\xd2\x36\x13\xca\xd1" . "\x12\x93\xb1\x82\x30\x83\xb0\xc1\xe6\xa9\x86\x7a\x65\x3f\x65\x69" . "\xe8\x15\x3d\xa2\xeb\x88\xc9\x11\x12\xf9\x7a\x67\xd8\x42\x5d\x6a" . "\x8e\xac\x0c\x39\xb6\x6c\x18\x9f\xf8\x0c\xe3\xf1\x06\xa1\x9d\x92" . "\x08\x04\xa5\x70\xd1\xcf\x05\xe8\xd9\xbb\x41\x91\x0b\xa9\x38\x47" . "\x73\x6d\x08\x68\x32\x7c\xb4\x5a\xa3\xb5\xce\x0f\xf1\x5c\x39\xb7" . "\x3b\xde\x45\xa7\x88\x9f\x6d\x50\xe9\x05\xc2\xc4\x41\xf2\x4c\x82" . "\xa2\x0a\x50\x90\xf0\x29\xcb\xd9\x15\xb9\xa9\x92\xa9\xf8\x7c\x5c" . "\xe5\xa2\xa8\xca\x08\x29\xe5\x4f\xb3\xd0\xca\xa1\x55\xe0\xfa\x3b" . "\x5e\xc2\xac\xbc\x9c\x13\x17\x1a\x66\xbe\x79\xee\xe4\x67\x19\xf7" . "\xbc\x8b\x35\xe7\xf2\xb5\xd6\x68\x6d\x51\xaa\xc8\x7c\x3e\x09\x49" . "\x01\x89\x8e\x6e\x36\x45\x94\xc1\x45\x21\xe9\x02\xa3\xed\xbc\xf7" . "\x2b\x59\xed\xe0\x5a\x48\x81\x10\x3d\xca\xe8\x4b\x50\x55\x13\x68" . "\xa6\x63\x7a\xfd\x21\x45\x6f\x94\xd3\x4a\xdc\x25\x74\x9b\xb8\x8d" . "\x67\xe9\x36\xcf\x13\x9a\x09\x6d\x33\x21\xfa\x16\x95\x02\x12\x02" . "\x26\x26\x86\xb6\xe0\xc6\x23\x07\x39\x54\x3a\xc6\x27\x3e\xc7\x64" . "\xe3\x14\xd2\x8d\x51\xa1\xc9\x72\x14\x37\x45\x52\x44\x8b\x22\xfa" . "\x78\xc9\x26\xfe\xe2\x54\x46\x9c\xcb\x13\xab\xa2\xa0\xd0\x9a\x52" . "\x69\x7a\x73\x31\x6e\x61\x4c\x86\x92\x4a\x51\xf5\x7b\x84\xc2\x10" . "\x34\xf4\xfa\x25\x83\xba\x42\x69\x4d\x48\x29\x7f\x66\x57\x02\x42" . "\x0e\xba\x16\x35\xdf\x84\xdc\x58\x89\x73\xed\x51\x0a\x73\xa6\x20" . "\x82\x49\x91\xc9\xf6\x29\x8e\x3f\xfc\x71\xd6\xfa\x0a\x3f\xdd\xe0" . "\x91\x07\xef\x7f\xee\xe4\x5f\x7e\xc5\x15\x67\x1e\x7f\xe4\xf3\x6b" . "\x24\x21\xcd\xd9\xcc\xe0\x5d\xc6\x13\x5a\x61\x0b\x43\x08\x31\x4b" . "\x8c\x45\x08\x5d\x83\x56\x06\x65\x7b\xf8\xae\xc3\xe8\x3a\xdb\xb5" . "\x84\x84\x12\x4d\xd7\x4e\x72\xb9\x2d\x09\x51\x06\x92\xce\x2d\xb7" . "\xe4\x88\xd3\x0d\x70\x89\xaa\xbf\xca\xee\x6c\x1b\xd3\xed\x40\x52" . "\x24\x76\x33\x5d\x5b\x29\x44\x02\x92\x0a\x0a\xab\xe9\x89\xe3\xf0" . "\x5a\xc5\x4a\x51\x12\xb6\xce\xb0\xb3\xf1\x2c\xa9\x1b\x73\x31\xac" . "\x41\x72\xf5\x29\x31\xcf\xeb\xe6\x0b\x6c\xe6\xbd\x89\x9c\x94\xb5" . "\x36\x97\x7e\x3f\xa4\x88\x11\x21\xc4\x84\x47\x48\x3e\xa2\x12\x44" . "\xe7\xe9\xd7\x15\x5a\x02\x48\x8f\x62\xf5\x10\xb6\xe7\x19\x39\x8f" . "\x67\x86\xe0\xe9\x92\xc5\x66\x9c\x09\xa8\x4c\x21\x93\x32\xd5\x3e" . "\x6f\xbd\x2a\xa5\xd0\x46\x65\x2f\x89\xa0\x50\x56\xd1\x53\x63\xce" . "\x3f\x7e\x1f\xef\x3e\x7b\x81\x66\xf1\x7a\x9e\x3d\x7d\xea\xb9\x93" . "\x7f\xe4\xe8\x15\x0f\xd8\xa2\x9c\x17\x5a\x69\xfe\x95\xf5\xc9\x49" . "\x42\x7e\xe4\xb4\xcc\x75\xf3\x0a\x3d\xf7\xc0\xac\x8c\x65\xd0\xeb" . "\x53\x54\xb9\xbd\xd7\xb4\x79\x48\x24\x6f\x54\x22\xcc\x3f\x68\x4c" . "\x49\xbe\x92\xa2\x20\xf9\x29\xbb\x5b\xe7\x18\x0e\x16\xb1\xd5\x88" . "\xa8\x0c\x29\xe5\x34\x15\xbd\xc3\x77\x1d\xda\x3b\x7a\xb1\xe3\x40" . "\x2f\x71\xc3\xde\x9a\x51\x73\x96\xd9\xc9\x07\x19\x9f\x39\x4e\x68" . "\xc6\x78\xef\x33\x72\xe9\x5c\xfe\x5e\x4a\xcd\xdb\x79\x8a\x28\xd9" . "\x30\xc9\x47\x9f\xa7\x63\x94\xba\xd4\x20\x72\x21\xe0\x62\xa0\x0b" . "\x91\xd6\x79\x9c\x73\x38\xef\x08\xc4\xdc\x0a\x14\x8d\xc7\xb2\xde" . "\x46\x3e\xfb\xd8\xa3\x6c\x4f\x1a\x66\xc9\x23\xca\x52\x2a\x41\x8b" . "\x23\x99\x04\x16\xb4\x01\x6d\x84\xc2\x08\x95\x55\xf4\x2a\x9d\x1f" . "\x58\x95\x50\x7a\xae\xf4\xd3\x20\x2a\x21\x12\xa9\x6b\x21\xa5\x19" . "\xcb\x8b\x03\xf6\xae\x2c\x3d\x77\xf2\x8f\x5d\x71\xd5\xf8\xb1\x87" . "\x1e\xe5\x99\xe3\xc7\xf3\xb5\x21\x8b\xa5\x32\xbf\x9f\x03\xed\x7d" . "\xa4\x57\x2f\x10\x55\xa2\x8b\xb9\x79\x3d\xbd\xf8\x71\x79\x18\x7a" . "\xc3\x3e\xf5\x68\x84\xe8\x92\xe9\x17\x48\x0e\x05\x2e\x4e\xa6\x48" . "\x44\x52\xc7\x74\xeb\x34\xc3\xd5\x03\x14\xbd\x25\x66\xd3\x4d\xb4" . "\x6a\x09\x2a\x82\xf6\x18\x99\xd0\xd7\x89\x63\x6b\x6b\xac\xf5\x13" . "\xe3\x73\x9f\x27\xec\x9c\x23\x76\x33\x54\x8c\x19\x61\x24\x08\x73" . "\x0b\xc8\x34\x3f\xc5\x09\x99\x3f\xf0\x39\x7d\xe6\xb6\x7a\x1e\x35" . "\x32\x5a\xe7\xd4\x29\xe0\x25\xcf\x7a\x49\x48\x14\xc1\x53\x5a\x45" . "\x59\x28\x5a\x97\x40\x69\x92\x2e\x79\xd5\xd7\x7d\x3d\x51\x6b\x96" . "\xd3\x29\xd8\x9c\x30\x6d\xcf\x51\x99\x40\x4d\x4b\xe7\x25\xcf\x90" . "\x85\x6c\xd4\x91\x45\xc4\x10\x24\x37\x50\x92\x12\x44\x03\x3e\xe6" . "\xb7\x84\x44\x88\x90\x6c\xc1\xd5\x37\xbd\x98\x2d\x73\x80\x03\x61" . "\xf0\xdc\xc9\x5f\x5f\xdf\xf8\xe8\xe5\x47\x8f\x62\xac\x41\xcd\xd1" . "\x4e\x8c\xf9\x1f\xa7\xc5\x61\xe8\xa8\x4c\x42\x42\x43\x4f\x84\x1e" . "\x9a\xa1\x29\x19\x94\x35\x4b\x0b\x8b\xf4\xfa\x3d\x3a\xe7\x98\x4c" . "\x26\xa4\x14\x19\x8d\x46\x39\x29\xa4\xe7\x6e\x10\x73\xff\x34\x49" . "\x2d\xbe\xd9\x62\x3a\xdb\xa1\xe8\x8f\x50\x76\x80\x52\x99\xa6\x2d" . "\x63\xc7\xbe\x2a\x71\xd5\x10\xaa\x9d\x93\x6c\x3c\xf9\x19\xfc\xe6" . "\x19\xba\x66\x86\x8b\xe0\x63\xc8\xf5\x13\x0a\x2d\x42\x4c\x79\x6a" . "\x25\x4f\x33\x66\x7f\x1e\x0d\x14\x4a\x61\x11\x8a\xb9\x33\x61\xdd" . "\xef\x53\xd5\x35\xaa\x30\x78\x20\x28\x4d\x52\x06\xef\x03\xc6\xd6" . "\x98\xfe\x72\xb7\xb0\xf7\xf0\xbf\x39\x70\xdd\x6d\x5c\x08\x86\x77" . "\xfd\xd6\xef\xf0\xbb\xef\xb9\x8f\xcf\x3d\xb6\xc1\xae\xec\x25\x2e" . "\x1d\x61\x26\x16\x2d\x50\xa8\x84\x52\x11\xa5\x13\x5a\xe5\xe0\x6b" . "\x95\x28\xad\x50\x95\x1a\xa3\x21\xa6\x80\xcc\x9b\x2e\x4a\xe7\x6c" . "\xd2\xb6\x1d\x37\xdf\x74\x1b\x2a\x0a\xd7\x5f\x7d\xd5\x73\x27\xff" . "\xaa\xa3\x57\x7e\x64\xd8\xeb\xa7\x87\x1f\x7e\x40\xd6\x4f\x9f\xa1" . "\x50\x82\x01\x14\x1d\x5a\x25\x0a\x84\x82\x80\x4e\x0e\x69\x1b\xa2" . "\x28\x52\xd3\xd2\x9a\x0a\xd1\x0e\x53\x6a\x8a\xfe\x1e\x28\x86\x4c" . "\x67\x53\x74\x33\x03\x4c\xa6\x60\xe7\x79\x3f\xfa\x96\xa4\x73\xd5" . "\x49\x1c\xd3\xee\xae\x33\x5a\xbb\x9a\x6e\xb8\x46\x8c\x9e\x01\x2d" . "\x47\xf6\x2c\xb3\x56\x6b\x66\x1b\x67\x98\x75\xd3\x79\x07\x99\x8b" . "\xae\x0c\xb9\x5a\x96\x0c\x0b\x2f\x3e\x78\x04\x45\x8a\x09\xa3\x22" . "\x51\x14\x4a\x69\x0c\x11\x53\x68\x4c\x59\xa2\x47\x2b\x78\x5d\xfc" . "\xca\x6c\x3a\xfd\x71\xa3\x2d\x6e\xe6\xd8\x73\xf8\xd8\x35\xeb\x67" . "\xce\x1d\x16\x81\xa2\x1e\xa5\x7b\x5f\xff\xc6\xf7\xde\x79\xf7\xcb" . "\x9f\x78\xea\xf4\xe9\xef\xbd\xe5\x95\xe3\x9f\x78\xec\xf1\xe3\x5c" . "\x7d\xe4\x6a\x1e\xf9\xc4\x7d\x94\xab\x2b\x5c\xb9\xaf\xe2\x99\xf7" . "\x3d\x94\xc7\x9c\x52\x4e\xa3\x5a\xc7\xe7\x28\x64\x04\x3d\x2f\xba" . "\x62\x80\x14\x04\x51\x82\x2d\x33\x7d\x6d\x48\x98\xd8\xf2\xf0\xfd" . "\xef\x47\x85\x83\x0c\x0e\xac\xf4\x2e\x05\xff\x6f\xfe\xc0\x0f\x3c" . "\xf5\x7d\x3f\xf0\xdf\x7e\xbe\x2e\xab\xab\x15\x50\x29\x4d\x21\x0a" . "\x2d\x89\x42\x2b\x6a\xa5\xa8\x44\x63\xb5\xa2\x30\x05\xa3\xd1\x90" . "\xc1\xc2\x22\x83\x95\x7d\x78\xdb\xe7\xa9\xad\x31\x27\xd6\xcf\x53" . "\x54\x25\xca\x78\x36\xb7\xd6\x2f\xb1\xd3\x4a\xe7\x53\xa9\xb5\x26" . "\x88\x20\x12\x51\xd1\x11\x76\x36\x29\xd6\x14\x2b\x0b\x8b\x54\x66" . "\xc2\xe5\xcb\x35\xba\x9b\x31\x5d\x3f\x4d\xea\x26\x59\xd5\xf0\xc7" . "\x94\x73\x17\xa7\x49\xd3\x1c\x55\x64\x64\xa5\xf3\x8d\x9a\x7f\xc8" . "\x8d\x16\x33\x97\x2d\xe6\xc1\xbd\xe5\xbd\x87\xe9\x1d\xbc\x6c\xfd" . "\xd8\xd5\x57\xbf\xe3\x07\xff\xee\xdf\xbb\x64\xed\xf8\xc9\xc7\x9e" . "\xf9\x82\x21\x85\x7f\xf9\xc1\xdf\x67\x63\xfd\x82\xfd\xd8\x43\x9f" . "\xfb\xb9\x8f\x7c\xf8\x23\x1b\xc3\x5e\xff\xef\x3e\x1d\x67\x97\xdf" . "\x73\xcf\x8d\x2c\x14\xe7\xa9\xc5\x73\xbe\x5f\x91\x3a\x41\x82\x47" . "\x05\xc1\x26\x4d\x0c\x59\x6c\xe3\x53\x44\xe9\x38\x1f\x7f\x15\x08" . "\x60\x95\x42\x4c\xa2\xb0\x73\xa5\x86\x0e\x3c\xf5\xd8\xc7\x18\x1c" . "\xbc\x9b\xe4\x8e\x1e\xb8\x14\xfc\xe5\xc5\xbe\x7b\xe9\xdd\xf7\xbc" . "\x67\x67\x6b\xfb\x6a\x2d\x19\x3a\x59\x49\x14\x3a\xb7\xc9\x2a\x11" . "\x4a\xa5\xb0\x5a\x51\xd7\x35\x4b\xa3\x45\x56\x56\xd6\xd8\x7f\xd9" . "\x51\xd6\x0e\x1c\xe1\xaf\x1c\xbb\x8c\x8d\x26\xf1\x4f\x7e\xfd\x5f" . "\xe1\xb7\x77\x99\x6d\x9f\xcd\x0e\xe1\x51\x5f\xd2\x70\x86\xf9\x28" . "\x51\x1e\x88\x8e\x14\xcd\x0e\xbd\x6e\x87\x3d\x4b\x25\xc3\xb2\xa2" . "\xdd\x3a\x4d\x3b\xdd\x25\xb6\x33\x94\x8a\x59\x27\x9a\x31\x52\x46" . "\x52\xe9\xb9\x9a\x50\xe6\x8f\x68\x9a\x33\xac\xa2\x32\x77\xa3\xb0" . "\x28\x0d\xa6\xac\xe8\x2d\x1d\x60\xb0\xff\x18\x83\x3d\x6b\x3f\xf2" . "\xc7\x03\xff\xef\xb5\xa1\x59\x5d\xb9\x58\x43\xfd\xd2\xb7\xfc\x95" . "\xb7\xfd\x1f\xef\xff\xc0\xa7\xdf\xc8\x9b\x5f\xf5\x5f\xdf\x73\x45" . "\x78\xed\x85\x27\x3f\xc6\x40\x6f\x51\x96\x02\xce\x12\x55\xc0\x28" . "\x21\xb9\x39\x19\x49\x42\x9b\x9c\xf3\x8c\xe4\x53\x22\x24\xa4\x10" . "\x6c\x6d\x88\xd6\x20\x80\xeb\x26\xec\x6e\x9f\xe4\xe4\xd3\x4f\xde" . "\xf2\x3d\xdf\xf1\x6d\xd7\x5f\x9a\x77\x19\xef\x6c\x3f\xbb\xbd\xb9" . "\x8d\x56\x09\x51\x0a\x51\x60\x75\x6e\xa4\x24\x40\x44\xa1\x6d\x1e" . "\xc9\x14\xad\x31\x45\xf1\xff\xb5\x77\xad\x31\x76\x55\x55\xf8\x5b" . "\x6b\xef\x7d\xce\x7d\xdf\xb9\x33\x77\xa6\xa5\x9d\x96\x96\x02\x95" . "\xc6\x60\x8d\x75\x90\xd0\xa6\x80\x18\x95\xaa\x08\x04\x22\x1a\x83" . "\x2f\x12\x88\x40\x22\xa2\x88\xc2\x0f\x0d\x26\x44\x12\x8d\x98\x28" . "\x51\x4c\xa3\x11\x0d\x81\x94\x04\x8d\xd0\xd6\x6a\x81\xa2\x24\x86" . "\x36\x80\x14\x27\x74\x6c\x3b\x25\x7d\xd0\x29\xf3\xbc\xaf\x73\xce" . "\xde\xdb\x1f\x6b\xdf\x0b\xa4\x55\x22\xe0\x8f\x3e\x56\x72\x93\xf9" . "\x71\x33\x3f\xf6\xd9\x67\xdf\xb5\xbf\xf5\x3d\xe0\x59\x18\xbb\x8a" . "\x22\x9c\xb1\xa0\x8a\x9b\xbe\x78\x25\x6e\xbe\xed\x76\x90\x6d\x81" . "\xe0\xe4\x82\xe6\x44\xcd\x08\xa7\x10\x29\x8d\x62\x21\x46\xbd\x52" . "\x46\xbd\x38\x80\x81\x52\x07\x9d\xc9\x71\x4c\x4f\x1d\x00\xb2\x36" . "\x82\xdc\x0e\xa9\xf7\x20\x56\xf0\xb6\xab\x11\xe0\xd7\x11\x57\x52" . "\x3d\x1c\x85\x40\xd2\x59\x40\x12\x43\xb5\x56\xc8\x15\xfa\x50\x18" . "\x38\x0d\xf9\xf9\x0b\x91\xc5\xf9\x7b\xc6\xc7\x5f\xb9\xf7\x7f\x55" . "\xa7\x3c\xf0\xd0\xc3\x09\x80\x0d\xcf\xdf\xb5\xb9\xf8\xd7\xf5\x37" . "\x7e\x84\xb0\x1b\xa6\xdc\x86\x4d\x15\x7c\x47\x2c\xc8\x9c\x0d\x2d" . "\xa6\x95\x59\x08\x1b\x85\xd4\xcb\xf8\x50\xb3\x87\x56\x04\xc4\x00" . "\xe7\x15\xac\x66\x24\x19\xc1\x38\x46\x2b\x6d\x60\xf6\xf0\xc1\xf8" . "\xd9\xed\x2f\xfe\xa0\xb7\xf8\x2f\xed\xdc\xf9\x3c\x28\xf0\x74\x98" . "\xa0\xb5\x12\xc0\x48\x31\x3c\x69\x58\x74\x7b\x68\x0f\x76\x99\xe0" . "\xd6\xec\x60\xd9\x23\xf3\x31\xc8\x33\x4e\x9f\x5f\x47\x2d\xef\x30" . "\x49\x09\x40\x1e\x11\x79\x14\x14\x23\x3f\x50\x47\xa5\x5c\x44\xb5" . "\x58\xc6\x60\x5f\x09\x05\x4d\x68\x1e\x3e\x82\xd9\x03\xa3\xc8\x92" . "\x59\x64\x59\x22\xbf\x05\x9a\x61\x61\xe1\x10\x72\x58\x25\x2c\x0b" . "\x8a\xa8\x47\x5b\xf4\x4e\xb0\x21\xb0\xf4\x32\x86\x10\xa8\x26\x39" . "\x14\x0a\x55\x94\xfa\x87\x11\xd5\x16\x60\x26\xcd\xb6\xae\xbe\xf8" . "\x82\xef\xdd\xf8\x95\x6b\xde\xb6\x65\xfb\xee\x97\x9e\x5f\xd6\x3a" . "\xbc\x13\xa5\x32\x80\x44\x41\x25\x80\x55\x16\xc8\x34\xb2\x54\xac" . "\x0b\xd8\x10\x88\x15\xb2\xcc\x8b\x86\xcd\x10\x58\xc9\xe6\x81\x11" . "\xf9\x6c\x66\x01\x8f\x08\x96\x35\xac\xca\xa1\xd9\x4e\x70\xe8\xd5" . "\xfd\xeb\xf4\x1b\x85\xc9\xdd\x0e\xa5\x9b\xdc\x16\xae\x5b\x12\xb3" . "\x01\x82\x77\xc1\xe9\xdb\x39\x24\x99\x15\xf4\xd0\x08\xea\xd8\x6a" . "\xa5\x50\xd6\x62\xd9\xe9\x8b\xd1\xe9\x64\x28\x15\xca\xa8\x16\xfb" . "\x30\x34\x7f\x01\x6a\xfd\x35\x14\xe2\x08\x69\x63\x0e\x07\xf7\x8d" . "\xe1\xd0\xf4\x04\xec\x5c\x13\x69\x96\xc8\x9d\x42\x5e\x52\x99\x93" . "\x32\x01\x99\x83\x23\xe9\x64\xe4\x01\x84\x85\xf7\x3e\x40\xb7\x0a" . "\x2e\xd8\xfe\x6a\x28\x20\x57\x40\xdc\x57\x47\x7f\x7d\x11\x74\xae" . "\x82\xa8\x92\xff\xf3\xe7\x3f\x77\xf5\x67\xd6\x5c\xb8\x7a\xee\x1d" . "\x49\x43\x27\xa7\x98\xe7\x2d\x47\x14\xd7\x61\x67\x5f\x83\x9d\x9e" . "\x04\x45\x29\x5c\xdb\x82\x53\x0b\xe5\x34\x9c\x65\x64\x19\xe0\x95" . "\x83\xd6\x92\x0b\xa0\xd8\x41\x47\x04\x6b\x14\x9a\x94\x43\x8a\x12" . "\x5a\x69\x19\x6d\x1a\xc0\x64\xb3\x86\x97\xf7\x1d\xb1\xc5\x62\xe9" . "\xd7\xbd\xc5\x5f\xb6\x6c\x59\x32\x36\x36\xd6\xfb\x81\x73\xd6\xc9" . "\x85\x36\x44\xb6\x09\xe8\xe9\x91\x5a\x91\x39\xce\xb5\x9b\x30\x33" . "\x33\xe0\x83\x07\x31\xd7\x48\x61\x5d\x8a\x66\x6b\x06\xcb\x97\x9e" . "\x83\x25\x0b\xcf\x84\x22\x46\x96\xa4\x70\x99\x45\x67\x72\x12\x87" . "\xe7\x66\x30\x37\x33\x81\xe6\xec\x11\xb8\xb4\x1d\xa0\x58\xd7\x7b" . "\xe8\xc2\x8f\x10\x49\x90\x23\x82\x0d\xa3\x3e\xc1\x69\x02\xfd\x9a" . "\x48\x06\x20\x10\xda\xa0\x89\x22\x68\x8e\x11\x0f\x2c\x44\x34\xb4" . "\x18\x3e\x57\xc0\xd9\x2b\x96\xff\xe5\xdc\x95\x2b\x2f\x5b\xbe\xe2" . "\xec\xe4\x9d\xca\x42\x37\x3d\xb5\xe3\xf1\xb5\xab\xaf\xb8\xb3\x5c" . "\xb2\x48\xa7\xf7\x63\x66\xff\x28\x74\x67\x1a\xc8\x9a\xc8\x1a\xd3" . "\xa0\xd6\x2c\x4c\x96\x40\x59\x91\x42\x65\x16\xd2\x0d\x29\x03\x1b" . "\x03\x36\xaa\x80\x72\xc3\x98\x9a\x89\x71\xa0\xad\x1a\xe3\x07\x9b" . "\x2f\x4c\x4c\x35\x36\xf4\x0f\x2d\x7e\xee\xc5\x3f\xfe\x69\x53\x4f" . "\xd5\xa5\x94\x8a\x00\xdf\x51\x0c\x54\xa2\x08\x25\x45\xc8\x93\xdc" . "\xd8\x22\x32\x88\x94\x82\xd6\x40\x94\x8b\x51\x2e\x57\x11\x17\xcb" . "\xf0\x2a\x0f\x65\x8a\x00\xcb\xeb\xa5\x58\x21\xa2\xa0\x53\x52\x84" . "\x66\x63\x16\x59\xb3\x89\xb9\x29\xa1\x6b\x78\x97\xc0\xda\x44\xe0" . "\x68\x56\x20\xe2\x40\xff\x53\xd2\x4e\x92\x0d\xde\xc9\x32\x01\x23" . "\x62\x68\x68\x68\xf1\x3d\x12\x74\x94\x00\x56\x72\xcb\xe6\x7c\x09" . "\x71\x75\x11\xf4\xbc\xa5\x98\x6a\xce\x62\x61\xad\x7a\xff\x17\x3e" . "\x7b\xd5\xd7\x2f\xba\xf4\xc3\x33\xef\x86\x26\x77\x6a\x66\x22\xbf" . "\x77\xef\xae\x8f\x3e\xb9\x65\xdb\x75\xc3\x83\x15\xb3\x77\xf4\x59" . "\x8c\xac\x5a\x79\xfe\xfc\xd3\x6a\x7a\x66\xe2\x95\x5c\xf3\xc8\x6e" . "\xa0\xfd\x1a\xda\x8d\x29\x64\x1d\x0b\xe2\x08\x96\xf2\x28\xd6\x16" . "\xa0\x32\x7f\xc1\x91\xca\xbc\xe1\xfd\xe3\xfb\x8e\x3c\x73\x60\xa2" . "\xb9\x8d\x4d\x61\xe3\xd5\xd7\xde\x7c\xe8\x98\x22\x68\x66\x56\x44" . "\xb4\x1b\xde\x2d\xaa\xc6\x11\xaa\x91\x42\x0c\x40\x91\x87\x61\x0d" . "\xc3\x0c\xad\x85\xa2\x6d\xe2\x1c\x48\x47\x70\x30\xc8\xc5\x05\xc0" . "\x77\xe0\x95\x47\x31\x57\x04\x52\x46\xc6\x40\xa3\xdd\x80\x4d\x65" . "\x24\xe7\xd2\x44\x60\x0a\x97\x80\x49\xc1\x5a\x84\x9e\xbd\xcb\x87" . "\x21\x78\x9f\x06\x27\xc1\x20\x53\x27\x61\x34\x68\x30\xb4\x0f\x01" . "\x43\x2c\xf9\x5a\x26\x8e\x60\x8a\x25\x98\xfa\x22\xb4\xf2\xc3\x78" . "\x35\xa5\xe6\xf0\xbc\xca\xed\x8f\xac\xff\xe1\xbd\xf8\x3f\x57\x6b" . "\xee\x70\x64\xe1\xce\x49\x5a\x8d\x2b\x7d\x63\x66\x6d\x44\xb6\xb0" . "\x67\xec\x65\xdd\x68\x4c\x63\xdf\xf8\xbe\x27\x0a\xd5\xfa\xd3\x1f" . "\xbf\xfc\x9a\xad\x5c\x9c\xf7\x96\xf1\x7f\x6f\xd2\x33\x6a\xa3\xb7" . "\x7a\xe7\xd6\x56\xe3\x18\x65\xcd\x88\x03\xab\x41\x2b\x46\xa4\x14" . "\x22\x23\xf2\x20\xee\xa2\x98\x2a\x58\x02\x84\xe3\x80\x40\xf0\xce" . "\x23\xb1\x09\xbc\x17\xac\xa6\x1b\xb3\xe7\xde\x30\x50\x27\xcf\x70" . "\x5e\xc3\x06\x3e\x28\x03\x80\x4b\xc3\x05\x8a\xa0\x3c\x04\x0d\x05" . "\x10\x79\x61\x26\x40\x33\xbc\x62\xc4\xb1\x82\x29\xf7\x23\x37\x74" . "\x06\x66\x55\x05\x53\xb3\x8d\x17\xfb\xea\xfd\x97\x3f\xf6\xd0\x7d" . "\x2f\x1f\x6f\x96\x2f\x6f\x1a\xa6\x94\x4a\xa5\x67\xbd\x47\x2f\xa7" . "\xb6\x47\xe2\x09\x3a\x5c\x6b\x2d\x6c\x96\xca\x4e\xce\x52\x64\xed" . "\x36\x92\x56\x13\x2e\x6d\x22\x69\xcd\xf6\x3e\x36\x6d\xc2\x67\x5d" . "\xc6\xb2\x93\xd8\x25\x0f\x19\xe5\x41\xac\x7b\x13\x38\x24\x2e\x83" . "\x25\x87\xd4\x59\xb8\x9e\xe5\x97\x07\x94\xcc\x02\x88\x3c\x3c\x67" . "\x80\xf6\x20\x05\xb9\x49\xd7\x86\x60\x06\xcf\xc0\x2c\x55\x6d\x1c" . "\x99\x6f\x5e\x71\xc5\xa5\x1f\x38\x1e\x17\xfe\xa8\x9d\xcf\x4a\x7d" . "\x87\x80\xbb\xf2\x9a\x31\x90\x8b\x61\xbc\xb4\x94\x5a\x0b\x07\x52" . "\x31\x20\x51\x02\x2a\xdc\x3a\x65\x9e\x48\x4a\x78\x99\xf0\xd2\xb9" . "\x74\x47\x6a\x8a\xc5\x19\xdc\x06\xeb\x75\x87\xe0\x18\x0b\x19\x36" . "\xd8\x80\xfd\xb0\xf5\xd0\xc4\xc2\x4b\x81\xdc\xaa\x99\xb4\x90\x6d" . "\x7d\x06\x65\x72\xd0\x71\x1e\x51\xb5\x06\x14\x6b\x68\x20\x9e\x68" . "\x74\xcc\xea\xbf\x6f\xdb\x30\x8a\xe3\xb8\xde\xb4\xf3\x47\xce\x1b" . "\x79\x90\x15\x27\x40\x18\x81\x75\x55\x2a\xf0\xc1\x26\x41\xee\x00" . "\x0e\x0e\x99\x4b\x61\xbd\x13\x76\x2e\x11\x3c\x09\xc6\x01\x56\xc8" . "\x3c\xe0\x99\xd1\xb1\x4e\x00\x31\x2b\x21\x93\x99\x95\x94\x37\x17" . "\x46\x7c\x82\xd6\xb0\xa0\x8f\x0c\x80\xc4\xe0\xce\xfb\x08\x84\x18" . "\x8a\x23\x28\x1d\x41\xc7\x79\xe4\xfb\xe6\xa1\x93\x1b\xc0\x64\x62" . "\x37\xac\x59\xbb\x66\xf1\xd6\xc7\x7f\xb9\x0b\xc7\x79\x1d\xa5\x61" . "\x2f\x57\x4a\x13\x68\xb5\x07\xaa\xb1\x81\x51\x0e\x86\xe4\x66\x1a" . "\x11\x60\x08\x60\xcd\xc8\xbc\x83\x47\x50\x89\x7b\x09\x0a\x96\xbf" . "\x43\xc8\x70\x00\xc3\x32\x6b\xc5\xe2\xc5\x21\xa8\xb4\x45\xd0\xe6" . "\xbd\x97\x09\x50\xe0\xba\x88\xc7\x0e\xc3\x42\xa4\xa5\x06\x80\x61" . "\x25\x6f\x5d\x21\x06\xfa\xe6\x63\xd6\x47\x87\x16\x2e\x1c\xbc\x6d" . "\xd5\x79\x6b\x1e\xb8\xed\xd6\xaf\x66\x38\x01\xea\xa8\xc5\xaf\x0f" . "\xf4\xff\xbc\x3d\x3d\x73\x5d\x5f\x3e\x86\xe6\x0c\x4c\x8c\x58\x47" . "\x88\x99\xa0\xe1\x43\xba\xa6\x0f\xb4\xda\x2e\x70\x26\x0f\xa3\x3b" . "\xed\x0a\x94\x52\xd1\x2c\x51\xf7\xa8\xa2\x00\x11\x08\x6a\xa3\x03" . "\x3b\x4e\x87\xc0\x32\x22\xd1\x36\x39\xe7\x85\x0b\xaf\x63\x44\xc5" . "\x2a\x7c\xa1\x02\x97\x2b\x1e\xda\xb5\x77\xdf\xc5\xe3\x7b\x46\x77" . "\xe2\x04\xaa\xa3\xac\x33\x26\x27\xa7\x9f\x70\xc4\xc8\x7c\x37\xf6" . "\x5a\x60\x85\xc4\x7b\x99\xde\x3b\xb9\x7d\x66\xde\x0b\x47\xde\x3a" . "\x24\xce\xa3\x9d\xc9\xc4\xbe\xe3\x1c\x12\xef\x91\x38\x0f\x0b\x86" . "\x47\x37\x01\x42\x68\xd8\xc2\xee\xe2\x9e\x58\xb8\xc7\x0f\x0d\x9a" . "\x5f\x65\x14\x38\x97\x87\xa9\x54\x51\x5e\xb0\xb8\xd5\x40\xf4\xed" . "\x0f\x5d\xb0\xe6\xec\x13\x6d\xe1\x8f\xb9\xf3\x95\xd2\x4b\x0d\xf3" . "\xbf\xca\x91\x42\x51\x07\xe7\x6e\x56\xd0\x0c\x90\x77\x61\x44\x86" . "\x30\xc8\x90\xdd\xdf\x1b\x1e\xcb\x6b\x01\x0e\x9c\xf5\xae\xbc\x54" . "\x13\x0b\xcf\x31\xf4\x50\x4c\x32\x84\x60\xe6\xde\xe0\xda\xb3\x12" . "\xe1\x5c\xbe\x08\x53\x1d\x70\x4b\x96\x9d\xf9\xe8\x85\x6b\x2f\xfa" . "\xd6\xb5\xd7\x7d\x79\x14\x27\x68\x1d\xb5\xf8\x5a\x47\x55\x82\xdb" . "\x55\x31\xaa\x5e\x32\x12\x9b\x47\x00\x74\xe0\x3a\xaa\x20\x83\x94" . "\xa6\x5c\xce\x71\x1b\x60\x5e\x04\x9e\x03\xe9\x80\x11\x59\x51\x64" . "\x33\x00\x15\x8e\x17\xe9\xaa\x48\x04\x64\x5d\x0b\x30\x62\x98\x38" . "\x0f\xca\xe7\xb0\x74\xc5\x7b\x5f\x58\x39\xb2\xe6\x6b\xb7\x7e\xe3" . "\x96\x2d\x38\xc1\xeb\x98\x9e\x55\xb5\x6a\x75\xb3\x6d\x36\x2e\xa9" . "\x44\x0a\x4a\x13\x62\x63\x7a\x58\x3c\x7c\x57\x2a\x24\xd4\x08\xe7" . "\x3d\x1c\x13\x3c\x29\xb1\xc1\x72\x29\xa0\x20\x92\x7d\x2b\x54\x14" . "\xa5\xc4\xb2\xb1\xb7\xf8\x2c\x74\x3e\x80\xc0\xca\x40\x2b\x83\x72" . "\xff\x60\x76\xee\xc8\x07\xef\xfc\xd1\x7d\xbf\xb8\x1b\x27\x49\x1d" . "\x33\x33\x25\x4d\xd3\xf7\x7b\xef\xce\xd7\x5a\x8e\x1c\xc5\x0c\x1f" . "\x8c\x1d\xd0\xb3\x7f\x21\x31\xc0\x60\x12\xe9\x65\x10\xd3\x51\x77" . "\x60\x1c\x04\x16\xdd\xc7\xdb\xed\x86\xba\x47\x13\x41\x5c\x49\xa0" . "\x62\x0c\x0c\x9d\xf6\x54\xa1\x5a\xbb\xec\x57\x0f\x3d\xbc\x01\x27" . "\x51\x1d\x33\xbc\x60\xe9\xb2\x33\x9f\xb4\x20\x24\x4e\x50\x3a\x6b" . "\xf1\xba\x47\x5a\xf8\x74\x21\x98\xa0\xc1\x96\x2e\xc7\x31\x6c\x46" . "\xe1\x42\x45\x3d\x54\x54\x7c\x74\xc2\xff\x72\x22\xbe\xf3\xda\xc0" . "\x99\x18\xc5\xfe\xfa\xfa\x8f\x7d\xea\xb2\x75\x8f\x6e\xd9\xf2\x02" . "\x4e\xb2\x3a\xe6\xe2\x5f\x7f\xfd\x0d\x7f\x73\xc4\x73\x49\xf0\xd0" . "\x71\xce\xf7\x18\xb8\xd6\xb9\xc0\xcb\x0c\x7c\x18\x79\x02\xc2\xd0" . "\xf2\x0c\x19\xbd\xeb\xd0\xe1\xc8\x4c\xc4\x83\x90\x58\x87\xcc\x8b" . "\x5e\xc9\x14\x0a\x88\xca\x95\xf6\x92\xb3\xce\xba\x65\xdb\xf6\x1d" . "\x5f\xba\xe5\x8e\x3b\x66\x71\x12\xd6\x31\x8f\x9d\x4d\x9b\x36\x36" . "\xfa\xfb\x6b\x83\xad\x76\xe7\x7c\xe5\x83\x3a\xc5\x0b\x1d\xd7\xb3" . "\x08\xc1\xd8\xeb\xd0\xd3\x4b\xc0\x8c\xf7\x41\xfc\x4b\x8c\x0c\x2c" . "\xdf\x73\x0e\xce\x91\x18\x5d\x28\x03\xe8\x08\x1c\xe7\x41\x51\xfe" . "\xf7\x97\x5c\xba\xee\x93\xeb\x7f\xf3\xdb\xc7\x70\x12\xd7\x7f\x34" . "\x89\x1c\x19\x19\x79\xcf\x8e\xed\xdb\xff\xa1\x19\x2a\x62\x46\xac" . "\x09\x86\x21\xc1\x31\x50\x20\x27\xec\x63\xc7\x0e\xd2\xef\x70\xa0" . "\x8f\xaa\xc0\x74\x73\x80\xf2\x80\xd2\x20\x9d\x07\xeb\x18\x95\x52" . "\xf9\x9f\xf3\x86\x06\xbf\x7f\xd5\x95\x57\x3f\x7c\xfd\x4d\x37\xb4" . "\x71\x92\xd7\x7f\x75\xe8\x54\x4a\x3d\x02\xc2\xa7\x8d\x62\x44\x8a" . "\x10\x31\xa0\x08\x50\xd0\x10\x76\x8c\x44\x6b\x38\xb2\xe2\x7b\x1c" . "\xd8\x6d\x4c\x04\x65\x14\x2c\x03\x51\xae\x70\x48\x45\x85\xa7\xfb" . "\x06\x06\xef\x1f\xdf\xb3\x7b\xf3\xc4\xc1\x03\x19\x4e\xd5\x5b\x2f" . "\xfe\xaa\x55\xab\x56\x6c\xdf\xf1\xdc\x33\x8a\x7d\xd9\x70\x90\xc0" . "\x2b\x86\x77\x04\x05\xf1\xde\x24\x05\x01\x8a\x49\x41\x99\x68\x4f" . "\x9c\xcb\x8f\x36\xe7\x9a\xa3\xf5\xc1\x81\x23\xe5\x6a\xe5\x89\x5a" . "\x7f\xfd\xe9\x8d\x1b\x37\x9f\x5a\xf0\xb7\x53\x5a\xeb\x7b\x8c\x31" . "\xde\x18\xed\x73\x71\xe4\xcb\x85\x82\xaf\xe4\xf3\xbe\xbf\x54\x79" . "\xb5\x56\x2c\xff\xf8\x7d\x2b\xce\xb9\xbc\xde\x57\x1c\x9e\x3f\xd4" . "\x3f\x7c\xf7\x5d\xdf\x8d\x4e\xad\xd8\xbb\xb4\xf3\x01\x20\x9f\xcf" . "\x2f\x58\xb4\x68\xd1\x1f\xc6\xc6\xc6\x7e\xc7\xcc\x88\xa3\x08\x83" . "\x03\xf5\xd9\x4f\xac\x5b\xf7\xe0\x4f\x7e\xf6\xd3\xc9\x53\x4b\xf8" . "\xf6\xeb\xdf\x6f\xae\x68\xfd\xce\x54\x8f\x14\x00\x00\x00\x00\x49" . "\x45\x4e\x44\xae\x42\x60\x82\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x" ; } sub get_file_owner { my $path = shift; my ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path); my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid); if (!defined $gcos) { return undef; } my $owner = $gcos; $owner =~ s/[,;].*$//; return decode("utf8", $owner, Encode::FB_DEFAULT); } sub git_read_projects { my @list; if (-d $projects_list) { # search in directory my $dir = $projects_list; opendir my $dh, $dir or return undef; while (my $dir = readdir($dh)) { if (-e "$projectroot/$dir/HEAD") { my $pr = { path => $dir, }; push @list, $pr } } closedir($dh); } elsif (-f $projects_list) { # read from file(url-encoded): # 'git%2Fgit.git Linus+Torvalds' # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' # 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman' open my $fd , $projects_list or return undef; while (my $line = <$fd>) { chomp $line; my ($path, $owner) = split ' ', $line; $path = unescape($path); $owner = unescape($owner); if (!defined $path) { next; } if (-e "$projectroot/$path/HEAD") { my $pr = { path => $path, owner => decode("utf8", $owner, Encode::FB_DEFAULT), }; push @list, $pr } } close $fd; } @list = sort {$a->{'path'} cmp $b->{'path'}} @list; return @list; } sub git_project_list { my @list = git_read_projects(); my @projects; if (!@list) { die_error(undef, "No project found."); } foreach my $pr (@list) { my $head = git_read_head($pr->{'path'}); if (!defined $head) { next; } $ENV{'GIT_DIR'} = "$projectroot/$pr->{'path'}"; my %co = git_read_commit($head); if (!%co) { next; } $pr->{'commit'} = \%co; if (!defined $pr->{'descr'}) { my $descr = git_read_description($pr->{'path'}) || ""; $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { $pr->{'owner'} = get_file_owner("$projectroot/$pr->{'path'}") || ""; } push @projects, $pr; } git_header_html(); if (-f $home_text) { print "
\n"; open (my $fd, $home_text); print <$fd>; close $fd; print "
\n"; } print "\n" . "\n"; if (!defined($order) || (defined($order) && ($order eq "project"))) { @projects = sort {$a->{'path'} cmp $b->{'path'}} @projects; print "\n"; } else { print "\n"; } if (defined($order) && ($order eq "descr")) { @projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects; print "\n"; } else { print "\n"; } if (defined($order) && ($order eq "owner")) { @projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects; print "\n"; } else { print "\n"; } if (defined($order) && ($order eq "age")) { @projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects; print "\n"; } else { print "\n"; } print "\n" . "\n"; my $alternate = 0; foreach my $pr (@projects) { if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n"; my $colored_age; if ($pr->{'commit'}{'age'} < 60*60*2) { $colored_age = "$pr->{'commit'}{'age_string'}"; } elsif ($pr->{'commit'}{'age'} < 60*60*24*2) { $colored_age = "$pr->{'commit'}{'age_string'}"; } else { $colored_age = "$pr->{'commit'}{'age_string'}"; } print "\n" . "\n" . "\n"; } print "
Project" . $cgi->a({-class => "header", -href => "$my_uri?" . esc_param("o=project")}, "Project") . "Description" . $cgi->a({-class => "header", -href => "$my_uri?" . esc_param("o=descr")}, "Description") . "Owner" . $cgi->a({-class => "header", -href => "$my_uri?" . esc_param("o=owner")}, "Owner") . "Last Change" . $cgi->a({-class => "header", -href => "$my_uri?" . esc_param("o=age")}, "Last Change") . "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=summary"), -class => "list"}, esc_html($pr->{'path'})) . "$pr->{'descr'}" . chop_str($pr->{'owner'}, 15) . "$colored_age" . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=log")}, "log") . "
\n"; git_footer_html(); } sub read_info_ref { my $type = shift || ""; my %refs; # 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11 # c39ae07f393806ccf406ef966e9a15afc43cc36a refs/tags/v2.6.11^{} open my $fd, "$projectroot/$project/info/refs" or return; while (my $line = <$fd>) { chomp($line); if ($line =~ m/^([0-9a-fA-F]{40})\t.*$type\/([^\^]+)/) { if (defined $refs{$1}) { $refs{$1} .= " / $2"; } else { $refs{$1} = $2; } } } close $fd or return; return \%refs; } sub git_read_refs { my $ref_dir = shift; my @reflist; my @refs; opendir my $dh, "$projectroot/$project/$ref_dir"; while (my $dir = readdir($dh)) { if ($dir =~ m/^\./) { next; } if (-d "$projectroot/$project/$ref_dir/$dir") { opendir my $dh2, "$projectroot/$project/$ref_dir/$dir"; my @subdirs = grep !m/^\./, readdir $dh2; closedir($dh2); foreach my $subdir (@subdirs) { push @refs, "$dir/$subdir" } next; } push @refs, $dir; } closedir($dh); foreach my $ref_file (@refs) { my $ref_id = git_read_hash("$project/$ref_dir/$ref_file"); my $type = git_get_type($ref_id) || next; my %ref_item; my %co; $ref_item{'type'} = $type; $ref_item{'id'} = $ref_id; $ref_item{'epoch'} = 0; $ref_item{'age'} = "unknown"; if ($type eq "tag") { my %tag = git_read_tag($ref_id); $ref_item{'comment'} = $tag{'comment'}; if ($tag{'type'} eq "commit") { %co = git_read_commit($tag{'object'}); $ref_item{'epoch'} = $co{'committer_epoch'}; $ref_item{'age'} = $co{'age_string'}; } elsif (defined($tag{'epoch'})) { my $age = time - $tag{'epoch'}; $ref_item{'epoch'} = $tag{'epoch'}; $ref_item{'age'} = age_string($age); } $ref_item{'reftype'} = $tag{'type'}; $ref_item{'name'} = $tag{'name'}; $ref_item{'refid'} = $tag{'object'}; } elsif ($type eq "commit"){ %co = git_read_commit($ref_id); $ref_item{'reftype'} = "commit"; $ref_item{'name'} = $ref_file; $ref_item{'title'} = $co{'title'}; $ref_item{'refid'} = $ref_id; $ref_item{'epoch'} = $co{'committer_epoch'}; $ref_item{'age'} = $co{'age_string'}; } push @reflist, \%ref_item; } # sort tags by age @reflist = sort {$b->{'epoch'} <=> $a->{'epoch'}} @reflist; return \@reflist; } sub git_summary { my $descr = git_read_description($project) || "none"; my $head = git_read_head($project); my %co = git_read_commit($head); my %cd = date_str($co{'committer_epoch'}, $co{'committer_tz'}); my $owner; if (-f $projects_list) { open (my $fd , $projects_list); while (my $line = <$fd>) { chomp $line; my ($pr, $ow) = split ' ', $line; $pr = unescape($pr); $ow = unescape($ow); if ($pr eq $project) { $owner = decode("utf8", $ow, Encode::FB_DEFAULT); last; } } close $fd; } if (!defined $owner) { $owner = get_file_owner("$projectroot/$project"); } my $refs = read_info_ref(); git_header_html(); print "
\n" . "summary". " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$head")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$head")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree")}, "tree") . "

\n" . "
\n"; print "
 
\n"; print "\n" . "\n" . "\n" . "\n" . "
description" . esc_html($descr) . "
owner$owner
last change$cd{'rfc2822'}
\n"; open my $fd, "-|", "$gitbin/git-rev-list --max-count=17 " . git_read_head($project) or die_error(undef, "Open failed."); my (@revlist) = map { chomp; $_ } <$fd>; close $fd; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog"), -class => "title"}, "shortlog") . "
\n"; my $i = 16; print "\n"; my $alternate = 0; foreach my $commit (@revlist) { my %co = git_read_commit($commit); my %ad = date_str($co{'author_epoch'}); if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; if ($i-- > 0) { my $ref = ""; if (defined $refs->{$commit}) { $ref = " " . esc_html($refs->{$commit}) . ""; } print "\n" . "\n" . "\n" . "\n" . ""; } else { print "\n" . ""; last; } } print ""; my $taglist = git_read_refs("refs/tags"); if (defined @$taglist) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tags"), -class => "title"}, "tags") . "
\n"; my $i = 16; print "
$co{'age_string'}" . esc_html(chop_str($co{'author_name'}, 10)) . ""; if (length($co{'title_short'}) < length($co{'title'})) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list", -title => "$co{'title'}"}, "" . esc_html($co{'title_short'}) . "$ref"); } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list"}, "" . esc_html($co{'title'}) . "$ref"); } print "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$commit")}, "commitdiff") . "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "...") . "
\n"; my $alternate = 0; foreach my $entry (@$taglist) { my %tag = %$entry; my $comment_lines = $tag{'comment'}; my $comment = shift @$comment_lines; if (defined($comment)) { $comment = chop_str($comment, 30, 5); } if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; if ($i-- > 0) { print "\n" . "\n" . "\n" . "\n" . ""; } else { print "\n" . ""; last; } } print ""; } my $headlist = git_read_refs("refs/heads"); if (defined @$headlist) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=heads"), -class => "title"}, "heads") . "
\n"; my $i = 16; print "
$tag{'age'}" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}"), -class => "list"}, "" . esc_html($tag{'name'}) . "") . ""; if (defined($comment)) { print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, $comment); } print ""; if ($tag{'type'} eq "tag") { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, "tag") . " | "; } print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); } print "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tags")}, "...") . "
\n"; my $alternate = 0; foreach my $entry (@$headlist) { my %tag = %$entry; if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; if ($i-- > 0) { print "\n" . "\n" . "\n" . ""; } else { print "\n" . ""; last; } } print ""; } git_footer_html(); } sub git_tag { my $head = git_read_head($project); git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$head")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$head")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;hb=$head")}, "tree") . "
\n" . "
\n" . "
\n"; my %tag = git_read_tag($hash); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash"), -class => "title"}, esc_html($tag{'name'})) . "\n" . "
\n"; print "
\n" . "
$tag{'age'}" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}"), -class => "list"}, "" . esc_html($tag{'name'}) . "") . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'name'}")}, "log") . "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=heads")}, "...") . "
\n" . "\n" . "\n" . "\n" . "\n" . "\n"; if (defined($tag{'author'})) { my %ad = date_str($tag{'epoch'}, $tag{'tz'}); print "\n"; print "\n"; } print "
object" . $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=$tag{'type'};h=$tag{'object'}")}, $tag{'object'}) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'type'};h=$tag{'object'}")}, $tag{'type'}) . "
author" . esc_html($tag{'author'}) . "
" . $ad{'rfc2822'} . sprintf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}) . "
\n\n" . "\n"; print "
"; my $comment = $tag{'comment'}; foreach my $line (@$comment) { print esc_html($line) . "
\n"; } print "
\n"; git_footer_html(); } sub git_tags { my $head = git_read_head($project); git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$head")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$head")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;hb=$head")}, "tree") . "
\n" . "
\n" . "
\n"; my $taglist = git_read_refs("refs/tags"); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary"), -class => "title"}, " ") . "
\n"; print "\n"; my $alternate = 0; if (defined @$taglist) { foreach my $entry (@$taglist) { my %tag = %$entry; my $comment_lines = $tag{'comment'}; my $comment = shift @$comment_lines; if (defined($comment)) { $comment = chop_str($comment, 30, 5); } if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . "\n" . ""; } } print ""; git_footer_html(); } sub git_heads { my $head = git_read_head($project); git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$head")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$head")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;hb=$head")}, "tree") . "
\n" . "
\n" . "
\n"; my $taglist = git_read_refs("refs/heads"); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary"), -class => "title"}, " ") . "
\n"; print "
$tag{'age'}" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}"), -class => "list"}, "" . esc_html($tag{'name'}) . "") . ""; if (defined($comment)) { print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, $comment); } print ""; if ($tag{'type'} eq "tag") { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, "tag") . " | "; } print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); } print "
\n"; my $alternate = 0; if (defined @$taglist) { foreach my $entry (@$taglist) { my %tag = %$entry; if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . ""; } } print ""; git_footer_html(); } sub git_get_hash_by_path { my $base = shift; my $path = shift || return undef; my $tree = $base; my @parts = split '/', $path; while (my $part = shift @parts) { open my $fd, "-|", "$gitbin/git-ls-tree $tree" or die_error(undef, "Open git-ls-tree failed."); my (@entries) = map { chomp; $_ } <$fd>; close $fd or return undef; foreach my $line (@entries) { #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/; my $t_mode = $1; my $t_type = $2; my $t_hash = $3; my $t_name = validate_input(unquote($4)); if ($t_name eq $part) { if (!(@parts)) { return $t_hash; } if ($t_type eq "tree") { $tree = $t_hash; } last; } } } } sub git_blob { if (!defined $hash && defined $file_name) { my $base = $hash_base || git_read_head($project); $hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file."); } open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error(undef, "Open failed."); git_header_html(); if (defined $hash_base && (my %co = git_read_commit($hash_base))) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "
\n"; if (defined $file_name) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash;f=$file_name")}, "plain") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=HEAD;f=$file_name")}, "head") . "
\n"; } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash")}, "plain") . "
\n"; } print "
\n". "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) . "
\n"; } else { print "
\n" . "

\n" . "
$hash
\n"; } if (defined $file_name) { print "
" . esc_html($file_name) . "
\n"; } print "
\n"; my $nr; while (my $line = <$fd>) { chomp $line; $nr++; while ((my $pos = index($line, "\t")) != -1) { if (my $count = (8 - ($pos % 8))) { my $spaces = ' ' x $count; $line =~ s/\t/$spaces/; } } printf "
%4i %s
\n", $nr, $nr, $nr, esc_html($line); } close $fd or print "Reading blob failed.\n"; print "
"; git_footer_html(); } sub git_blob_plain { my $save_as = "$hash.txt"; if (defined $file_name) { $save_as = $file_name; } print $cgi->header(-type => "text/plain", -charset => 'utf-8', '-content-disposition' => "inline; filename=\"$save_as\""); open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or return; undef $/; print <$fd>; $/ = "\n"; close $fd; } sub git_tree { if (!defined $hash) { $hash = git_read_head($project); if (defined $file_name) { my $base = $hash_base || $hash; $hash = git_get_hash_by_path($base, $file_name, "tree"); } if (!defined $hash_base) { $hash_base = $hash; } } $/ = "\0"; open my $fd, "-|", "$gitbin/git-ls-tree -z $hash" or die_error(undef, "Open git-ls-tree failed."); chomp (my (@entries) = <$fd>); close $fd or die_error(undef, "Reading tree failed."); $/ = "\n"; my $refs = read_info_ref(); my $ref = ""; if (defined $refs->{$hash_base}) { $ref = " " . esc_html($refs->{$hash_base}) . ""; } git_header_html(); my $base_key = ""; my $base = ""; if (defined $hash_base && (my %co = git_read_commit($hash_base))) { $base_key = ";hb=$hash_base"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash_base")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash_base")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . " | tree" . "

\n" . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'}) . $ref) . "\n" . "
\n"; } else { print "
\n"; print "

\n"; print "
$hash
\n"; } if (defined $file_name) { $base = esc_html("$file_name/"); print "
/" . esc_html($file_name) . "
\n"; } else { print "
/
\n"; } print "
\n"; print "
$tag{'age'}" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}"), -class => "list"}, "" . esc_html($tag{'name'}) . "") . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'name'}")}, "log") . "
\n"; my $alternate = 0; foreach my $line (@entries) { #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/; my $t_mode = $1; my $t_type = $2; my $t_hash = $3; my $t_name = validate_input($4); if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n"; if ($t_type eq "blob") { print "\n" . "\n"; } elsif ($t_type eq "tree") { print "\n" . "\n"; } print "\n"; } print "
" . mode_str($t_mode) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name"), -class => "list"}, esc_html($t_name)) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name")}, "blob") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$t_hash$base_key;f=$base$t_name")}, esc_html($t_name)) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$t_hash$base_key;f=$base$t_name")}, "tree") . "
\n" . ""; git_footer_html(); } sub git_rss { # http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ open my $fd, "-|", "$gitbin/git-rev-list --max-count=150 " . git_read_head($project) or die_error(undef, "Open failed."); my (@revlist) = map { chomp; $_ } <$fd>; close $fd or die_error(undef, "Reading rev-list failed."); print $cgi->header(-type => 'text/xml', -charset => 'utf-8'); print "\n". "\n"; print "\n"; print "$project\n". "" . esc_html("$my_url?p=$project;a=summary") . "\n". "$project log\n". "en\n"; for (my $i = 0; $i <= $#revlist; $i++) { my $commit = $revlist[$i]; my %co = git_read_commit($commit); # we read 150, we always show 30 and the ones more recent than 48 hours if (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) { last; } my %cd = date_str($co{'committer_epoch'}); open $fd, "-|", "$gitbin/git-diff-tree -r $co{'parent'} $co{'id'}" or next; my @difftree = map { chomp; $_ } <$fd>; close $fd or next; print "\n" . "" . sprintf("%d %s %02d:%02d", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . " - " . esc_html($co{'title'}) . "\n" . "" . esc_html($co{'author'}) . "\n" . "$cd{'rfc2822'}\n" . "" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "\n" . "" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "\n" . "" . esc_html($co{'title'}) . "\n" . "" . "\n"; } print "
\n"; foreach my $line (@difftree) { if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) { next; } my $file = validate_input(unquote($7)); $file = decode("utf8", $file, Encode::FB_DEFAULT); print "$file
\n"; } print "]]>\n" . "
\n" . "
\n"; } print "
"; } sub git_opml { my @list = git_read_projects(); print $cgi->header(-type => 'text/xml', -charset => 'utf-8'); print "\n". "\n". "". " Git OPML Export\n". "\n". "\n". "\n"; foreach my $pr (@list) { my %proj = %$pr; my $head = git_read_head($proj{'path'}); if (!defined $head) { next; } $ENV{'GIT_DIR'} = "$projectroot/$proj{'path'}"; my %co = git_read_commit($head); if (!%co) { next; } my $path = esc_html(chop_str($proj{'path'}, 25, 5)); my $rss = "$my_url?p=$proj{'path'};a=rss"; my $html = "$my_url?p=$proj{'path'};a=summary"; print "\n"; } print "\n". "\n". "\n"; } sub git_log { my $head = git_read_head($project); if (!defined $hash) { $hash = $head; } if (!defined $page) { $page = 0; } my $refs = read_info_ref(); git_header_html(); print "
\n"; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash")}, "shortlog") . " | log" . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$hash;hb=$hash")}, "tree") . "
\n"; my $limit = sprintf("--max-count=%i", (100 * ($page+1))); open my $fd, "-|", "$gitbin/git-rev-list $limit $hash" or die_error(undef, "Open failed."); my (@revlist) = map { chomp; $_ } <$fd>; close $fd; if ($hash ne $head || $page) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "HEAD"); } else { print "HEAD"; } if ($page > 0) { print " ⋅ " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash;pg=" . ($page-1)), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { print " ⋅ prev"; } if ($#revlist >= (100 * ($page+1)-1)) { print " ⋅ " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash;pg=" . ($page+1)), -accesskey => "n", -title => "Alt-n"}, "next"); } else { print " ⋅ next"; } print "
\n" . "
\n"; if (!@revlist) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary"), -class => "title"}, " ") . "
\n"; my %co = git_read_commit($hash); print "
Last change $co{'age_string'}.

\n"; } for (my $i = ($page * 100); $i <= $#revlist; $i++) { my $commit = $revlist[$i]; my $ref = ""; if (defined $refs->{$commit}) { $ref = " " . esc_html($refs->{$commit}) . ""; } my %co = git_read_commit($commit); next if !%co; my %ad = date_str($co{'author_epoch'}); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "title"}, "$co{'age_string'}" . esc_html($co{'title'}) . $ref) . "\n"; print "
\n"; print "
\n" . "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$commit")}, "commitdiff") . "
\n" . "
\n" . "" . esc_html($co{'author_name'}) . " [$ad{'rfc2822'}]
\n" . "
\n" . "
\n"; my $comment = $co{'comment'}; my $empty = 0; foreach my $line (@$comment) { if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { next; } if ($line eq "") { if ($empty) { next; } $empty = 1; } else { $empty = 0; } print format_log_line_html($line) . "
\n"; } if (!$empty) { print "
\n"; } print "
\n"; } git_footer_html(); } sub git_commit { my %co = git_read_commit($hash); if (!%co) { die_error(undef, "Unknown commit object."); } my %ad = date_str($co{'author_epoch'}, $co{'author_tz'}); my %cd = date_str($co{'committer_epoch'}, $co{'committer_tz'}); my @difftree; my $root = ""; my $parent = $co{'parent'}; if (!defined $parent) { $root = " --root"; $parent = ""; } open my $fd, "-|", "$gitbin/git-diff-tree -r -M $root $parent $hash" or die_error(undef, "Open failed."); @difftree = map { chomp; $_ } <$fd>; close $fd or die_error(undef, "Reading diff-tree failed."); # non-textual hash id's can be cached my $expires; if ($hash =~ m/^[0-9a-fA-F]{40}$/) { $expires = "+1d"; } my $refs = read_info_ref(); my $ref = ""; if (defined $refs->{$co{'id'}}) { $ref = " " . esc_html($refs->{$co{'id'}}) . ""; } git_header_html(undef, $expires); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash")}, "log") . " | commit"; if (defined $co{'parent'}) { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff"); } print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "\n" . "

\n"; if (defined $co{'parent'}) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash"), -class => "title"}, esc_html($co{'title'}) . $ref) . "\n" . "
\n"; } else { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash"), -class => "title"}, esc_html($co{'title'})) . "\n" . "
\n"; } print "
\n" . "\n"; print "\n". "" . "" . "\n"; print "\n"; print "\n"; print "\n"; print "" . "" . "" . "" . "\n"; my $parents = $co{'parents'}; foreach my $par (@$parents) { print "" . "" . "" . "" . "\n"; } print "
author" . esc_html($co{'author'}) . "
$ad{'rfc2822'}"; if ($ad{'hour_local'} < 6) { printf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); } else { printf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); } print "
committer" . esc_html($co{'committer'}) . "
$cd{'rfc2822'}" . sprintf(" (%02d:%02d %s)", $cd{'hour_local'}, $cd{'minute_local'}, $cd{'tz_local'}) . "
commit$co{'id'}
tree" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash"), class => "list"}, $co{'tree'}) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "
parent" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$par"), class => "list"}, $par) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$par")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash;hp=$par")}, "commitdiff") . "
". "
\n"; print "
\n"; my $comment = $co{'comment'}; my $empty = 0; my $signed = 0; foreach my $line (@$comment) { # print only one empty line if ($line eq "") { if ($empty || $signed) { next; } $empty = 1; } else { $empty = 0; } if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { $signed = 1; print "" . esc_html($line) . "
\n"; } else { $signed = 0; print format_log_line_html($line) . "
\n"; } } print "
\n"; print "
\n"; if ($#difftree > 10) { print(($#difftree + 1) . " files changed:\n"); } print "
\n"; print "\n"; my $alternate = 0; foreach my $line (@difftree) { # ':100644 100644 03b218260e99b78c6df0ed378e59ed9205ccc96d 3b93d5e7cc7f7dd4ebed13a5cc1a4ad976fc94d8 M ls-files.c' # ':100644 100644 7f9281985086971d3877aca27704f2aaf9c448ce bc190ebc71bbd923f2b728e505408f5e54bd073a M rev-tree.c' if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) { next; } my $from_mode = $1; my $to_mode = $2; my $from_id = $3; my $to_id = $4; my $status = $5; my $similarity = $6; my $file = validate_input(unquote($7)); if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; if ($status eq "A") { my $mode_chng = ""; if (S_ISREG(oct $to_mode)) { $mode_chng = sprintf(" with mode: %04o", (oct $to_mode) & 0777); } print "\n" . "\n" . "\n"; } elsif ($status eq "D") { print "\n" . "\n" . "\n" } elsif ($status eq "M" || $status eq "T") { my $mode_chnge = ""; if ($from_mode != $to_mode) { $mode_chnge = " [changed"; if (((oct $from_mode) & S_IFMT) != ((oct $to_mode) & S_IFMT)) { $mode_chnge .= " from " . file_type($from_mode) . " to " . file_type($to_mode); } if (((oct $from_mode) & 0777) != ((oct $to_mode) & 0777)) { if (S_ISREG($from_mode) && S_ISREG($to_mode)) { $mode_chnge .= sprintf(" mode: %04o->%04o", (oct $from_mode) & 0777, (oct $to_mode) & 0777); } elsif (S_ISREG($to_mode)) { $mode_chnge .= sprintf(" mode: %04o", (oct $to_mode) & 0777); } } $mode_chnge .= "]\n"; } print "\n" . "\n" . "\n"; } elsif ($status eq "R") { my ($from_file, $to_file) = split "\t", $file; my $mode_chng = ""; if ($from_mode != $to_mode) { $mode_chng = sprintf(", mode: %04o", (oct $to_mode) & 0777); } print "\n" . "\n" . "\n"; } print "\n"; } print "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)) . "[new " . file_type($to_mode) . "$mode_chng]" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file")}, "blob") . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)) . "[deleted " . file_type($from_mode). "]" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file")}, "blob") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash;f=$file")}, "history") . ""; if ($to_id ne $from_id) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff;h=$to_id;hp=$from_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)); } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)); } print "$mode_chnge"; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file")}, "blob"); if ($to_id ne $from_id) { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff;h=$to_id;hp=$from_id;hb=$hash;f=$file")}, "diff"); } print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash;f=$file")}, "history") . "\n"; print "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$to_file"), -class => "list"}, esc_html($to_file)) . "[moved from " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$from_file"), -class => "list"}, esc_html($from_file)) . " with " . (int $similarity) . "% similarity$mode_chng]" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$to_file")}, "blob"); if ($to_id ne $from_id) { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff;h=$to_id;hp=$from_id;hb=$hash;f=$to_file")}, "diff"); } print "
\n"; git_footer_html(); } sub git_blobdiff { mkdir($git_temp, 0700); git_header_html(); if (defined $hash_base && (my %co = git_read_commit($hash_base))) { print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "
\n"; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff_plain;h=$hash;hp=$hash_parent")}, "plain") . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) . "\n" . "
\n"; } else { print "
\n" . "

\n" . "
$hash vs $hash_parent
\n"; } if (defined $file_name) { print "
/" . esc_html($file_name) . "
\n"; } print "
\n" . "
blob:" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash_parent;hb=$hash_base;f=$file_name")}, $hash_parent) . " -> blob:" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash;hb=$hash_base;f=$file_name")}, $hash) . "
\n"; git_diff_print($hash_parent, $file_name || $hash_parent, $hash, $file_name || $hash); print "
"; git_footer_html(); } sub git_blobdiff_plain { mkdir($git_temp, 0700); print $cgi->header(-type => "text/plain", -charset => 'utf-8'); git_diff_print($hash_parent, $file_name || $hash_parent, $hash, $file_name || $hash, "plain"); } sub git_commitdiff { mkdir($git_temp, 0700); my %co = git_read_commit($hash); if (!%co) { die_error(undef, "Unknown commit object."); } if (!defined $hash_parent) { $hash_parent = $co{'parent'}; } open my $fd, "-|", "$gitbin/git-diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed."); my (@difftree) = map { chomp; $_ } <$fd>; close $fd or die_error(undef, "Reading diff-tree failed."); # non-textual hash id's can be cached my $expires; if ($hash =~ m/^[0-9a-fA-F]{40}$/) { $expires = "+1d"; } my $refs = read_info_ref(); my $ref = ""; if (defined $refs->{$co{'id'}}) { $ref = " " . esc_html($refs->{$co{'id'}}) . ""; } git_header_html(undef, $expires); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") . " | commitdiff" . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "
\n"; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff_plain;h=$hash;hp=$hash_parent")}, "plain") . "\n" . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash"), -class => "title"}, esc_html($co{'title'}) . $ref) . "\n" . "
\n"; print "
\n"; my $comment = $co{'comment'}; my $empty = 0; my $signed = 0; my @log = @$comment; # remove first and empty lines after that shift @log; while (defined $log[0] && $log[0] eq "") { shift @log; } foreach my $line (@log) { if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { next; } if ($line eq "") { if ($empty) { next; } $empty = 1; } else { $empty = 0; } print format_log_line_html($line) . "
\n"; } print "
\n"; foreach my $line (@difftree) { # ':100644 100644 03b218260e99b78c6df0ed378e59ed9205ccc96d 3b93d5e7cc7f7dd4ebed13a5cc1a4ad976fc94d8 M ls-files.c' # ':100644 100644 7f9281985086971d3877aca27704f2aaf9c448ce bc190ebc71bbd923f2b728e505408f5e54bd073a M rev-tree.c' $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/; my $from_mode = $1; my $to_mode = $2; my $from_id = $3; my $to_id = $4; my $status = $5; my $file = validate_input(unquote($6)); if ($status eq "A") { print "
" . file_type($to_mode) . ":" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file")}, $to_id) . "(new)" . "
\n"; git_diff_print(undef, "/dev/null", $to_id, "b/$file"); } elsif ($status eq "D") { print "
" . file_type($from_mode) . ":" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file")}, $from_id) . "(deleted)" . "
\n"; git_diff_print($from_id, "a/$file", undef, "/dev/null"); } elsif ($status eq "M") { if ($from_id ne $to_id) { print "
" . file_type($from_mode) . ":" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file")}, $from_id) . " -> " . file_type($to_mode) . ":" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file")}, $to_id); print "
\n"; git_diff_print($from_id, "a/$file", $to_id, "b/$file"); } } } print "
\n" . "
"; git_footer_html(); } sub git_commitdiff_plain { mkdir($git_temp, 0700); open my $fd, "-|", "$gitbin/git-diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed."); my (@difftree) = map { chomp; $_ } <$fd>; close $fd or die_error(undef, "Reading diff-tree failed."); # try to figure out the next tag after this commit my $tagname; my $refs = read_info_ref("tags"); open $fd, "-|", "$gitbin/git-rev-list HEAD"; chomp (my (@commits) = <$fd>); close $fd; foreach my $commit (@commits) { if (defined $refs->{$commit}) { $tagname = $refs->{$commit} } if ($commit eq $hash) { last; } } print $cgi->header(-type => "text/plain", -charset => 'utf-8', '-content-disposition' => "inline; filename=\"git-$hash.patch\""); my %co = git_read_commit($hash); my %ad = date_str($co{'author_epoch'}, $co{'author_tz'}); my $comment = $co{'comment'}; print "From: $co{'author'}\n" . "Date: $ad{'rfc2822'} ($ad{'tz_local'})\n". "Subject: $co{'title'}\n"; if (defined $tagname) { print "X-Git-Tag: $tagname\n"; } print "X-Git-Url: $my_url?p=$project;a=commitdiff;h=$hash\n" . "\n"; foreach my $line (@$comment) {; print "$line\n"; } print "---\n\n"; foreach my $line (@difftree) { $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/; my $from_id = $3; my $to_id = $4; my $status = $5; my $file = $6; if ($status eq "A") { git_diff_print(undef, "/dev/null", $to_id, "b/$file", "plain"); } elsif ($status eq "D") { git_diff_print($from_id, "a/$file", undef, "/dev/null", "plain"); } elsif ($status eq "M") { git_diff_print($from_id, "a/$file", $to_id, "b/$file", "plain"); } } } sub git_history { if (!defined $hash) { $hash = git_read_head($project); } my %co = git_read_commit($hash); if (!%co) { die_error(undef, "Unknown commit object."); } my $refs = read_info_ref(); git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "

\n" . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash"), -class => "title"}, esc_html($co{'title'})) . "\n" . "
\n"; print "
/" . esc_html($file_name) . "
\n"; open my $fd, "-|", "$gitbin/git-rev-list $hash | $gitbin/git-diff-tree -r --stdin \'$file_name\'"; my $commit; print "\n"; my $alternate = 0; while (my $line = <$fd>) { if ($line =~ m/^([0-9a-fA-F]{40})/){ $commit = $1; next; } if ($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/ && (defined $commit)) { my %co = git_read_commit($commit); if (!%co) { next; } my $ref = ""; if (defined $refs->{$commit}) { $ref = " " . esc_html($refs->{$commit}) . ""; } if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . "\n" . "\n"; undef $commit; } } print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 3)) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list"}, "" . esc_html(chop_str($co{'title'}, 50)) . "$ref") . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$commit")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=$commit;f=$file_name")}, "blob"); my $blob = git_get_hash_by_path($hash, $file_name); my $blob_parent = git_get_hash_by_path($commit, $file_name); if (defined $blob && defined $blob_parent && $blob ne $blob_parent) { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff;h=$blob;hp=$blob_parent;hb=$commit;f=$file_name")}, "diff to current"); } print "
\n"; close $fd; git_footer_html(); } sub git_search { if (!defined $searchtext) { die_error("", "Text field empty."); } if (!defined $hash) { $hash = git_read_head($project); } my %co = git_read_commit($hash); if (!%co) { die_error(undef, "Unknown commit object."); } # pickaxe may take all resources of your box and run for several minutes # with every query - so decide by yourself how public you make this feature :) my $commit_search = 1; my $author_search = 0; my $committer_search = 0; my $pickaxe_search = 0; if ($searchtext =~ s/^author\\://i) { $author_search = 1; } elsif ($searchtext =~ s/^committer\\://i) { $committer_search = 1; } elsif ($searchtext =~ s/^pickaxe\\://i) { $commit_search = 0; $pickaxe_search = 1; } git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary;h=$hash")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "

\n" . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash"), -class => "title"}, esc_html($co{'title'})) . "\n" . "
\n"; print "\n"; my $alternate = 0; if ($commit_search) { $/ = "\0"; open my $fd, "-|", "$gitbin/git-rev-list --header --parents $hash" or next; while (my $commit_text = <$fd>) { if (!grep m/$searchtext/i, $commit_text) { next; } if ($author_search && !grep m/\nauthor .*$searchtext/i, $commit_text) { next; } if ($committer_search && !grep m/\ncommitter .*$searchtext/i, $commit_text) { next; } my @commit_lines = split "\n", $commit_text; my %co = git_read_commit(undef, \@commit_lines); if (!%co) { next; } if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . "\n" . "\n"; } close $fd; } if ($pickaxe_search) { $/ = "\n"; open my $fd, "-|", "$gitbin/git-rev-list $hash | $gitbin/git-diff-tree -r --stdin -S\'$searchtext\'"; undef %co; my @files; while (my $line = <$fd>) { if (%co && $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) { my %set; $set{'file'} = $6; $set{'from_id'} = $3; $set{'to_id'} = $4; $set{'id'} = $set{'to_id'}; if ($set{'id'} =~ m/0{40}/) { $set{'id'} = $set{'from_id'}; } if ($set{'id'} =~ m/0{40}/) { next; } push @files, \%set; } elsif ($line =~ m/^([0-9a-fA-F]{40})$/){ if (%co) { if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . "\n" . "\n"; } %co = git_read_commit($1); } } close $fd; } print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$co{'id'}"), -class => "list"}, "" . esc_html(chop_str($co{'title'}, 50)) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { if ($line =~ m/^(.*)($searchtext)(.*)$/i) { my $lead = esc_html($1) || ""; $lead = chop_str($lead, 30, 10); my $match = esc_html($2) || ""; my $trail = esc_html($3) || ""; $trail = chop_str($trail, 30, 10); my $text = "$lead$match$trail"; print chop_str($text, 80, 5) . "
\n"; } } print "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$co{'id'}")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$co{'id'}")}, "tree"); print "
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$co{'id'}"), -class => "list"}, "" . esc_html(chop_str($co{'title'}, 50)) . "
"); while (my $setref = shift @files) { my %set = %$setref; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$set{'id'};hb=$co{'id'};f=$set{'file'}"), class => "list"}, "" . esc_html($set{'file'}) . "") . "
\n"; } print "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$co{'id'}")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$co{'id'}")}, "tree"); print "
\n"; git_footer_html(); } sub git_shortlog { my $head = git_read_head($project); if (!defined $hash) { $hash = $head; } if (!defined $page) { $page = 0; } my $refs = read_info_ref(); git_header_html(); print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . " | shortlog" . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$hash")}, "log") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$hash;hb=$hash")}, "tree") . "
\n"; my $limit = sprintf("--max-count=%i", (100 * ($page+1))); open my $fd, "-|", "$gitbin/git-rev-list $limit $hash" or die_error(undef, "Open failed."); my (@revlist) = map { chomp; $_ } <$fd>; close $fd; if ($hash ne $head || $page) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "HEAD"); } else { print "HEAD"; } if ($page > 0) { print " ⋅ " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash;pg=" . ($page-1)), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { print " ⋅ prev"; } if ($#revlist >= (100 * ($page+1)-1)) { print " ⋅ " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash;pg=" . ($page+1)), -accesskey => "n", -title => "Alt-n"}, "next"); } else { print " ⋅ next"; } print "
\n" . "
\n"; print "
\n" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary"), -class => "title"}, " ") . "
\n"; print "\n"; my $alternate = 0; for (my $i = ($page * 100); $i <= $#revlist; $i++) { my $commit = $revlist[$i]; my $ref = ""; if (defined $refs->{$commit}) { $ref = " " . esc_html($refs->{$commit}) . ""; } my %co = git_read_commit($commit); my %ad = date_str($co{'author_epoch'}); if ($alternate) { print "\n"; } else { print "\n"; } $alternate ^= 1; print "\n" . "\n" . "\n" . "\n" . ""; } if ($#revlist >= (100 * ($page+1)-1)) { print "\n" . "\n" . "\n"; } print ""; git_footer_html(); }
$co{'age_string_date'}" . esc_html(chop_str($co{'author_name'}, 10)) . ""; if (length($co{'title_short'}) < length($co{'title'})) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list", -title => "$co{'title'}"}, "" . esc_html($co{'title_short'}) . "$ref"); } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list"}, "" . esc_html($co{'title_short'}) . "$ref"); } print "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$commit")}, "commitdiff") . "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$hash;pg=" . ($page+1)), -title => "Alt-n"}, "next") . "