source: main/trunk/greenstone2/perllib/cpan/URI/_generic.pm@ 27174

Last change on this file since 27174 was 27174, checked in by davidb, 11 years ago

Perl modules from CPAN that are used in supporting activate.pl, but not part of the Perl core. Only PMs included.

File size: 5.6 KB
Line 
1package URI::_generic;
2require URI;
3require URI::_query;
4@ISA=qw(URI URI::_query);
5
6use strict;
7use URI::Escape qw(uri_unescape);
8use Carp ();
9
10my $ACHAR = $URI::uric; $ACHAR =~ s,\\[/?],,g;
11my $PCHAR = $URI::uric; $PCHAR =~ s,\\[?],,g;
12
13sub _no_scheme_ok { 1 }
14
15sub authority
16{
17 my $self = shift;
18 $$self =~ m,^((?:$URI::scheme_re:)?)(?://([^/?\#]*))?(.*)$,os or die;
19
20 if (@_) {
21 my $auth = shift;
22 $$self = $1;
23 my $rest = $3;
24 if (defined $auth) {
25 $auth =~ s/([^$ACHAR])/ URI::Escape::escape_char($1)/ego;
26 utf8::downgrade($auth);
27 $$self .= "//$auth";
28 }
29 _check_path($rest, $$self);
30 $$self .= $rest;
31 }
32 $2;
33}
34
35sub path
36{
37 my $self = shift;
38 $$self =~ m,^((?:[^:/?\#]+:)?(?://[^/?\#]*)?)([^?\#]*)(.*)$,s or die;
39
40 if (@_) {
41 $$self = $1;
42 my $rest = $3;
43 my $new_path = shift;
44 $new_path = "" unless defined $new_path;
45 $new_path =~ s/([^$PCHAR])/ URI::Escape::escape_char($1)/ego;
46 utf8::downgrade($new_path);
47 _check_path($new_path, $$self);
48 $$self .= $new_path . $rest;
49 }
50 $2;
51}
52
53sub path_query
54{
55 my $self = shift;
56 $$self =~ m,^((?:[^:/?\#]+:)?(?://[^/?\#]*)?)([^\#]*)(.*)$,s or die;
57
58 if (@_) {
59 $$self = $1;
60 my $rest = $3;
61 my $new_path = shift;
62 $new_path = "" unless defined $new_path;
63 $new_path =~ s/([^$URI::uric])/ URI::Escape::escape_char($1)/ego;
64 utf8::downgrade($new_path);
65 _check_path($new_path, $$self);
66 $$self .= $new_path . $rest;
67 }
68 $2;
69}
70
71sub _check_path
72{
73 my($path, $pre) = @_;
74 my $prefix;
75 if ($pre =~ m,/,) { # authority present
76 $prefix = "/" if length($path) && $path !~ m,^[/?\#],;
77 }
78 else {
79 if ($path =~ m,^//,) {
80 Carp::carp("Path starting with double slash is confusing")
81 if $^W;
82 }
83 elsif (!length($pre) && $path =~ m,^[^:/?\#]+:,) {
84 Carp::carp("Path might look like scheme, './' prepended")
85 if $^W;
86 $prefix = "./";
87 }
88 }
89 substr($_[0], 0, 0) = $prefix if defined $prefix;
90}
91
92sub path_segments
93{
94 my $self = shift;
95 my $path = $self->path;
96 if (@_) {
97 my @arg = @_; # make a copy
98 for (@arg) {
99 if (ref($_)) {
100 my @seg = @$_;
101 $seg[0] =~ s/%/%25/g;
102 for (@seg) { s/;/%3B/g; }
103 $_ = join(";", @seg);
104 }
105 else {
106 s/%/%25/g; s/;/%3B/g;
107 }
108 s,/,%2F,g;
109 }
110 $self->path(join("/", @arg));
111 }
112 return $path unless wantarray;
113 map {/;/ ? $self->_split_segment($_)
114 : uri_unescape($_) }
115 split('/', $path, -1);
116}
117
118
119sub _split_segment
120{
121 my $self = shift;
122 require URI::_segment;
123 URI::_segment->new(@_);
124}
125
126
127sub abs
128{
129 my $self = shift;
130 my $base = shift || Carp::croak("Missing base argument");
131
132 if (my $scheme = $self->scheme) {
133 return $self unless $URI::ABS_ALLOW_RELATIVE_SCHEME;
134 $base = URI->new($base) unless ref $base;
135 return $self unless $scheme eq $base->scheme;
136 }
137
138 $base = URI->new($base) unless ref $base;
139 my $abs = $self->clone;
140 $abs->scheme($base->scheme);
141 return $abs if $$self =~ m,^(?:$URI::scheme_re:)?//,o;
142 $abs->authority($base->authority);
143
144 my $path = $self->path;
145 return $abs if $path =~ m,^/,;
146
147 if (!length($path)) {
148 my $abs = $base->clone;
149 my $query = $self->query;
150 $abs->query($query) if defined $query;
151 $abs->fragment($self->fragment);
152 return $abs;
153 }
154
155 my $p = $base->path;
156 $p =~ s,[^/]+$,,;
157 $p .= $path;
158 my @p = split('/', $p, -1);
159 shift(@p) if @p && !length($p[0]);
160 my $i = 1;
161 while ($i < @p) {
162 #print "$i ", join("/", @p), " ($p[$i])\n";
163 if ($p[$i-1] eq ".") {
164 splice(@p, $i-1, 1);
165 $i-- if $i > 1;
166 }
167 elsif ($p[$i] eq ".." && $p[$i-1] ne "..") {
168 splice(@p, $i-1, 2);
169 if ($i > 1) {
170 $i--;
171 push(@p, "") if $i == @p;
172 }
173 }
174 else {
175 $i++;
176 }
177 }
178 $p[-1] = "" if @p && $p[-1] eq "."; # trailing "/."
179 if ($URI::ABS_REMOTE_LEADING_DOTS) {
180 shift @p while @p && $p[0] =~ /^\.\.?$/;
181 }
182 $abs->path("/" . join("/", @p));
183 $abs;
184}
185
186# The opposite of $url->abs. Return a URI which is as relative as possible
187sub rel {
188 my $self = shift;
189 my $base = shift || Carp::croak("Missing base argument");
190 my $rel = $self->clone;
191 $base = URI->new($base) unless ref $base;
192
193 #my($scheme, $auth, $path) = @{$rel}{qw(scheme authority path)};
194 my $scheme = $rel->scheme;
195 my $auth = $rel->canonical->authority;
196 my $path = $rel->path;
197
198 if (!defined($scheme) && !defined($auth)) {
199 # it is already relative
200 return $rel;
201 }
202
203 #my($bscheme, $bauth, $bpath) = @{$base}{qw(scheme authority path)};
204 my $bscheme = $base->scheme;
205 my $bauth = $base->canonical->authority;
206 my $bpath = $base->path;
207
208 for ($bscheme, $bauth, $auth) {
209 $_ = '' unless defined
210 }
211
212 unless ($scheme eq $bscheme && $auth eq $bauth) {
213 # different location, can't make it relative
214 return $rel;
215 }
216
217 for ($path, $bpath) { $_ = "/$_" unless m,^/,; }
218
219 # Make it relative by eliminating scheme and authority
220 $rel->scheme(undef);
221 $rel->authority(undef);
222
223 # This loop is based on code from Nicolai Langfeldt <[email protected]>.
224 # First we calculate common initial path components length ($li).
225 my $li = 1;
226 while (1) {
227 my $i = index($path, '/', $li);
228 last if $i < 0 ||
229 $i != index($bpath, '/', $li) ||
230 substr($path,$li,$i-$li) ne substr($bpath,$li,$i-$li);
231 $li=$i+1;
232 }
233 # then we nuke it from both paths
234 substr($path, 0,$li) = '';
235 substr($bpath,0,$li) = '';
236
237 if ($path eq $bpath &&
238 defined($rel->fragment) &&
239 !defined($rel->query)) {
240 $rel->path("");
241 }
242 else {
243 # Add one "../" for each path component left in the base path
244 $path = ('../' x $bpath =~ tr|/|/|) . $path;
245 $path = "./" if $path eq "";
246 $rel->path($path);
247 }
248
249 $rel;
250}
251
2521;
Note: See TracBrowser for help on using the repository browser.