~ubuntu-branches/ubuntu/dapper/xscreensaver/dapper-updates

« back to all changes in this revision

Viewing changes to hacks/webcollage

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Hildebrandt
  • Date: 2005-04-09 00:06:43 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050409000643-z0abtifbt9s20pcc
Tags: 4.21-3
Patch by Joachim Breitner to check more frequently if DPMS kicked in (closes: #303374, #286664).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/perl -w
2
2
#
3
 
# webcollage, Copyright (c) 1999-2001 by Jamie Zawinski <jwz@jwz.org>
 
3
# webcollage, Copyright (c) 1999-2005 by Jamie Zawinski <jwz@jwz.org>
4
4
# This program decorates the screen with random images from the web.
5
5
# One satisfied customer described it as "a nonstop pop culture brainbath."
6
6
#
9
9
# the above copyright notice appear in all copies and that both that
10
10
# copyright notice and this permission notice appear in supporting
11
11
# documentation.  No representations are made about the suitability of this
12
 
# software for any purpose.  It is provided "as is" without express or 
 
12
# software for any purpose.  It is provided "as is" without express or
13
13
# implied warranty.
14
14
 
 
15
 
15
16
# To run this as a display mode with xscreensaver, add this to `programs':
16
17
#
17
 
#   default-n:  webcollage -root                                        \n\
18
 
#   default-n:  webcollage -root -filter 'vidwhacker -stdin -stdout'    \n\
 
18
#     webcollage -root
 
19
#     webcollage -root -filter 'vidwhacker -stdin -stdout'
 
20
#
 
21
#
 
22
# You can see this in action at http://www.jwz.org/webcollage/ --
 
23
# it auto-reloads about once a minute.  To make a page similar to
 
24
# that on your own system, do this:
 
25
#
 
26
#     webcollage -size '800x600' -imagemap $HOME/www/webcollage/index
 
27
#
 
28
#
 
29
# If you have the "driftnet" program installed, webcollage can display a
 
30
# collage of images sniffed off your local ethernet, instead of pulled out
 
31
# of search engines: in that way, your screensaver can display the images
 
32
# that your co-workers are downloading!
 
33
#
 
34
# Driftnet is available here: http://www.ex-parrot.com/~chris/driftnet/
 
35
# Use it like so:
 
36
#
 
37
#     webcollage -root -driftnet
 
38
#
 
39
# Driftnet is the Unix implementation of the MacOS "EtherPEG" program.
19
40
 
20
41
 
21
42
require 5;
33
54
use Fcntl ':flock'; # import LOCK_* constants
34
55
use POSIX qw(strftime);
35
56
 
 
57
use bytes;  # Larry can take Unicode and shove it up his ass sideways.
 
58
            # Perl 5.8.0 causes us to start getting incomprehensible
 
59
            # errors about UTF-8 all over the place without this.
 
60
 
36
61
 
37
62
my $progname = $0; $progname =~ s@.*/@@g;
38
 
my $version = q{ $Revision: 1.78 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
39
 
my $copyright = "WebCollage $version, Copyright (c) 1999-2001" .
 
63
my $version = q{ $Revision: 1.125 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 
64
my $copyright = "WebCollage $version, Copyright (c) 1999-2005" .
40
65
    " Jamie Zawinski <jwz\@jwz.org>\n" .
41
 
    "            http://www.jwz.org/xscreensaver/\n";
42
 
 
43
 
 
44
 
 
45
 
my @search_methods = (  30, "imagevista", \&pick_from_alta_vista_images,
46
 
                        28, "altavista",  \&pick_from_alta_vista_text,
47
 
                        18, "yahoorand",  \&pick_from_yahoo_random_link,
48
 
                        14, "googleimgs", \&pick_from_google_images,
49
 
                         2, "yahoonews",  \&pick_from_yahoo_news_text,
50
 
                         8, "lycos",      \&pick_from_lycos_text,
51
 
 
52
 
                     # Hotbot gives me "no matches" just about every time.
53
 
                     # Then I try the same URL again, and it works.  I guess
54
 
                     # it caches searches, and webcollage always busts its
55
 
                     # cache and time out?  Or it just sucks.
56
 
                     #   0, "hotbot",     \&pick_from_hotbot_text,
 
66
    "            http://www.jwz.org/webcollage/\n";
 
67
 
 
68
 
 
69
 
 
70
my @search_methods = (  58, "altavista",    \&pick_from_alta_vista_random_link,
 
71
                        11, "livejournal",  \&pick_from_livejournal_images,
 
72
                         7, "yahoorand",    \&pick_from_yahoo_random_link,
 
73
                        10, "googlephotos", \&pick_from_google_image_photos,
 
74
                         6, "googleimgs",   \&pick_from_google_images,
 
75
                         3, "googlenums",   \&pick_from_google_image_numbers,
 
76
                         5, "flickr",       \&pick_from_flickr,
 
77
 
 
78
                     # In Apr 2002, Google asked me to stop searching them.
 
79
                     # I asked them to add a "random link" url.  They said
 
80
                     # "that would be easy, we'll think about it" and then
 
81
                     # never wrote back.  Booo Google!  Booooo!  So, screw
 
82
                     # those turkeys, I've turned Google searching back on.
 
83
                     # I'm sure they can take it.  (Jan 2005.)
 
84
 
 
85
                     # Jan 2005: Yahoo fucked up their search form so that
 
86
                     # it's no longer possible to do "or" searches on news
 
87
                     # images, so we rarely get any hits there any more.
 
88
                     # 
 
89
                     #  0, "yahoonews",   \&pick_from_yahoo_news_text,
 
90
 
 
91
                     # Dec 2004: the ircimages guy's server can't take the
 
92
                     # heat, so he started banning the webcollage user agent.
 
93
                     # I tried to convince him to add a lighter-weight page to
 
94
                     # support webcollage better, but he doesn't care.
 
95
                     #
 
96
                     #  0, "ircimages", \&pick_from_ircimages,
 
97
 
 
98
                     # Dec 2002: Alta Vista has a new "random link" URL now.
 
99
                     # They added it specifically to better support webcollage!
 
100
                     # That was super cool of them.  This is how we used to do
 
101
                     # it, before:
 
102
                     #
 
103
                     #  0, "avimages", \&pick_from_alta_vista_images,
 
104
                     #  0, "avtext",   \&pick_from_alta_vista_text,
 
105
 
 
106
                     # This broke in 2004.  Eh, Lycos sucks anyway.
 
107
                     #
 
108
                     #   0, "lycos",      \&pick_from_lycos_text,
 
109
 
 
110
                     # This broke in 2003, I think.  I suspect Hotbot is
 
111
                     # actually the same search engine data as Lycos.
 
112
                     #
 
113
                     #  0, "hotbot",     \&pick_from_hotbot_text,
57
114
                      );
58
115
 
59
 
#@search_methods=(100, "lycos",     \&pick_from_lycos_text);
60
 
@search_methods=(100, "googleimgs",\&pick_from_google_images);
61
 
 
62
116
# programs we can use to write to the root window (tried in ascending order.)
63
117
#
64
 
my @root_displayers = ( 
 
118
my @root_displayers = (
 
119
  "xscreensaver-getimage -root -file",
 
120
  "chbg       -once -xscreensaver -max_size 100",
 
121
  "xv         -root -quit -viewonly +noresetroot -quick24 -rmode 5" .
 
122
  "           -rfg black -rbg black",
 
123
  "xli        -quiet -onroot -center -border black",
65
124
  "xloadimage -quiet -onroot -center -border black",
66
 
  "xli        -quiet -onroot -center -border black",
67
 
  "xv         -root -quit -viewonly +noresetroot -rmode 5" .
68
 
  "           -rfg black -rbg black",
69
 
  "chbg       -once -xscreensaver",
70
125
 
71
126
# this lame program wasn't built with vroot.h:
72
127
# "xsri       -scale -keep-aspect -center-horizontal -center-vertical",
79
134
  "www.altavista.com"  =>  "AV_ALL=1",   # request uncensored searches
80
135
  "web.altavista.com"  =>  "AV_ALL=1",
81
136
 
82
 
                                         # log in as "cpunks"
83
 
  "www.nytimes.com"    =>  "NYT-S=104nv1sChNnnWAvTLGx6eiDhzQcbSoN" .
84
 
                                 "6zOMB7s0Qm8MlMaa8It.2/BlXTrpbBk" .
85
 
                                 "jinV68IcqxOvAABDyKdciIJ8O000",
 
137
                                         # log in as "cipherpunk"
 
138
  "www.nytimes.com"    =>  'NYT-S=18cHMIlJOn2Y1bu5xvEG3Ufuk6E1oJ.' .
 
139
                           'FMxWaQV0igaB5Yi/Q/guDnLeoL.pe7i1oakSb' .
 
140
                           '/VqfdUdb2Uo27Vzt1jmPn3cpYRlTw9',
 
141
 
 
142
  "ircimages.com"      =>  'disclaimer=1',
86
143
);
87
144
 
88
145
 
 
146
# If this is set, it's a helper program to use for pasting images together:
 
147
# this is a lot faster and more efficient than using PPM pipelines, which is
 
148
# what we do if this program doesn't exist.  (We check for "webcollage-helper"
 
149
# on $PATH at startup, and set this variable appropriately.)
 
150
#
 
151
my $webcollage_helper = undef;
 
152
 
 
153
 
 
154
# If we have the webcollage-helper program, then it will paste the images
 
155
# together with transparency!  0.0 is invisible, 1.0 is totally opaque.
 
156
#
 
157
my $opacity = 0.85;
 
158
 
 
159
 
89
160
# Some sites have  managed to poison the search engines.  These are they.
90
161
# (We auto-detect sites that have poisoned the search engines via excessive
91
162
# keywords or dictionary words,  but these are ones that slip through
95
166
#
96
167
my %poisoners = (
97
168
  "die.net"                 => 1,  # 'l33t h4ck3r d00dz.
98
 
  "genforum.genealogy.com"  => 1,  # Cluttering altavista with human names.
99
 
  "rootsweb.com"            => 1,  # Cluttering altavista with human names.
 
169
  "genforum.genealogy.com"  => 1,  # Cluttering avtext with human names.
 
170
  "rootsweb.com"            => 1,  # Cluttering avtext with human names.
100
171
  "akamai.net"              => 1,  # Lots of sites have their images on Akamai.
101
 
                                   # But those are pretty much all banners.
 
172
  "akamaitech.net"          => 1,  # But those are pretty much all banners.
102
173
                                   # Since Akamai is super-expensive, let's
103
174
                                   # go out on a limb and assume that all of
104
175
                                   # their customers are rich-and-boring.
 
176
  "bartleby.com"            => 1,  # Dictionary, cluttering avtext.
 
177
  "encyclopedia.com"        => 1,  # Dictionary, cluttering avtext.
 
178
  "onlinedictionary.datasegment.com" => 1,  # Dictionary, cluttering avtext.
 
179
  "hotlinkpics.com"         => 1,  # Porn site that has poisoned avimages
 
180
                                   # (I don't see how they did it, though!)
 
181
  "alwayshotels.com"        => 1,  # Poisoned Lycos pretty heavily.
 
182
  "nextag.com"              => 1,  # Poisoned Alta Vista real good.
105
183
);
106
184
 
107
185
 
116
194
  "www.geocities.com"       => 1,
117
195
  "www.angelfire.com"       => 1,
118
196
  "members.aol.com"         => 1,
 
197
  "img.photobucket.com"     => 1,
 
198
  "pics.livejournal.com"    => 1,
 
199
  "tinypic.com"             => 1,
 
200
  "flickr.com"              => 1,
119
201
 
120
202
  "yimg.com"                => 1,  # This is where dailynews.yahoo.com stores
121
203
  "eimg.com"                => 1,  # its images, so pick_from_yahoo_news_text()
122
204
                                   # hits this every time.
 
205
 
 
206
  "images.quizfarm.com"     => 1,  # damn those LJ quizzes...
 
207
  "images.quizilla.com"     => 1,
 
208
  "images.quizdiva.net"     => 1,
 
209
 
 
210
  "driftnet"                => 1,  # builtin...
123
211
);
124
212
 
125
213
 
148
236
my $report_performance_interval = 60 * 15;  # print some stats every 15 minutes
149
237
 
150
238
my $http_proxy = undef;
151
 
my $http_timeout = 30;
 
239
my $http_timeout = 20;
152
240
my $cvt_timeout = 10;
153
241
 
154
242
my $min_width = 50;
155
243
my $min_height = 50;
156
244
my $min_ratio = 1/5;
157
245
 
 
246
my $min_gif_area = (120 * 120);
 
247
 
 
248
 
158
249
my $no_output_p = 0;
159
250
my $urls_only_p = 0;
 
251
my $imagemap_base = undef;
 
252
 
 
253
my @pids_to_kill = ();  # forked pids we should kill when we exit, if any.
 
254
 
 
255
my $driftnet_magic = 'driftnet';
 
256
my $driftnet_dir = undef;
 
257
my $default_driftnet_cmd = "driftnet -a -m 100";
160
258
 
161
259
my $wordlist;
162
260
 
198
296
  my ($url_proto, $dummy, $serverstring, $path) = split(/\//, $url, 4);
199
297
  $path = "" unless $path;
200
298
 
 
299
  if (!$url_proto || !$serverstring) {
 
300
    LOG (($verbose_net || $verbose_load), "unparsable URL: $url");
 
301
    return ();
 
302
  }
 
303
 
201
304
  my ($them,$port) = split(/:/, $serverstring);
202
305
  $port = 80 unless $port;
203
306
 
205
308
  my $port2 = $port;
206
309
  if ($http_proxy) {
207
310
    $serverstring = $http_proxy if $http_proxy;
 
311
    $serverstring =~ s@^[a-z]+://@@;
208
312
    ($them2,$port2) = split(/:/, $serverstring);
209
313
    $port2 = 80 unless $port2;
210
314
  }
250
354
      my $cookie = $cookies{$them};
251
355
 
252
356
      my $user_agent = "$progname/$version";
253
 
      if ($url =~ m@^http://www\.altavista\.com/@) {
 
357
 
 
358
      if ($url =~ m@^http://www\.altavista\.com/@ ||
 
359
          $url =~ m@^http://random\.yahoo\.com/@ ||
 
360
          $url =~ m@^http://images\.google\.com/@) {
254
361
        # block this, you turkeys.
255
 
        $user_agent = "Mozilla/4.76 [en] (X11; U; Linux 2.2.16-22 i686; Nav)";
 
362
        $user_agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5)" .
 
363
          " Gecko/20041111 Firefox/1.0";
256
364
      }
257
365
 
258
366
      my $hdrs = "GET " . ($http_proxy ? $url : "/$path") . " HTTP/1.0\r\n" .
262
370
        $hdrs .= "Referer: $referer\r\n";
263
371
      }
264
372
      if ($cookie) {
265
 
        foreach (split(/\r?\n/, $cookie)) {
266
 
          $hdrs .= "Cookie: $_\r\n";
267
 
        }
 
373
        my @cc = split(/\r?\n/, $cookie);
 
374
        $hdrs .= "Cookie: " . join('; ', @cc) . "\r\n";
268
375
      }
269
376
      $hdrs .= "\r\n";
270
377
 
272
379
        LOG ($verbose_http, "  ==> $_");
273
380
      }
274
381
      print S $hdrs;
275
 
      my $http = <S>;
 
382
      my $http = <S> || "";
 
383
 
 
384
      # Kludge: the Yahoo Random Link is now returning as its first
 
385
      # line "Status: 301" instead of "HTTP/1.0 301 Found".  Fix it...
 
386
      #
 
387
      $http =~ s@^Status:\s+(\d+)\b@HTTP/1.0 $1@i;
276
388
 
277
389
      $_  = $http;
278
390
      s/[\r\n]+$//s;
305
417
        return ();
306
418
      }
307
419
 
 
420
      $SIG{ALRM} = 'DEFAULT';  # seem to be suffering a race?
308
421
      return ( $http, $head, $body );
309
422
    };
310
423
  die if ($@ && $@ ne "alarm\n");       # propagate errors
 
424
 
 
425
  if ($@ && $@ ne "alarm\n") {
 
426
    print STDERR blurb() . "DIE " . join(" ", $@) . "\n";
 
427
    die;
 
428
  }
 
429
 
311
430
  if ($@) {
312
431
    # timed out
313
432
    $head = undef;
329
448
  my ( $url, $referer, $timeout ) = @_;
330
449
  my $start = time;
331
450
 
 
451
  if (defined($referer) && $referer eq $driftnet_magic) {
 
452
    return get_driftnet_file ($url);
 
453
  }
 
454
 
332
455
  my $orig_url = $url;
333
456
  my $loop_count = 0;
334
457
  my $max_loop_count = 4;
355
478
 
356
479
    if ( $http =~ m@^HTTP/[0-9.]+ 30[123]@ ) {
357
480
      $_ = $head;
 
481
 
358
482
      my ( $location ) = m@^location:[ \t]*(.*)$@im;
359
483
      if ( $location ) {
360
484
        $location =~ s/[\r\n]$//;
473
597
  # randomly from the set of images on the web.  All the logic here for
474
598
  # rejecting some images is really a set of heuristics for rejecting
475
599
  # images that are not really images: for rejecting *text* that is in
476
 
  # GIF/JPEG form.  I don't want text, I want pictures, and I want the
477
 
  # content of the pictures to be randomly selected from among all the
478
 
  # available content.
 
600
  # GIF/JPEG/PNG form.  I don't want text, I want pictures, and I want
 
601
  # the content of the pictures to be randomly selected from among all
 
602
  # the available content.
479
603
  #
480
604
  # So, filtering out "dirty" pictures by looking for "dirty" keywords
481
605
  # would be wrong: dirty pictures exist, like it or not, so webcollage
533
657
 
534
658
    } elsif ( m/^(img|a) .*(src|href) ?= ?\"? ?(.*?)[ >\"]/io ) {
535
659
 
536
 
      my $was_inline = ( "$1" eq "a" || "$1" eq "A" );
 
660
      my $was_inline = (! ( "$1" eq "a" || "$1" eq "A" ));
537
661
      my $link = $3;
538
662
      my ( $width )  = m/width ?=[ \"]*(\d+)/oi;
539
663
      my ( $height ) = m/height ?=[ \"]*(\d+)/oi;
546
670
      } elsif ( ! m@^[^/:?]+:@ ) {
547
671
        $_ = "$base$link";
548
672
        s@/\./@/@g;
549
 
        while (s@/\.\./@/@g) {
550
 
        }
 
673
        1 while (s@/[^/]+/\.\./@/@g);
551
674
      }
552
675
 
553
676
      # skip non-http
556
679
      }
557
680
 
558
681
      # skip non-image
559
 
      if ( ! m@[.](gif|jpg|jpeg|pjpg|pjpeg)$@io ) {
 
682
      if ( ! m@[.](gif|jpg|jpeg|pjpg|pjpeg|png)$@io ) {
560
683
        next;
561
684
      }
562
685
 
581
704
        next;
582
705
      }
583
706
 
 
707
      # skip GIFs with a small number of pixels -- those usually suck.
 
708
      if ($width && $height &&
 
709
          m/\.gif$/io &&
 
710
          ($width * $height) < $min_gif_area) {
 
711
        LOG ($verbose_filter, "  skip small GIF $_ (${width}x$height)");
 
712
        next;
 
713
      }
 
714
      
 
715
      # skip images with a URL that indicates a Yahoo thumbnail.
 
716
      if (m@\.yimg\.com/.*/t/@) {
 
717
        if (!$width)  { $width  = "?"; }
 
718
        if (!$height) { $height = "?"; }
 
719
        LOG ($verbose_filter, "  skip yahoo thumb $_ (${width}x$height)");
 
720
        next;
 
721
      }
 
722
 
584
723
      my $url = $_;
585
724
 
586
725
      if ($unique_urls{$url}) {
589
728
      }
590
729
 
591
730
      LOG ($verbose_filter,
592
 
           "  image $url" . 
 
731
           "  image $url" .
593
732
           ($width && $height ? " (${width}x${height})" : "") .
594
733
           ($was_inline ? " (inline)" : ""));
595
734
 
596
735
      $urls[++$#urls] = $url;
597
736
      $unique_urls{$url}++;
598
737
 
599
 
      # jpegs are preferable to gifs.
 
738
      # JPEGs are preferable to GIFs and PNGs.
600
739
      $_ = $url;
601
 
      if ( ! m@[.]gif$@io ) {
 
740
      if ( ! m@[.](gif|png)$@io ) {
602
741
        $urls[++$#urls] = $url;
603
742
      }
604
743
 
615
754
  $_ = undef;
616
755
  $body = undef;
617
756
 
 
757
  @urls = depoison (@urls);
 
758
 
618
759
  if ( $#urls < 0 ) {
619
760
    LOG ($verbose_load, "no images on $base" . ($fsp ? " (frameset)" : ""));
620
761
    return ();
621
762
  }
622
763
 
623
 
  @urls = depoison (@urls);
624
 
 
625
764
  # pick a random element of the table
626
765
  my $i = int(rand($#urls+1));
627
766
  $url = $urls[$i];
656
795
# returns a random word from the dictionary
657
796
#
658
797
sub random_word {
659
 
    
660
 
    my $word = 0;
661
 
    if (open (IN, "<$wordlist")) {
662
 
        my $size = (stat(IN))[7];
663
 
        my $pos = rand $size;
664
 
        if (seek (IN, $pos, 0)) {
665
 
            $word = <IN>;   # toss partial line
666
 
            $word = <IN>;   # keep next line
667
 
        }
668
 
        if (!$word) {
669
 
          seek( IN, 0, 0 );
670
 
          $word = <IN>;
671
 
        }
672
 
        close (IN);
673
 
    }
674
 
 
675
 
    return 0 if (!$word);
676
 
 
677
 
    $word =~ s/^[ \t\n\r]+//;
678
 
    $word =~ s/[ \t\n\r]+$//;
679
 
    $word =~ s/ys$/y/;
680
 
    $word =~ s/ally$//;
681
 
    $word =~ s/ly$//;
682
 
    $word =~ s/ies$/y/;
683
 
    $word =~ s/ally$/al/;
684
 
    $word =~ s/izes$/ize/;
685
 
    $word =~ tr/A-Z/a-z/;
686
 
 
687
 
    if ( $word =~ s/[ \t\n\r]/\+/g ) {  # convert intra-word spaces to "+".
688
 
      $word = "\%22$word\%22";          # And put quotes (%22) around it.
689
 
    }
690
 
 
691
 
    return $word;
 
798
 
 
799
  local *IN;
 
800
  if (! open (IN, "<$wordlist")) {
 
801
    return undef;
 
802
  }
 
803
 
 
804
  my $size = (stat(IN))[7];
 
805
  my $word = undef;
 
806
  my $count = 0;
 
807
 
 
808
  while (1) {
 
809
    error ("looping ($count) while reading $wordlist")
 
810
      if (++$count > 100);
 
811
 
 
812
    my $pos = int (rand ($size));
 
813
    if (seek (IN, $pos, 0)) {
 
814
      $word = <IN>;   # toss partial line
 
815
      $word = <IN>;   # keep next line
 
816
    }
 
817
 
 
818
    next unless ($word);
 
819
    next if ($word =~ m/^[-\']/);
 
820
 
 
821
    $word = lc($word);
 
822
    $word =~ s/^.*-//s;
 
823
    $word =~ s/^[^a-z]+//s;
 
824
    $word =~ s/[^a-z]+$//s;
 
825
    $word =~ s/\'s$//s;
 
826
    $word =~ s/ys$/y/s;
 
827
    $word =~ s/ally$//s;
 
828
    $word =~ s/ly$//s;
 
829
    $word =~ s/ies$/y/s;
 
830
    $word =~ s/ally$/al/s;
 
831
    $word =~ s/izes$/ize/s;
 
832
    $word =~ s/esses$/ess/s;
 
833
    $word =~ s/(.{5})ing$/$1/s;
 
834
 
 
835
    next if (length ($word) > 14);
 
836
    last if ($word);
 
837
  }
 
838
 
 
839
  close (IN);
 
840
 
 
841
  if ( $word =~ s/\s/\+/gs ) {  # convert intra-word spaces to "+".
 
842
    $word = "\%22$word\%22";    # And put quotes (%22) around it.
 
843
  }
 
844
 
 
845
  return $word;
692
846
}
693
847
 
 
848
 
694
849
sub random_words {
695
 
  return (random_word . "%20" .
696
 
          random_word . "%20" .
697
 
          random_word . "%20" .
698
 
          random_word . "%20" .
 
850
  my ($or_p) = @_;
 
851
  my $sep = ($or_p ? "%20OR%20" : "%20");
 
852
  return (random_word . $sep .
 
853
          random_word . $sep .
 
854
          random_word . $sep .
 
855
          random_word . $sep .
699
856
          random_word);
700
857
}
701
858
 
702
859
 
 
860
sub url_quote {
 
861
  my ($s) = @_;
 
862
  $s =~ s|([^-a-zA-Z0-9.\@/_\r\n])|sprintf("%%%02X", ord($1))|ge;
 
863
  return $s;
 
864
}
 
865
 
 
866
sub url_unquote {
 
867
  my ($s) = @_;
 
868
  $s =~ s/[+]/ /g;
 
869
  $s =~ s/%([a-z0-9]{2})/chr(hex($1))/ige;
 
870
  return $s;
 
871
}
 
872
 
 
873
sub html_quote {
 
874
  my ($s) = @_;
 
875
  $s =~ s/&/&amp;/gi;
 
876
  $s =~ s/</&lt;/gi;
 
877
  $s =~ s/>/&gt;/gi;
 
878
  $s =~ s/\"/&quot;/gi;
 
879
  return $s;
 
880
}
 
881
 
 
882
sub html_unquote {
 
883
  my ($s) = @_;
 
884
  $s =~ s/&lt;/</gi;       # far from exhaustive...
 
885
  $s =~ s/&gt;/</gi;
 
886
  $s =~ s/&quot;/\"/gi;
 
887
  $s =~ s/&amp;/&/gi;
 
888
  return $s;
 
889
}
 
890
 
 
891
 
703
892
# Loads the given URL (a search on some search engine) and returns:
704
893
# - the total number of hits the search engine claimed it had;
705
894
# - a list of URLs from the page that the search engine returned;
746
935
    $search_count = $1;
747
936
  } elsif ($body =~ m@found about ((\d{1,3})(,\d{3})*|\d+) results@) {
748
937
    $search_count = $1;
749
 
  } elsif ($body =~ m@\b\d+ - \d+ of (\d+)\b@i) { # imagevista
750
 
    $search_count = $1;
751
 
  } elsif ($body =~ m@About ((\d{1,3})(,\d{3})*) images@i) { # imagevista
752
 
    $search_count = $1;
 
938
  } elsif ($body =~ m@\b\d+ - \d+ of (\d+)\b@i) { # avimages
 
939
    $search_count = $1;
 
940
  } elsif ($body =~ m@About ((\d{1,3})(,\d{3})*) images@i) { # avimages
 
941
    $search_count = $1;
 
942
  } elsif ($body =~ m@We found ((\d{1,3})(,\d{3})*|\d+) results@i) { # *vista
 
943
    $search_count = $1;
 
944
  } elsif ($body =~ m@ of about <B>((\d{1,3})(,\d{3})*)<@i) { # googleimages
 
945
    $search_count = $1;
 
946
  } elsif ($body =~ m@<B>((\d{1,3})(,\d{3})*)</B> Web sites were found@i) {
 
947
    $search_count = $1;    # lycos
753
948
  } elsif ($body =~ m@WEB.*?RESULTS.*?\b((\d{1,3})(,\d{3})*)\b.*?Matches@i) {
754
949
    $search_count = $1;                          # hotbot
755
 
  } elsif ($body =~ m@no photos were found containing@i) { # imagevista
 
950
  } elsif ($body =~ m@no photos were found containing@i) { # avimages
756
951
    $search_count = "0";
757
 
  } elsif ($body =~ m@found no document matching@i) { # altavista
 
952
  } elsif ($body =~ m@found no document matching@i) { # avtext
758
953
    $search_count = "0";
759
954
  }
760
955
  1 while ($search_count =~ s/^(\d+)(\d{3})/$1,$2/);
839
1034
 
840
1035
# given a list of URLs, picks one at random; loads it; and returns a
841
1036
# random image from it.
842
 
# returns the url of the page loaded; the url of the image chosen;
843
 
# and a debugging description string.
 
1037
# returns the url of the page loaded; the url of the image chosen.
844
1038
#
845
1039
sub pick_image_from_pages {
846
1040
  my ($base, $total_hit_count, $unfiltered_link_count, $timeout, @pages) = @_;
886
1080
############################################################################
887
1081
 
888
1082
# yahoorand
889
 
my $yahoo_random_link = "http://random.yahoo.com/bin/ryl";
 
1083
my $yahoo_random_link = "http://random.yahoo.com/fast/ryl";
890
1084
 
891
1085
 
892
1086
# Picks a random page; picks a random image on that page;
909
1103
    return;
910
1104
  }
911
1105
 
912
 
  LOG ($verbose_load, "redirected to: $base"); 
 
1106
  LOG ($verbose_load, "redirected to: $base");
 
1107
 
 
1108
  my $img = pick_image_from_body ($base, $body);
 
1109
  $body = undef;
 
1110
 
 
1111
  if ($img) {
 
1112
    return ($base, $img);
 
1113
  } else {
 
1114
    return ();
 
1115
  }
 
1116
}
 
1117
 
 
1118
 
 
1119
############################################################################
 
1120
#
 
1121
# Pick images from random pages returned by the Alta Vista Random Link
 
1122
#
 
1123
############################################################################
 
1124
 
 
1125
# altavista
 
1126
my $alta_vista_random_link = "http://www.altavista.com/image/randomlink";
 
1127
 
 
1128
 
 
1129
# Picks a random page; picks a random image on that page;
 
1130
# returns two URLs: the page containing the image, and the image.
 
1131
# Returns () if nothing found this time.
 
1132
#
 
1133
sub pick_from_alta_vista_random_link {
 
1134
  my ( $timeout ) = @_;
 
1135
 
 
1136
  print STDERR "\n\n" if ($verbose_load);
 
1137
  LOG ($verbose_load, "URL: $alta_vista_random_link");
 
1138
 
 
1139
  $last_search = $alta_vista_random_link;   # for warnings
 
1140
 
 
1141
  $suppress_audit = 1;
 
1142
 
 
1143
  my ( $base, $body ) = get_document ($alta_vista_random_link,
 
1144
                                      undef, $timeout);
 
1145
  if (!$base || !$body) {
 
1146
    $body = undef;
 
1147
    return;
 
1148
  }
 
1149
 
 
1150
  LOG ($verbose_load, "redirected to: $base");
913
1151
 
914
1152
  my $img = pick_image_from_body ($base, $body);
915
1153
  $body = undef;
929
1167
############################################################################
930
1168
 
931
1169
 
932
 
my $alta_vista_images_url = "http://www.altavista.com/cgi-bin/query" .
 
1170
my $alta_vista_images_url = "http://www.altavista.com/image/results" .
933
1171
                            "?ipht=1" .       # photos
934
1172
                            "&igrph=1" .      # graphics
935
1173
                            "&iclr=1" .       # color
936
1174
                            "&ibw=1" .        # b&w
937
1175
                            "&micat=1" .      # no partner sites
938
 
                            "&imgset=1" .     # no partner sites
939
 
                            "&stype=simage" . # do image search
940
 
                            "&mmW=1" .        # unknown, but required
 
1176
                            "&sc=on" .        # "site collapse"
941
1177
                            "&q=";
942
1178
 
943
 
 
944
 
# imagevista
 
1179
# avimages
945
1180
sub pick_from_alta_vista_images {
946
1181
  my ( $timeout ) = @_;
947
1182
 
948
 
  my $words = random_words;
 
1183
  my $words = random_word();
949
1184
  my $page = (int(rand(9)) + 1);
950
1185
  my $search_url = $alta_vista_images_url . $words;
951
1186
 
959
1194
 
960
1195
  my @candidates = ();
961
1196
  foreach my $u (@subpages) {
 
1197
 
 
1198
    # avimages is encoding their URLs now.
 
1199
    next unless ($u =~ s/^.*\*\*(http%3a.*$)/$1/gsi);
 
1200
    $u = url_unquote($u);
 
1201
 
962
1202
    next unless ($u =~ m@^http://@i);    #  skip non-HTTP or relative URLs
963
1203
    next if ($u =~ m@[/.]altavista\.com\b@i);     # skip altavista builtins
 
1204
    next if ($u =~ m@[/.]yahoo\.com\b@i);         # yahoo and av in cahoots?
964
1205
    next if ($u =~ m@[/.]doubleclick\.net\b@i);   # you cretins
965
1206
    next if ($u =~ m@[/.]clicktomarket\.com\b@i); # more cretins
966
1207
 
979
1220
 
980
1221
############################################################################
981
1222
#
982
 
# Pick images by feeding random words into Google Image Search
 
1223
# Pick images by feeding random words into Google Image Search.
983
1224
# By Charles Gales <gales@us.ibm.com>
984
1225
#
985
1226
############################################################################
994
1235
 
995
1236
# googleimgs
996
1237
sub pick_from_google_images {
997
 
  my ( $timeout ) = @_;
998
 
 
999
 
  my $words = random_word;   # only one word for Google
 
1238
  my ( $timeout, $words, $max_page ) = @_;
 
1239
 
 
1240
  if (!defined($words)) {
 
1241
    $words = random_word;   # only one word for Google
 
1242
  }
 
1243
 
1000
1244
  my $page = (int(rand(9)) + 1);
1001
1245
  my $num = 20;     # 20 images per page
1002
1246
  my $search_url = $google_images_url . $words;
1010
1254
    pick_from_search_engine ($timeout, $search_url, $words);
1011
1255
 
1012
1256
  my @candidates = ();
 
1257
  my %referers;
1013
1258
  foreach my $u (@subpages) {
1014
1259
    next unless ($u =~ m@imgres\?imgurl@i);    #  All pics start with this
1015
1260
    next if ($u =~ m@[/.]google\.com\b@i);     # skip google builtins
1016
1261
 
1017
1262
    if ($u =~ m@^/imgres\?imgurl=(.*?)\&imgrefurl=(.*?)\&@) {
1018
 
      my $urlf = $2;
1019
 
      LOG ($verbose_filter, "  candidate: $urlf");
1020
 
      push @candidates, $urlf;
 
1263
      my $ref = $2;
 
1264
      my $img = $1;
 
1265
      $img = "http://$img" unless ($img =~ m/^http:/i);
 
1266
 
 
1267
      LOG ($verbose_filter, "  candidate: $ref");
 
1268
      push @candidates, $img;
 
1269
      $referers{$img} = $ref;
1021
1270
    }
1022
1271
  }
1023
1272
 
1024
 
  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
1025
 
                                $timeout, @candidates);
 
1273
  @candidates = depoison (@candidates);
 
1274
  return () if ($#candidates < 0);
 
1275
  my $i = int(rand($#candidates+1));
 
1276
  my $img = $candidates[$i];
 
1277
  my $ref = $referers{$img};
 
1278
 
 
1279
  LOG ($verbose_load, "picked image " . ($i+1) . ": $img (on $ref)");
 
1280
  return ($ref, $img);
 
1281
}
 
1282
 
 
1283
 
 
1284
 
 
1285
############################################################################
 
1286
#
 
1287
# Pick images by feeding random numbers into Google Image Search.
 
1288
# By jwz, suggested by Ian O'Donnell.
 
1289
#
 
1290
############################################################################
 
1291
 
 
1292
 
 
1293
# googlenums
 
1294
sub pick_from_google_image_numbers {
 
1295
  my ( $timeout ) = @_;
 
1296
 
 
1297
  my $max = 9999;
 
1298
  my $number = int(rand($max));
 
1299
 
 
1300
  $number = sprintf("%04d", $number)
 
1301
    if (rand() < 0.3);
 
1302
 
 
1303
  pick_from_google_images ($timeout, "$number");
 
1304
}
 
1305
 
 
1306
 
 
1307
 
 
1308
############################################################################
 
1309
#
 
1310
# Pick images by feeding random digital camera file names into 
 
1311
# Google Image Search.
 
1312
# By jwz, inspired by the excellent Random Personal Picture Finder
 
1313
# at http://www.diddly.com/random/
 
1314
#
 
1315
############################################################################
 
1316
 
 
1317
my @photomakers = (
 
1318
  #
 
1319
  # Common digital camera file name formats, as described at
 
1320
  # http://www.diddly.com/random/about.html
 
1321
  #
 
1322
  sub { sprintf ("dcp%05d.jpg",  int(rand(4000))); },   # Kodak
 
1323
  sub { sprintf ("dsc%05d.jpg",  int(rand(4000))); },   # Nikon
 
1324
  sub { sprintf ("dscn%04d.jpg", int(rand(4000))); },   # Nikon
 
1325
  sub { sprintf ("mvc-%03d.jpg", int(rand(999)));  },   # Sony Mavica
 
1326
  sub { sprintf ("mvc%05d.jpg",  int(rand(9999))); },   # Sony Mavica
 
1327
  sub { sprintf ("P101%04d.jpg", int(rand(9999))); },   # Olympus w/ date=101
 
1328
  sub { sprintf ("P%x%02d%04d.jpg",                     # Olympus
 
1329
                 int(rand(0xC)), int(rand(30))+1,
 
1330
                 rand(9999)); },
 
1331
  sub { sprintf ("IMG_%03d.jpg",  int(rand(999))); },   # ?
 
1332
  sub { sprintf ("IMAG%04d.jpg",  int(rand(9999))); },  # RCA and Samsung
 
1333
  sub { my $n = int(rand(9999));                        # Canon
 
1334
          sprintf ("1%02d-%04d.jpg", int($n/100), $n); },
 
1335
  sub { my $n = int(rand(9999));                        # Canon
 
1336
          sprintf ("1%02d-%04d_IMG.jpg",
 
1337
                   int($n/100), $n); },
 
1338
  sub { sprintf ("IMG_%04d.jpg", int(rand(9999))); },   # Canon
 
1339
  sub { sprintf ("dscf%04d.jpg", int(rand(9999))); },   # Fuji Finepix
 
1340
  sub { sprintf ("pdrm%04d.jpg", int(rand(9999))); },   # Toshiba PDR
 
1341
  sub { sprintf ("IM%06d.jpg", int(rand(9999))); },     # HP Photosmart
 
1342
  sub { sprintf ("EX%06d.jpg", int(rand(9999))); },     # HP Photosmart
 
1343
#  sub { my $n = int(rand(3));                          # Kodak DC-40,50,120
 
1344
#        sprintf ("DC%04d%s.jpg", int(rand(9999)),
 
1345
#                 $n == 0 ? 'S' : $n == 1 ? 'M' : 'L'); },
 
1346
  sub { sprintf ("pict%04d.jpg", int(rand(9999))); },   # Minolta Dimage
 
1347
  sub { sprintf ("P%07d.jpg", int(rand(9999))); },      # Kodak DC290
 
1348
#  sub { sprintf ("%02d%02d%04d.jpg",                   # Casio QV3000, QV4000
 
1349
#                 int(rand(12))+1, int(rand(31))+1,
 
1350
#                 int(rand(999))); },
 
1351
#  sub { sprintf ("%02d%x%02d%04d.jpg",                 # Casio QV7000
 
1352
#                 int(rand(6)), # year
 
1353
#                 int(rand(12))+1, int(rand(31))+1,
 
1354
#                 int(rand(999))); },
 
1355
  sub { sprintf ("IMGP%04d.jpg", int(rand(9999))); },   # Pentax Optio S
 
1356
  sub { sprintf ("PANA%04d.jpg", int(rand(9999))); },   # Panasonic vid still
 
1357
  sub { sprintf ("HPIM%04d.jpg", int(rand(9999))); },   # HP Photosmart
 
1358
  sub { sprintf ("PCDV%04d.jpg", int(rand(9999))); },   # ?
 
1359
 );
 
1360
 
 
1361
 
 
1362
# googlephotos
 
1363
sub pick_from_google_image_photos {
 
1364
  my ( $timeout ) = @_;
 
1365
 
 
1366
  my $i = int(rand($#photomakers + 1));
 
1367
  my $fn = $photomakers[$i];
 
1368
  my $file = &$fn;
 
1369
  my $words .= $file . "%20filetype:jpg";
 
1370
 
 
1371
  pick_from_google_images ($timeout, $words);
1026
1372
}
1027
1373
 
1028
1374
 
1034
1380
############################################################################
1035
1381
 
1036
1382
 
1037
 
my $alta_vista_url = "http://www.altavista.com/cgi-bin/query?pg=q" .
1038
 
                     "&text=yes&kl=XX&stype=stext&q=";
 
1383
my $alta_vista_url = "http://www.altavista.com/web/results" .
 
1384
                     "?pg=aq" .
 
1385
                     "&aqmode=s" .
 
1386
                     "&filetype=html" .
 
1387
                     "&sc=on" .        # "site collapse"
 
1388
                     "&nbq=50" .
 
1389
                     "&aqo=";
1039
1390
 
1040
 
# altavista
 
1391
# avtext
1041
1392
sub pick_from_alta_vista_text {
1042
1393
  my ( $timeout ) = @_;
1043
1394
 
1044
 
  my $words = random_words;
 
1395
  my $words = random_words(0);
1045
1396
  my $page = (int(rand(9)) + 1);
1046
1397
  my $search_url = $alta_vista_url . $words;
1047
1398
 
1061
1412
    # onMouseOver to make it look like they're not!  Well, it makes it
1062
1413
    # easier for us to identify search results...
1063
1414
    #
1064
 
    next unless ($u =~ m@^/r\?ck_sm=[a-zA-Z0-9]+\&ref=[a-zA-Z0-9]+\&r=(.*)@);
1065
 
    $u = $1;
 
1415
    next unless ($u =~ s/^.*\*\*(http%3a.*$)/$1/gsi);
 
1416
    $u = url_unquote($u);
 
1417
 
 
1418
    next unless ($u =~ m@^http://@i);    #  skip non-HTTP or relative URLs
 
1419
    next if ($u =~ m@[/.]altavista\.com\b@i);     # skip altavista builtins
 
1420
    next if ($u =~ m@[/.]yahoo\.com\b@i);         # yahoo and av in cahoots?
1066
1421
 
1067
1422
    LOG ($verbose_filter, "  candidate: $u");
1068
1423
    push @candidates, $u;
1080
1435
#
1081
1436
############################################################################
1082
1437
 
1083
 
my $hotbot_search_url = "http://hotbot.lycos.com/" .
1084
 
                        "?SM=SC" .
1085
 
                        "&DV=0" .
1086
 
                        "&LG=any" .
1087
 
                        "&FVI=1" .
1088
 
                        "&DC=100" .
1089
 
                        "&DE=0" .
1090
 
                        "&SQ=1" .
1091
 
                        "&TR=13" .
1092
 
                        "&AM1=MC" .
1093
 
                        "&MT=";
 
1438
my $hotbot_search_url =("http://hotbot.lycos.com/default.asp" .
 
1439
                        "?ca=w" .
 
1440
                        "&descriptiontype=0" .
 
1441
                        "&imagetoggle=1" .
 
1442
                        "&matchmode=any" .
 
1443
                        "&nummod=2" .
 
1444
                        "&recordcount=50" .
 
1445
                        "&sitegroup=1" .
 
1446
                        "&stem=1" .
 
1447
                        "&cobrand=undefined" .
 
1448
                        "&query=");
1094
1449
 
1095
1450
sub pick_from_hotbot_text {
1096
1451
  my ( $timeout ) = @_;
1097
1452
 
1098
 
  my $words = random_words;
1099
 
  my $search_url = $hotbot_search_url . $words;
 
1453
  $last_search = $hotbot_search_url;   # for warnings
 
1454
 
 
1455
  # lycos seems to always give us back dictionaries and word lists if
 
1456
  # we search for more than one word...
 
1457
  #
 
1458
  my $words = random_word();
 
1459
 
 
1460
  my $start = int(rand(8)) * 10 + 1;
 
1461
  my $search_url = $hotbot_search_url . $words . "&first=$start&page=more";
1100
1462
 
1101
1463
  my ($search_hit_count, @subpages) =
1102
1464
    pick_from_search_engine ($timeout, $search_url, $words);
1105
1467
  foreach my $u (@subpages) {
1106
1468
 
1107
1469
    # Hotbot plays redirection games too
1108
 
    next unless ($u =~ m@^/director.asp\?target=([^&]+)@);
1109
 
    $u = url_decode($1);
 
1470
    # (not any more?)
 
1471
#    next unless ($u =~ m@/director.asp\?.*\btarget=([^&]+)@);
 
1472
#    $u = url_decode($1);
 
1473
 
 
1474
    next unless ($u =~ m@^http://@i);    #  skip non-HTTP or relative URLs
 
1475
    next if ($u =~ m@[/.]hotbot\.com\b@i);     # skip hotbot builtins
 
1476
    next if ($u =~ m@[/.]lycos\.com\b@i);      # skip hotbot builtins
 
1477
    next if ($u =~ m@[/.]inktomi\.com\b@i);    # skip hotbot builtins
1110
1478
 
1111
1479
    LOG ($verbose_filter, "  candidate: $u");
1112
1480
    push @candidates, $u;
1124
1492
#
1125
1493
############################################################################
1126
1494
 
1127
 
my $lycos_search_url = "http://lycospro.lycos.com/srchpro/" .
 
1495
my $lycos_search_url = "http://search.lycos.com/default.asp" .
1128
1496
                       "?lpv=1" .
1129
 
                       "&t=any" .
 
1497
                       "&loc=searchhp" .
 
1498
                       "&tab=web" .
1130
1499
                       "&query=";
1131
1500
 
1132
1501
sub pick_from_lycos_text {
1133
1502
  my ( $timeout ) = @_;
1134
1503
 
1135
 
  my $words = random_words;
 
1504
  $last_search = $lycos_search_url;   # for warnings
 
1505
 
 
1506
  # lycos seems to always give us back dictionaries and word lists if
 
1507
  # we search for more than one word...
 
1508
  #
 
1509
  my $words = random_word();
 
1510
 
1136
1511
  my $start = int(rand(8)) * 10 + 1;
1137
 
  my $search_url = $lycos_search_url . $words . "&start=$start";
 
1512
  my $search_url = $lycos_search_url . $words . "&first=$start&page=more";
1138
1513
 
1139
1514
  my ($search_hit_count, @subpages) =
1140
1515
    pick_from_search_engine ($timeout, $search_url, $words);
1142
1517
  my @candidates = ();
1143
1518
  foreach my $u (@subpages) {
1144
1519
 
1145
 
    # Lycos plays exact the same redirection game as hotbot.
1146
 
    # Note that "id=0" is used for internal advertising links,
1147
 
    # and 1+ are used for  search results.
1148
 
    next unless ($u =~ m@^http://click.hotbot.com/director.asp\?id=[1-9]\d*&target=([^&]+)@);
1149
 
    $u = url_decode($1);
 
1520
    # Lycos plays redirection games.
 
1521
    # (not any more?)
 
1522
#    next unless ($u =~ m@^http://click.lycos.com/director.asp
 
1523
#                         .*
 
1524
#                         \btarget=([^&]+)
 
1525
#                         .*
 
1526
#                        @x);
 
1527
#    $u = url_decode($1);
 
1528
 
 
1529
    next unless ($u =~ m@^http://@i);    #  skip non-HTTP or relative URLs
 
1530
    next if ($u =~ m@[/.]hotbot\.com\b@i);     # skip lycos builtins
 
1531
    next if ($u =~ m@[/.]lycos\.com\b@i);      # skip lycos builtins
 
1532
    next if ($u =~ m@[/.]terralycos\.com\b@i); # skip lycos builtins
 
1533
    next if ($u =~ m@[/.]inktomi\.com\b@i);    # skip lycos builtins
 
1534
 
1150
1535
 
1151
1536
    LOG ($verbose_filter, "  candidate: $u");
1152
1537
    push @candidates, $u;
1164
1549
#
1165
1550
############################################################################
1166
1551
 
1167
 
my $yahoo_news_url = "http://search.news.yahoo.com/search/news_photos?" .
1168
 
                     "&z=&n=100&o=o&2=&3=&p=";
 
1552
my $yahoo_news_url = "http://news.search.yahoo.com/search/news" .
 
1553
                     "?c=news_photos" .
 
1554
                     "&p=";
1169
1555
 
1170
1556
# yahoonews
1171
1557
sub pick_from_yahoo_news_text {
1172
1558
  my ( $timeout ) = @_;
1173
1559
 
1174
 
  my $words = random_words;
 
1560
  $last_search = $yahoo_news_url;   # for warnings
 
1561
 
 
1562
  my $words = random_word();
1175
1563
  my $search_url = $yahoo_news_url . $words;
1176
1564
 
1177
1565
  my ($search_hit_count, @subpages) =
1179
1567
 
1180
1568
  my @candidates = ();
1181
1569
  foreach my $u (@subpages) {
 
1570
 
 
1571
    # de-redirectize the URLs
 
1572
    $u =~ s@^http://rds\.yahoo\.com/.*-http%3A@http:@s;
 
1573
 
1182
1574
    # only accept URLs on Yahoo's news site
1183
 
    next unless ($u =~ m@^http://dailynews.yahoo.com/@i);
 
1575
    next unless ($u =~ m@^http://dailynews\.yahoo\.com/@i ||
 
1576
                 $u =~ m@^http://story\.news\.yahoo\.com/@i);
 
1577
    next unless ($u =~ m@&u=/@);
1184
1578
 
1185
1579
    LOG ($verbose_filter, "  candidate: $u");
1186
1580
    push @candidates, $u;
1191
1585
}
1192
1586
 
1193
1587
 
 
1588
 
 
1589
############################################################################
 
1590
#
 
1591
# Pick images from LiveJournal's list of recently-posted images.
 
1592
#
 
1593
############################################################################
 
1594
 
 
1595
my $livejournal_img_url = "http://www.livejournal.com/stats/latest-img.bml";
 
1596
 
 
1597
# With most of our image sources, we get a random page and then select
 
1598
# from the images on it.  However, in the case of LiveJournal, the page
 
1599
# of images tends to update slowly; so we'll remember the last N entries
 
1600
# on it and randomly select from those, to get a wider variety each time.
 
1601
 
 
1602
my $lj_cache_size = 1000;
 
1603
my @lj_cache = (); # fifo, for ordering by age
 
1604
my %lj_cache = (); # hash, for detecting dups
 
1605
 
 
1606
# livejournal
 
1607
sub pick_from_livejournal_images {
 
1608
  my ( $timeout ) = @_;
 
1609
 
 
1610
  $last_search = $livejournal_img_url;   # for warnings
 
1611
 
 
1612
  my ( $base, $body ) = get_document ($livejournal_img_url, undef, $timeout);
 
1613
  return () unless $body;
 
1614
 
 
1615
  $body =~ s/\n/ /gs;
 
1616
  $body =~ s/(<recent-image)\b/\n$1/gsi;
 
1617
 
 
1618
  foreach (split (/\n/, $body)) {
 
1619
    next unless (m/^<recent-image\b/);
 
1620
    next unless (m/\bIMG=[\'\"]([^\'\"]+)[\'\"]/si);
 
1621
    my $img = html_unquote ($1);
 
1622
 
 
1623
    next if ($lj_cache{$img}); # already have it
 
1624
 
 
1625
    next unless (m/\bURL=[\'\"]([^\'\"]+)[\'\"]/si);
 
1626
    my $page = html_unquote ($1);
 
1627
    my @pair = ($img, $page);
 
1628
    LOG ($verbose_filter, "  candidate: $img");
 
1629
    push @lj_cache, \@pair;
 
1630
    $lj_cache{$img} = \@pair;
 
1631
  }
 
1632
 
 
1633
  return () if ($#lj_cache == -1);
 
1634
 
 
1635
  my $n = $#lj_cache+1;
 
1636
  my $i = int(rand($n));
 
1637
  my ($img, $page) = @{$lj_cache[$i]};
 
1638
 
 
1639
  # delete this one from @lj_cache and from %lj_cache.
 
1640
  #
 
1641
  @lj_cache = ( @lj_cache[0 .. $i-1],
 
1642
                @lj_cache[$i+1 .. $#lj_cache] );
 
1643
  delete $lj_cache{$img};
 
1644
 
 
1645
  # Keep the size of the cache under the limit by nuking older entries
 
1646
  #
 
1647
  while ($#lj_cache >= $lj_cache_size) {
 
1648
    my $pairP = shift @lj_cache;
 
1649
    my $img = $pairP->[0];
 
1650
    delete $lj_cache{$img};
 
1651
  }
 
1652
 
 
1653
  LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img");
 
1654
 
 
1655
  return ($page, $img);
 
1656
}
 
1657
 
 
1658
 
 
1659
############################################################################
 
1660
#
 
1661
# Pick images from ircimages.com (images that have been in the /topic of
 
1662
# various IRC channels.)
 
1663
#
 
1664
############################################################################
 
1665
 
 
1666
my $ircimages_url = "http://ircimages.com/";
 
1667
 
 
1668
# ircimages
 
1669
sub pick_from_ircimages {
 
1670
  my ( $timeout ) = @_;
 
1671
 
 
1672
  $last_search = $ircimages_url;   # for warnings
 
1673
 
 
1674
  my $n = int(rand(2900));
 
1675
  my $search_url = $ircimages_url . "page-$n";
 
1676
 
 
1677
  my ( $base, $body ) = get_document ($search_url, undef, $timeout);
 
1678
  return () unless $body;
 
1679
 
 
1680
  my @candidates = ();
 
1681
 
 
1682
  $body =~ s/\n/ /gs;
 
1683
  $body =~ s/(<A)\b/\n$1/gsi;
 
1684
 
 
1685
  foreach (split (/\n/, $body)) {
 
1686
 
 
1687
    my ($u) = m@<A\s.*\bHREF\s*=\s*([^>]+)>@i;
 
1688
    next unless $u;
 
1689
 
 
1690
    if ($u =~ m/^\"([^\"]*)\"/) { $u = $1; }   # quoted string
 
1691
    elsif ($u =~ m/^([^\s]*)\s/) { $u = $1; }  # or token
 
1692
 
 
1693
    next unless ($u =~ m/^http:/i);
 
1694
    next if ($u =~ m@^http://(searchirc\.com\|ircimages\.com)@i);
 
1695
    next unless ($u =~ m@[.](gif|jpg|jpeg|pjpg|pjpeg|png)$@i);
 
1696
 
 
1697
    LOG ($verbose_http, "    HREF: $u");
 
1698
    push @candidates, $u;
 
1699
  }
 
1700
 
 
1701
  LOG ($verbose_filter, "" . $#candidates+1 . " links on $search_url");
 
1702
 
 
1703
  return () if ($#candidates == -1);
 
1704
 
 
1705
  my $i = int(rand($#candidates+1));
 
1706
  my $img = $candidates[$i];
 
1707
 
 
1708
  LOG ($verbose_load, "picked image " .($i+1) . "/" . ($#candidates+1) .
 
1709
       ": $img");
 
1710
 
 
1711
  $search_url = $img;  # hmm...
 
1712
  return ($search_url, $img);
 
1713
}
 
1714
 
 
1715
 
 
1716
############################################################################
 
1717
#
 
1718
# Pick images from Flickr's page of recently-posted photos.
 
1719
#
 
1720
############################################################################
 
1721
 
 
1722
my $flickr_img_url = "http://www.flickr.com/photos/";
 
1723
 
 
1724
# Like LiveJournal, the Flickr page of images tends to update slowly,
 
1725
# so remember the last N entries on it and randomly select from those.
 
1726
 
 
1727
# I know that Flickr has an API (http://www.flickr.com/services/api/)
 
1728
# but it was easy enough to scrape the HTML, so I didn't bother exploring.
 
1729
 
 
1730
my $flickr_cache_size = 1000;
 
1731
my @flickr_cache = (); # fifo, for ordering by age
 
1732
my %flickr_cache = (); # hash, for detecting dups
 
1733
 
 
1734
 
 
1735
# flickr
 
1736
sub pick_from_flickr {
 
1737
  my ( $timeout ) = @_;
 
1738
 
 
1739
  my $start = 16 * int(rand(100));
 
1740
 
 
1741
  $last_search = $flickr_img_url;   # for warnings
 
1742
  $last_search .= "?start=$start" if ($start > 0);
 
1743
 
 
1744
  my ( $base, $body ) = get_document ($last_search, undef, $timeout);
 
1745
  return () unless $body;
 
1746
 
 
1747
  $body =~ s/[\r\n]/ /gs;
 
1748
  $body =~ s/(<a)\b/\n$1/gsi;
 
1749
 
 
1750
  my $count = 0;
 
1751
  my $count2 = 0;
 
1752
  foreach (split (/\n/, $body)) {
 
1753
    my ($page, $thumb) = m@<A \s [^<>]* \b HREF=\"([^<>\"]+)\" [^<>]* > \s*
 
1754
                           <IMG \s [^<>]* \b SRC=\"([^<>\"]+)\" @xsi;
 
1755
    next unless defined ($thumb);
 
1756
    $page = html_unquote ($page);
 
1757
    $thumb = html_unquote ($thumb);
 
1758
 
 
1759
    next unless ($thumb =~ m@^http://photos\d*\.flickr\.com/@);
 
1760
 
 
1761
    my $base = "http://www.flickr.com/";
 
1762
    $page  =~ s@^/@$base@;
 
1763
    $thumb =~ s@^/@$base@;
 
1764
 
 
1765
    my $img = $thumb;
 
1766
    $img =~ s/_[a-z](\.[a-z\d]+)$/$1/si;  # take off "thumb" suffix
 
1767
 
 
1768
    $count++;
 
1769
    next if ($flickr_cache{$img}); # already have it
 
1770
 
 
1771
    my @pair = ($img, $page, $start);
 
1772
    LOG ($verbose_filter, "  candidate: $img");
 
1773
    push @flickr_cache, \@pair;
 
1774
    $flickr_cache{$img} = \@pair;
 
1775
    $count2++;
 
1776
  }
 
1777
 
 
1778
  return () if ($#flickr_cache == -1);
 
1779
 
 
1780
  my $n = $#flickr_cache+1;
 
1781
  my $i = int(rand($n));
 
1782
  my ($img, $page) = @{$flickr_cache[$i]};
 
1783
 
 
1784
  # delete this one from @flickr_cache and from %flickr_cache.
 
1785
  #
 
1786
  @flickr_cache = ( @flickr_cache[0 .. $i-1],
 
1787
                    @flickr_cache[$i+1 .. $#flickr_cache] );
 
1788
  delete $flickr_cache{$img};
 
1789
 
 
1790
  # Keep the size of the cache under the limit by nuking older entries
 
1791
  #
 
1792
  while ($#flickr_cache >= $flickr_cache_size) {
 
1793
    my $pairP = shift @flickr_cache;
 
1794
    my $img = $pairP->[0];
 
1795
    delete $flickr_cache{$img};
 
1796
  }
 
1797
 
 
1798
  LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img");
 
1799
 
 
1800
  return ($page, $img);
 
1801
}
 
1802
 
 
1803
 
 
1804
############################################################################
 
1805
#
 
1806
# Pick images by waiting for driftnet to populate a temp dir with files.
 
1807
# Requires driftnet version 0.1.5 or later.
 
1808
# (Driftnet is a program by Chris Lightfoot that sniffs your local ethernet
 
1809
# for images being downloaded by others.)
 
1810
# Driftnet/webcollage integration by jwz.
 
1811
#
 
1812
############################################################################
 
1813
 
 
1814
# driftnet
 
1815
sub pick_from_driftnet {
 
1816
  my ( $timeout ) = @_;
 
1817
 
 
1818
  my $id = $driftnet_magic;
 
1819
  my $dir = $driftnet_dir;
 
1820
  my $start = time;
 
1821
  my $now;
 
1822
 
 
1823
  error ("\$driftnet_dir unset?") unless ($dir);
 
1824
  $dir =~ s@/+$@@;
 
1825
 
 
1826
  error ("$dir unreadable") unless (-d "$dir/.");
 
1827
 
 
1828
  $timeout = $http_timeout unless ($timeout);
 
1829
  $last_search = $id;
 
1830
 
 
1831
  while ($now = time, $now < $start + $timeout) {
 
1832
    local *DIR;
 
1833
    opendir (DIR, $dir) || error ("$dir: $!");
 
1834
    while (my $file = readdir(DIR)) {
 
1835
      next if ($file =~ m/^\./);
 
1836
      $file = "$dir/$file";
 
1837
      closedir DIR;
 
1838
      LOG ($verbose_load, "picked file $file ($id)");
 
1839
      return ($id, $file);
 
1840
    }
 
1841
    closedir DIR;
 
1842
  }
 
1843
  LOG (($verbose_net || $verbose_load), "timed out for $id");
 
1844
  return ();
 
1845
}
 
1846
 
 
1847
 
 
1848
sub get_driftnet_file {
 
1849
  my ($file) = @_;
 
1850
 
 
1851
  error ("\$driftnet_dir unset?") unless ($driftnet_dir);
 
1852
 
 
1853
  my $id = $driftnet_magic;
 
1854
  my $re = qr/$driftnet_dir/;
 
1855
  error ("$id: $file not in $driftnet_dir?")
 
1856
    unless ($file =~ m@^$re@o);
 
1857
 
 
1858
  local *IN;
 
1859
  open (IN, $file) || error ("$id: $file: $!");
 
1860
  my $body = '';
 
1861
  while (<IN>) { $body .= $_; }
 
1862
  close IN || error ("$id: $file: $!");
 
1863
  unlink ($file) || error ("$id: $file: rm: $!");
 
1864
  return ($id, $body);
 
1865
}
 
1866
 
 
1867
 
 
1868
sub spawn_driftnet {
 
1869
  my ($cmd) = @_;
 
1870
 
 
1871
  # make a directory to use.
 
1872
  while (1) {
 
1873
    my $tmp = $ENV{TEMPDIR} || "/tmp";
 
1874
    $driftnet_dir = sprintf ("$tmp/driftcollage-%08x", rand(0xffffffff));
 
1875
    LOG ($verbose_exec, "mkdir $driftnet_dir");
 
1876
    last if mkdir ($driftnet_dir, 0700);
 
1877
  }
 
1878
 
 
1879
  if (! ($cmd =~ m/\s/)) {
 
1880
    # if the command didn't have any arguments in it, then it must be just
 
1881
    # a pointer to the executable.  Append the default args to it.
 
1882
    my $dargs = $default_driftnet_cmd;
 
1883
    $dargs =~ s/^[^\s]+//;
 
1884
    $cmd .= $dargs;
 
1885
  }
 
1886
 
 
1887
  # point the driftnet command at our newly-minted private directory.
 
1888
  #
 
1889
  $cmd .= " -d $driftnet_dir";
 
1890
  $cmd .= ">/dev/null" unless ($verbose_exec);
 
1891
 
 
1892
  my $pid = fork();
 
1893
  if ($pid < 0) { error ("fork: $!\n"); }
 
1894
  if ($pid) {
 
1895
    # parent fork
 
1896
    push @pids_to_kill, $pid;
 
1897
    LOG ($verbose_exec, "forked for \"$cmd\"");
 
1898
  } else {
 
1899
    # child fork
 
1900
    nontrapping_system ($cmd) || error ("exec: $!");
 
1901
  }
 
1902
 
 
1903
  # wait a bit, then make sure the process actually started up.
 
1904
  #
 
1905
  sleep (1);
 
1906
  error ("pid $pid failed to start \"$cmd\"")
 
1907
    unless (1 == kill (0, $pid));
 
1908
}
1194
1909
 
1195
1910
 
1196
1911
############################################################################
1201
1916
 
1202
1917
 
1203
1918
# Picks a random image on a random page, and returns two URLs:
1204
 
# the page containing the image, and the image. 
 
1919
# the page containing the image, and the image.
1205
1920
# Returns () if nothing found this time.
1206
 
# Uses the url-randomizer 1 time in 5, else the image randomizer.
1207
1921
#
1208
1922
 
1209
1923
sub pick_image {
1254
1968
}
1255
1969
 
1256
1970
sub error {
1257
 
  ($_) = @_;
1258
 
  print STDERR blurb() . "$_\n";
 
1971
  my ($err) = @_;
 
1972
  print STDERR blurb() . "$err\n";
1259
1973
  exit 1;
1260
1974
}
1261
1975
 
 
1976
sub stacktrace {
 
1977
  my $i = 1;
 
1978
  print STDERR "$progname: stack trace:\n";
 
1979
  while (1) {
 
1980
    my ($package, $filename, $line, $subroutine) = caller($i++);
 
1981
    last unless defined($package);
 
1982
    $filename =~ s@^.*/@@;
 
1983
    print STDERR "  $filename#$line, $subroutine\n";
 
1984
  }
 
1985
}
 
1986
 
1262
1987
 
1263
1988
my $lastlog = "";
1264
1989
 
1427
2152
 
1428
2153
  $_ = $url;
1429
2154
  my ($site) = m@^http://([^ \t\n\r/:]+)@;
 
2155
  return unless defined ($site);
 
2156
 
 
2157
  if ($base eq $driftnet_magic) {
 
2158
    $site = $driftnet_magic;
 
2159
    @recent_images = ();
 
2160
  }
1430
2161
 
1431
2162
  my $done = 0;
1432
2163
  foreach (@recent_images) {
1511
2242
  while (ord($ch) != 0xDA && $i < $L) {
1512
2243
    # Find next marker, beginning with 0xFF.
1513
2244
    while (ord($ch) != 0xFF) {
 
2245
      return () if (length($body) <= $i);
1514
2246
      $ch = substr($body, $i, 1); $i++;
1515
2247
    }
1516
2248
    # markers can be padded with any number of 0xFF.
1517
2249
    while (ord($ch) == 0xFF) {
 
2250
      return () if (length($body) <= $i);
1518
2251
      $ch = substr($body, $i, 1); $i++;
1519
2252
    }
1520
2253
 
1526
2259
        ($marker != 0xC4) &&
1527
2260
        ($marker != 0xCC)) {  # it's a SOFn marker
1528
2261
      $i += 3;
 
2262
      return () if (length($body) <= $i);
1529
2263
      my $s = substr($body, $i, 4); $i += 4;
1530
2264
      my ($a,$b,$c,$d) = unpack("C"x4, $s);
1531
2265
      return (($c<<8|$d), ($a<<8|$b));
1533
2267
    } else {
1534
2268
      # We must skip variables, since FFs in variable names aren't
1535
2269
      # valid JPEG markers.
 
2270
      return () if (length($body) <= $i);
1536
2271
      my $s = substr($body, $i, 2); $i += 2;
1537
 
      my ($c1, $c2) = unpack ("C"x2, $s); 
 
2272
      my ($c1, $c2) = unpack ("C"x2, $s);
1538
2273
      my $length = ($c1 << 8) | $c2;
1539
2274
      return () if ($length < 2);
1540
2275
      $i += $length-2;
1543
2278
  return ();
1544
2279
}
1545
2280
 
1546
 
# Given the raw body of a GIF or JPEG document, returns the dimensions of
1547
 
# the image.
 
2281
# Given the raw body of a PNG document, returns the dimensions of the image.
 
2282
#
 
2283
sub png_size {
 
2284
  my ($body) = @_;
 
2285
  return () unless ($body =~ m/^\211PNG\r/);
 
2286
  my ($bits) = ($body =~ m/^.{12}(.{12})/s);
 
2287
  return () unless defined ($bits);
 
2288
  return () unless ($bits =~ /^IHDR/);
 
2289
  my ($ign, $w, $h) = unpack("a4N2", $bits);
 
2290
  return ($w, $h);
 
2291
}
 
2292
 
 
2293
 
 
2294
# Given the raw body of a GIF, JPEG, or PNG document, returns the dimensions
 
2295
# of the image.
1548
2296
#
1549
2297
sub image_size {
1550
2298
  my ($body) = @_;
1551
2299
  my ($w, $h) = gif_size ($body);
1552
2300
  if ($w && $h) { return ($w, $h); }
1553
 
  return jpeg_size ($body);
 
2301
  ($w, $h) = jpeg_size ($body);
 
2302
  if ($w && $h) { return ($w, $h); }
 
2303
  return png_size ($body);
1554
2304
}
1555
2305
 
1556
2306
 
1576
2326
}
1577
2327
 
1578
2328
 
 
2329
sub exit_cleanup {
 
2330
  x_cleanup();
 
2331
  print STDERR "$progname: exiting\n" if ($verbose_warnings);
 
2332
  if (@pids_to_kill) {
 
2333
    print STDERR blurb() . "killing: " . join(' ', @pids_to_kill) . "\n";
 
2334
    kill ('TERM', @pids_to_kill);
 
2335
  }
 
2336
}
 
2337
 
 
2338
sub signal_cleanup {
 
2339
  my ($sig) = @_;
 
2340
  print STDERR blurb() . (defined($sig)
 
2341
                          ? "caught signal $sig."
 
2342
                          : "exiting.")
 
2343
                       . "\n"
 
2344
    if ($verbose_exec || $verbose_warnings);
 
2345
  exit 1;
 
2346
}
 
2347
 
 
2348
 
 
2349
 
1579
2350
##############################################################################
1580
2351
#
1581
2352
# Generating a list of urls only
1595
2366
 
1596
2367
##############################################################################
1597
2368
#
1598
 
# Running as an xscreensaver module
 
2369
# Running as an xscreensaver module, or as a web page imagemap
1599
2370
#
1600
2371
##############################################################################
1601
2372
 
1602
 
my $image_ppm   = ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp") . "/webcollage." . $$;
1603
 
my $image_tmp1  = $image_ppm . "-1";
1604
 
my $image_tmp2  = $image_ppm . "-2";
 
2373
my $image_ppm   = sprintf ("%s/webcollage-%08x",
 
2374
                           ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"),
 
2375
                           rand(0xFFFFFFFF));
 
2376
my $image_tmp1  = sprintf ("%s/webcollage-1-%08x",
 
2377
                           ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"),
 
2378
                           rand(0xFFFFFFFF));
 
2379
my $image_tmp2  = sprintf ("%s/webcollage-2-%08x",
 
2380
                           ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"),
 
2381
                           rand(0xFFFFFFFF));
1605
2382
 
1606
2383
my $filter_cmd = undef;
1607
2384
my $post_filter_cmd = undef;
1608
2385
my $background = undef;
1609
2386
 
 
2387
my @imagemap_areas = ();
 
2388
my $imagemap_html_tmp = undef;
 
2389
my $imagemap_jpg_tmp = undef;
 
2390
 
 
2391
 
1610
2392
my $img_width;            # size of the image being generated.
1611
2393
my $img_height;
1612
2394
 
1613
 
my $delay = 0;
1614
 
 
 
2395
my $delay = 2;
1615
2396
 
1616
2397
sub x_cleanup {
1617
 
  my ($sig) = @_;
1618
 
  print STDERR blurb() . "caught signal $sig.\n" if ($verbose_exec);
1619
2398
  unlink $image_ppm, $image_tmp1, $image_tmp2;
1620
 
  exit 1;
 
2399
  unlink $imagemap_html_tmp, $imagemap_jpg_tmp
 
2400
    if (defined ($imagemap_html_tmp));
1621
2401
}
1622
2402
 
1623
2403
 
1626
2406
#
1627
2407
sub nontrapping_system {
1628
2408
  $! = 0;
1629
 
    
 
2409
 
1630
2410
  $_ = join(" ", @_);
1631
2411
  s/\"[^\"]+\"/\"...\"/g;
1632
2412
 
1653
2433
}
1654
2434
 
1655
2435
 
1656
 
# Given the URL of a GIF or JPEG image, and the body of that image, writes a
1657
 
# PPM to the given output file.  Returns the width/height of the image if 
1658
 
# successful.
 
2436
# Given the URL of a GIF, JPEG, or PNG image, and the body of that image,
 
2437
# writes a PPM to the given output file.  Returns the width/height of the
 
2438
# image if successful.
1659
2439
#
1660
2440
sub image_to_pnm {
1661
2441
  my ($url, $body, $output) = @_;
1667
2447
  } elsif ((@_ = jpeg_size ($body))) {
1668
2448
    ($w, $h) = @_;
1669
2449
    $cmd = "djpeg";
 
2450
  } elsif ((@_ = png_size ($body))) {
 
2451
    ($w, $h) = @_;
 
2452
    $cmd = "pngtopnm";
1670
2453
  } else {
1671
2454
    LOG (($verbose_pbm || $verbose_load),
1672
 
         "not a GIF or JPG" .
1673
 
         (($body =~ m@<(base|html|head|body|script|table|a href)>@i)
 
2455
         "not a GIF, JPG, or PNG" .
 
2456
         (($body =~ m@<(base|html|head|body|script|table|a href)\b@i)
1674
2457
          ? " (looks like HTML)" : "") .
1675
2458
         ": $url");
1676
2459
    $suppress_audit = 1;
1767
2550
 
1768
2551
 
1769
2552
sub x_or_pbm_output {
 
2553
  my ($window_id) = @_;
 
2554
 
 
2555
  # Check for our helper program, to see whether we need to use PPM pipelines.
 
2556
  #
 
2557
  $_ = "webcollage-helper";
 
2558
  if (defined ($webcollage_helper) || which ($_)) {
 
2559
    $webcollage_helper = $_ unless (defined($webcollage_helper));
 
2560
    LOG ($verbose_pbm, "found \"$webcollage_helper\"");
 
2561
    $webcollage_helper .= " -v";
 
2562
  } else {
 
2563
    LOG (($verbose_pbm || $verbose_load), "no $_ program");
 
2564
  }
1770
2565
 
1771
2566
  # make sure the various programs we execute exist, right up front.
1772
2567
  #
1773
 
  foreach ("ppmmake", "giftopnm", "djpeg", "pnmpaste", "pnmscale", "pnmcut") {
 
2568
  my @progs = ("ppmmake");  # always need this one
 
2569
 
 
2570
  if (!defined($webcollage_helper)) {
 
2571
    # Only need these others if we don't have the helper.
 
2572
    @progs = (@progs,
 
2573
              "giftopnm", "pngtopnm", "djpeg",
 
2574
              "pnmpaste", "pnmscale", "pnmcut");
 
2575
  }
 
2576
 
 
2577
  foreach (@progs) {
1774
2578
    which ($_) || error "$_ not found on \$PATH.";
1775
2579
  }
1776
2580
 
1778
2582
  #
1779
2583
  $ppm_to_root_window_cmd = pick_root_displayer();
1780
2584
 
1781
 
 
1782
 
  $SIG{HUP}  = \&x_cleanup;
1783
 
  $SIG{INT}  = \&x_cleanup;
1784
 
  $SIG{QUIT} = \&x_cleanup;
1785
 
  $SIG{ABRT} = \&x_cleanup;
1786
 
  $SIG{KILL} = \&x_cleanup;
1787
 
  $SIG{TERM} = \&x_cleanup;
1788
 
 
1789
 
  # Need this so that if giftopnm dies, we don't die.
1790
 
  $SIG{PIPE} = 'IGNORE';
 
2585
  if (defined ($window_id)) {
 
2586
    error ("-window-id only works if xscreensaver-getimage is installed")
 
2587
      unless ($ppm_to_root_window_cmd =~ m/^xscreensaver-getimage\b/);
 
2588
 
 
2589
    error ("unparsable window id: $window_id")
 
2590
      unless ($window_id =~ m/^\d+$|^0x[\da-f]+$/i);
 
2591
    $ppm_to_root_window_cmd =~ s/--?root\b/$window_id/ ||
 
2592
      error ("unable to munge displayer: $ppm_to_root_window_cmd");
 
2593
  }
1791
2594
 
1792
2595
  if (!$img_width || !$img_height) {
1793
 
    $_ = "xdpyinfo";
1794
 
    which ($_) || error "$_ not found on \$PATH.";
1795
 
    $_ = `$_`;
1796
 
    ($img_width, $img_height) = m/dimensions: *(\d+)x(\d+) /;
1797
 
    if (!defined($img_height)) {
1798
 
      error "xdpyinfo failed.";
 
2596
 
 
2597
    if (!defined ($window_id) &&
 
2598
        defined ($ENV{XSCREENSAVER_WINDOW})) {
 
2599
      $window_id = $ENV{XSCREENSAVER_WINDOW};
 
2600
    }
 
2601
 
 
2602
    if (!defined ($window_id)) {
 
2603
      $_ = "xdpyinfo";
 
2604
      which ($_) || error "$_ not found on \$PATH.";
 
2605
      $_ = `$_`;
 
2606
      ($img_width, $img_height) = m/dimensions: *(\d+)x(\d+) /;
 
2607
      if (!defined($img_height)) {
 
2608
        error "xdpyinfo failed.";
 
2609
      }
 
2610
    } else {  # we have a window id
 
2611
      $_ = "xwininfo";
 
2612
      which ($_) || error "$_ not found on \$PATH.";
 
2613
      $_ .= " -id $window_id";
 
2614
      $_ = `$_`;
 
2615
      ($img_width, $img_height) = m/^\s*Width:\s*(\d+)\n\s*Height:\s*(\d+)\n/m;
 
2616
 
 
2617
      if (!defined($img_height)) {
 
2618
        error "xwininfo failed.";
 
2619
      }
1799
2620
    }
1800
2621
  }
1801
2622
 
1844
2665
      ($iw, $ih) = @_;
1845
2666
      $cmd = "djpeg |";
1846
2667
 
 
2668
    } elsif ((@_ = png_size ($body))) {
 
2669
      ($iw, $ih) = @_;
 
2670
      $cmd = "pngtopnm |";
 
2671
 
1847
2672
    } elsif ($body =~ m/^P\d\n(\d+) (\d+)\n/) {
1848
2673
      $iw = $1;
1849
2674
      $ih = $2;
1850
2675
      $cmd = "";
1851
2676
 
1852
2677
    } else {
1853
 
      error "$bgimage is not a GIF, JPEG, or PPM.";
 
2678
      error "$bgimage is not a GIF, JPEG, PNG, or PPM.";
1854
2679
    }
1855
2680
 
1856
2681
    my $x = int (($img_width  - $iw) / 2);
1898
2723
 
1899
2724
  LOG ($verbose_pbm, "got $img (" . length($body) . ")");
1900
2725
 
1901
 
  my ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1);
1902
 
  $body = undef;
1903
 
  if (!$iw || !$ih) {
1904
 
    LOG ($verbose_pbm, "unable to make PBM from $img");
1905
 
    return 0;
 
2726
  my ($iw, $ih);
 
2727
 
 
2728
  # If we are using the webcollage-helper, then we do not need to convert this
 
2729
  # image to a PPM.  But, if we're using a filter command, we still must, since
 
2730
  # that's what the filters expect (webcollage-helper can read PPMs, so that's
 
2731
  # fine.)
 
2732
  #
 
2733
  if (defined ($webcollage_helper) &&
 
2734
      !defined ($filter_cmd)) {
 
2735
 
 
2736
    ($iw, $ih) = image_size ($body);
 
2737
    if (!$iw || !$ih) {
 
2738
      LOG (($verbose_pbm || $verbose_load),
 
2739
           "not a GIF, JPG, or PNG" .
 
2740
           (($body =~ m@<(base|html|head|body|script|table|a href)>@i)
 
2741
            ? " (looks like HTML)" : "") .
 
2742
           ": $img");
 
2743
      $suppress_audit = 1;
 
2744
      $body = undef;
 
2745
      return 0;
 
2746
    }
 
2747
 
 
2748
    local *OUT;
 
2749
    open (OUT, ">$image_tmp1") || error ("writing $image_tmp1: $!");
 
2750
    print OUT $body || error ("writing $image_tmp1: $!");
 
2751
    close OUT || error ("writing $image_tmp1: $!");
 
2752
 
 
2753
  } else {
 
2754
    ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1);
 
2755
    $body = undef;
 
2756
    if (!$iw || !$ih) {
 
2757
      LOG ($verbose_pbm, "unable to make PBM from $img");
 
2758
      return 0;
 
2759
    }
1906
2760
  }
1907
2761
 
1908
2762
  record_success ($load_method, $img, $base);
1935
2789
    return 0 unless ($iw && $ih);
1936
2790
  }
1937
2791
 
1938
 
  my $target_w = $img_width;
 
2792
  my $target_w = $img_width;   # max rectangle into which the image must fit
1939
2793
  my $target_h = $img_height;
1940
2794
 
1941
2795
  my $cmd = "";
 
2796
  my $scale = 1.0;
1942
2797
 
1943
2798
 
1944
2799
  # Usually scale the image to fit on the screen -- but sometimes scale it
1945
 
  # to fit on half or a quarter of the screen.  Note that we don't merely
1946
 
  # scale it to fit, we instead cut it in half until it fits -- that should
1947
 
  # give a wider distribution of sizes.
 
2800
  # to fit on half or a quarter of the screen.  (We do this by reducing the
 
2801
  # size of the target rectangle.)  Note that the image is not merely scaled
 
2802
  # to fit; we instead cut the image in half repeatedly until it fits in the
 
2803
  # target rectangle -- that gives a wider distribution of sizes.
1948
2804
  #
1949
 
  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
 
2805
  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; } # reduce target rect
1950
2806
  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
1951
2807
 
1952
2808
  if ($iw > $target_w || $ih > $target_h) {
1954
2810
           $ih > $target_h) {
1955
2811
      $iw = int($iw / 2);
1956
2812
      $ih = int($ih / 2);
 
2813
      $scale /= 2;
1957
2814
    }
1958
2815
    if ($iw <= 10 || $ih <= 10) {
1959
2816
      LOG ($verbose_pbm, "scaling to ${iw}x$ih would have been bogus.");
1960
2817
      return 0;
1961
2818
    }
1962
2819
 
1963
 
    LOG ($verbose_pbm, "scaling to ${iw}x$ih");
 
2820
    LOG ($verbose_pbm, "scaling to ${iw}x$ih ($scale)");
1964
2821
 
1965
2822
    $cmd .= " | pnmscale -xsize $iw -ysize $ih";
1966
2823
  }
1995
2852
  }
1996
2853
 
1997
2854
  if (rand() < $crop_chance) {
1998
 
    
 
2855
 
1999
2856
    my $ow = $crop_w;
2000
2857
    my $oh = $crop_h;
2001
 
    
 
2858
 
2002
2859
    if ($crop_w > $min_width) {
2003
2860
      # if it's a banner, select the width linearly.
2004
2861
      # otherwise, select a bell.
2013
2870
      $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height));
2014
2871
      $crop_y = int (rand() * ($oh - $crop_h));
2015
2872
    }
2016
 
    
 
2873
 
2017
2874
    if ($crop_x != 0   || $crop_y != 0 ||
2018
2875
        $crop_w != $iw || $crop_h != $ih) {
2019
2876
      LOG ($verbose_pbm,
2033
2890
      $y < 0 ||
2034
2891
      $x + $crop_w > $img_width ||
2035
2892
      $y + $crop_h > $img_height) {
2036
 
    
 
2893
 
2037
2894
    LOG ($verbose_pbm,
2038
2895
         "cropping for effective paste of ${crop_w}x$crop_h \@ $x,$y");
2039
 
    
 
2896
 
2040
2897
    if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; }
2041
2898
    if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; }
2042
 
    
 
2899
 
2043
2900
    if ($x + $crop_w >= $img_width)  { $crop_w = $img_width  - $x - 1; }
2044
2901
    if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; }
2045
2902
  }
2047
2904
  # If any cropping needs to happen, add pnmcut.
2048
2905
  #
2049
2906
  if ($crop_x != 0   || $crop_y != 0 ||
2050
 
        $crop_w != $iw || $crop_h != $ih) {
 
2907
      $crop_w != $iw || $crop_h != $ih) {
2051
2908
    $iw = $crop_w;
2052
2909
    $ih = $crop_h;
2053
2910
    $cmd .= " | pnmcut $crop_x $crop_y $iw $ih";
2060
2917
 
2061
2918
  $cmd =~ s@^ *\| *@@;
2062
2919
 
2063
 
  $_ = "($cmd)";
2064
 
  $_ .= " < $image_tmp1 > $image_tmp2";
 
2920
  if (defined ($webcollage_helper)) {
 
2921
    $cmd = "$webcollage_helper $image_tmp1 $image_ppm " .
 
2922
                              "$scale $opacity " .
 
2923
                              "$crop_x $crop_y $x $y " .
 
2924
                              "$iw $ih";
 
2925
    $_ = $cmd;
 
2926
 
 
2927
  } else {
 
2928
    # use a PPM pipeline
 
2929
    $_ = "($cmd)";
 
2930
    $_ .= " < $image_tmp1 > $image_tmp2";
 
2931
  }
2065
2932
 
2066
2933
  if ($verbose_pbm) {
2067
2934
    $_ = "($_) 2>&1 | sed s'/^/" . blurb() . "/'";
2068
2935
  } else {
2069
2936
    $_ .= " 2> /dev/null";
2070
2937
  }
 
2938
 
2071
2939
  my $rc = nontrapping_system ($_);
2072
2940
 
 
2941
  if (defined ($webcollage_helper) && -z $image_ppm) {
 
2942
    LOG (1, "failed command: \"$cmd\"");
 
2943
    print STDERR "\naudit log:\n\n\n";
 
2944
    print STDERR ("#" x 78) . "\n";
 
2945
    print STDERR blurb() . "$image_ppm has zero size\n";
 
2946
    showlog();
 
2947
    print STDERR "\n\n";
 
2948
    exit (1);
 
2949
  }
 
2950
 
2073
2951
  if ($rc != 0) {
2074
2952
    LOG (($verbose_pbm || $verbose_load), "failed command: \"$cmd\"");
2075
2953
    LOG (($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)");
2076
2954
    return;
2077
2955
  }
2078
2956
 
2079
 
  rename ($image_tmp2, $image_ppm) || return;
 
2957
  if (!defined ($webcollage_helper)) {
 
2958
    rename ($image_tmp2, $image_ppm) || return;
 
2959
  }
2080
2960
 
2081
2961
  my $target = "$image_ppm";
2082
2962
 
2085
2965
  # cumulative.
2086
2966
  #
2087
2967
  if ($post_filter_cmd) {
 
2968
 
 
2969
    my $cmd;
 
2970
 
2088
2971
    $target = $image_tmp1;
2089
 
    $rc = nontrapping_system "($post_filter_cmd) < $image_ppm > $target";
 
2972
    if (!defined ($webcollage_helper)) {
 
2973
      $cmd = "($post_filter_cmd) < $image_ppm > $target";
 
2974
    } else {
 
2975
      # Blah, my scripts need the JPEG data, but some other folks need
 
2976
      # the PPM data -- what to do?  Ignore the problem, that's what!
 
2977
#     $cmd = "djpeg < $image_ppm | ($post_filter_cmd) > $target";
 
2978
      $cmd = "($post_filter_cmd) < $image_ppm > $target";
 
2979
    }
 
2980
 
 
2981
    $rc = nontrapping_system ($cmd);
2090
2982
    if ($rc != 0) {
2091
2983
      LOG ($verbose_pbm, "filter failed: \"$post_filter_cmd\"\n");
2092
2984
      return;
2097
2989
    my $tsize = (stat($target))[7];
2098
2990
    if ($tsize > 200) {
2099
2991
      $cmd = "$ppm_to_root_window_cmd $target";
2100
 
      
 
2992
 
2101
2993
      # xv seems to hate being killed.  it tends to forget to clean
2102
2994
      # up after itself, and leaves windows around and colors allocated.
2103
2995
      # I had this same problem with vidwhacker, and I'm not entirely
2109
3001
      # to do anyway.
2110
3002
      #
2111
3003
      $cmd .= " &";
2112
 
      
 
3004
 
2113
3005
      $rc = nontrapping_system ($cmd);
2114
 
      
 
3006
 
2115
3007
      if ($rc != 0) {
2116
3008
        LOG (($verbose_pbm || $verbose_load), "display failed: \"$cmd\"");
2117
3009
        return;
2118
3010
      }
2119
 
      
 
3011
 
2120
3012
    } else {
2121
3013
      LOG ($verbose_pbm, "$target size is $tsize");
2122
3014
    }
2125
3017
  $source .= "-" . stats_of($source);
2126
3018
  print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n"
2127
3019
    if ($verbose_imgmap);
 
3020
  if ($imagemap_base) {
 
3021
    update_imagemap ($base, $x, $y, $iw, $ih,
 
3022
                     $image_ppm, $img_width, $img_height);
 
3023
  }
2128
3024
 
2129
3025
  clearlog();
2130
3026
 
2132
3028
}
2133
3029
 
2134
3030
 
 
3031
sub update_imagemap {
 
3032
  my ($url, $x, $y, $w, $h, $image_ppm, $image_width, $image_height) = @_;
 
3033
 
 
3034
  $current_state = "imagemap";
 
3035
 
 
3036
  my $max_areas = 200;
 
3037
 
 
3038
  $url = html_quote ($url);
 
3039
  my $x2 = $x + $w;
 
3040
  my $y2 = $y + $h;
 
3041
  my $area = "<AREA SHAPE=RECT COORDS=\"$x,$y,$x2,$y2\" HREF=\"$url\">";
 
3042
  unshift @imagemap_areas, $area;       # put one on the front
 
3043
  if ($#imagemap_areas >= $max_areas) {
 
3044
    pop @imagemap_areas;                # take one off the back.
 
3045
  }
 
3046
 
 
3047
  LOG ($verbose_pbm, "area: $x,$y,$x2,$y2 (${w}x$h)");
 
3048
 
 
3049
  my $map_name = $imagemap_base;
 
3050
  $map_name =~ s@^.*/@@;
 
3051
  $map_name = 'collage' if ($map_name eq '');
 
3052
 
 
3053
  my $imagemap_html = $imagemap_base . ".html";
 
3054
  my $imagemap_jpg  = $imagemap_base . ".jpg";
 
3055
 
 
3056
  if (!defined ($imagemap_html_tmp)) {
 
3057
    $imagemap_html_tmp = $imagemap_html . sprintf (".%08x", rand(0xffffffff));
 
3058
    $imagemap_jpg_tmp  = $imagemap_jpg  . sprintf (".%08x", rand(0xffffffff));
 
3059
  }
 
3060
 
 
3061
  # Read the imagemap html file (if any) to get a template.
 
3062
  #
 
3063
  my $template_html = '';
 
3064
  {
 
3065
    local *IN;
 
3066
    if (open (IN, "<$imagemap_html")) {
 
3067
      while (<IN>) { $template_html .= $_; }
 
3068
      close IN;
 
3069
      LOG ($verbose_pbm, "read template $imagemap_html");
 
3070
    }
 
3071
 
 
3072
    if ($template_html =~ m/^\s*$/s) {
 
3073
      $template_html = ("<MAP NAME=\"$map_name\"></MAP>\n" .
 
3074
                        "<IMG SRC=\"$imagemap_base.jpg\"" .
 
3075
                        " USEMAP=\"$map_name\">\n");
 
3076
      LOG ($verbose_pbm, "created dummy template");
 
3077
    }
 
3078
  }
 
3079
 
 
3080
  # Write the jpg to a tmp file
 
3081
  #
 
3082
  {
 
3083
    my $cmd;
 
3084
    if (defined ($webcollage_helper)) {
 
3085
      $cmd = "cp -p $image_ppm $imagemap_jpg_tmp";
 
3086
    } else {
 
3087
      $cmd = "cjpeg < $image_ppm > $imagemap_jpg_tmp";
 
3088
    }
 
3089
    my $rc = nontrapping_system ($cmd);
 
3090
    if ($rc != 0) {
 
3091
      error ("imagemap jpeg failed: \"$cmd\"\n");
 
3092
    }
 
3093
  }
 
3094
 
 
3095
  # Write the html to a tmp file
 
3096
  #
 
3097
  {
 
3098
    my $body = $template_html;
 
3099
    my $areas = join ("\n\t", @imagemap_areas);
 
3100
    my $map = ("<MAP NAME=\"$map_name\">\n\t$areas\n</MAP>");
 
3101
    my $img = ("<IMG SRC=\"$imagemap_base.jpg\" " .
 
3102
               "BORDER=0 " .
 
3103
               "WIDTH=$image_width HEIGHT=$image_height " .
 
3104
               "USEMAP=\"#$map_name\">");
 
3105
    $body =~ s@(<MAP\s+NAME=\"[^\"]*\"\s*>).*?(</MAP>)@$map@is;
 
3106
    $body =~ s@<IMG\b[^<>]*\bUSEMAP\b[^<>]*>@$img@is;
 
3107
 
 
3108
    # if there are magic webcollage spans in the html, update those too.
 
3109
    #
 
3110
    {
 
3111
      my @st = stat ($imagemap_jpg_tmp);
 
3112
      my $date = strftime("%d-%b-%Y %l:%M:%S %p %Z", localtime($st[9]));
 
3113
      my $size = int(($st[7] / 1024) + 0.5) . "K";
 
3114
      $body =~ s@(<SPAN\s+CLASS=\"webcollage_date\">).*?(</SPAN>)@$1$date$2@si;
 
3115
      $body =~ s@(<SPAN\s+CLASS=\"webcollage_size\">).*?(</SPAN>)@$1$size$2@si;
 
3116
    }
 
3117
 
 
3118
    local *OUT;
 
3119
    open (OUT, ">$imagemap_html_tmp") || error ("$imagemap_html_tmp: $!");
 
3120
    print OUT $body                   || error ("$imagemap_html_tmp: $!");
 
3121
    close OUT                         || error ("$imagemap_html_tmp: $!");
 
3122
    LOG ($verbose_pbm, "wrote $imagemap_html_tmp");
 
3123
  }
 
3124
 
 
3125
  # Rename the two tmp files to the real files
 
3126
  #
 
3127
  rename ($imagemap_html_tmp, $imagemap_html) ||
 
3128
    error "renaming $imagemap_html_tmp to $imagemap_html";
 
3129
  LOG ($verbose_pbm, "wrote $imagemap_html");
 
3130
  rename ($imagemap_jpg_tmp,  $imagemap_jpg) ||
 
3131
    error "renaming $imagemap_jpg_tmp to $imagemap_jpg";
 
3132
  LOG ($verbose_pbm, "wrote $imagemap_jpg");
 
3133
}
 
3134
 
 
3135
 
 
3136
sub init_signals {
 
3137
 
 
3138
  $SIG{HUP}  = \&signal_cleanup;
 
3139
  $SIG{INT}  = \&signal_cleanup;
 
3140
  $SIG{QUIT} = \&signal_cleanup;
 
3141
  $SIG{ABRT} = \&signal_cleanup;
 
3142
  $SIG{KILL} = \&signal_cleanup;
 
3143
  $SIG{TERM} = \&signal_cleanup;
 
3144
 
 
3145
  # Need this so that if giftopnm dies, we don't die.
 
3146
  $SIG{PIPE} = 'IGNORE';
 
3147
}
 
3148
 
 
3149
END { exit_cleanup(); }
 
3150
 
 
3151
 
2135
3152
sub main {
2136
3153
  $| = 1;
2137
3154
  srand(time ^ $$);
2138
3155
 
2139
3156
  my $verbose = 0;
2140
3157
  my $dict;
 
3158
  my $driftnet_cmd = 0;
2141
3159
 
2142
3160
  $current_state = "init";
2143
3161
  $load_method = "none";
2144
3162
 
2145
3163
  my $root_p = 0;
 
3164
  my $window_id = undef;
2146
3165
 
2147
3166
  # historical suckage: the environment variable name is lower case.
2148
3167
  $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
2158
3177
      $ENV{DISPLAY} = shift @ARGV;
2159
3178
    } elsif ($_ eq "-root") {
2160
3179
      $root_p = 1;
 
3180
    } elsif ($_ eq "-window-id" || $_ eq "--window-id") {
 
3181
      $window_id = shift @ARGV;
 
3182
      $root_p = 1;
2161
3183
    } elsif ($_ eq "-no-output") {
2162
3184
      $no_output_p = 1;
2163
3185
    } elsif ($_ eq "-urls-only") {
2164
3186
      $urls_only_p = 1;
2165
3187
      $no_output_p = 1;
 
3188
    } elsif ($_ eq "-imagemap") {
 
3189
      $imagemap_base = shift @ARGV;
 
3190
      $no_output_p = 1;
2166
3191
    } elsif ($_ eq "-verbose") {
2167
3192
      $verbose++;
2168
3193
    } elsif (m/^-v+$/) {
2189
3214
      $http_proxy = shift @ARGV;
2190
3215
    } elsif ($_ eq "-dictionary" || $_ eq "-dict") {
2191
3216
      $dict = shift @ARGV;
 
3217
    } elsif ($_ eq "-opacity") {
 
3218
      $opacity = shift @ARGV;
 
3219
      error ("opacity must be between 0.0 and 1.0")
 
3220
        if ($opacity <= 0 || $opacity > 1);
 
3221
    } elsif ($_ eq "-driftnet" || $_ eq "--driftnet") {
 
3222
      @search_methods = ( 100, "driftnet", \&pick_from_driftnet );
 
3223
      if (! ($ARGV[0] =~ m/^-/)) {
 
3224
        $driftnet_cmd = shift @ARGV;
 
3225
      } else {
 
3226
        $driftnet_cmd = $default_driftnet_cmd;
 
3227
      }
 
3228
    } elsif ($_ eq "-debug" || $_ eq "--debug") {
 
3229
      my $which = shift @ARGV;
 
3230
      my @rest = @search_methods;
 
3231
      my $ok = 0;
 
3232
      while (@rest) {
 
3233
        my $pct  = shift @rest;
 
3234
        my $name = shift @rest;
 
3235
        my $tfn  = shift @rest;
 
3236
 
 
3237
        if ($name eq $which) {
 
3238
          @search_methods = (100, $name, $tfn);
 
3239
          $ok = 1;
 
3240
          last;
 
3241
        }
 
3242
      }
 
3243
      error "no such search method as \"$which\"" unless ($ok);
 
3244
      LOG (1, "DEBUG: using only \"$which\"");
 
3245
 
2192
3246
    } else {
2193
 
      print STDERR "$copyright\nusage: $progname [-root]" .
2194
 
                 " [-display dpy] [-root] [-verbose] [-timeout secs]\n" .
2195
 
                 "\t\t  [-delay secs] [-filter cmd] [-filter2 cmd]\n" .
2196
 
                 "\t\t  [-dictionary dictionary-file]\n" .
2197
 
                 "\t\t  [-http-proxy host[:port]]\n";
 
3247
      print STDERR "$copyright\nusage: $progname " .
 
3248
              "[-root] [-display dpy] [-verbose] [-debug which]\n" .
 
3249
        "\t\t  [-timeout secs] [-delay secs] [-size WxH]\n" .
 
3250
        "\t\t  [-no-output] [-urls-only] [-imagemap filename]\n" .
 
3251
        "\t\t  [-filter cmd] [-filter2 cmd] [-background color]\n" .
 
3252
        "\t\t  [-dictionary dictionary-file] [-http-proxy host[:port]]\n" .
 
3253
        "\t\t  [-driftnet [driftnet-program-and-args]]\n" .
 
3254
        "\n";
2198
3255
      exit 1;
2199
3256
    }
2200
3257
  }
2274
3331
    pick_dictionary();
2275
3332
  }
2276
3333
 
 
3334
  init_signals();
 
3335
 
 
3336
  spawn_driftnet ($driftnet_cmd) if ($driftnet_cmd);
 
3337
 
2277
3338
  if ($urls_only_p) {
2278
 
    url_only_output;
 
3339
    url_only_output ();
2279
3340
  } else {
2280
 
    x_or_pbm_output;
 
3341
    x_or_pbm_output ($window_id);
2281
3342
  }
2282
3343
}
2283
3344