File Coverage

blib/lib/WebService/FreeDB.pm
Criterion Covered Total %
statement 86 313 27.4
branch 30 174 17.2
condition 4 75 5.3
subroutine 5 10 50.0
pod 0 8 0.0
total 125 580 21.5


|g;
line stmt bran cond sub pod time code
1             package WebService::FreeDB; # -*- tab-width:8 -*-
2 1     1   29835 use Data::Dumper;
  1         17472  
  1         81  
3 1     1   13590 use LWP::UserAgent; # Erweiterung jb
  1         105493  
  1         6342  
4              
5             require Exporter;
6             @ISA = qw(Exporter);
7             @EXPORT = qw//;
8             @EXPORT_OK = qw/getdiscs getdiscinfo ask4discurls outdumper outstd/;
9             $VERSION = '0.79';
10              
11             #####
12             # Description: for getting a instace of this Class
13             # Params: %hash with keys:
14             # HOST : Destination host, if not defined: www.freedb.org
15             # PATH : Path on HOST to CGI
16             # PROXY: Define Proxy to use
17             # DEFAULTVALUES : Default parameters for CGI, will be set always
18             # Returns: an object of this class
19             #####
20             sub new {
21 2     2 0 4153 my $class = shift;
22 2         7 my $self = {};
23 2         9 $self->{ARG} = {@_};
24 2 50       11 if(!defined($self->{ARG}->{HOST})) {
25             #Maybe there are other freedb-web-interfaces ?!
26 2         10 $self->{ARG}->{HOST}='http://www.freedb.org'
27             }
28 2 50       9 if(!defined($self->{ARG}->{PATH})) {
29             #Path to CGI-script
30 2         6 $self->{ARG}->{PATH}='/freedb_search.php'}
31 2 50       11 if(!defined($self->{ARG}->{PROXY})) {
32             #If there's no proxy, define but don't change it
33 2         8 $self->{ARG}->{PROXY}=''
34             }
35 2 50       7 if(!defined($self->{ARG}->{DEFAULTVALUES})) {
36             #default Parameters
37 2         6 $self->{ARG}->{DEFAULTVALUES}='&allfields=NO&grouping=none'
38             }
39 2         7 bless($self, $class);
40 2 50       19 $self ? return $self : return undef;
41            
42             }
43              
44             #####
45             # Description: out of Keywords it will return a List of entries in FreeDB
46             # Params: ,[Array of fields to search in],
47             # [Array of categories to search in]
48             # Returns: %Hash, where urls are Key and [Array of Artist,Album] is value%
49             #####
50             sub getdiscs {
51 1     1 0 9 my $self = shift;
52 1         7 my @keywords = split(/ /,shift);
53 1         1 my @fields = @{$_[0]};
  1         4  
54 1 50       6 if(defined $_[1]) {@cats = @{$_[1]};}
  0         0  
  0         0  
55 1         2 my %discs;
56 1         7 my $url = $self->{ARG}->{HOST}.
57             $self->{ARG}->{PATH}."?".
58             $self->{ARG}->{DEFAULTVALUES};
59            
60            
61 1         4 $url .="&words=".shift(@keywords);
62 1         6 for my $word (@keywords) {
63 0         0 $url .= "+".$word;
64             }
65            
66            
67 1         2 for my $field (@fields) {
68 2 50       16 if(!($field =~ /^(artist|title|track|rest)$/)) {
69 0 0 0     0 if (defined $self->{ARG}->{DEBUG} &&
70             $self->{ARG}->{DEBUG} >= 1) {
71 0         0 print STDERR "*unknown field-type: $field;\n"
72             }
73 0         0 next;
74             }
75 2         7 $url .= "&fields=".$field;
76             }
77 1 50       4 if (@cats) {
78 0         0 $url .= "&allcats=NO";
79 0         0 for my $cat (@cats) {
80 0 0       0 if(!($cat =~ /^(blues|classical|country|data|folk|jazz|misc|newage|reggae|rock|soundtrack)$/)) {
81 0 0 0     0 if (defined $self->{ARG}->{DEBUG} &&
82             $self->{ARG}->{DEBUG} >= 1) {
83 0         0 print STDERR "*unknown cat-type: $cat;\n"
84             }
85 0         0 next;
86             }
87 0         0 $url .= "&cats=".$cat;
88             }
89             } else {
90 1         3 $url .= "&allcats=YES";
91             }
92            
93 1 50 33     9 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 2) {
94 0         0 print STDERR "**url-search: $url;\n" ;
95             }
96              
97 1         15 my $ua = LWP::UserAgent->new();
98 1         4567 $ua->proxy('http' => $self->{ARG}->{PROXY});
99 1         111 my $req = HTTP::Request->new(GET => $url);
100 1         11847 my $response = $ua->request($req);
101 1 50       756913 if ($response->is_success) {
102 1         31 my $data = $response->content;
103 1         514 my ($line) = grep {m|^|} split(/\n/, $data);
  258         642  
104 1 50       39 die "no match" unless $line;
105 1         736 $discs{$1} = [$2,$3]
106             while $line =~ m|(.+?) / (.+?)
107             }
108             else {
109 0         0 die $response->status_line;
110             }
111 1         386 return %discs;
112             }
113              
114             #####
115             # Description: out of a URL (you got as key from getdiscs() ) will retrieve
116             # concrete Informations of this CD.
117             # Params:
118             # Returns: %Hash of items of the CD%
119             #####
120             sub getdiscinfo {
121 1     1 0 10 my $self = shift;
122 1         4 my $url = shift;
123 1         3 my %disc;
124              
125 1 50 33     10 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 2) {
126 0         0 print STDERR "**url-disc:$url;\n";
127             }
128 1         20 my $ua = LWP::UserAgent->new();
129 1         279 $ua->proxy('http' => $self->{ARG}->{PROXY});
130 1         82 my $req = HTTP::Request->new(GET => $url);
131 1         185 my $response = $ua->request($req);
132 1 50       246670 if ($response->is_success) {
133 1         15 my $data = $response->content;
134 1 50       27 if (!defined($data)) {
135 0 0 0     0 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
136 0         0 print STDERR "*found no disc;\n";
137             }
138 0         0 return ;
139             }
140 1         4 $disc{url} = $url;
141 1         106 @lines = split(/\n/,$data);
142 1         3 $line = shift(@lines);
143             #ignore until begin of searchResult data
144 1         5 while (!($line =~ m|^|)) {
145 234         213 $line = shift(@lines);
146 234 50       475 last unless @lines;
147             }
148 1 50 33     7 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 2) {
149 0         0 print STDERR "**found start of data :$line;\n";
150             }
151 1 50       4 die "found no data. FreeDB template format changed?\n" unless $line;
152 1 50       31 if ($line =~ m|/id="searchU11" title="(.+?) / (.+?)">|) {
153 0         0 $disc{artist} = $1;
154 0         0 $disc{album} = $2;
155             } else {
156 1 50 33     6 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
157 0         0 print STDERR "*format error(artist+album):$line;\n";
158             }
159             }
160 1 50       9 if ($line =~ m|Tracks:\s*?(\d+)
|) {
161 1         3 $disc{tracks} = $1;
162             } else {
163 0 0 0     0 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
164 0         0 print STDERR "*format error(tracks):$line;\n";
165             }
166             }
167 1 50       7 if ($line =~ m|Total time:\s*(\d+:\d+)
|) {
168 1         3 $disc{totaltime} = $1;
169             } else {
170 0 0 0     0 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
171 0         0 print STDERR "*format error(totaltime):$line;\n";
172             }
173             }
174 1 50       7 if ($line =~ m|Year:\s*(\d*)
|) {
175 1         3 $disc{year} = $1;
176             } else {
177 0 0 0     0 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
178 0         0 print STDERR "*format error(year):$line;\n";
179             }
180             }
181 1 50       7 if ($line =~ m|Disc-ID:\s*(.*?) / |) {
182 1         3 $disc{genre} = $1;
183             } else {
184 0 0 0     0 if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
185 0         0 print STDERR "*format error(genre):$line;\n";
186             }
187             }
188 1 50       3 if(!defined($disc{artist})) {$disc{artist} = "";}
  1         3  
189 1 50       4 if(!defined($disc{album})) {$disc{album} = "";}
  1         2  
190 1 50       4 if(!defined($disc{year})) {$disc{year} = "";}
  0         0  
191 1 50       5 if(!defined($disc{genre})) {$disc{genre} = "";}
  0         0  
192              
193 1         4 while (!($line =~ /^$/)) { #ignore until begin of tackinfo
194 63 50       80 if ($line =~ /^

$/) { 
195 0         0 $line = shift(@lines);
196 0         0 while (!($line =~ /<\/pre><\/tr><\/td><\/table><\/center>/)) {
197 0         0 $disc{rest} .= $line."\n";
198 0         0 $line = shift(@lines);
199 0 0       0 last unless $line;
200             }
201             }
202 63         59 $line = shift(@lines);
203 63 100       120 if (!defined($line)) {
204 1         4 $disc{trackinfo} = defined;
205 1         61 return %disc; #break if not found beginning (empty entries)
206             }
207             }
208 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 2) {
209 0           print STDERR "**found start of trackinfo:$line;\n";
210             }
211 0           $index = 1;
212 0           for my $line (@lines) {
213 0 0         if ($line =~ /^

<\/td><\/tr>$/) {next;}
  0 0          
  0 0          
    0          
    0          
214             elsif ($line =~ /^.*?<\/font>/) {next;} # ignore ext-desc of a track
215             elsif ($line =~ /^
{0,1}$index\.<\/td> {0,1}(\d+:\d+)<\/td>(.+)<\/b>/) {
216 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 3) {
217 0           print STDERR "***found track: $line;\n";
218             }
219 0           $disc{trackinfo}[$index-1]=[$2,$1];
220 0           $index++;
221             } elsif ($line =~ /^
\d+\.<\/td> (\d+:\d+)<\/td>(.+)<\/b>/) {
222 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
223 0           print STDERR "*out of sync for trackinfo:$line;\n";
224             }
225 0           } elsif ($line =~ /^<\/table>$/) {
226 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 2) {
227 0           print STDERR "**found end of trackinfo & data: $line;\n";
228             }
229             } else {next;}
230              
231             }
232 0           return %disc;
233             } else {
234             #print STDERR "Url was: ".$url."\n";
235 0           die $response->status_line;
236             }
237             }
238              
239             #####
240             # Description: User interactive method (console) for selecting CDs for retrieval
241             # Params: %Hash, where urls are Key and [Array of Artist,Album] is value%
242             # (you got it from getdiscs())
243             # Returns: [Array of URLs, which where selected by User]
244             #####
245             sub ask4discurls {
246 0     0 0   my $self = shift;
247 0           my %discs = %{$_[0]};
  0            
248             #sort for artists
249 0 0         my @keys = sort { $discs{$a}[0] cmp $discs{$b}[0] || $discs{$a}[1] cmp $discs{$b}[1]} keys %discs;
  0            
250 0           my @urls;
251              
252 0 0         if(!defined($keys[0])) {
253 0           print STDERR "Sorry - no matching discs found\n";
254 0           return 1;
255             }
256             #giving list 2 user
257 0           for (my $i=0;$i<@keys;$i++) {
258 0           print STDERR "$i) ".$discs{$keys[$i]}[0]." / ".$discs{$keys[$i]}[1];
259 0 0         if (defined $discs{$keys[$i]}[2]) {
260 0           print STDERR " [".(@{$discs{$keys[$i]}} - 2)." alternatives]";
  0            
261             }
262 0           print STDERR "\n";
263             }
264 0           print STDERR "Select discs (space seperated numbers or -;alternatives by appending 'A' and alternate-number):\n";
265 0           $userin = ;
266 0           chomp $userin;
267 0           while($userin =~ /(\d+)A(\d+)-(\d+)A(\d+)/) { # 23A2-42A3 - so with beginning alternatives
268 0 0         if(!($1<$3)) {
269 0           print STDERR "Ignoring $1-$3 ...";
270             }
271 0           my $tmpadd = $1."A".$2." ";
272 0           for(my $i=$1+1;$i<=$3-1;$i++) {
273 0           $tmpadd .= $i." ";
274             }
275 0           $tmpadd .= $3."A".$4;
276 0           $userin =~ s/$1A$2-$3A$4/$tmpadd/;
277             }
278 0           while($userin =~ /(\d+)A(\d+)-(\d+)/) { # 23A2-42 - so with beginning alternatives
279 0 0         if(!($1<$3)) {
280 0           print STDERR "Ignoring $1-$3 ...";
281             }
282 0           my $tmpadd = $1."A".$2." ";
283 0           for(my $i=$1+1;$i<=$3;$i++) {
284 0           $tmpadd .= $i." ";
285             }
286 0           $userin =~ s/$1A$2-$3/$tmpadd/;
287             }
288 0           while($userin =~ /(\d+)-(\d+)A(\d+)/) { # 23-42A2 - so with beginning alternatives
289 0 0         if(!($1<$2)) {
290 0           print STDERR "Ignoring $1-$2 ...";
291             }
292 0           my $tmpadd = "";
293 0           for(my $i=$1;$i<=$2-1;$i++) {
294 0           $tmpadd .= $i." ";
295             }
296 0           $tmpadd .= $2."A".$3;
297 0           $userin =~ s/$1-$2A$3/$tmpadd/;
298             }
299 0           while($userin =~ /(\d+)-(\d+)/) { # 23-42 - so without alternatives
300 0 0         if(!($1<$2)) {
301 0           print STDERR "Ignoring $1-$2 ...";
302             }
303 0           my $tmpadd = "";
304 0           for(my $i=$1;$i<=$2;$i++) {
305 0           $tmpadd .= $i." ";
306             }
307 0           $userin =~ s/$1-$2/$tmpadd/;
308             }
309 0           @select = split (/ /,$userin);
310 0           for my $cd (@select) {
311 0 0 0       if ($cd =~ /^\d+$/ && defined($keys[$cd])) {
    0 0        
312 0           push(@urls,$keys[$cd]);
313             } elsif ($cd =~ /^(\d+)A(\d+)$/ && $discs{$keys[$1]}[($2+2)]) {
314 0           push(@urls,$discs{$keys[$1]}[($2+2)]);
315             } else {
316 0           print STDERR "not defined '$cd' - ignoring!\n";
317             }
318             }
319 0           return @urls;
320             }
321              
322             #####
323             # Description: output-method of the retrieved CD
324             # this goes out to STDOUT by using Data:Dumper
325             # Params: %Hash of items of the CD%
326             # (you got it from getdiscinfo())
327             # Returns: nothing
328             #####
329             sub outdumper {
330 0 0   0 0   if(!defined($disc{url})) {
331 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
332 0           print STDERR "*no disc info \n";
333             }
334 0           return 1;
335             }
336 0           my $self = shift;
337 0           my $disc = shift;
338 0           print Dumper $disc;
339             }
340              
341             #####
342             # Description: output-method of the retrieved CD
343             # this goes out to STDOUT in a pretty formated Look
344             # Params: %Hash of items of the CD%
345             # (you got it from getdiscinfo())
346             # Returns: nothing
347             #####
348             sub outstd {
349 0     0 0   my $self = shift;
350 0           my %disc = %{$_[0]};
  0            
351 0 0         if(!defined($disc{url})) {
352 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
353 0           print STDERR "*no disc info \n";
354             }
355 0           return 1;
356             }
357 0           print "DiscInfo:\n########\n";
358 0           print "Artist:".$disc{artist}." - Album: ".$disc{album}."\n";
359 0           print "Reference:".$disc{url}."\n";
360 0           print "Total-Tracks:".$disc{tracks}." - Total-Time:".$disc{totaltime}."\n";
361 0           print "Year:".$disc{year}." - Genre:".$disc{genre}."\n";
362 0 0         if(defined($disc{rest})) {print "Comment:".$disc{rest}."\n";}
  0            
363 0           print "Tracks:\n";
364 0           for (my $i=0;$i<@{$disc{trackinfo}};$i++) {
  0            
365 0           print 1+$i.") ".${$disc{trackinfo}}[$i][0]." (".${$disc{trackinfo}}[$i][1].")\n";
  0            
  0            
366             }
367             }
368              
369             #####
370             # Description: output-method of the retrieved CD
371             # this goes out to STDOUT in XML
372             # validating against example/cdcollection.dtd
373             # Params: %Hash of items of the CD%
374             # (you got it from getdiscinfo())
375             # Returns: nothing
376             #####
377             sub outxml {
378 0     0 0   my $self = shift;
379 0           my %disc = %{$_[0]};
  0            
380 0 0         if(!defined($disc{url})) {
381 0 0 0       if (defined $self->{ARG}->{DEBUG} && $self->{ARG}->{DEBUG} >= 1) {
382 0           print STDERR "*no disc info \n" ;
383             }
384 0           return 1;
385             }
386 0           print "\n";
387 0 0         if(defined($disc{medium})) {print "\t".ascii2xml($disc{medium})."\n";}
  0            
388 0 0         if(defined($disc{id})) {print "\t".ascii2xml($disc{id})."\n";}
  0            
389 0 0         if (defined($disc{artist})) {print "\t".ascii2xml($disc{artist})."\n";}
  0            
390 0           print "\t".ascii2xml($disc{album})."\n";
391 0 0         if (defined($disc{year})) {print "\t".ascii2xml($disc{year})."\n";}
  0            
392 0 0         if(defined($disc{source})) {print "\t".ascii2xml($disc{source})."\n";}
  0            
393 0 0         if(defined($disc{quality})) {print "\t".ascii2xml($disc{quality})."\n";}
  0            
394 0 0         if(defined($disc{comment})) {print "\t".ascii2xml($disc{comment})."\n";}
  0            
395 0           print "\t\n";
396 0           for (my $i=0;$i<@{$disc{trackinfo}};$i++) {
  0            
397 0           my ($artist1,$name1) = split(/ \/ /,${$disc{trackinfo}}[$i][0]);
  0            
398 0           my ($artist2,$name2) = split(/ - /,${$disc{trackinfo}}[$i][0]);
  0            
399 0 0 0       if (defined($disc{type}) && $disc{type} eq "sampler" && defined $name1) {
    0 0        
    0 0        
      0        
      0        
400 0           print "\t\t\n";
401 0 0         if(defined($artist1)) {print "\t\t\t".ascii2xml($artist1)."\n";}
  0            
402 0 0         if(defined($name1)) {print "\t\t\t".ascii2xml($name1)."\n";}
  0            
403 0 0         if(defined($disc{trackinfo}[$i][1])) {print "\t\t\t\n";}
  0            
  0            
404 0 0         if(defined($disc{trackinfo}[$i][2])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][2])."\n";}
  0            
  0            
405 0           print "\t\t\n";
406 0           print STDERR "Splitted title ' / ' - highly recommed to check this !\n";
407             } elsif (defined($disc{type}) && $disc{type} eq "sampler" && defined $name2) {
408 0           print "\t\t\n";
409 0 0         if(defined($artist2)) {print "\t\t\t".ascii2xml($artist2)."\n";}
  0            
410 0 0         if(defined($name2)) {print "\t\t\t".ascii2xml($name2)."\n";}
  0            
411 0 0         if(defined($disc{trackinfo}[$i][1])) {print "\t\t\t\n";}
  0            
  0            
412 0 0         if(defined($disc{trackinfo}[$i][2])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][2])."\n";}
  0            
  0            
413 0           print "\t\t\n";
414 0           print STDERR "Splitted title ' - ' - highly recommed to check this !\n";
415             } elsif (defined($disc{type}) && $disc{type} eq "sampler") {
416 0           print "\t\t\n";
417 0 0         if(defined($disc{trackinfo}[$i][0])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][0])."\n";}
  0            
  0            
418 0 0         if(defined($disc{trackinfo}[$i][1])) {print "\t\t\t\n";}
  0            
  0            
419 0 0         if(defined($disc{trackinfo}[$i][2])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][2])."\n";}
  0            
  0            
420 0           print "\t\t\n";
421 0           print STDERR "NOT Splitted title - highly recommed to check this !\n";
422             } else {
423 0           print "\t\t\n";
424 0 0         if(defined($disc{trackinfo}[$i][0])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][0])."\n";}
  0            
  0            
425 0 0         if(defined($disc{trackinfo}[$i][1])) {print "\t\t\t\n";}
  0            
  0            
426 0 0         if(defined($disc{trackinfo}[$i][2])) {print "\t\t\t".ascii2xml(${$disc{trackinfo}}[$i][2])."\n";}
  0            
  0            
427 0           print "\t\t\n";
428             }
429             }
430 0           print "\t\n";
431 0           print "\n";
432             }
433             #####
434             # Description: PRIVATE - not for use outside !
435             # Converts special XML Chars to XML-style
436             # Params:
437             # Returns:
438             #####
439             sub ascii2xml {
440 0     0 0   $ascii = $_[0];
441              
442 0           $ascii =~ s/&/&/g;
443 0           $ascii =~ s/
444 0           $ascii =~ s/>/>/g;
445 0           $ascii =~ s/'/'/g;
446 0           $ascii =~ s/"/"/g;
447              
448 0           return $ascii;
449             }
450              
451             return 1;
452             __END__