SYN SYN
[p5sagit/p5-mst-13.2.git] / lib / CGI / Push.pm
CommitLineData
54310121 1package CGI::Push;
2
3# See the bottom of this file for the POD documentation. Search for the
4# string '=head'.
5
6# You can run this file through either pod2man or pod2html to produce pretty
7# documentation in manual or html file format (these utilities are part of the
8# Perl 5 distribution).
9
10# Copyright 1995,1996, Lincoln D. Stein. All rights reserved.
11# It may be used and modified freely, but I do request that this copyright
12# notice remain attached to the file. You may modify this module as you
13# wish, but if you redistribute a modified version, please attach a note
14# listing the modifications you have made.
15
16# The most recent version and complete docs are available at:
71f3e297 17# http://stein.cshl.org/WWW/software/CGI/
54310121 18
22d4bb9c 19$CGI::Push::VERSION='1.03';
54310121 20use CGI;
ee8c7f54 21use CGI::Util 'rearrange';
54310121 22@ISA = ('CGI');
23
424ec8fa 24$CGI::DefaultClass = 'CGI::Push';
25$CGI::Push::AutoloadClass = 'CGI';
26
27# add do_push() and push_delay() to exported tags
28push(@{$CGI::EXPORT_TAGS{':standard'}},'do_push','push_delay');
54310121 29
30sub do_push {
424ec8fa 31 my ($self,@p) = CGI::self_or_default(@_);
54310121 32
33 # unbuffer output
34 $| = 1;
35 srand;
424ec8fa 36 my ($random) = sprintf("%16.0f",rand()*1E16);
54310121 37 my ($boundary) = "----------------------------------$random";
38
39 my (@header);
40 my ($type,$callback,$delay,$last_page,$cookie,$target,$expires,@other) =
ee8c7f54 41 rearrange([TYPE,NEXT_PAGE,DELAY,LAST_PAGE,[COOKIE,COOKIES],TARGET,EXPIRES],@p);
54310121 42 $type = 'text/html' unless $type;
43 $callback = \&simple_counter unless $callback && ref($callback) eq 'CODE';
44 $delay = 1 unless defined($delay);
424ec8fa 45 $self->push_delay($delay);
54310121 46
47 my(@o);
48 foreach (@other) { push(@o,split("=")); }
49 push(@o,'-Target'=>$target) if defined($target);
50 push(@o,'-Cookie'=>$cookie) if defined($cookie);
51 push(@o,'-Type'=>"multipart/x-mixed-replace; boundary=$boundary");
52 push(@o,'-Server'=>"CGI.pm Push Module");
53 push(@o,'-Status'=>'200 OK');
54 push(@o,'-nph'=>1);
55 print $self->header(@o);
56 print "${boundary}$CGI::CRLF";
ee8c7f54 57
54310121 58 # now we enter a little loop
59 my @contents;
60 while (1) {
61 last unless (@contents = &$callback($self,++$COUNTER)) && defined($contents[0]);
424ec8fa 62 print "Content-type: ${type}$CGI::CRLF$CGI::CRLF"
22d4bb9c 63 unless $type =~ /^dynamic|heterogeneous$/i;
54310121 64 print @contents,"$CGI::CRLF";
65 print "${boundary}$CGI::CRLF";
424ec8fa 66 do_sleep($self->push_delay()) if $self->push_delay();
67 }
68
69 # Optional last page
70 if ($last_page && ref($last_page) eq 'CODE') {
71 print "Content-type: ${type}$CGI::CRLF$CGI::CRLF" unless $type =~ /^dynamic|heterogeneous$/i;
72 print &$last_page($self,$COUNTER),"$CGI::CRLF${boundary}$CGI::CRLF";
54310121 73 }
54310121 74}
75
76sub simple_counter {
77 my ($self,$count) = @_;
78 return (
79 CGI->start_html("CGI::Push Default Counter"),
80 CGI->h1("CGI::Push Default Counter"),
81 "This page has been updated ",CGI->strong($count)," times.",
82 CGI->hr(),
83 CGI->a({'-href'=>'http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html'},'CGI.pm home page'),
84 CGI->end_html
85 );
86}
87
88sub do_sleep {
89 my $delay = shift;
90 if ( ($delay >= 1) && ($delay!~/\./) ){
91 sleep($delay);
92 } else {
93 select(undef,undef,undef,$delay);
94 }
95}
96
424ec8fa 97sub push_delay {
98 my ($self,$delay) = CGI::self_or_default(@_);
99 return defined($delay) ? $self->{'.delay'} =
100 $delay : $self->{'.delay'};
101}
102
54310121 1031;
104
105=head1 NAME
106
107CGI::Push - Simple Interface to Server Push
108
109=head1 SYNOPSIS
110
111 use CGI::Push qw(:standard);
112
113 do_push(-next_page=>\&next_page,
114 -last_page=>\&last_page,
115 -delay=>0.5);
116
117 sub next_page {
118 my($q,$counter) = @_;
119 return undef if $counter >= 10;
120 return start_html('Test'),
121 h1('Visible'),"\n",
122 "This page has been called ", strong($counter)," times",
123 end_html();
124 }
125
126 sub last_page {
127 my($q,$counter) = @_;
128 return start_html('Done'),
129 h1('Finished'),
130 strong($counter),' iterations.',
131 end_html;
132 }
133
134=head1 DESCRIPTION
135
136CGI::Push is a subclass of the CGI object created by CGI.pm. It is
137specialized for server push operations, which allow you to create
138animated pages whose content changes at regular intervals.
139
140You provide CGI::Push with a pointer to a subroutine that will draw
141one page. Every time your subroutine is called, it generates a new
142page. The contents of the page will be transmitted to the browser
143in such a way that it will replace what was there beforehand. The
144technique will work with HTML pages as well as with graphics files,
145allowing you to create animated GIFs.
146
ee8c7f54 147Only Netscape Navigator supports server push. Internet Explorer
148browsers do not.
149
54310121 150=head1 USING CGI::Push
151
152CGI::Push adds one new method to the standard CGI suite, do_push().
153When you call this method, you pass it a reference to a subroutine
154that is responsible for drawing each new page, an interval delay, and
155an optional subroutine for drawing the last page. Other optional
156parameters include most of those recognized by the CGI header()
157method.
158
159You may call do_push() in the object oriented manner or not, as you
160prefer:
161
162 use CGI::Push;
163 $q = new CGI::Push;
164 $q->do_push(-next_page=>\&draw_a_page);
165
166 -or-
3e3baf6d 167
54310121 168 use CGI::Push qw(:standard);
169 do_push(-next_page=>\&draw_a_page);
170
171Parameters are as follows:
172
173=over 4
3e3baf6d 174
54310121 175=item -next_page
176
177 do_push(-next_page=>\&my_draw_routine);
178
179This required parameter points to a reference to a subroutine responsible for
180drawing each new page. The subroutine should expect two parameters
181consisting of the CGI object and a counter indicating the number
182of times the subroutine has been called. It should return the
183contents of the page as an B<array> of one or more items to print.
184It can return a false value (or an empty array) in order to abort the
185redrawing loop and print out the final page (if any)
186
187 sub my_draw_routine {
188 my($q,$counter) = @_;
189 return undef if $counter > 100;
190 return start_html('testing'),
191 h1('testing'),
192 "This page called $counter times";
193 }
194
424ec8fa 195You are of course free to refer to create and use global variables
196within your draw routine in order to achieve special effects.
197
54310121 198=item -last_page
199
200This optional parameter points to a reference to the subroutine
201responsible for drawing the last page of the series. It is called
202after the -next_page routine returns a false value. The subroutine
203itself should have exactly the same calling conventions as the
204-next_page routine.
205
206=item -type
207
208This optional parameter indicates the content type of each page. It
424ec8fa 209defaults to "text/html". Normally the module assumes that each page
71f3e297 210is of a homogenous MIME type. However if you provide either of the
424ec8fa 211magic values "heterogeneous" or "dynamic" (the latter provided for the
212convenience of those who hate long parameter names), you can specify
213the MIME type -- and other header fields -- on a per-page basis. See
214"heterogeneous pages" for more details.
54310121 215
216=item -delay
217
218This indicates the delay, in seconds, between frames. Smaller delays
219refresh the page faster. Fractional values are allowed.
220
221B<If not specified, -delay will default to 1 second>
222
223=item -cookie, -target, -expires
224
225These have the same meaning as the like-named parameters in
226CGI::header().
227
228=back
229
424ec8fa 230=head2 Heterogeneous Pages
231
232Ordinarily all pages displayed by CGI::Push share a common MIME type.
233However by providing a value of "heterogeneous" or "dynamic" in the
234do_push() -type parameter, you can specify the MIME type of each page
235on a case-by-case basis.
236
237If you use this option, you will be responsible for producing the
238HTTP header for each page. Simply modify your draw routine to
239look like this:
240
241 sub my_draw_routine {
242 my($q,$counter) = @_;
243 return header('text/html'), # note we're producing the header here
244 start_html('testing'),
245 h1('testing'),
246 "This page called $counter times";
247 }
248
249You can add any header fields that you like, but some (cookies and
250status fields included) may not be interpreted by the browser. One
251interesting effect is to display a series of pages, then, after the
252last page, to redirect the browser to a new URL. Because redirect()
253does b<not> work, the easiest way is with a -refresh header field,
254as shown below:
255
256 sub my_draw_routine {
257 my($q,$counter) = @_;
258 return undef if $counter > 10;
259 return header('text/html'), # note we're producing the header here
260 start_html('testing'),
261 h1('testing'),
262 "This page called $counter times";
263 }
3cb6de81 264
424ec8fa 265 sub my_last_page {
266 header(-refresh=>'5; URL=http://somewhere.else/finished.html',
267 -type=>'text/html'),
268 start_html('Moved'),
269 h1('This is the last page'),
270 'Goodbye!'
271 hr,
272 end_html;
273 }
274
275=head2 Changing the Page Delay on the Fly
276
277If you would like to control the delay between pages on a page-by-page
278basis, call push_delay() from within your draw routine. push_delay()
279takes a single numeric argument representing the number of seconds you
280wish to delay after the current page is displayed and before
281displaying the next one. The delay may be fractional. Without
282parameters, push_delay() just returns the current delay.
283
54310121 284=head1 INSTALLING CGI::Push SCRIPTS
285
286Server push scripts B<must> be installed as no-parsed-header (NPH)
287scripts in order to work correctly. On Unix systems, this is most
288often accomplished by prefixing the script's name with "nph-".
289Recognition of NPH scripts happens automatically with WebSTAR and
290Microsoft IIS. Users of other servers should see their documentation
291for help.
292
54310121 293=head1 AUTHOR INFORMATION
294
71f3e297 295Copyright 1995-1998, Lincoln D. Stein. All rights reserved.
296
297This library is free software; you can redistribute it and/or modify
298it under the same terms as Perl itself.
54310121 299
71f3e297 300Address bug reports and comments to: lstein@cshl.org
54310121 301
302=head1 BUGS
303
304This section intentionally left blank.
305
306=head1 SEE ALSO
307
308L<CGI::Carp>, L<CGI>
3e3baf6d 309
54310121 310=cut
311