File Coverage

blib/lib/WWW/Scraper/Typo3.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package WWW::Scraper::Typo3;
2              
3 1     1   20704 use common::sense;
  1         7  
  1         5  
4              
5 1     1   735 use File::chdir;
  1         3209  
  1         90  
6 1     1   819 use File::Copy; # For move.
  1         4690  
  1         59  
7 1     1   843 use File::Slurp; # For read_dir and read_file.
  1         14989  
  1         70  
8 1     1   1261 use File::Temp;
  1         19478  
  1         94  
9              
10 1     1   1115 use HTML::TreeBuilder;
  1         32029  
  1         14  
11              
12 1     1   874 use LWP::Simple;
  1         100289  
  1         11  
13              
14 1     1   1004 use Moose;
  0            
  0            
15              
16             has base_url =>
17             (
18             is => 'rw',
19             isa => 'Str',
20             required => 0,
21             default => '/',
22             );
23              
24             has dir =>
25             (
26             is => 'rw',
27             isa => 'Str',
28             required => 0,
29             default => '',
30             );
31              
32             has home_page =>
33             (
34             is => 'rw',
35             isa => 'Str',
36             required => 0,
37             default => 'index.html',
38             );
39              
40             has host =>
41             (
42             is => 'rw',
43             isa => 'Str',
44             required => 0,
45             default => '127.0.0.1',
46             );
47              
48             has port =>
49             (
50             is => 'rw',
51             isa => 'Int',
52             required => 0,
53             default => 80,
54             );
55              
56             has verbose =>
57             (
58             is => 'ro',
59             isa => 'Int',
60             required => 0,
61             default => 0,
62             );
63              
64             our %image;
65             our %link;
66             our %seen;
67              
68             our $VERSION = '1.01';
69              
70             # -----------------------------------------------
71              
72             sub build_url
73             {
74             my($self, $host, $port, $base_url) = @_;
75              
76             return "http://$host:$port$base_url";
77              
78             } # End of build_url.
79              
80             # -----------------------------------------------
81             # Return $href for success and '' for failure.
82              
83             sub get_attributes
84             {
85             my($self, $base, $key, $a) = @_;
86             my($href) = $a -> attr('href');
87              
88             # The '@' picks up mailto:..@.. which has been transformed.
89              
90             return '' if ( ($href =~ /@/) || $seen{$href});
91              
92             $seen{$href} = 1;
93              
94             if (! $link{$base})
95             {
96             $link{$base} = {};
97             }
98              
99             my($text) = $self -> transform_text($a -> as_text);
100             $link{$key}{$text} = "$base$href";
101              
102             return $href;
103              
104             } # End of get_attributes.
105              
106             # -----------------------------------------------
107             # Return $tree for success and 1 for failure.
108              
109             sub get_page
110             {
111             my($self, $url) = @_;
112             my($store) = File::Temp -> new -> filename;
113             my($response) = LWP::Simple::getstore($url, $store);
114              
115             if ($response ne '200')
116             {
117             $self -> log('Unable to retrieve url ' . $url);
118              
119             return 0;
120             }
121              
122             return HTML::TreeBuilder -> new -> parse_file($store);
123              
124             } # End of get_page.
125              
126             # -----------------------------------------------
127              
128             sub log
129             {
130             my($self, $message) = @_;
131             $message ||= '';
132              
133             if ($self -> verbose)
134             {
135             print "$message\n";
136             }
137              
138             } # End of log.
139              
140             # -----------------------------------------------
141              
142             sub parse
143             {
144             my($self, $base, $page, $doc, $tree, $level) = @_;
145              
146             $self -> parse_tbody($base, $page, $doc, $tree, $level);
147             $self -> parse_img($base, $page, $doc, $tree);
148            
149             } # End of parse.
150              
151             # -----------------------------------------------
152              
153             sub parse_img
154             {
155             my($self, $base, $page, $doc, $tree) = @_;
156             my(@image) = $tree -> find_by_tag_name('img');
157              
158             my($dt);
159             my($href);
160             my($path);
161             my($s);
162              
163             for my $image (@image)
164             {
165             $href = $image -> attr('src');
166              
167             next if ($seen{$href} || ($href !~ /typo3temp/) );
168              
169             $seen{$href} = 1;
170             $image{$doc}{$href} = '-';
171             $dt = $image -> look_up(_tag => 'dt');
172              
173             if ($dt)
174             {
175             $s = $dt -> find_by_tag_name(a => 'href');
176              
177             if ($s)
178             {
179             $path = $s -> attr('onclick');
180              
181             if ($path)
182             {
183             $path =~ s|.+file=(uploads.+?)&.+|$1|;
184             $path =~ s|%2F|/|g;
185             $image{$doc}{$href} = "$base$path";
186             }
187             }
188             }
189             }
190              
191             } # End of parse_img.
192              
193             # -----------------------------------------------
194              
195             sub parse_tbody
196             {
197             my($self, $base, $page, $doc, $tree, $level) = @_;
198             my(@tbody) = $tree -> find_by_tag_name('tbody');
199              
200             my(@a, $a);
201             my($href);
202             my($sub_tree, $sub_url);
203              
204             for my $tbody (@tbody)
205             {
206             @a = $tbody -> find_by_tag_name('a');
207              
208             for $a (@a)
209             {
210             $href = $self -> get_attributes($base, $doc, $a);
211              
212             next if ($href eq '');
213              
214             $self -> log("Switching to $base$href");
215              
216             $sub_url = $self -> build_url($self -> host, $self -> port, $base);
217             $sub_tree = $self -> get_page("$sub_url$href");
218              
219             if ($sub_tree)
220             {
221             $self -> parse($base, $href, "$base$href", $sub_tree, $level + 1);
222             $sub_tree -> delete;
223             }
224             }
225             }
226              
227             } # End of parse_tbody.
228              
229             # -----------------------------------------------
230              
231             sub patch_files
232             {
233             my($self) = @_;
234             local $CWD = $self -> dir;
235              
236             my(@line, $line);
237              
238             for my $file (read_dir('.') )
239             {
240             next if ( ($file !~ /id\.(?:\d+).html$/) && ($file ne $self -> home_page) );
241              
242             @line = read_file($file);
243              
244             for $line (@line)
245             {
246             $line =~ tr/\cM//d;
247              
248             next if ($line !~ /tbody/);
249              
250             $line =~ s|</a></tr></tr>|</a></td></tr>|g;
251             $line =~ s|(index.php\?id=\d+)|$self->transform_href($1)|eg;
252             }
253              
254             write_file($file, @line);
255             }
256              
257             return 0;
258              
259             } # End of patch_files.
260              
261             # -----------------------------------------------
262              
263             sub rename_files
264             {
265             my($self) = @_;
266             local $CWD = $self -> dir;
267             my(@file) = read_dir('.');
268              
269             my($new_name);
270              
271             for my $file (@file)
272             {
273             next if ($file !~ /index\.php\?id=(?:\d+)$/);
274              
275             $new_name = $self -> transform_href($file);
276              
277             if (move $file, $new_name)
278             {
279             $self -> log("Renamed $file to $new_name");
280             }
281             else
282             {
283             $self -> log("Failed to rename $file to $new_name: $!");
284             }
285             }
286              
287             return 0;
288              
289             } # End of rename_files.
290              
291             # -----------------------------------------------
292              
293             sub report
294             {
295             my($self) = @_;
296              
297             my($href);
298             my($url);
299              
300             for $url (sort keys %link)
301             {
302             for $href (sort keys %{$link{$url} })
303             {
304             $self -> log("$url '$href' links to $link{$url}{$href}");
305             }
306             }
307              
308             for $url (sort keys %image)
309             {
310             for $href (sort keys %{$image{$url} })
311             {
312             $self -> log("$url links to $href");
313             }
314             }
315              
316             } # End of report.
317              
318             # -----------------------------------------------
319             # Return 0 for success and 1 for failure.
320              
321             sub report_files
322             {
323             my($self) = @_;
324              
325             if ($self -> base_url !~ m|^/|)
326             {
327             $self -> base_url('/' . $self -> base_url);
328             }
329              
330             if ($self -> base_url !~ m|/$|)
331             {
332             $self -> base_url($self -> base_url . '/');
333             }
334              
335             my($base) = $self -> build_url($self -> host, $self -> port, $self -> base_url);
336             my($page) = $self -> home_page;
337             my($doc) = "$base$page";
338              
339             $self -> log("Starting from $doc");
340              
341             my($tree) = $self -> get_page($doc);
342             my($result) = $tree ? 0 : 1;
343              
344             if ($tree)
345             {
346             $self -> parse($self -> base_url, $page, $doc, $tree, 0);
347             $tree -> delete;
348             $self -> report;
349             }
350              
351             return $result;
352              
353             } # End of report_files.
354              
355             # -----------------------------------------------
356              
357             sub transform_href
358             {
359             my($self, $href) = @_;
360             $href =~ tr/?=/../;
361             substr($href, 0, 10) = ''; # Zap /^index.php./.
362             $href .= '.html';
363              
364             return $href;
365              
366             } # End of transform_href.
367              
368             # -----------------------------------------------
369              
370             sub transform_text
371             {
372             my($self, $text) = @_;
373             $text =~ s/^\s+//;
374             $text =~ s/\s+$//;
375              
376             return $text;
377              
378             } # End of transform_text.
379              
380             # -----------------------------------------------
381              
382             1;
383              
384             __END__
385              
386             =pod
387              
388             =head1 NAME
389              
390             C<WWW::Scraper::Typo3> - Clean up files managed by the CMS called Typo3
391              
392             =head1 Synopsis
393              
394             Note: The code assumes you are running a web server locally, so the scripts
395             can both read and write files, and use LWP::Simple::getstore to process files.
396              
397             cd ~/misc
398             wget -o wget.log --limit-rate=100k -w 4 -r -k -P tewoaf -E -p http://tewoaf.org.au
399             cd tewoaf
400             rm *eID* # This removes pop-up files generated by clicking on images.
401             cd $DR # This is doc root for your web server.
402             rm -rf tewoaf
403             cp -r ~/misc/tewoaf
404             cd ~/perl.modules/WWW-Scraper-Typo3
405             perl scripts/rename.files.pl -d $DR/tewoaf -v 1
406             perl scripts/patch.files.pl -d $DR/tewoaf -v 1
407             perl scripts/report.files.pl -b /tewoaf -v 1
408              
409             patch.files.pl is the only program which overwrites files.
410              
411             =head1 Description
412              
413             C<WWW::Scraper::Typo3> is a pure Perl module.
414              
415             It processes the set of files downloaded from a web site whose files are managed by
416             the CMS called Typo3.
417              
418             =head1 Distributions
419              
420             This module is available as a Unix-style distro (*.tgz).
421              
422             See http://savage.net.au/Perl-modules.html for details.
423              
424             See http://savage.net.au/Perl-modules/html/installing-a-module.html for
425             help on unpacking and installing.
426              
427             =head1 Constructor and initialization
428              
429             new(...) returns an object of type C<WWW::Scraper::Typo3>.
430              
431             This is the class's contructor.
432              
433             Usage: C<< WWW::Scraper::Typo3 -> new() >>.
434              
435             This method takes a hash of options.
436              
437             Call C<new()> as C<< new(option_1 => value_1, option_2 => value_2, ...) >>.
438              
439             Available options:
440              
441             =over 4
442              
443             =item base_url aURL
444              
445             The script report.files.pl uses "http://$host:$port$base_url$home_page" as the URL
446             where processing starts.
447              
448             If necessary, both a leading '/' and a trailing '/' are added to the value you supply.
449              
450             The default value is '/'.
451              
452             This parameter is mandatory for the script report.files.pl.
453              
454             =item dir aDirName
455              
456             This option is used by the 2 scripts rename.files.pl and patch.files.pl.
457              
458             It is the directory where these scripts read and write files.
459              
460             From the synopsis, you can see I suggest you download the site's files to a directory
461             outside your local web server's doc root, and work on a copy of the files within that
462             doc root.
463              
464             The default value is ''.
465              
466             This parameter is optional.
467              
468             =item home_page aHTMLFileName
469              
470             The name of the home page of the site.
471              
472             The default value is index.html.
473              
474             This parameter is mandatory for the script report.files.pl.
475              
476             =item host aHostName
477              
478             The domain name or IP address of the host.
479              
480             The default value is 127.0.0.1.
481              
482             This parameter is mandatory for the script report.files.pl.
483              
484             =item post aPortNumber
485              
486             The number of the port to use.
487              
488             The default value is 80.
489              
490             This parameter is mandatory for the script report.files.pl.
491              
492             =item verbose #
493              
494             Display more (1) or less (0) output.
495              
496             The default is 0.
497              
498             This parameter is optional.
499              
500             =back
501              
502             =head1 Method: patch_files()
503              
504             Run the code which patches various aspects of Typo3-managed files.
505              
506             See scripts/patch.files.pl.
507              
508             =head1 Method: rename_files()
509              
510             Run the code which renames Typo3-managed files.
511              
512             See scripts/rename.files.pl.
513              
514             =head1 Method: report_files()
515              
516             Run the code which reports on various aspects of Typo3-managed files.
517              
518             See scripts/report.files.pl.
519              
520             =head1 Author
521              
522             C<WWW::Scraper::Typo3> was written by Ron Savage I<E<lt>ron@savage.net.auE<gt>> in 2010.
523              
524             Home page: http://savage.net.au/index.html
525              
526             =head1 Copyright
527              
528             Australian copyright (c) 20010 Ron Savage.
529              
530             All Programs of mine are 'OSI Certified Open Source Software';
531             you can redistribute them and/or modify them under the terms of
532             The Artistic License, a copy of which is available at:
533             http://www.opensource.org/licenses/index.html
534              
535              
536             =cut