line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Repository::Simple::Util; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
4
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
40
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.06'; |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
80
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
5
|
use Exporter; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
572
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our @ISA = qw( Exporter ); |
13
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
14
|
|
|
|
|
|
|
normalize_path |
15
|
|
|
|
|
|
|
basename |
16
|
|
|
|
|
|
|
dirname |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our @CARP_NOT = qw( |
20
|
|
|
|
|
|
|
Repository::Simple::Engine |
21
|
|
|
|
|
|
|
Repository::Simple::Node |
22
|
|
|
|
|
|
|
Repository::Simple::Permission |
23
|
|
|
|
|
|
|
Repository::Simple::Property |
24
|
|
|
|
|
|
|
Repository::Simple::Type::Node |
25
|
|
|
|
|
|
|
Repository::Simple::Type::Property |
26
|
|
|
|
|
|
|
Repository::Simple::Type::Value |
27
|
|
|
|
|
|
|
Repository::Simple::Value |
28
|
|
|
|
|
|
|
Repository::Simple |
29
|
|
|
|
|
|
|
); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 NAME |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
Repository::Simple::Util - Utility methods shared by repository components |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 SYNOPSIS |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
use Repository::Simple::Util qw( normalize_path dirname basename ); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
my $clean_path = normalize_path("/usr", "../messy/../.././///messy/path"); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $dirname = dirname("/foo/bar/baz"); # returns "/foo/bar" |
42
|
|
|
|
|
|
|
my $basename = basename("/foo/bar/baz"); # returns "baz" |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 DESCRIPTION |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
The methods here are for use by the content repository and content repository engines internally. Unless you are extending the repository system, you will probably want to avoid the use of these methods. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 METHODS |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=over |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item $clean_path = normalize_path($current_path, $messy_path) |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
This method creates a "normal" path out of the given "messy" path, C<$messy_path>. In case the C<$messy_path> is relative, the C<$current_path> gives the absolute path we're working from. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
It provides the following: |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=over |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item 1. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
If the messy path is relative, this method merges the messy path and the current path to create an absolute path. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=item 2. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
All superfluous "." and ".." elements will be stripped from the path so that the resulting path will be the most concise and direct name for the named file. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=item 3. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Enforces the principle that ".." applied to the root returns the root. This provides security by preventing users from getting to a file outside of the root. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=back |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub normalize_path { |
77
|
0
|
|
|
0
|
1
|
|
my ($current_path, $messy_path) = @_; |
78
|
|
|
|
|
|
|
|
79
|
0
|
0
|
|
|
|
|
if (!defined $current_path) { |
80
|
0
|
|
|
|
|
|
croak "normalize_path must be given a current path"; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
0
|
0
|
|
|
|
|
if (!defined $messy_path) { |
84
|
0
|
|
|
|
|
|
croak "normalize_path must be given a messy path"; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Fix us up to an absolute path |
88
|
0
|
|
|
|
|
|
my $abs_path; |
89
|
0
|
0
|
|
|
|
|
if ($messy_path !~ m#^/#) { |
90
|
0
|
|
|
|
|
|
$abs_path = "$current_path/$messy_path"; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
else { |
93
|
0
|
|
|
|
|
|
$abs_path = $messy_path; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Break into components |
97
|
0
|
|
|
|
|
|
my @components = split m#/+#, $abs_path; |
98
|
0
|
0
|
|
|
|
|
@components = ('', '') unless @components; # account for root |
99
|
0
|
0
|
|
|
|
|
unshift @components, '' unless @components > 1; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Manipulate the path components based upon each entry, work left-to-right |
102
|
|
|
|
|
|
|
# to ensure proper handling of each component. |
103
|
0
|
|
|
|
|
|
for (my $i = 1; $i < @components;) { |
104
|
|
|
|
|
|
|
# Drop any "." components |
105
|
0
|
0
|
0
|
|
|
|
if ($components[$i] eq '.') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
splice @components, $i, 1; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Drop any ".." that go above root |
110
|
|
|
|
|
|
|
elsif ($components[$i] eq '..' && $i == 1) { |
111
|
0
|
|
|
|
|
|
splice @components, $i, 1; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Drop any ".." and the component above |
115
|
|
|
|
|
|
|
elsif ($components[$i] eq '..') { |
116
|
0
|
|
|
|
|
|
splice @components, ($i - 1), 2; |
117
|
0
|
|
|
|
|
|
$i--; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Otherwise, do nothing and move on to the next element |
121
|
|
|
|
|
|
|
else { |
122
|
0
|
|
|
|
|
|
$i++; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Make sure to tack on an empty "" in case we're back to root |
127
|
0
|
0
|
|
|
|
|
unshift @components, '' unless @components > 1; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Reassemble the result |
130
|
0
|
|
|
|
|
|
return join '/', @components; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item $dirname = dirname($path) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Given a normalized path, this returns the path with the last element stripped. That is, it returns the parent of the given path. If the root path ("/") is given, then the same path is returned. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=cut |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub dirname { |
140
|
0
|
|
|
0
|
1
|
|
my $path = shift; |
141
|
|
|
|
|
|
|
|
142
|
0
|
0
|
|
|
|
|
if ($path eq '/') { |
143
|
0
|
|
|
|
|
|
return '/'; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
else { |
147
|
0
|
|
|
|
|
|
my @components = split m{/}, $path; |
148
|
0
|
|
|
|
|
|
pop @components; |
149
|
0
|
0
|
|
|
|
|
push @components, '' if @components == 1; |
150
|
0
|
|
|
|
|
|
return join '/', @components; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item $basename = basename($path) |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Given a normalized path, this method returns the last path element of the path. That is, it returns the last name in the path. If the root path ("/") is given, then the same is returned. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub basename { |
161
|
0
|
|
|
0
|
1
|
|
my $path = shift; |
162
|
|
|
|
|
|
|
|
163
|
0
|
0
|
|
|
|
|
if ($path eq '/') { |
164
|
0
|
|
|
|
|
|
return '/'; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
else { |
168
|
0
|
|
|
|
|
|
my @components = split m{/}, $path; |
169
|
0
|
|
|
|
|
|
return pop @components; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=back |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 AUTHOR |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Andrew Sterling Hanenkamp, Ehanenkamp@cpan.orgE |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Copyright 2005 Andrew Sterling Hanenkamp Ehanenkamp@cpan.orgE. All |
182
|
|
|
|
|
|
|
Rights Reserved. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it under |
185
|
|
|
|
|
|
|
the same terms as Perl itself. See L. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT |
188
|
|
|
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
189
|
|
|
|
|
|
|
FOR A PARTICULAR PURPOSE. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=cut |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
1 |