PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/development/checkurls/CheckURL.pm

https://bitbucket.org/sfranchi/lyx
Perl | 246 lines | 187 code | 19 blank | 40 comment | 39 complexity | 7d2fa1a74fda94848955277adb22a917 MD5 | raw file
  1. # -*- mode: perl; -*-
  2. package CheckURL;
  3. # file CheckURL.pm
  4. #
  5. # This file is part of LyX, the document processor.
  6. # Licence details can be found in the file COPYING.
  7. #
  8. # authors: Kornel Benko <kornel@lyx.org>
  9. # Scott Kostyshak <skotysh@lyx.org>
  10. #
  11. # Check if given URL exists and is accessible
  12. #
  13. use strict;
  14. our(@EXPORT, @ISA);
  15. BEGIN {
  16. use Exporter ();
  17. @ISA = qw(Exporter);
  18. @EXPORT = qw(check_url);
  19. }
  20. # Prototypes
  21. sub check_http_url($$$$);
  22. sub check_ftp_dir_entry($$);
  23. sub check_ftp_url($$$$);
  24. sub check_unknown_url($$$$);
  25. sub check_url($);
  26. ################
  27. sub check_http_url($$$$)
  28. {
  29. use Net::HTTP;
  30. use Net::HTTPS;
  31. my ($protocol, $host, $path, $file) = @_;
  32. my $s;
  33. if ($protocol eq "http") {
  34. $s = Net::HTTP->new(Host => $host, Timeout => 120);
  35. }
  36. elsif ($protocol eq "https") {
  37. $s = Net::HTTPS->new(Host => $host, Timeout => 120);
  38. }
  39. else {
  40. print " Unhandled http protocol \"$protocol\"";
  41. return 3;
  42. }
  43. if (! $s) {
  44. print " " . $@;
  45. return 3;
  46. }
  47. my $getp = "/";
  48. if ($path ne "") {
  49. $getp .= $path;
  50. }
  51. if (defined($file)) {
  52. if ($getp =~ /\/$/) {
  53. $getp .= $file;
  54. }
  55. else {
  56. $getp .= "/$file";
  57. }
  58. }
  59. #print " Trying to use GET => \"$getp\"";
  60. $s->write_request(GET => $getp, 'User-Agent' => "Mozilla/6.0");
  61. my($code, $mess, %h) = $s->read_response_headers;
  62. # Try to read something
  63. my $buf;
  64. my $n = $s->read_entity_body($buf, 1024);
  65. if (! defined($n)) {
  66. print " Read from \"$protocol://$host$getp\" failed";
  67. return 3;
  68. }
  69. }
  70. # Returns ($err, $isdir)
  71. # returns 0, x if file does not match entry
  72. # 1, x everything OK
  73. # 2, x if not accesible (permission)
  74. sub check_ftp_dir_entry($$)
  75. {
  76. my ($file, $e) = @_;
  77. my $other = '---';
  78. my $isdir = 0;
  79. #print "Checking '$file' against '$e'\n";
  80. $file =~ s/^\///;
  81. $isdir = 1 if ($e =~ /^d/);
  82. return(0,$isdir) if ($e !~ /\s$file$/);
  83. if ($e =~ /^.[-rwx]{6}([-rwx]{3})\s/) {
  84. $other = $1;
  85. }
  86. else {
  87. #print "Invalid entry\n";
  88. # Invalid entry
  89. return(0,$isdir);
  90. }
  91. return(2,$isdir) if ($other !~ /^r/); # not readable
  92. if ($isdir) {
  93. #return(2,$isdir) if ($other !~ /x$/); # directory, but not executable
  94. }
  95. return(1,$isdir);
  96. }
  97. sub check_ftp_url($$$$)
  98. {
  99. use Net::FTP;
  100. my ($protocol, $host, $path, $file) = @_;
  101. my $res = 0;
  102. my $message = "";
  103. my $ftp = Net::FTP->new($host, Debug => 0, Timeout => 120);
  104. if(!$ftp) {
  105. return(3,"Cannot connect to $host");
  106. }
  107. if (! $ftp->login("anonymous",'-anonymous@')) {
  108. $message = $ftp->message;
  109. $res = 3;
  110. }
  111. else {
  112. my $rEntries;
  113. if ($path ne "") {
  114. #print "Path = $path\n";
  115. #if (!$ftp->cwd($path)) {
  116. # $message = $ftp->message;
  117. # $res = 3;
  118. #}
  119. $rEntries = $ftp->dir($path);
  120. }
  121. else {
  122. $rEntries = $ftp->dir();
  123. }
  124. if (! $rEntries) {
  125. $res = 3;
  126. $message = "Could not read directory \"$path\"";
  127. }
  128. elsif (defined($file)) {
  129. my $found = 0;
  130. my $found2 = 0;
  131. for my $f ( @{$rEntries}) {
  132. #print "Entry: $path $f\n";
  133. my ($res1,$isdir) = check_ftp_dir_entry($file,$f);
  134. if ($res1 == 1) {
  135. $found = 1;
  136. last;
  137. }
  138. elsif ($res1 == 2) {
  139. # found, but not accessible
  140. $found2 = 1;
  141. $message = "Permission denied for '$file'";
  142. }
  143. }
  144. if (! $found) {
  145. $res = 4;
  146. if (! $found2) {
  147. $message = "File or directory '$file' not found";
  148. }
  149. }
  150. }
  151. }
  152. $ftp->quit;
  153. #print "returning ($res,$message)\n";
  154. return($res, $message);
  155. }
  156. sub check_unknown_url($$$$)
  157. {
  158. use LWP::Simple;
  159. my ($protocol, $host, $path, $file) = @_;
  160. my $res = 1;
  161. my $url = "$protocol://$host";
  162. if ($path ne "") {
  163. if ($path =~ /^\//) {
  164. $url .= $path;
  165. }
  166. else {
  167. $url .= "/$path";
  168. }
  169. }
  170. if(defined($file)) {
  171. #print "Trying $url$file\n";
  172. $res = head("$url/$file");
  173. if(! $res) {
  174. # try to check for directory '/';
  175. #print "Trying $url$file/\n";
  176. $res = head("$url/$file/");
  177. }
  178. }
  179. else {
  180. #print "Trying $url\n";
  181. $res = head($url);
  182. }
  183. return(! $res);
  184. }
  185. #
  186. # Main entry
  187. sub check_url($)
  188. {
  189. my($url) = @_;
  190. my $file = undef;
  191. my ($protocol,$host,$path);
  192. my $res = 0;
  193. # Split the url to protocol,host,path
  194. if ($url =~ /^([a-z]+):\/\/([^\/]+)(.*)$/) {
  195. $protocol = $1;
  196. $host = $2;
  197. $path = $3;
  198. $path =~ s/^\///;
  199. if($path =~ s/\/([^\/]+)$//) {
  200. $file = $1;
  201. if($file =~ / /) {
  202. # Filename contains ' ', maybe invalid. Don't check
  203. $file = undef;
  204. }
  205. $path .= "/";
  206. }
  207. }
  208. else {
  209. print " Invalid url '$url'";
  210. return 2;
  211. }
  212. if ($protocol =~ /^https?$/) {
  213. return check_http_url($protocol, $host, $path, $file);
  214. }
  215. elsif ($protocol eq "ftp") {
  216. my $message;
  217. ($res, $message) = check_ftp_url($protocol, $host, $path, $file);
  218. return $res;
  219. }
  220. else {
  221. # it never should reach this point
  222. print " What protocol is '$protocol'?";
  223. $res = check_unknown_url($protocol, $host, $path, $file);
  224. return $res;
  225. }
  226. }
  227. 1;