File Coverage

blib/lib/HTTP/MobileAgent/Plugin/Location.pm
Criterion Covered Total %
statement 46 319 14.4
branch 1 126 0.7
condition 0 25 0.0
subroutine 14 35 40.0
pod 0 5 0.0
total 61 510 11.9


line stmt bran cond sub pod time code
1             package HTTP::MobileAgent::Plugin::Location;
2              
3 8     8   618075 use warnings;
  8         25  
  8         297  
4 8     8   464 use strict;
  8         13  
  8         230  
5 8     8   45 use Carp;
  8         60  
  8         667  
6 8     8   19611 use CGI;
  8         148054  
  8         65  
7 8     8   8460 use Class::Data::Inheritable;
  8         2297  
  8         229  
8 8     8   8374 use Class::Accessor::Fast;
  8         41264  
  8         94  
9 8     8   7107 use HTTP::MobileAgent::Plugin::Location::Support;
  8         29  
  8         322  
10 8     8   6525 use HTTP::MobileAgent::Plugin::Location::LocationObject;
  8         24  
  8         88  
11 8     8   8774 use URI;
  8         44371  
  8         261  
12 8     8   7787 use URI::QueryParam;
  8         6522  
  8         270  
13 8     8   52 use URI::Escape;
  8         18  
  8         728  
14              
15 8     8   123 use version; our $VERSION = qv('0.0.5');
  8         19  
  8         67  
16             my @accuracy = qw(gps hybrid sector);
17             my @modes = qw(gps sector area);
18             my @methods = qw(gps sector area);
19              
20             my %corx = (
21             "XHTML" => [
22             ' />',
23             'lcs="lcs"',
24             'z="z"',
25             ],
26             "CHTML" => [
27             '>',
28             'lcs',
29             'z',
30             ],
31             );
32              
33             my $escape = {
34             "'" => ''',
35             '"' => '"',
36             '&' => '&',
37             '>' => '>',
38             '<' => '<',
39             };
40              
41             # Inherit
42             push (@HTTP::MobileAgent::ISA,qw/Class::Data::Inheritable Class::Accessor::Fast/);
43              
44             # Class property
45              
46             HTTP::MobileAgent->mk_classdata("_use_area",0);
47             HTTP::MobileAgent->mk_classdata("_use_geopoint",0);
48             HTTP::MobileAgent->mk_classdata("_use_geocoordinate",0);
49              
50             # Object property
51              
52             HTTP::MobileAgent->mk_accessors(qw/location area err/);
53              
54             # Initialize
55              
56             sub import {
57 8     8   94 my @ARG = @_;
58              
59 8         20 my $caller = shift;
60 8         92 foreach my $arg (@_)
61             {
62 7         18 my $method = "_$arg";
63 7         12 eval{ HTTP::MobileAgent->$method(1) };
  7         33  
64 7 50       221 croak "No such option $arg" if ($@);
65             }
66             }
67              
68             ##########################################
69             # Base Module
70              
71             package # hide from PAUSE
72             HTTP::MobileAgent;
73              
74             # Set/get query objext
75              
76             sub query{
77 0     0 0   my $self = shift;
78 0           my $query = shift;
79              
80 0 0         $self->{query} = $query if ($query);
81 0 0 0       $self->{query} ||= ref($self->{_request}) eq "HTTP::MobileAgent::Request::Apache" ? $self->{_request}->{r} : CGI->new;
82              
83 0           $self->{query};
84             }
85              
86             # Error set (and return undef)
87              
88             sub set_err{
89 0     0 0   $_[0]->{err} = $_[1];
90 0           return;
91             }
92              
93             # "UseArea" option methods for object (can override class setting)
94              
95             sub use_area{
96 0     0 0   my $self = shift;
97 0 0         $self->{use_area} = $_[0] if (defined($_[0]));
98 0 0         defined($self->{use_area}) ? $self->{use_area} : $self->_use_area;
99             }
100              
101             # General location html descriptor
102              
103             sub location_description{
104 0     0 0   my $self = shift;
105 0           $self->{err} = undef;
106 0 0         my $uri = shift or return $self->set_err("URI value is needed");
107 0 0         my $desc = shift or return $self->set_err("Description value is needed");
108 0   0       my $opt = shift || {};
109              
110 0           $desc =~ s/([<>&'"])/$escape->{$1}/ge;
  0            
111              
112 0 0         return $self->set_err("Not support any location description") unless ($self->support_location);
113              
114 0 0         $uri = ref($uri) ? $uri->clone : URI->new($uri);
115 0   0       my $method = uc($opt->{method}) || "ANY";
116 0   0       my $html = uc($opt->{html}) || ((!$self->is_airh_phone && $self->xhtml_compliant) ? "XHTML" : "CHTML");
117              
118 0 0         my @reqmodes = $opt->{mode} ? ($opt->{mode}) : @modes;
119 0 0         return $self->set_err("Not support $method method location description") if ($method !~ /^(A|ANY|POST|GET)$/);
120 0 0         return $self->set_err("Not support $html as markup language") if ($html !~ /^[XC]HTML$/);
121              
122 0           foreach my $each (@reqmodes) {
123 0           my $support = "support_$each";
124 0 0         next unless (eval { $self->$support() });
  0            
125              
126 0           my $descriptor ="_${each}_description";
127 0           return $self->$descriptor($uri,$desc,$method,$html);
128             }
129            
130 0           return $self->set_err("Not support " . $opt->{mode} . " type location description");
131             }
132              
133             # Base methods of each location html descriptor
134              
135             {
136 8     8   8537 no strict 'refs'; ## no critic
  8         19  
  8         35589  
137             foreach my $accessor (@modes) {
138 0     0     *{"HTTP::MobileAgent::_${accessor}_description"} = sub { return $_[0]->set_err("Not suppot $accessor type location description") };
139             }
140             }
141              
142             # General location parser
143              
144             sub parse_location{
145 0     0 0   my $self = shift;
146 0           $self->{err} = undef;
147 0           $self->{area} = undef;
148              
149 0           $self->{location} = $self->_parse_location;
150 0 0         if ($self->use_area) {
151 0           require HTTP::MobileAgent::Plugin::Location::AreaObject;
152 0           $self->{area} = $self->_parse_area;
153             }
154              
155 0           $self->{location};
156             }
157              
158             # Base method of location parser
159              
160 0     0     sub _parse_location{ undef }
161              
162             # Base method of area parser
163              
164             sub _parse_area{
165 0     0     my $self = shift;
166 0 0         if ($self->location) {
167 0           return HTTP::MobileAgent::Plugin::Location::AreaObject->__create_coord($self->location);
168             }
169             }
170              
171             ##########################################
172             # DoCoMo Module
173              
174             package # hide from PAUSE
175             HTTP::MobileAgent::DoCoMo;
176              
177             # Method of gps location html descriptor
178              
179             sub _gps_description{
180 0     0     my $self = shift;
181 0           my ($uri,$desc,$method,$html) = @_;
182 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
183              
184 0           my $retcode;
185              
186 0 0         if ($self->is_foma) {
187             # FOMA
188              
189 0 0         if ($method =~ /^A/) {
190             # A, ANY
191              
192 0           $retcode = $uri->canonical;
193 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
194              
195 0           $retcode = "$desc\n";
196             } else {
197             # POST, GET
198              
199 0           my @query_form = $uri->query_form;
200 0           $uri->query_form([]);
201              
202 0           $retcode = "
canonical . "\" method=\"" . lc($method) . "\" $lcs>\n";
203 0           $retcode .= "
204              
205 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
206 0           $retcode .= "
207             }
208 0           $retcode .= "\n";
209             }
210             } else {
211             # mova
212              
213             # A is not allowed
214              
215 0 0         return $self->set_err("Not support A method location description") if ($method eq "A");
216              
217             # POST, GET, ANY(=POST)
218              
219 0           my @query_form = $uri->query_form;
220 0           $uri->query_form([]);
221              
222 0 0         $method = "POST" if ($method eq "ANY");
223              
224 0           $retcode = "
canonical . "\" method=\"" . lc($method) . "\">\n";
225 0           $retcode .= "
226              
227 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
228 0           $retcode .= "
229             }
230 0           $retcode .= "\n";
231             }
232              
233 0           $retcode;
234             }
235              
236             # Method of sector location html descriptor
237              
238             sub _sector_description{
239 0     0     my $self = shift;
240 0           my ($uri,$desc,$method,$html) = @_;
241 0           $self->_area_description($uri,$desc,$method,$html,1);
242             }
243              
244             # Method of area location html descriptor
245              
246             sub _area_description{
247 0     0     my $self = shift;
248 0           my ($uri,$desc,$method,$html,$use_sector) = @_;
249 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
250              
251 0           my $retcode;
252              
253 0           my @query_form = $uri->query_form;
254 0 0         if (@query_form > 4) {
255             # Only 2 parameters are allowed
256              
257 0           @query_form = @query_form[0..3];
258 0           $self->set_err("Only 2 parameters allowed but over it. Over parameters are discarded");
259             }
260 0           $uri->query_form([]);
261              
262 0           my @docomo_form = (
263             ecode => "OPENAREACODE",
264             msn => "OPENAREAKEY",
265             nl => $uri->canonical,
266             );
267              
268 0           my $count = 0;
269 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
270 0           my $argval = "$key=$vals";
271 0           $count++;
272 0           push (@docomo_form,"arg$count",$argval);
273             }
274 0 0         push (@docomo_form,"posinfo",1) if ($use_sector);
275              
276 0 0         if ($method eq "A") {
277             # A
278              
279 0           $uri = URI->new("http://w1m.docomo.ne.jp/cp/iarea");
280 0           $uri->query_form(\@docomo_form);
281              
282 0           $retcode = $uri->canonical;
283 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
284              
285 0           $retcode = "$desc\n";
286             } else {
287             # POST, GET, ANY(=POST)
288              
289 0 0         $method = "POST" if ($method eq "ANY");
290              
291 0           $retcode = "
\n";
292 0           $retcode .= "
293              
294 0           while (my($key,$vals) = splice(@docomo_form, 0, 2)) {
295 0           $retcode .= "
296             }
297 0           $retcode .= "\n";
298             }
299              
300 0           $retcode;
301             }
302              
303             # Method of location parser
304              
305             sub _parse_location{
306 0     0     my $self = shift;
307 0           my $q = $self->query;
308 0           my $loc;
309              
310 0 0 0       if ($q->param("pos")) {
    0 0        
    0          
311             # mova gps parser
312              
313 0           $q->param("pos") =~ /^(N|S)([\d\.]+)(W|E)([\d\.]+)$/;
314 0 0         my $lat = (($1 eq 'S') ? "-" : "").$2;
315 0 0         my $long = (($3 eq 'W') ? "-" : "").$4;
316              
317 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,'wgs84','gpsone');
318 0           $loc->accuracy($accuracy[3 - $q->param("X-acc")]);
319 0           $loc->mode("gps");
320             } elsif ($q->param("lat") && $q->param("lon")) {
321             # For FOMA gps
322              
323 0           my $lat = $q->param("lat");
324 0           my $long = $q->param("lon");
325              
326 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,'wgs84','gpsone');
327 0           $loc->accuracy($accuracy[3 - $q->param("x-acc")]);
328 0           $loc->mode("gps");
329             } elsif ($q->param("LAT") && $q->param("LON")) {
330             # For FOMA sector(extended i-area) parser
331              
332 0           my $lat = $q->param("LAT");
333 0           my $long = $q->param("LON");
334              
335 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,'wgs84','gpsone');
336 0           $loc->accuracy($accuracy[3 - $q->param("XACC")]);
337 0           $loc->mode("sector");
338             }
339 0           $loc;
340             }
341              
342             # Method of area parser
343              
344             sub _parse_area{
345 0     0     my $self = shift;
346 0           my $q = $self->query;
347 0 0         if ($q->param("AREACODE")) {
348             # sector or i-area
349              
350 0           return HTTP::MobileAgent::Plugin::Location::AreaObject->create_iarea($q->param("AREACODE"));
351             } else {
352             # gps
353              
354 0           return $self->SUPER::_parse_area;
355             }
356             }
357              
358             ##########################################
359             # EZWeb Module
360              
361             package # hide from PAUSE
362             HTTP::MobileAgent::EZweb;
363              
364             # Method of gps location html descriptor
365              
366             sub _gps_description{
367 0     0     my $self = shift;
368 0           my ($uri,$desc,$method,$html) = @_;
369 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
370              
371             # POST is not allowed
372 0 0         return $self->set_err("Not support POST method location description") if ($method eq "POST");
373              
374 0           my $retcode;
375            
376              
377 0           my @query_form = $uri->query_form;
378 0 0         if (@query_form) {
379             # Parameters are not allowed
380              
381 0           $self->set_err("Parameters are not allowed, so they are discarded");
382             }
383 0           $uri->query_form([]);
384              
385 0           @query_form = (
386             url => $uri->canonical,
387             ver => 1,
388             datum => 0,
389             unit => 0,
390             acry => 0,
391             number => 0,
392             );
393              
394 0 0         if ($method =~ /^A/) {
395             # A, ANY
396              
397 0           $uri = URI->new("device:gpsone");
398 0           $uri->query_form(\@query_form);
399              
400 0           $retcode = $uri->canonical;
401 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
402              
403 0           $retcode = "$desc\n";
404             } else {
405             # GET
406              
407 0           $retcode = "
\n";
408 0           $retcode .= "
409              
410 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
411 0           $retcode .= "
412             }
413 0           $retcode .= "\n";
414             }
415              
416 0           $retcode;
417             }
418              
419             # Method of sector location html descriptor
420              
421             sub _sector_description{
422 0     0     my $self = shift;
423 0           my ($uri,$desc,$method,$html) = @_;
424 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
425              
426             # POST is not allowed
427 0 0         return $self->set_err("Not support POST method location description") if ($method eq "POST");
428              
429 0           my $retcode;
430              
431              
432 0           my @query_form = $uri->query_form;
433 0 0         if (@query_form) {
434             # Parameters are not allowed
435              
436 0           $self->set_err("Parameters are not allowed, so they are discarded");
437             }
438 0           $uri->query_form([]);
439              
440 0           @query_form = (
441             url => $uri->canonical,
442             );
443              
444 0 0         if ($method =~ /^A/) {
445             # A, ANY
446              
447 0           $uri = URI->new("device:location");
448 0           $uri->query_form(\@query_form);
449              
450 0           $retcode = $uri->canonical;
451 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
452              
453 0           $retcode = "$desc\n";
454             } else {
455             # GET
456              
457 0           $retcode = "
\n";
458 0           $retcode .= "
459              
460 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
461 0           $retcode .= "
462             }
463 0           $retcode .= "\n";
464             }
465              
466 0           $retcode;
467             }
468              
469             # Method of location parser
470              
471             sub _parse_location{
472 0     0     my $self = shift;
473 0           my $q = $self->query;
474 0           my $loc;
475              
476 0 0 0       if (($q->param("lat")) && ($q->param("lon"))) {
477 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($q->param("lat"),$q->param("lon"),'wgs84','gpsone');
478 0 0         if (defined($q->param("fm"))) {
479             # gps
480              
481 0 0         $loc->accuracy($accuracy[$q->param("fm") < 2 ? $q->param("fm") : 2]);
482 0           $loc->mode("gps");
483             } else {
484             # sector
485              
486 0           $loc->accuracy($accuracy[2]);
487 0           $loc->mode("sector");
488             }
489             }
490 0           $loc;
491             }
492              
493             ##########################################
494             # SoftBank Module
495              
496             package # hide from PAUSE
497             HTTP::MobileAgent::Vodafone;
498              
499             # Method of gps location html descriptor
500              
501             sub _gps_description{
502 0     0     my $self = shift;
503 0           my ($uri,$desc,$method,$html,$cell) = @_;
504 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
505              
506 0 0         my $mode = $cell ? 'cell' : 'gps';
507              
508 0           my $retcode;
509              
510 0 0         if ($method =~ /^A/) {
511             # A, ANY
512              
513 0           my $query = $uri->query;
514 0           $uri->query_form([]);
515              
516 0           $retcode = "location:$mode?url=" . $uri->canonical;
517 0 0         $retcode .= "&$query" if ($query);
518 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
519              
520 0           $retcode = "$desc\n";
521             } else {
522             # POST, GET
523              
524 0           my @query_form = $uri->query_form;
525 0           $uri->query_form([]);
526 0           @query_form = (
527             url => $uri->canonical,
528             @query_form,
529             );
530              
531 0           $retcode = "
\n";
532 0           $retcode .= "
533              
534 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
535 0           $retcode .= "
536             }
537 0           $retcode .= "\n";
538             }
539              
540 0           $retcode;
541             }
542              
543             # Method of sector location html descriptor
544              
545             sub _sector_description{
546 0     0     my $self = shift;
547 0           my ($uri,$desc,$method,$html) = @_;
548 0           my ($tagend,$lcs,$z) = @{$corx{$html}};
  0            
549              
550 0           my $retcode;
551              
552 0 0         if ($self->is_type_3gc) {
553             # For 3G
554              
555 0           $retcode = $self->_gps_description($uri,$desc,$method,$html,1);
556             } else {
557             # For 2G
558              
559 0 0         if ($method =~ /^A/) {
560             # A, ANY
561              
562 0           $retcode = $uri->canonical;
563 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
564              
565 0           $retcode = "$desc\n";
566             } else {
567             # POST, GET
568              
569 0           my @query_form = $uri->query_form;
570 0           $uri->query_form([]);
571              
572 0           $retcode = "
canonical . "\" method=\"" . lc($method) . "\" $z>\n";
573 0           $retcode .= "
574              
575 0           while (my($key,$vals) = splice(@query_form, 0, 2)) {
576 0           $retcode .= "
577             }
578 0           $retcode .= "\n";
579             }
580             }
581              
582 0           $retcode;
583             }
584              
585             # Method of location parser
586              
587             sub _parse_location{
588 0     0     my $self = shift;
589 0           my $q = $self->query;
590 0           my $h = $self->get_header('x-jphone-geocode');
591 0           my $loc;
592              
593 0 0         if ($q->param("pos")) {
    0          
594             # 3G gps, sector parser
595              
596 0           $q->param("pos") =~ /^(N|S)([\d\.]+)(W|E)([\d\.]+)$/;
597 0 0         my $lat = (($1 eq 'S') ? "-" : "").$2;
598 0 0         my $long = (($3 eq 'W') ? "-" : "").$4;
599 0 0         my $geo = $q->param("geo") eq 'itrf' ? 'wgs84' : $q->param("geo");
600              
601 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,$geo,'gpsone');
602 0           $loc->accuracy($accuracy[3 - $q->param("x-acr")]);
603 0 0         $loc->mode($q->param("x-acr") == 1 ? "sector" : "gps");
604             } elsif ($h) {
605             # 2G sector parser
606              
607 0           my ($lat,$long,$addr) = split(/%1A/,$h);
608              
609 0 0 0       if (($lat =~ /^0+$/) || ($long =~ /^0+$/)) {
610             # Bad data
611              
612 0           return $self->set_err("Bad data error");
613             } else {
614 0           $lat =~ s/^(\d{2,3})(\d{2})(\d{2})$/$1.$2.$3.0/;
615 0           $long =~ s/^(\d{2,3})(\d{2})(\d{2})$/$1.$2.$3.0/;
616 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,'tokyo','gpsone');
617 0           $loc->accuracy($loc->mode("sector"));
618             }
619             }
620 0           $loc;
621             }
622              
623             ##########################################
624             # WILLCOM Module
625              
626             package # hide from PAUSE
627             HTTP::MobileAgent::AirHPhone;
628              
629             # Method of sector location html descriptor
630              
631             sub _sector_description{
632 0     0     my $self = shift;
633 0           my ($uri,$desc,$method,$html) = @_;
634              
635             # POST, GET are not allowed
636 0 0         return $self->set_err("Not support $method method location description") if ($method =~ /^(POST|GET)$/);
637              
638 0           my $retcode;
639 0           my $ah_uri = URI->new("");
640              
641 0           my $query = $uri->query;
642              
643 0           my @query_form = $uri->query_form;
644 0           $uri->query_form([]);
645              
646 0           $retcode = "http://location.request/dummy.cgi?my=" . URI::Escape::uri_escape($uri->canonical) . "&pos=\$location";
647 0 0         $retcode .= "&$query" if ($query);
648 0 0         $retcode =~ s/&/&/g if ($html eq "XHTML");
649              
650 0           $retcode = "$desc\n";
651              
652 0           $retcode;
653             }
654              
655             # Method of location parser
656              
657             sub _parse_location{
658 0     0     my $self = shift;
659 0           my $q = $self->query;
660 0           my $loc;
661              
662 0 0         if ($q->param("pos")) {
663 0           $q->param("pos") =~ /^(N|S)([\d\.]+)(W|E)([\d\.]+)$/;
664 0 0         my $lat = (($1 eq 'S') ? "-" : "").$2;
665 0 0         my $long = (($3 eq 'W') ? "-" : "").$4;
666              
667 0 0 0       if (($lat =~ /^[90\.]+$/) || ($long =~ /^[90\.]+$/)) {
668 0           return $self->set_err("Bad data error");
669             } else {
670 0           $loc = HTTP::MobileAgent::Plugin::Location::LocationObject->__create_coord($lat,$long,'tokyo','gpsone');
671 0           $loc->accuracy($loc->mode("sector"));
672             }
673             }
674 0           $loc;
675             }
676              
677             1; # Magic true value required at end of module
678             __END__