H.H. Knerr

This site should appear as the creator intended if viewed in Explorer 3.0 or higher.  Netscape should be OK too.  Users of other browsers are up a creek and must paddle as best they can.


Harold H. Knerr is best known as the artist who once drew the famous Sunday color comic strip "The Katzenjammer Kids."

Knerr was not the original artist.  He took over the strip from its creator, Rudolph Dirks, following a famous lawsuit between the Hearst and Pulitzer publishing empires.  Knerr began drawing the "Katzies" in November 1914, although it would be six months before his signature appeared on the page.  He continued drawing the feature until his death in 1949.  During that 35-year period, he produced some 1800 renditions of these characters' adventures.

Knerr's beautiful and consistent style, together with his ability to recast essentially the same situation hundreds of times, combine to make him the most successful "stepfather" ever to adopt the comic strip creation of another artist.

Who, between Dirks and Knerr, was the better artist?  The better storyteller?  Other critics have disagreed and argued the point endlessly, but the view from here is biased toward Knerr.  If forced to do so, I might admit that Dirks did some better work during part of the 1940s, but overall the quality of Knerr's pages right from the very first one in 1914, and particularly for the ensuing 10 years, were hands down the superior.


KNERR -- THE MAN

Surprisingly little is known about the personal life of H.H. Knerr.  The son of a German physician, he never married and remains something of a mystery man.

In the early years, Knerr worked and socialized with many of the greats: Jimmy Swinnerton, Billy DeBeck, and George McManus, among them.  He spent the latter part of his life as something of a recluse, working without assistance in the confines of his New York hotel apartment, where he died of a heart attack in 1949.


KNERR -- THE ARTIST

Knerr studied art for two years in Philadelphia and got his start as a newspaper cartoonist just after the turn of the century.  "My first newspaper work was drawing pictures of gravestones atop the oldest graves in a local cemetery for the Philadelphia Record," he once said.  "These were paid for at the fee of three dollars each."

This reduced portion of a picture rendered by Knerr around 1901, is an example of his early attempts at realistic illustration.  Notice the two boys apparently stealing something from a vendor's cart--real world counterparts to the comic strip Hans and Fritz.  Even as a teenager, Knerr clearly demonstrated commercial potential as an artist.

He later blossomed into one of the most skilled comic strip artists of the age--an age in which many other legendary cartoonists were getting their start.  His drawings were soft and round, a characteristic that gave them a special warmth and appeal.


THE EARLY YEARS
In The Beginning ...

The very beginning dates back to 1901, shortly after the dawn of the Sunday color comic strip, itself.  Knerr was living in Philadelphia, an aspiring artist finding what work he could doing some spot illustrations for local papers.

For the next couple of years, color comic strips by Knerr appeared in at least three Philadelphia papers.  Most of these were "one-shot" features and, if you can put your hands on examples of these, you are a better man than I.

Shown here is a 1901 panel from what is believed to be the very first Sunday strip by Knerr (his signature appears in one of the other panels), entitled "Willie's Revenge."

The whole comic strip genre was in its infancy at that time.  Many early strips had more of an illustrator's style than that of a cartoonist.  The poor quality of this reproduction is due to its being a scan of a second generation photocopy.  Still, it offers something of the flavor of 19-year-old Knerr's ability.


The Fineheimer Twins

The incredible popularity of the Katzenjammer Kids, syndicated by Hearst's papers, spawned a number of imitative competitors.  Chief among these was the Fineheimer Twins.

The characters were obviously derivative of Dirks', but no more so than those of several other imitators.  Knerr drew the Fineheimer Twins for more than 10 years (1903-1914).  His skill and artistry did not go unnoticed.  When the time came to select someone to take over the "Katzies," Knerr was the obvious choice.

The panels shown here are from the page of Sunday, February 9, 1908.  In addition to the characters which resemble the cast of the Katzenjammer Kids, it is interesting to note two characters that foreshadow the appearance of characters that Knerr would introduce many years later.  The lady spanking one of the twins is a dead ringer for Miss Twiddle, who would join the cast of the Katzenjammer Kids nearly 20 years later.  The portly gentleman in the center resembles Herr Dinglehoofer, of whom you may read more below.

For those who wish to examine a complete Fineheimer Twins episode, you may click on the image at left.  You will be taken to a reproduction of the episode of November 17, 1907, as it appeared in the Sunday comics section more than 90 years ago!  The file is 156K in size, so it may take a moment to load. The image is reproduced at 75% of its original size.  I think you will be surprised at how much of the dialogue is in German or German dialect.


Mr. George

Sometimes known as "Mr. George and Wifey," this strip is also blatantly derivative.  Its premise is lifted without embarrassment from the adventures of "Mr. Jack" by cartoonist Jimmy Swinnerton.

Mr. George had an eye for the ladies.  Nearly every strip began with him ogling or making a pass at a pretty girl (or two) and ended with him being hit on the head by his wife.  Knerr drew Mr. George from 1904 until 1914.  The strip continued under the pen of another artist for a number of years.  This panel is from an episode in that final year.


Scary William

Like so many other comic strips in the early years, Scary William, was a one-joke feature.  The title is somewhat of a misnomer.  William himself wasn't scary.  He was a hyper-sensitive young boy, who could fly into a panic upon the slightest provocation.  Seen here in an episode of December, 15, 1907, he is frightened by a provocation that is not so slight--the sudden appearance of his Uncle Bing, crashing down the chimney in a Santa Claus suit.

Knerr did not originate "Scary William."  He took it over in 1906 and continued it until 1914.  It was further continued under the pen of Joe Doyle.


The Irresistible Rag

Following the appearance of Scott Joplin at the St. Louis World's Fair, "ragtime" music was all the rage.

The premise of this strip was that a certain tune, once heard, simply could not be resisted.  The listener became immediately afflicted with a sort of pre-Steve Martin case of "happy feet," dancing uncontrollably in spite of everything.

The primary character was a highly stereotypical negro musician who delighted in the mischievous playing of the magical tune.  Of course, such a character could not appear in the comic pages today.  Students of comics history, however, know that there were many comic strips which featured such stereotypical characters.  After all, the same people who were reading the "funnies" during this period were also attending live minstrel shows.  While it is not a strip for which fans of Knerr may be proud, it is no more contemptible than many others of its type which appeared during the same period.

My best information indicates that this strip, as drawn by Knerr, ran from June 15, 1913, until November 15, 1914.  It too was continued by Joe Doyle.


Wooly Willie and Little Chief Rain-in-the-Face

My collection includes only one example of this strip, having the full title "The Doings of Wooly Willie and Little Chief Rain-in-the-Face."  Knerr had his hands full with other strips at the time this one appeared, but for whatever reason he undertook the rendering of these two young adventurers in 1905 for what proved to be a very short period.  The real "Chief Rain-in-the-Face" was a famous Native-American who, at that time, was still a contemporary figure.

The strip ran for only a few weeks.  I can confirm the period August 20 to October 8, 1905.  The panel shown here, which depicts the two characters named in the title, is from the strip of that last date.


Zoo-Illogical Snapshots

Knerr is known for his exceptional "animal" cartoons.  I suspect that it was his secret desire to concentrate on such a strip.  For reasons yet to be discovered, Knerr went outside the syndication that published his other early pages, and produced "Zoo-Illogical" for a minor syndicate.  It appeared in very few papers, but perhaps he was given the freedom there to do what was not available to him in the mainstream press.

Knerr certainly approached the strip with a free hand.  Some weeks it resembled a standard comic strip, but more often it consisted of several large (sometimes very large) panels each of which presented a single gag-type cartoon.

Collectors will find that pages of Zoo-Illogical Snapshots are about as rare as hen's teeth.  As best I can determine, the strip ran for about a year during the period 1911-1912.  The panel shown is from the December 3, 1911, page, in which Mama Kangaroo sneaks her two joeys into the circus without having to buy additional tickets.


THE KATZENJAMMER KIDS

What a thrill it must have been for the 32-year old Knerr to be summoned from the comic strip backwater of Philadelphia to come to work for William Randolph Hearst in New York and assume control of the most popular comic strip in creation!  Knerr took to the task with gusto, dropping all of his former strips and concentrating on producing the very best Sunday pages of which he was capable.  And such pages they were!

Knerr certainly hit the ground running.  At left, we see the first panel from his very first Katzenjammer Kids page, dated November 29, 1914.  The soft, round, "cartoony" style, of which he was a master, was evident from the very first effort.  This was his first Katzenjammer page, folks!  The little lawyer with the brief case looks like he could step right off the page!

Knerr proceeded to turn out a long series of wonderfully vivid and complex Sunday pages, as evidenced by this 3-panel excerpt from a page dated November 4, 1917, and featuring "der Prime Minister uf Peru."


Knerr did his very best work in the late teens and early 1920's.  During those years the Katzenjammer family ventured to the far corners of the world, engaging in many interesting adventures from the arctic to the tropics.

Here are some of the cast of characters that were featured in those days.


Hans and Fritz were not only mischievous, but often malicious, as well.  That seems to be the way their reading audience preferred them.  Once in awhile, however, Knerr would show his softer side, with the mischief being more sweet than mean-spirited.  For a classic example from December 18, 1921, click on the "kitties" graphic.  [Caution: 170K]


In the mid-'30s, the family settled down on a tropical island and Knerr introduced three new characters--"Rollo," "Lena," and "Miss Twiddle"--as additional foils for our little hellions.  This major change distinguished "The Katzenjammer Kids" from "The Captain and the Kids" forever, as these characters had no counterparts in the Dirks version.  Here we see the three of them, with "Der Captain" and "Mamma" in a panel from January 28, 1940.


DINGLEHOOFER UND HIS DOG

Until the mid-1920s, many Sunday comic strips were permitted to take up an entire page (!), quite unlike today when five or six strips may be severely reduced and chopped up to squeeze on a singe page.  This trend began when publishers figured out that a greater number of individual strips could be promoted to potential newspaper buyers (without increasing the number of pages in the comics section), if more than one were printed on the same page.

A number of popular artists responded to the new demands by creating a secondary strip, a so-called "topper," that would run in the top one-third or so of a page, reserving the other two-thirds for the primary feature.  This way the same artist still had the whole page.

"Dinglehoofer Und His Dog" first appeared as a topper on May 16, 1926.  It was very well received and Knerr continued it until his death, some 23 years later.

The gentle and engaging strip initially featured the adventures of a kindly German-American bachelor and his curious little pup, Adolph.  Eight years into the strip, a little orphan boy, "Tadpole" Doogan, literally fell out of a tree into the life of "Mr. Dingy."  Their subsequent adventures ranged over a wide spectrum, touching subjects as simple as chasing a butterfly and as nefarious as kidnapping.

By 1936, events in far-away Germany affected the American funny pages: It was no longer fashionable for a little dog named "Adolph" to be the focus of amusing antics.  Consequently, Knerr crafted a series of events resulting in the adoption of "Adolph" by a farm family and the arrival of a new pup, an adorable dachshund known as "Schnappsy."

     

On the left we see Dinglehoofer and Adolph from a strip which appeared on January 6, 1929.  Having been responsible for the apprehension of some dangerous crooks, Adolph was awarded a check in the amount of $2000.  Considering the date, we can only hope that the funds remained in the bank, rather than being invested in the stock market.

On the right is the entire cast, as it appeared on January 2, 1938.  Adolph has been replaced by Schnappsy.  The family cook and maid "Lilly" is also present.


THE MULTIMEDIA PAGE
Where else will you have a chance to see H.H. Knerr in living black and white.  Assuming your computer supports the playing of mpeg-1 movie files, the MultiMedia Page awaits you.


ORIGINAL ART

Years ago, original comic strip drawings were not regarded as having any collectible value and were routinely discarded.  Only a fraction of the more than 1800 "original" Sunday page drawings of the Katzenjammer Kids by H.H. Knerr has survived.   My research indicates that about 100 such originals are still in existence, largely because Knerr was willing to respond to the requests of fans who sought him out.

It is a little known fact that the original drawings were all in black and white, rendered on heavy stock with pen and ink.  The color was added during the printing process.  Today these originals are sold at auction or by specialty dealers for hundreds of dollars each.  In addition to the original comic strip art, Knerr occasionally produced a "specialty" drawing at the request of a fan as well as for particular occasions.  Special drawings and personalized inscriptions were sometimes provided to enthusiastic fans.  Details with regard to all of this may be found on the Knerr original art page.  Needless to say, if you are in possession of original art by Knerr, and are willing to part with it, you may consider me to be a willing purchaser.


In addition to original art by Mr. Knerr, I am always looking for copies of "Circulation" magazine.  This was a trade magazine published by King Features Syndicate between 1916 and 1933.  If you have copies that you would be interested in selling (or lending for research purposes), please contact me by e-mail.


BEYOND THE COMIC PAGE

Knerr also did a bit of work outside of the Sunday comic page, but not nearly as much as he should have.  There is little beyond illustrations of the Katzenjammer Kids in other formats such as children's books and small specialty sketches mailed to those fans who wrote to request them.

This illustration, clearly by Knerr, although not signed, was made into a "Kiddies Jigsaw Puzzle" by the Jaymar company.

And for those of you who are still with me, there is a really terrific specialty illustration and self portrait.  This one's for you!



Well, that's about it ... what?  You're recalling that the Katzenjammer Kids spent a lot of time at sea?  You've been told that one of Knerr's strong points was the rendering of wonderful little pigs?  What the heck, before you leave, go ahead and take a look at another wonderful Katzenjammer Kids page, this time one from 1935.

Please feel free to e-mail me with your comments.


If you would like to support this page and save yourself some money in the process, please consider shopping for your books, CDs, and videos from Amazon.com.


Just click one of these icons and bookmark or make a favorite of the page it takes you to.  Thereafter, your purchases from Amazon will produce a small credit to yours truly.  The eBay icon takes you to a list of items that my alter ego, Otto, is offering at auction this week.

Donations Are Welcome   If you are one of those rare angels who would like to make a modest donation to support my efforts, you may do so by clicking the Pay Pal "Donate" image and filling in the pertinent information that will appear on the next screen.  It's fast and easy and your surprising generosity will be greatly appreciated.

MORE?   Many other areas of the "Popular Culture Excavation Site" await you.  Full descriptions are on the main menu or go directly to the area of your choice by clicking one of these seductive little images.

The Katzenjammer KidsWillie the KOOL penguinMistinguettCarl "Duck Man" BarksSvend AsmussenTim "Kingfish" MooreWestern SwingHazel CourtRhythm and Blues RevuesEuropean Jazz and Close Harmony Vocal GroupsThe Pie Girl DinnerSally RandWLAC Radio: Nashville

Who are these guys?  Just place your cursor on each image to get a clue.

Back to The Katzenjammer Kids page.

Return to the main menu.


On May 18, 2002, the 5th anniversary of the creation of the main site, hosting of this page was transferred from Yahoo/GeoCities to an independent server.  You are the most recent of the #!/usr/local/bin/perl5 use GD; alarm(600); # cgi-bin access counter program # Version 4.0.7 # # Copyright (C) 1995 George Burgyan # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or (at # your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # A full copy of the GNU General Public License can be retrieved from # http://www.webtools.org/counter/copying.html # # gburgyan@webtools.org # # George Burgyan # 1380 Dill Road # South Euclid, OH 44121 # # For more information look at http://www.webtools.org/counter/ ######################################################################## # # CHANGE THESE TO SUIT YOUR SITE # # The default language option (english, french, swedish) $default_lang = "english"; # The name of the file to use. You should probably give this an absolute path $FileName = "$ENV{'DOCUMENT_ROOT'}/counter/access_count"; # Replace with a list of regular expression IP addresses that we # are supposed to ignore. If you don't know what this means, just use # "\." instead of periods. Comment out entirely to ignore nothing. #@IgnoreIP = ("199\.18\.203\..*", # "199\.18\.159\.1", # ); # Aliases: Set this up so that diffent pages will all yield the same # count. For instance, if you have a link like "index.html -> home.html" # set it up like ("/index.html", "/home.html"). Make sure you give a full # path to it. This will treat "/index.html" as if it were "/home.html". %Aliases = ("/fakename.html", "/realname.html", "/index.html", "/home.html", ); # AUTOMATICALLY SET BY INSTALL!! Modify only if necessary!!! # # BaseName: set to whatever you have counter installed as. This is # used to derive the arguments. No not touch the next comment. ### AUTOMAGIC ### $BaseName = "counter"; # counter or counterbanner or counterfiglet # # Outputs the number of times a specific page has been accessed. # The output depends on which page 'called' it, and what the program # is named: # # The counter can "take arguments" via its name. That is, if you tack # -arg to the end of the program name, -arg is taken to be an argument. # For example, if you call the counter 'counter-ord', '-ord' is considered # an argument, and an ordinal count (1st, 2nd, 3rd, ...) will be printed # instead of (1, 2, 3, ...). Note that counterord does the same thing as # counter-ord for backward compatibility. # # Currently recognized arguments: # # -f=font sets "font" to be the font for figlet # -lang=lang sets the language used to ordinalize to "lang" # -nc no count; don't to write the incremented count back to the file # -nl no link; don't automatically generate a link # -nd no display; don't display anything, just count # -ord make an ordinal count instead of regular # -doc=document override the DOCUMENT_URI environment variable # # Example: counterfiglet-ord-f=bigfont-nc # # This will cause the counter to call figlet as the output routine, printing # in a big font an ordinal count, without updating the access count file. # Note that the order of arguments is irrelevant so long as you spell the # file name correctly. It is generally assumed that the ability to take # different arguments/use different output routines is done with symlinks: # i.e. ln -s counter counterfiglet-ord-f=bigfont-nc # # More complete documentation can be found at # http://www.webtools.org/counter/ # ######################################################################## # # Thing that shouldn't really need changing, but are configurable anyway. # # Maximum number of times to try to lock the file. # Each try is .1 second. Try for 1 second. $MaxTries = 10; # Set this to point to something, or comment it out, and it # won't be a link at all. # $Link = "http://www.webtools.org/counter/"; # Whether or not to use locking. If perl complains that flock is not # defined, change this to 0. Not *really* necessary because we check # to make sure it works properly. $UseLocking = 0; # What version of the counter file format are we using? $FileVersion = "02.000"; # Common names of the counter to install... @CommonExtensions = ("-ord", # Ordinam "figlet", # Figlet'ed "figlet-ord",# Ordinal figlet "banner", # Bannered "banner-ord",# Ordinal banner ); # ######################################################################### # # Misc documents to refer people to in case of errors. # $CreateFile = "[Error Creating Counter File -- Click for more info]"; $AccessRights = "[Error Opening Counter File -- Click for more info]"; $TimeoutLock = "[Timeout locking counter file]"; $BadVersion = "[Version access_count newer than this program. Please upgrade.]"; ######################################################################### # # The actual program! ### Stage 1 ### ### Parse the arguments... (just ignore this part) # Get arguments from program name. Argh...what a horrible way to do it! $prog = $0; $prog =~ s/(\.cgi|\.pl)//; #strip .cgi|.pl name extension $prog =~ s!^(.*/)!!; # separate program name $prog =~ s/\\(.)/sprintf("%%%02x", ord($1))/ge; # quote \c to %xx ($printer, @args) = split(/-/, $prog); # args are separated by dashes $printer =~ s/%(..)/pack("c", hex($1))/ge; # unquote printer function name $printer =~ s/$BaseName/counter/; # Make it cannonical. # This gets path info, which is only applicable if you are using our # ssis script (see above). This makes counter/ord the same as counter-ord push(@args, split("/", $ENV{"PATH_INFO"})) if $ENV{"PATH_INFO"}; # put them in assoc array %arg foreach (@args) # means do this for each element in the array { s/%(..)/pack("c", hex($1))/ge; # unquote %xx /^([^=]*)=?(.*)$/; # extract "=" part, if any $arg{$1} = $2 ? $2 : 1; } if ($ARGV[0] eq '-install') { &CheckPerl; &SetBaseName; &MakeCommon(0); exit(0); } if ($ARGV[0] eq '-installforce') { &CheckPerl; &SetBaseName; &MakeCommon(1); exit(0); } if ($ARGV[0] eq '-unlock') { open(FILE,"$FileName"); &UnlockFile(FILE); exit(0); } undef $Link if $arg{'nl'}; # make link? ### Stage 2 ### ### Print out the header # Print out the header print "Content-type: text/html\n\n"; #print "Debug 1: $ConfName
Debug 2: $FileName"; ### Stage 3 ### ### Open the access_count file for read-write taking all the precautions # Make sure the file exists: if (!(-f $FileName)) { if (!open (COUNT,">$FileName")) { # Can't create the file print $CreateFile; exit 1; } else { # We got the file, print out the version number print COUNT "$FileVersion\n"; $version = 2; } } else { if (!((-r $FileName) && (-w $FileName))) { # Make sure that we can in fact read and write to the file in # question. If not, direct them to the FAQ. print $AccessRights; exit 1; } if (!open (COUNT,"+<$FileName")) { # Now make sure it *really* opens print $AccessRights; # ...just in case... exit 1; } # Try to read in a version number $version = ; if (!($version =~ /^\d+.\d+$/)) { # No version number, assume version 1 and reset the file. $version = 1; seek(COUNT,0,0); } } # This is for the future: the access_count file will have a version number. if ($version > 2) { print $BadVersion; exit 1; } ### Stage 4 ### ### Attempt to lock the file $lockerror = &LockFile(COUNT); # You would figure that $MaxTries would equal 0 if it didn't work. The # post-decrement takes it to -1 when the loop finally exits. if ($lockerror) { print $TimeoutLock; exit(0); } ### Stage 5 ### ### Check if we need to update the file to a newer version if ($version < 2) { &UpdateVersion1; } ### Stage 6 ### ### Convert the information the server gave us into the document ### identifier. # Make sure perl doesn't spit out warnings... if (defined $ENV{'DOCUMENT_URI'}) { $doc_uri = $ENV{'DOCUMENT_URI'}; } else { $doc_uri = ""; } # Campatibility: Version 2 files have the server name in front if and # only if it doesn't have a "~" in it. $old_uri = $doc_uri; # Add the server name in front to support multi-homed hosts if and only if # it doesn't have a "~" in it. (usernames are global in most multi-homed # settings if (defined $ENV{'SERVER_NAME'} && !($doc_uri =~ /~/)) { $doc_uri = $ENV{'SERVER_NAME'} . "/" . $doc_uri; } if (defined $arg{'doc'}) { $doc_uri = $arg{'doc'}; } $doc_uri = $Aliases{$doc_uri} if defined $Aliases{$doc_uri}; ### Stage 7 ### ### Find the relevant place in the file $location = tell COUNT; while ($line = ) { # Read the file line-by-line. if (($uri,$accesses) = ($line =~ /^'(\S*)' (\d\d\d\d\d\d\d\d\d\d)$/)) { # An old line if ($uri eq $old_uri) { &ConvertDocV1($doc_uri,$old_uri,$accesses,$location); last; } } elsif (($uri,$accesses,$flags) = ($line =~ /^'(\S*)' (\d\d\d\d\d\d\d\d\d\d) (\w\w\w\w)$/)) { # A new line if ($uri eq $doc_uri) { $flags = hex($flags); last; } } last if ($uri eq $doc_uri); $location = tell COUNT; #reset the fields $accesses = 0; $flags = 0; } ### Stage 8 ### ### Update the access count of the file $accesses += 1; # *NOT* '++' because we don't want '++'s magic ### Stage 9 ### ### Figure out what to print out # If we have to ordinalize, do it now. if (defined $arg{'ord'}) { if (defined $arg{'lang'}) { $ord = eval("&ordinalize_$arg{lang}($accesses)"); } else { $ord = &ordinalize($accesses); } } else { $ord = ""; } $to_print = $accesses . $ord; # Give it to the printer function to actually produce the output from the # ascii text that we have (to_print) ($count, $nLink) = eval("&output_$printer('$to_print')"); # If the above line gave us an error, default to just the text. if ($@) { ($count, $nLink) = &output_counter($to_print); } ### Stage 10 ### ### Now we actually tell the browser what the count is. if (! $arg{"nd"} ) { # If we print anything # Print out a link to something informative (if we were requested to) $script_name = $ENV{'SCRIPT_NAME'}; print "" if $nLink; if ($script_name =~ /cgi-bin\/count(\w+)/) { $img_dir = $1; } if ($img_dir ne "er") { &give_graphic } else { print $count; print "" if $nLink; } } sub give_graphic { @img_count = split(//,$count); foreach (@img_count) { print ""; }; } sub comment1 { # create a new image print "Content-type: image/gif\n\n"; $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # Convert the image to GIF and print it on standard output print $im->gif; } ### Stage 11 ### ### Check if we are supposed to update the count in the file. (ie. we're ### not ignoring the host that just accessed us) # Make sure we are not ignoring the host: $ignore = 0; $ignore = grep($ENV{"REMOTE_ADDR"} =~ /$_/, @IgnoreIP) if defined ($ENV{"REMOTE_ADDR"}); $ignore = $ignore || $arg{"nc"}; ### Stage 12 ### ### Actually write the updated information back to the file if (!$ignore) # If we aren't ignoring this access { # Now update the counter file seek(COUNT, $location, 0); $longaccesses = sprintf("%010.10d", $accesses); $hexflags = sprintf("%04.4x", $flags); print COUNT "'$doc_uri' $longaccesses $hexflags\n"; } &UnlockFile(COUNT); close COUNT; ####################################################################### # # Support functions # # translate_output # # Quote any special characters with HTML quoting. sub translate_output { local($string) = @_; $_ = $string; s/è/è/g; return $_; } sub LockFile { local(*FILE) = @_; local($TrysLeft) = $MaxTries; if ($UseLocking) { # Try to get a lock on the file while ($TrysLeft--) { # Try to use locking, if it doesn't use locking, the eval would # die. Catch that, and don't use locking. # Try to grab the lock with a non-blocking (4) exclusive (2) lock. # (4 | 2 = 6) $lockresult = eval("flock(COUNT,6)"); if ($@) { $UseLocking = 0; last; } if (!$lockresult) { select(undef,undef,undef,0.1); # Wait for 1/10 sec. } else { last; # We have gotten the lock. } } } if ($TrysLeft >= 0) { # Success! return 0; } else { return -1; } } sub UnlockFile { local(*FILE) = @_; if ($UseLocking) { flock(FILE,8); # Unlock the file. } } #################################################################### # # Installation helpers # # SetBaseName # # Change the counter program itself to set the basename sub SetBaseName { local($name) = $0; $name =~ s/^.*\/([^\/]+)$/$1/; # Strip off any of the path if ($name eq $BaseName) { # The way we're set up now!!! return; # Don't need to change a thing. } if (!open(COUNTERFILE, "+<$0")) { print "Can't modify program. Set \$BaseName manually.\n"; return; } print "Configuring \$BaseName variable...\n"; local($oldsep) = $/; undef($/); local($program) = ; # The next line does all the magic. $program =~ s/\#\#\# AUTOMAGIC \#\#\#\n\$BaseName = \"[^\"]+\";\n/\#\#\# AUTOMAGIC \#\#\#\n\$BaseName = \"$name\";\n/; seek(COUNTERFILE,0,0) || return; truncate(COUNTERFILE,0); print COUNTERFILE $program; close COUNTERFILE; } # CheckPerl # # Make sure that the "#! /[path]/perl" points to something real... sub CheckPerl { if (!open(COUNTERFILE, "<$0")) { print "Can't check to make sure Perl is in the right place.\n"; return; } print "Checking to make sure Perl is found properly...\n"; $firstline = ; ($command) = ($firstline =~ /^\#! *([^\s]+) *$/); close(COUNTERFILE); if (! -x $command) { print "The location of Perl is misconfigured. Please edit the\n"; print "first line of this program to point to the locally installed\n"; print "copy of perl.\n\n"; print "Currently, it is configured to be \"$command\", however,\n"; print "that file either does not exist or is not a program.\n\n"; print "Some common locations for Perl are:\n"; print " /usr/bin/perl\n"; print " /usr/local/bin/perl\n"; print " /bin/perl\n"; print " /opt/gnu/bin/perl\n\n"; exit; } } # MakeCommon # # Make some common links to the counter sub MakeCommon { local($force) = @_; local($ext); print "Installing the counter...\n"; print " ...making counter executable\n"; chmod(0755,$0); local($path, $name, $cgi); $name = $0; if ($name =~ /^(.*\/)([^\/]+)$/) { $path = $1; $name = $2; } if ($name =~ /^(.*)(\.cgi)$/) { $name = $1, $cgi = $2; } foreach $ext (@CommonExtensions) { print " ...making link from $path$name$cgi to $path$name$ext$cgi\n"; if (!&MakeLink("$path$name$cgi","$path$name$ext$cgi",$force)) { # An error occured while making the link. :-( print " *** An error occured while making the link.\n"; } } if ($symlink_exists == 0 && $link_exists == 0) { print "* NOTE * Your system does not support symbolic or hard links,\n"; print " copies made instead. If you modify the counter, you must\n"; print " run counter -install again to recopy it to the other files.\n"; } print "...done!\n"; } # MakeLink # # Actually create the link. sub MakeLink { local($oldname,$newname,$force) = @_; # Check to see if we can make symbolic links instead of hard links if (!defined $symlink_exists) { $symlink_exists = (eval 'symlink("","");', $@ eq ''); } # Check to see if we can make a link if we can't make a symlink if (!symlink_exists) { $link_exists = (eval 'link("","");', $2 eq ''); } if ($force) { # Check to see if the file exists if (-e $newname) { if (!unlink ($newname)) { return 0; } } } if ($symlink_exists) { return symlink($oldname, $newname); } elsif ($link_exists) { return link($oldname, $newname); } else { # Copy it the old-fashioned way... *sigh* open(OLDFILE, $oldname) || die "Can't open $oldname for copy"; open(NEWFILE, ">$newname") || die "Can't open $newname for write"; while() { print NEWFILE $_; } close(NEWFILE); close(OLDFILE); } } #################################################################### # # Ordinalizing functions # # ordinalize # # Call the appropriate ordinalize function for the default language sub ordinalize { local($count) = @_; if (defined $arg{'lang'}) { return eval("&ordinalize_$arg{lang}($count)"); } else { return eval("&ordinalize_$default_lang($count)"); } } # ordinalize_english # # Figure out what suffix (st, nd, rd, th) a number would have in ordinal # form and return that extension. sub ordinalize_english { local($count) = @_; local($last, $last2); $last2 = $count % 100; $last = $count % 10; if ($last2 < 10 || $last2 > 13) { return "st" if $last == 1; return "nd" if $last == 2; return "rd" if $last == 3; } return "th"; # Catch "eleventh, twelveth, thirteenth" etc. } # ordinalize_french # # Trivial... Return the extension for french. The only exception is 1. # Thank you Chris Polewczuk sub ordinalize_french { local ($count) = @_; if ($count == 1) { return "'ière"; } else { return "ième"; } } # ordinalize_swedish # # A function to ordinalize in Swedish. Thanks go to Johan Linde # for the code! sub ordinalize_swedish { local($count) = @_; local($last, $last2); $last2 = $count % 100; $last = $count % 10; if ($last2 < 10 || $last2 > 12) { return ":a" if ($last == 1 || $last == 2); } return ":e"; } ######################################################################## # # Output functions # # The following are the routines that actually convert the number # of accesses into something that we print out. # # The name of each function is "output_" followed by the program's name. # For instance, is the program is called "counter" then "output_counter" # will be called; a program called "counterbanner" will call # "output_counterbanner" to get the output. # # If the function is not defined, then "output_counter" will be called. # # output_counter # # The simplest function: just returns the number of accesses and the link. sub output_counter { local($count) = @_; return &translate_output($count), $Link; # we return the count and the link } # output_counterord # # Return the number of accesses as an ordinal number. (ie. 1st, 2nd, 3rd, 4th) sub output_counterord { local($count) = @_; return &translate_output($count . &ordinalize($count)), $Link; } # output_counterbanner # # A somewhat silly one that uses the "banner" command to print out the # count. :) You might need to change the path to make it work. sub output_counterbanner { local($count) = @_; $banner = `banner $count`; return "

$banner
"; # return no link here (it would be annoying) } # output_counterfiglet # # An even sillier one than counterbanner. :) sub output_counterfiglet { local($count) = @_; $fig = "echo $count | /usr/games/figlet"; # setup command line $fig .= " -f $arg{'f'}" if $arg{"f"}; # use a different font? $fig = `$fig`; $fig =~ s!&!&!g; $fig =~ s!
" . $fig . "
"; # note no link here, either } ######################################################################### # # Conversion functions # # UpdateVersion # # Convert a version 1file into a version 2 file. sub UpdateVersion1 { local ($contents,$dummy); local ($oldsep) = $/; $/ = ""; seek(COUNT,0,0); # Go to the beginning of the file $contents = ; seek(COUNT,0,0); print COUNT "$FileVersion\n"; print COUNT $contents; seek(COUNT,0,0); $/ = $oldsep; $dummy = ; # Skip the new line } # ConvertDocV1 # # Convert the a version 1 line into a version 2 line sub ConvertDocV1 { local ($doc_uri,$old_uri,$accesses,$location) = @_; local ($contents,$dummy,$oldsep); $oldsep = $/; seek (COUNT,$location,0); # Skip the line in question $dummy = ; $/ = ""; # Read in the whole file $contents = ; seek (COUNT,$location,0); local ($longaccesses,$hexflags); $longaccesses = sprintf("%010.10d", $accesses); $hexflags = sprintf("%04.4x", $flags); # Print out the new stuff print COUNT "'$doc_uri' $longaccesses $hexflags\n"; print COUNT $contents; $/ = $oldsep; } cognoscenti who have ventured to this page since that date.


This page created and maintained by Vebmeister Jim Lowe
First appearance: May 18, 1997
Last updated: June 25, 2002

© 1997 by James R. Lowe, who reserves all rights to the content of this page not successfully claimed by others.  Speaking of which, King Features Syndicate could very well have something to say about that.  Indeed, they actually did.  I appreciate their gracious permission to continue displaying images of the Katzenjammer Kids for your enjoyment.  "Katzenjammer Kids" is a registered trademark of The Hearst Corporation and is used by permission.