#!/usr/local/bin/perl # Copyright(C) TAKASUGI Shinji (ts@sf.airnet.ne.jp) # Based on a script created by MUROTANI Yoshitaka # The counter will be postincremented. binmode STDOUT; $content_type_header = "Content-Type: image/gif\n\n"; if ($ENV{'REQUEST_METHOD'} eq 'HEAD') { print $content_type_header; exit 0; } require 'gifinput.pl'; require 'gifoutput.pl'; sub abort { print "Content-Type: text/html\n\n", "\n\nCounter Error\n\n\n", "\n

", $_[0], "

\n\n\n"; exit 0; } foreach (split(/[\&\;]/, $ENV{'QUERY_STRING'})) { ($key, $value) = split('=', $_, 2); $value =~ tr/+/ /; $value =~ s/%(..)/pack('C', hex($1))/ge; $param{$key} = $value; } $image = $param{'image'} || 'ac!d.gif'; $image =~ s/!/\%/g; $format = $param{'format'} || '!05d'; $format =~ s/!/\%/g; while (($digits = ($image =~ /\%(\d+)d/g))) { &abort("Too long string.") if ($digits > 20); } while (($digits = ($format =~ /\%(\d+)d/g))) { &abort("Too long string.") if ($digits > 20); } if ($param{'number'} ne '') { $visit = $param{'number'}; } else { $counter = $param{'counter'} || 'ac.dat'; open(COUNTER, $counter) || &abort("Failed to open $counter."); $visit = ; if ($visit ne '' && $param{'up'} && open(COUNTER, ">$counter")) { flock(COUNTER, 2); print COUNTER $visit + 1; } close(COUNTER); } $number = sprintf($format, $visit); &abort("Too long string.") if (length($number) > 20); @digits = split('', $number); foreach $digit (@digits) { $digit_hash{$digit}++; } # GIF functions sub read_gif { local($file, *GIFFILE) = @_; open(GIFFILE, $file) || &abort("Failed to open $file."); binmode GIFFILE; local($gif_data) = &gifinput::gif_read(\*GIFFILE); close(GIFFILE); $gif_data; } sub set_palette { local($gif_data_array) = @_; local($gif_data, $cx, $cy, $pixels, $palette, $transparent, $height, $index, $rgb, $global_palette, $palette_index, $palette_lookup, $global_transparent); $palette_index = 0; foreach $gif_data (@$gif_data_array) { ($cx, $cy, $pixels, $palette, $transparent) = @$gif_data; $transparent = -1 if !defined($transparent); undef($palette_lookup); if (!defined($height)) { $height = $cy; } elsif ($height != $cy) { die "gifxcat.pl: different height, stopped"; } for ($index = 0; $index < @$palette; $index++) { $rgb = $palette->[$index]; if (!exists($global_palette->{$rgb})) { if ($palette_index == 256) { return; } if ($index == $transparent && !defined($global_transparent)) { $global_transparent = $palette_index; } $global_palette->{$rgb} = $palette_index++; } $palette_lookup->{chr($index)} = chr($index == $transparent ? $global_transparent : $global_palette->{$rgb}); } push(@$gif_data, $palette_lookup); } ($height, $global_palette, $global_transparent); } sub force_palette { local($gif_data_array) = @_; local($gif_data, $cx, $cy, $pixels, $palette, $transparent, $height, $index, $rgb, $global_palette, $palette_index, $palette_lookup, $red, $green, $blue); $palette_index = 0; for ($red = 0; $red <= 5; $red++) { for ($green = 0; $green <= 5; $green++) { for ($blue = 0; $blue <= 5; $blue++) { $global_palette->{(($red * 0x33) << 16) + (($green * 0x33) << 8) + ($blue * 0x33)} = $red * 36 + $green * 6 + $blue; } } } foreach $gif_data (@$gif_data_array) { ($cx, $cy, $pixels, $palette, $transparent) = @$gif_data; $transparent = -1 if !defined($transparent); undef($palette_lookup); if (!defined($height)) { $height = $cy; } elsif ($height != $y) { die "gifxcat.pl: different height, stopped"; } for ($index = 0; $index < @$palette; $index++) { $rgb = $palette->[$index]; $rgb = ((int(((($rgb & 0xff0000) >> 16) + 25) / 51) * 51) << 16) | ((int(((($rgb & 0xff00) >> 8) + 25) / 51) * 51) << 8) | (int((($rgb & 0xff) + 25) / 51) * 51); if ($transparent) { $global_transparent = $global_palette->{$rgb}; } $palette_lookup->{chr($index)} = chr($global_palette->{$rgb}); } push(@$gif_data, $palette_lookup); } ($height, $global_palette, $global_transparent); } foreach $digit (keys(%digit_hash)) { $gif_data_hash{$digit} = &read_gif(sprintf($image, $digit)); } @gif_data_array = values(%gif_data_hash); ($height, $global_palette, $global_transparent) = &set_palette(\@gif_data_array); if (!$height) { ($height, $global_palette, $global_transparent) = &force_palette(\@gif_data_array); } foreach $gif_data (@gif_data_array) { ($cx, $cy, $pixels, $palette, $transparent, $palette_lookup) = @$gif_data; $pixels =~ s/(.)/$palette_lookup->{$1}/gs; $gif_data->[0] = $cx; $gif_data->[1] = $pixels; $#$gif_data = 1; } $#pixel_array = $height * @digits - 1; $total_width = 0; for ($index = 0; $index < @digits; $index++) { ($cx, $pixels) = @{$gif_data_hash{$digits[$index]}}; $total_width += $cx; for ($y = 0; $y < $height; $y++) { $pixel_array[$y * @digits + $index] = substr($pixels, $cx * $y, $cx); } } while (($rgb, $index) = each(%$global_palette)) { $merged_palette[$index] = $rgb; } print $content_type_header; &gifoutput::gif_write(\*STDOUT, $total_width, $height, join('', @pixel_array), \@merged_palette, $global_transparent, 1); exit 0;