]> git.lyx.org Git - lyx.git/blob - development/checkurls/search_url.pl
Cmake url tests: Use more sophiticated check for urls.
[lyx.git] / development / checkurls / search_url.pl
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 #
4 # file search_url.pl
5 # script to search for url's in lyxfiles
6 # and testing their validity.
7 #
8 # Syntax: search_url.pl [(filesToScan|(ignored|reverted|extra|selected)URLS)={path_to_control]*
9 # Param value is a path to a file containing list of xxx:
10 # filesToScan={xxx = lyx-file-names to be scanned for}
11 # ignoredURLS={xxx = urls that are discarded from test}
12 # revertedURLS={xxx = urls that should fail, to test the test with invalid urls}
13 # extraURLS={xxx = urls which should be also checked}
14 #
15 # This file is free software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public
17 # License as published by the Free Software Foundation; either
18 # version 2 of the License, or (at your option) any later version.
19 #
20 # This software is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 # General Public License for more details.
24 #
25 # You should have received a copy of the GNU General Public
26 # License along with this software; if not, write to the Free Software
27 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 #
29 # Copyright (c) 2013 Kornel Benko <kornel@lyx.org>
30 #           (c) 2013 Scott Kostyshak <skotysh@lyx.org>
31
32 use strict;
33
34 BEGIN  {
35   use File::Spec;
36   my $p = File::Spec->rel2abs(__FILE__);
37   $p =~ s/[\/\\]?[^\/\\]+$//;
38   unshift(@INC, "$p");
39 }
40
41 use CheckURL;
42 use Try::Tiny;
43 use locale;
44 use POSIX qw(locale_h);
45
46 setlocale(LC_CTYPE, "");
47 setlocale(LC_MESSAGES, "en_US.UTF-8");
48
49 # Prototypes
50 sub printNotUsedURLS($\%);
51 sub replaceSpecialChar($);
52 sub readUrls($\%);
53 sub parse_file($ );
54 sub handle_url($$$ );
55 ##########
56
57 my %URLS = ();
58 my %ignoredURLS = ();
59 my %revertedURLS = ();
60 my %extraURLS = ();
61 my %selectedURLS = ();
62 my %knownToRegisterURLS = ();
63 my $summaryFile = undef;
64
65 my $checkSelectedOnly = 0;
66 for my $arg (@ARGV) {
67   die("Bad argument \"$arg\"") if ($arg !~ /=/);
68   my ($type,$val) = split("=", $arg);
69   if ($type eq "filesToScan") {
70     #The file should be a list of files to search in
71     if (open(FLIST, $val)) {
72       while (my $l = <FLIST>) {
73         chomp($l);
74         parse_file($l);
75       }
76       close(FLIST);
77     }
78   }
79   elsif ($type eq "ignoredURLS") {
80     readUrls($val, %ignoredURLS);
81   }
82   elsif ($type eq "revertedURLS") {
83     readUrls($val, %revertedURLS);
84   }
85   elsif ($type eq "extraURLS") {
86     readUrls($val, %extraURLS);
87   }
88   elsif ($type eq "selectedURLS") {
89     $checkSelectedOnly = 1;
90     readUrls($val, %selectedURLS);
91   }
92   elsif ($type eq "knownToRegisterURLS") {
93     readUrls($val, %knownToRegisterURLS);
94   }
95   elsif ($type eq "summaryFile") {
96     if (open(SFO, '>', "$val")) {
97       $summaryFile = $val;
98     }
99   }
100   else {
101     die("Invalid argument \"$arg\"");
102   }
103 }
104
105 my @urls = sort keys %URLS, keys %extraURLS;
106 my $errorcount = 0;
107
108 my $URLScount = 0;
109
110 for my $u (@urls) {
111   if (defined($ignoredURLS{$u})) {
112     $ignoredURLS{$u}->{count} += 1;
113     next;
114   }
115   next if (defined($knownToRegisterURLS{$u}));
116   if (defined($selectedURLS{$u})) {
117     ${selectedURLS}{$u}->{count} += 1;
118   }
119   next if ($checkSelectedOnly && ! defined($selectedURLS{$u}));
120   $URLScount++;
121   print "Checking '$u': ";
122   my ($res, $prnt, $outSum);
123   try {
124     $res = check_url($u);
125     if ($res) {
126       print "Failed\n";
127       $prnt = "";
128       $outSum = 1;
129     }
130     else {
131       $prnt = "OK\n";
132       $outSum = 0;
133     }
134   }
135   catch {
136     $prnt = "Failed, caught error: $_\n";
137     $outSum = 1;
138     $res = 700;
139   };
140   printx("$prnt", $outSum);
141   my $printSourceFiles = 0;
142   my $err_txt = "Error url:";
143
144   if ($res || $checkSelectedOnly) {
145     $printSourceFiles = 1;
146   }
147   if ($res && defined($revertedURLS{$u})) {
148     $err_txt = "Failed url:";
149   }
150   $res = ! $res if (defined($revertedURLS{$u}));
151   if ($res || $checkSelectedOnly) {
152     printx("$err_txt \"$u\"\n", $outSum);
153   }
154   if ($printSourceFiles) {
155     if (defined($URLS{$u})) {
156       for my $f(sort keys %{$URLS{$u}}) {
157         my $lines = ":" . join(',', @{$URLS{$u}->{$f}});
158         printx("  $f$lines\n", $outSum);
159       }
160     }
161     if ($res ) {
162       $errorcount++;
163     }
164   }
165 }
166
167 if (%URLS) {
168   printNotUsedURLS("Ignored", %ignoredURLS);
169   printNotUsedURLS("Selected", %selectedURLS);
170   printNotUsedURLS("KnownInvalid", %extraURLS);
171 }
172
173 print "\n$errorcount URL-tests failed out of $URLScount\n\n";
174 if (defined($summaryFile)) {
175   close(SFO);
176 }
177 exit($errorcount);
178
179 ###############################################################################
180 sub printx($$)
181 {
182   my ($txt, $outSum) = @_;
183   print "$txt";
184   if ($outSum && defined($summaryFile)) {
185     print SFO "$txt";
186   }
187 }
188
189 sub printNotUsedURLS($\%)
190 {
191   my ($txt, $rURLS) = @_;
192   my @msg = ();
193   for my $u ( sort keys %{$rURLS}) {
194     if ($rURLS->{$u}->{count} < 2) {
195       my @submsg = ();
196       for my $f (sort keys %{$rURLS->{$u}}) {
197         next if ($f eq "count");
198         push(@submsg, "$f:" . $rURLS->{$u}->{$f});
199       }
200       push(@msg, "\n  $u\n    " . join("\n    ", @submsg) . "\n");
201     }
202   }
203   if (@msg) {
204     print "\n$txt URLs not found in sources: " . join(' ',@msg) . "\n";
205   }
206 }
207
208 sub replaceSpecialChar($)
209 {
210   my ($l) = @_;
211   $l =~ s/\\SpecialChar(NoPassThru)?\s*(TeX|LaTeX|LyX)[\s]?/\2/;
212   return($l);
213 }
214
215 sub readUrls($\%)
216 {
217   my ($file, $rUrls) = @_;
218
219   die("Could not read file $file") if (! open(ULIST, $file));
220   my $line = 0;
221   while (my $l = <ULIST>) {
222     $line++;
223     $l =~ s/[\r\n]+$//;         # remove eol
224     $l =~ s/\s*\#.*$//;         # remove comment
225     $l = &replaceSpecialChar($l);
226     next if ($l eq "");
227     if (! defined($rUrls->{$l} )) {
228       $rUrls->{$l} = {$file => $line, count => 1};
229     }
230   }
231   close(ULIST);
232 }
233
234 sub parse_file($)
235 {
236   my($f) = @_;
237   my $status = "out";           # outside of URL/href
238
239   return if ($f =~ /\/attic\//);
240   if(open(FI, $f)) {
241     my $line = 0;
242     while(my $l = <FI>) {
243       $line++;
244       $l =~ s/[\r\n]+$//;       #  Simulate chomp
245       if ($status eq "out") {
246         # searching for "\begin_inset Flex URL"
247         if($l =~ /^\s*\\begin_inset\s+Flex\s+URL\s*$/) {
248           $status = "inUrlInset";
249         }
250         elsif ($l =~ /^\s*\\begin_inset\s+CommandInset\s+href\s*$/) {
251           $status = "inHrefInset";
252         }
253         else {
254           # Outside of url, check also
255           if ($l =~ /"((ftp|http|https):\/\/[^ ]+)"/) {
256             my $url = $1;
257             handle_url($url, $f, "x$line");
258           }
259         }
260       }
261       else {
262         if($l =~ /^\s*\\end_(layout|inset)\s*$/) {
263           $status = "out";
264         }
265         elsif ($status eq "inUrlInset") {
266           if ($l =~ /\s*([a-z]+:\/\/.+)\s*$/) {
267             my $url = $1;
268             $status = "out";
269             handle_url($url, $f, "u$line");
270           }
271         }
272         elsif ($status eq "inHrefInset") {
273           if ($l =~ /^target\s+"([a-z]+:\/\/[^ ]+)"$/) {
274             my $url = $1;
275             $status = "out";
276             handle_url($url, $f, "h$line");
277           }
278         }
279       }
280     }
281     close(FI);
282   }
283 }
284
285 sub handle_url($$$)
286 {
287   my($url, $f, $line) = @_;
288
289   $url = &replaceSpecialChar($url);
290   if(!defined($URLS{$url})) {
291     $URLS{$url} = {};
292   }
293   if(!defined($URLS{$url}->{$f})) {
294     $URLS{$url}->{$f} = [];
295   }
296   push(@{$URLS{$url}->{$f}}, $line);
297 }