line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Fetchware; |
2
|
|
|
|
|
|
|
our $VERSION = '1.016'; # VERSION: generated by DZP::OurPkgVersion |
3
|
|
|
|
|
|
|
# ABSTRACT: App::Fetchware is Fetchware's API used to make extensions. |
4
|
|
|
|
|
|
|
###BUGALERT### Uses die instead of croak. croak is the preferred way of throwing |
5
|
|
|
|
|
|
|
#exceptions in modules. croak says that the caller was the one who caused the |
6
|
|
|
|
|
|
|
#error not the specific code that actually threw the error. |
7
|
50
|
|
|
50
|
|
82551
|
use strict; |
|
50
|
|
|
|
|
73
|
|
|
50
|
|
|
|
|
1516
|
|
8
|
50
|
|
|
50
|
|
180
|
use warnings; |
|
50
|
|
|
|
|
62
|
|
|
50
|
|
|
|
|
1536
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# CPAN modules making Fetchwarefile better. |
11
|
50
|
|
|
50
|
|
942
|
use File::Spec::Functions qw(catfile splitpath splitdir file_name_is_absolute); |
|
50
|
|
|
|
|
1149
|
|
|
50
|
|
|
|
|
2871
|
|
12
|
50
|
|
|
50
|
|
919
|
use Path::Class; |
|
50
|
|
|
|
|
57792
|
|
|
50
|
|
|
|
|
2016
|
|
13
|
50
|
|
|
50
|
|
1188
|
use Data::Dumper; |
|
50
|
|
|
|
|
9177
|
|
|
50
|
|
|
|
|
1775
|
|
14
|
50
|
|
|
50
|
|
1003
|
use File::Copy 'cp'; |
|
50
|
|
|
|
|
3102
|
|
|
50
|
|
|
|
|
1630
|
|
15
|
50
|
|
|
50
|
|
31450
|
use HTML::TreeBuilder; |
|
50
|
|
|
|
|
1150126
|
|
|
50
|
|
|
|
|
442
|
|
16
|
50
|
|
|
50
|
|
1905
|
use Scalar::Util qw(blessed looks_like_number); |
|
50
|
|
|
|
|
77
|
|
|
50
|
|
|
|
|
3303
|
|
17
|
50
|
|
|
50
|
|
27292
|
use Digest::SHA; |
|
50
|
|
|
|
|
101551
|
|
|
50
|
|
|
|
|
2019
|
|
18
|
50
|
|
|
50
|
|
286
|
use Digest::MD5; |
|
50
|
|
|
|
|
76
|
|
|
50
|
|
|
|
|
1324
|
|
19
|
|
|
|
|
|
|
#use Crypt::OpenPGP::KeyRing; |
20
|
|
|
|
|
|
|
#use Crypt::OpenPGP; |
21
|
50
|
|
|
50
|
|
1427
|
use Archive::Tar; |
|
50
|
|
|
|
|
116754
|
|
|
50
|
|
|
|
|
2463
|
|
22
|
50
|
|
|
50
|
|
27596
|
use Archive::Zip qw(:ERROR_CODES :CONSTANTS); |
|
50
|
|
|
|
|
1624600
|
|
|
50
|
|
|
|
|
6443
|
|
23
|
50
|
|
|
50
|
|
349
|
use Cwd 'cwd'; |
|
50
|
|
|
|
|
185
|
|
|
50
|
|
|
|
|
1744
|
|
24
|
50
|
|
|
50
|
|
1017
|
use Sub::Mage; |
|
50
|
|
|
|
|
10110
|
|
|
50
|
|
|
|
|
551
|
|
25
|
50
|
|
|
50
|
|
8858
|
use URI::Split qw(uri_split uri_join); |
|
50
|
|
|
|
|
3439
|
|
|
50
|
|
|
|
|
3505
|
|
26
|
50
|
|
|
50
|
|
1026
|
use Text::ParseWords 'quotewords'; |
|
50
|
|
|
|
|
1772
|
|
|
50
|
|
|
|
|
1820
|
|
27
|
50
|
|
|
50
|
|
188
|
use File::Temp 'tempfile'; |
|
50
|
|
|
|
|
54
|
|
|
50
|
|
|
|
|
1629
|
|
28
|
50
|
|
|
50
|
|
22201
|
use Term::ReadLine; |
|
50
|
|
|
|
|
95047
|
|
|
50
|
|
|
|
|
1286
|
|
29
|
50
|
|
|
50
|
|
20603
|
use Term::UI; |
|
50
|
|
|
|
|
837719
|
|
|
50
|
|
|
|
|
1873
|
|
30
|
|
|
|
|
|
|
|
31
|
50
|
|
|
50
|
|
2148
|
use App::Fetchware::Util ':UTIL'; |
|
50
|
|
|
|
|
77
|
|
|
50
|
|
|
|
|
11970
|
|
32
|
50
|
|
|
50
|
|
303
|
use App::Fetchware::Config ':CONFIG'; |
|
50
|
|
|
|
|
73
|
|
|
50
|
|
|
|
|
5547
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Enable Perl 6 knockoffs, and use 5.10.1, because smartmatching and other |
35
|
|
|
|
|
|
|
# things in 5.10 were changed in 5.10.1+. |
36
|
50
|
|
|
50
|
|
1402
|
use 5.010001; |
|
50
|
|
|
|
|
154
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# Set up Exporter to bring App::Fetchware's API to everyone who use's it |
39
|
|
|
|
|
|
|
# including fetchware's ability to let you rip into its guts, and customize it |
40
|
|
|
|
|
|
|
# as you need. |
41
|
50
|
|
|
50
|
|
233
|
use Exporter qw( import ); |
|
50
|
|
|
|
|
53
|
|
|
50
|
|
|
|
|
509596
|
|
42
|
|
|
|
|
|
|
# By default fetchware exports its configuration file like subroutines. |
43
|
|
|
|
|
|
|
# |
44
|
|
|
|
|
|
|
# These days popular dogma considers it bad to import stuff without being asked |
45
|
|
|
|
|
|
|
# to do so, but App::Fetchware is meant to be a configuration file that is both |
46
|
|
|
|
|
|
|
# human readable, and most importantly flexible enough to allow customization. |
47
|
|
|
|
|
|
|
# This is done by making the configuration file a perl source code file called a |
48
|
|
|
|
|
|
|
# Fetchwarefile that fetchware simply executes with eval. |
49
|
|
|
|
|
|
|
our @EXPORT = qw( |
50
|
|
|
|
|
|
|
program |
51
|
|
|
|
|
|
|
filter |
52
|
|
|
|
|
|
|
temp_dir |
53
|
|
|
|
|
|
|
fetchware_db_path |
54
|
|
|
|
|
|
|
user |
55
|
|
|
|
|
|
|
prefix |
56
|
|
|
|
|
|
|
configure_options |
57
|
|
|
|
|
|
|
make_options |
58
|
|
|
|
|
|
|
build_commands |
59
|
|
|
|
|
|
|
install_commands |
60
|
|
|
|
|
|
|
uninstall_commands |
61
|
|
|
|
|
|
|
lookup_url |
62
|
|
|
|
|
|
|
lookup_method |
63
|
|
|
|
|
|
|
gpg_keys_url |
64
|
|
|
|
|
|
|
gpg_sig_url |
65
|
|
|
|
|
|
|
sha1_url |
66
|
|
|
|
|
|
|
md5_url |
67
|
|
|
|
|
|
|
user_agent |
68
|
|
|
|
|
|
|
verify_method |
69
|
|
|
|
|
|
|
no_install |
70
|
|
|
|
|
|
|
verify_failure_ok |
71
|
|
|
|
|
|
|
user_keyring |
72
|
|
|
|
|
|
|
stay_root |
73
|
|
|
|
|
|
|
mirror |
74
|
|
|
|
|
|
|
config |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
new |
77
|
|
|
|
|
|
|
new_install |
78
|
|
|
|
|
|
|
check_syntax |
79
|
|
|
|
|
|
|
start |
80
|
|
|
|
|
|
|
lookup |
81
|
|
|
|
|
|
|
download |
82
|
|
|
|
|
|
|
verify |
83
|
|
|
|
|
|
|
unarchive |
84
|
|
|
|
|
|
|
build |
85
|
|
|
|
|
|
|
install |
86
|
|
|
|
|
|
|
end |
87
|
|
|
|
|
|
|
uninstall |
88
|
|
|
|
|
|
|
upgrade |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
hook |
91
|
|
|
|
|
|
|
); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# These tags allow you to replace some or all of fetchware's default behavior to |
94
|
|
|
|
|
|
|
# install unusual software. |
95
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
96
|
|
|
|
|
|
|
# No OVERRIDE_START OVERRIDE_END because start() does *not* use any helper |
97
|
|
|
|
|
|
|
# subs that could be beneficial to override()rs. |
98
|
|
|
|
|
|
|
OVERRIDE_NEW => [qw( |
99
|
|
|
|
|
|
|
extension_name |
100
|
|
|
|
|
|
|
fetchwarefile_name |
101
|
|
|
|
|
|
|
opening_message |
102
|
|
|
|
|
|
|
get_lookup_url |
103
|
|
|
|
|
|
|
download_lookup_url |
104
|
|
|
|
|
|
|
get_mirrors |
105
|
|
|
|
|
|
|
get_verification |
106
|
|
|
|
|
|
|
get_filter_option |
107
|
|
|
|
|
|
|
append_to_fetchwarefile |
108
|
|
|
|
|
|
|
prompt_for_other_options |
109
|
|
|
|
|
|
|
append_options_to_fetchwarefile |
110
|
|
|
|
|
|
|
edit_manually |
111
|
|
|
|
|
|
|
)], |
112
|
|
|
|
|
|
|
OVERRIDE_NEW_INSTALL => [qw( |
113
|
|
|
|
|
|
|
ask_to_install_now_to_test_fetchwarefile |
114
|
|
|
|
|
|
|
)], |
115
|
|
|
|
|
|
|
OVERRIDE_CHECK_SYNTAX => [qw( |
116
|
|
|
|
|
|
|
check_config_options |
117
|
|
|
|
|
|
|
)], |
118
|
|
|
|
|
|
|
OVERRIDE_LOOKUP => [qw( |
119
|
|
|
|
|
|
|
get_directory_listing |
120
|
|
|
|
|
|
|
parse_directory_listing |
121
|
|
|
|
|
|
|
determine_download_path |
122
|
|
|
|
|
|
|
ftp_parse_filelist |
123
|
|
|
|
|
|
|
http_parse_filelist |
124
|
|
|
|
|
|
|
file_parse_filelist |
125
|
|
|
|
|
|
|
lookup_by_timestamp |
126
|
|
|
|
|
|
|
lookup_by_versionstring |
127
|
|
|
|
|
|
|
lookup_determine_downloadpath |
128
|
|
|
|
|
|
|
)], |
129
|
|
|
|
|
|
|
OVERRIDE_DOWNLOAD => [qw( |
130
|
|
|
|
|
|
|
determine_package_path |
131
|
|
|
|
|
|
|
)], |
132
|
|
|
|
|
|
|
OVERRIDE_VERIFY => [qw( |
133
|
|
|
|
|
|
|
gpg_verify |
134
|
|
|
|
|
|
|
sha1_verify |
135
|
|
|
|
|
|
|
md5_verify |
136
|
|
|
|
|
|
|
digest_verify |
137
|
|
|
|
|
|
|
)], |
138
|
|
|
|
|
|
|
OVERRIDE_UNARCHIVE => [qw( |
139
|
|
|
|
|
|
|
check_archive_files |
140
|
|
|
|
|
|
|
list_files |
141
|
|
|
|
|
|
|
list_files_tar |
142
|
|
|
|
|
|
|
list_files_zip |
143
|
|
|
|
|
|
|
unarchive_package |
144
|
|
|
|
|
|
|
unarchive_tar |
145
|
|
|
|
|
|
|
unarchive_zip |
146
|
|
|
|
|
|
|
)], |
147
|
|
|
|
|
|
|
OVERRIDE_BUILD => [qw( |
148
|
|
|
|
|
|
|
run_star_commands |
149
|
|
|
|
|
|
|
run_configure |
150
|
|
|
|
|
|
|
)], |
151
|
|
|
|
|
|
|
OVERRIDE_INSTALL => [qw( |
152
|
|
|
|
|
|
|
chdir_unless_already_at_path |
153
|
|
|
|
|
|
|
)], |
154
|
|
|
|
|
|
|
OVERRIDE_UNINSTALL => [qw()], |
155
|
|
|
|
|
|
|
OVERRIDE_UPGRADE => [qw()], |
156
|
|
|
|
|
|
|
); |
157
|
|
|
|
|
|
|
# OVERRIDE_ALL is simply all other tags combined. |
158
|
|
|
|
|
|
|
@{$EXPORT_TAGS{OVERRIDE_ALL}} = map {@{$_}} values %EXPORT_TAGS; |
159
|
|
|
|
|
|
|
# *All* entries in @EXPORT_TAGS must also be in @EXPORT_OK. |
160
|
|
|
|
|
|
|
our @EXPORT_OK = @{$EXPORT_TAGS{OVERRIDE_ALL}}; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
###BUGALERT### Add strict argument checking to App::Fetchware's API subroutines |
166
|
|
|
|
|
|
|
#to check for not being called correctly to aid extension debugging. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
###BUGALERT### Recommend installing http://gpg4win.org if you use fetchware on |
171
|
|
|
|
|
|
|
# Windows so you have gpg support. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# _make_config_sub() is an internal subroutine that only App::Fetchware and |
179
|
|
|
|
|
|
|
# App::Fetchware::CreateConfigOptions should use. Use |
180
|
|
|
|
|
|
|
# App::Fetchware::CreateConfigOptions to create any configuration option |
181
|
|
|
|
|
|
|
# subroutines that you want your fetchware extensions to have. |
182
|
|
|
|
|
|
|
#=head2 _make_config_sub() |
183
|
|
|
|
|
|
|
# |
184
|
|
|
|
|
|
|
# _make_config_sub($name, $one_or_many_values) |
185
|
|
|
|
|
|
|
# |
186
|
|
|
|
|
|
|
#A function factory that builds many functions that are the exact same, but have |
187
|
|
|
|
|
|
|
#different names. It supports three types of functions determined by |
188
|
|
|
|
|
|
|
#_make_config_sub()'s second parameter. It's first parameter is the name of that |
189
|
|
|
|
|
|
|
#function. This is the subroutine that builds all of Fetchwarefile's |
190
|
|
|
|
|
|
|
#configuration subroutines such as lookupurl, mirror, fetchware, etc.... |
191
|
|
|
|
|
|
|
# |
192
|
|
|
|
|
|
|
#=over |
193
|
|
|
|
|
|
|
#=item LIMITATION |
194
|
|
|
|
|
|
|
# |
195
|
|
|
|
|
|
|
#_make_config_sub() creates subroutines that have prototypes, but in order for |
196
|
|
|
|
|
|
|
#perl to honor those prototypes perl B know about them at compile-time; |
197
|
|
|
|
|
|
|
#therefore, that is why _make_config_sub() must be called inside a C block. |
198
|
|
|
|
|
|
|
# |
199
|
|
|
|
|
|
|
#=back |
200
|
|
|
|
|
|
|
# |
201
|
|
|
|
|
|
|
#=over |
202
|
|
|
|
|
|
|
#=item NOTE |
203
|
|
|
|
|
|
|
#_make_config_sub() uses caller to determine the package that _make_config_sub() |
204
|
|
|
|
|
|
|
#was called from. This package is then prepended to the string that is eval'd to |
205
|
|
|
|
|
|
|
#create the designated subroutine in the caller's package. This is needed so that |
206
|
|
|
|
|
|
|
#App::Fetchware "subclasses" can import this function, and enjoy its simple |
207
|
|
|
|
|
|
|
#interface to create custom configuration subroutines. |
208
|
|
|
|
|
|
|
# |
209
|
|
|
|
|
|
|
#=back |
210
|
|
|
|
|
|
|
# |
211
|
|
|
|
|
|
|
#=over |
212
|
|
|
|
|
|
|
# |
213
|
|
|
|
|
|
|
#=item $one_or_many_values Supported Values |
214
|
|
|
|
|
|
|
# |
215
|
|
|
|
|
|
|
#=over |
216
|
|
|
|
|
|
|
# |
217
|
|
|
|
|
|
|
#=item * 'ONE' |
218
|
|
|
|
|
|
|
# |
219
|
|
|
|
|
|
|
#Generates a function with the name of _make_config_sub()'s first parameter that |
220
|
|
|
|
|
|
|
#can B be called one time per Fetchwarefile. If called more than one time |
221
|
|
|
|
|
|
|
#will die with an error message. |
222
|
|
|
|
|
|
|
# |
223
|
|
|
|
|
|
|
#Function created with C<$CONFIG{$name} = $value;> inside the generated function that |
224
|
|
|
|
|
|
|
#is named $name. |
225
|
|
|
|
|
|
|
# |
226
|
|
|
|
|
|
|
#=item * 'ONEARRREF' |
227
|
|
|
|
|
|
|
# |
228
|
|
|
|
|
|
|
#Generates a function with the name of _make_config_sub()'s first parameter that |
229
|
|
|
|
|
|
|
#can B be called one time per Fetchwarefile. And just like C<'ONE'> above |
230
|
|
|
|
|
|
|
#if called more than once it will throw an exception. However, C<'ONEARRREF'> can |
231
|
|
|
|
|
|
|
#be called with a list of values just like C<'MANY'> can, but it can still only |
232
|
|
|
|
|
|
|
#be called once like C<'ONE'>. |
233
|
|
|
|
|
|
|
# |
234
|
|
|
|
|
|
|
#=item * 'MANY' |
235
|
|
|
|
|
|
|
# |
236
|
|
|
|
|
|
|
#Generates a function with the name of _make_config_sub()'s first parameter that |
237
|
|
|
|
|
|
|
#can be called more than just once. This option is only used by fetchware's |
238
|
|
|
|
|
|
|
#C API call. |
239
|
|
|
|
|
|
|
# |
240
|
|
|
|
|
|
|
#Function created with C inside the generated function that |
241
|
|
|
|
|
|
|
#is named $name. |
242
|
|
|
|
|
|
|
# |
243
|
|
|
|
|
|
|
#=item * 'BOOLEAN' |
244
|
|
|
|
|
|
|
# |
245
|
|
|
|
|
|
|
#Generates a function with the name of _make_config_sub()'s first parameter that |
246
|
|
|
|
|
|
|
#can be called only once just like 'ONE' can be, but it also only support true or |
247
|
|
|
|
|
|
|
#false values. What is true and false is the same as in perl, with the exception |
248
|
|
|
|
|
|
|
#that /false/i and /off/i are also false. |
249
|
|
|
|
|
|
|
# |
250
|
|
|
|
|
|
|
#Function created the same way as 'ONE''s are, but with /false/i and /off/i |
251
|
|
|
|
|
|
|
#mutated into a Perl accepted false value (they're turned into zeros.). |
252
|
|
|
|
|
|
|
# |
253
|
|
|
|
|
|
|
#=back |
254
|
|
|
|
|
|
|
# |
255
|
|
|
|
|
|
|
#=back |
256
|
|
|
|
|
|
|
# |
257
|
|
|
|
|
|
|
#All API subroutines fetchware provides to Fetchwarefile's are generated by |
258
|
|
|
|
|
|
|
#_make_config_sub() except for fetchware() and override(). |
259
|
|
|
|
|
|
|
# |
260
|
|
|
|
|
|
|
#=cut |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
my @api_functions = ( |
263
|
|
|
|
|
|
|
[ program => 'ONE' ], |
264
|
|
|
|
|
|
|
[ filter => 'ONE' ], |
265
|
|
|
|
|
|
|
[ temp_dir => 'ONE' ], |
266
|
|
|
|
|
|
|
[ fetchware_db_path => 'ONE' ], |
267
|
|
|
|
|
|
|
[ user => 'ONE' ], |
268
|
|
|
|
|
|
|
[ prefix => 'ONE' ], |
269
|
|
|
|
|
|
|
[ configure_options=> 'ONEARRREF' ], |
270
|
|
|
|
|
|
|
[ make_options => 'ONEARRREF' ], |
271
|
|
|
|
|
|
|
[ build_commands => 'ONEARRREF' ], |
272
|
|
|
|
|
|
|
[ install_commands => 'ONEARRREF' ], |
273
|
|
|
|
|
|
|
[ uninstall_commands => 'ONEARRREF' ], |
274
|
|
|
|
|
|
|
[ lookup_url => 'ONE' ], |
275
|
|
|
|
|
|
|
[ lookup_method => 'ONE' ], |
276
|
|
|
|
|
|
|
[ gpg_keys_url => 'ONE' ], |
277
|
|
|
|
|
|
|
[ gpg_sig_url => 'ONE' ], |
278
|
|
|
|
|
|
|
[ sha1_url => 'ONE' ], |
279
|
|
|
|
|
|
|
[ md5_url => 'ONE' ], |
280
|
|
|
|
|
|
|
[ user_agent => 'ONE' ], |
281
|
|
|
|
|
|
|
[ verify_method => 'ONE' ], |
282
|
|
|
|
|
|
|
[ mirror => 'MANY' ], |
283
|
|
|
|
|
|
|
[ no_install => 'BOOLEAN' ], |
284
|
|
|
|
|
|
|
[ verify_failure_ok => 'BOOLEAN' ], |
285
|
|
|
|
|
|
|
[ stay_root => 'BOOLEAN' ], |
286
|
|
|
|
|
|
|
[ user_keyring => 'BOOLEAN' ], |
287
|
|
|
|
|
|
|
); |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Loop over the list of options needed by _make_config_sub() to generated the |
291
|
|
|
|
|
|
|
# needed API functions for Fetchwarefile. |
292
|
|
|
|
|
|
|
for my $api_function (@api_functions) { |
293
|
|
|
|
|
|
|
_make_config_sub(@{$api_function}); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub _make_config_sub { |
298
|
1276
|
|
|
1276
|
|
1265
|
my ($name, $one_or_many_values, $callers_package) = @_; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# Obtain caller's package name, so that the new configuration subroutine |
301
|
|
|
|
|
|
|
# can be created in the caller's package instead of our own. Use the |
302
|
|
|
|
|
|
|
# specifed $callers_package if the caller specified one. This allows |
303
|
|
|
|
|
|
|
# create_config_options() to reuse _make_config_sub() by passing in its |
304
|
|
|
|
|
|
|
# caller to _make_config_sub(). |
305
|
1276
|
|
66
|
|
|
3966
|
my $package = $callers_package // caller; |
306
|
|
|
|
|
|
|
|
307
|
1276
|
50
|
|
|
|
1743
|
die <
|
308
|
|
|
|
|
|
|
App-Fetchware: internal syntax error: _make_config_sub() was called without a |
309
|
|
|
|
|
|
|
name. It must receive a name parameter as its first paramter. See perldoc |
310
|
|
|
|
|
|
|
App::Fetchware. |
311
|
|
|
|
|
|
|
EOD |
312
|
1276
|
50
|
100
|
|
|
4161
|
unless ($one_or_many_values eq 'ONE' |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
313
|
|
|
|
|
|
|
or $one_or_many_values eq 'ONEARRREF', |
314
|
|
|
|
|
|
|
or $one_or_many_values eq 'MANY' |
315
|
|
|
|
|
|
|
or $one_or_many_values eq 'BOOLEAN') { |
316
|
0
|
|
|
|
|
0
|
die <
|
317
|
|
|
|
|
|
|
App-Fetchware: internal syntax error: _make_config_sub() was called without a |
318
|
|
|
|
|
|
|
one_or_many_values parameter as its second parameter. Or the parameter it was |
319
|
|
|
|
|
|
|
called with was invalid. Only 'ONE', 'MANY', and 'BOOLEAN' are acceptable |
320
|
|
|
|
|
|
|
values. See perldoc App::Fetchware. |
321
|
|
|
|
|
|
|
EOD |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
1276
|
100
|
|
|
|
2422
|
if ($one_or_many_values eq 'ONE') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
325
|
724
|
|
|
|
|
669
|
my $eval = <<'EOE'; |
326
|
|
|
|
|
|
|
package $package; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub $name (@) { |
329
|
|
|
|
|
|
|
my $value = shift; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
die <
|
332
|
|
|
|
|
|
|
App-Fetchware: internal syntax error: $name was called more than once in this |
333
|
|
|
|
|
|
|
Fetchwarefile. Currently only mirror supports being used more than once in a |
334
|
|
|
|
|
|
|
Fetchwarefile, but you have used $name more than once. Please remove all calls |
335
|
|
|
|
|
|
|
to $name but one. See perldoc App::Fetchware. |
336
|
|
|
|
|
|
|
EOD |
337
|
|
|
|
|
|
|
unless (@_) { |
338
|
|
|
|
|
|
|
config('$name', $value); |
339
|
|
|
|
|
|
|
} else { |
340
|
|
|
|
|
|
|
die <
|
341
|
|
|
|
|
|
|
App-Fetchware: internal syntax error. $name was called with more than one |
342
|
|
|
|
|
|
|
option. $name only supports just one option such as '$name 'option';'. It does |
343
|
|
|
|
|
|
|
not support more than one option such as '$name 'option', 'another option';'. |
344
|
|
|
|
|
|
|
Please chose one option not both, or combine both into one option. See perldoc |
345
|
|
|
|
|
|
|
App::Fetchware. |
346
|
|
|
|
|
|
|
EOD |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
1; # return true from eval |
350
|
|
|
|
|
|
|
EOE |
351
|
724
|
|
|
|
|
5140
|
$eval =~ s/\$name/$name/g; |
352
|
724
|
|
|
|
|
1820
|
$eval =~ s/\$package/$package/g; |
353
|
724
|
50
|
|
2
|
1
|
68211
|
eval $eval or die <
|
|
2
|
50
|
|
171
|
1
|
39
|
|
|
2
|
100
|
|
2
|
1
|
4
|
|
|
2
|
50
|
|
2
|
1
|
4
|
|
|
1
|
100
|
|
2
|
1
|
3
|
|
|
1
|
50
|
|
171
|
1
|
4
|
|
|
171
|
100
|
|
2
|
1
|
370
|
|
|
171
|
50
|
|
2
|
1
|
444
|
|
|
171
|
100
|
|
171
|
1
|
457
|
|
|
170
|
50
|
|
2
|
1
|
431
|
|
|
1
|
100
|
|
5
|
1
|
5
|
|
|
2
|
50
|
|
2
|
1
|
36
|
|
|
2
|
100
|
|
0
|
1
|
5
|
|
|
2
|
50
|
|
171
|
1
|
5
|
|
|
1
|
100
|
|
0
|
1
|
2
|
|
|
1
|
50
|
|
0
|
1
|
4
|
|
|
2
|
100
|
|
0
|
|
35
|
|
|
2
|
50
|
|
0
|
|
5
|
|
|
2
|
100
|
|
0
|
|
4
|
|
|
1
|
50
|
|
0
|
|
2
|
|
|
1
|
100
|
|
0
|
|
4
|
|
|
2
|
50
|
|
0
|
|
36
|
|
|
2
|
100
|
|
0
|
|
5
|
|
|
2
|
50
|
|
1
|
|
4
|
|
|
1
|
100
|
|
1
|
|
2
|
|
|
1
|
0
|
|
1
|
|
4
|
|
|
171
|
0
|
|
1
|
|
343
|
|
|
171
|
50
|
|
1
|
|
374
|
|
|
171
|
100
|
|
1
|
|
462
|
|
|
170
|
0
|
|
1
|
|
367
|
|
|
1
|
0
|
|
1
|
|
4
|
|
|
2
|
0
|
|
1
|
|
35
|
|
|
2
|
0
|
|
|
|
5
|
|
|
2
|
0
|
|
|
|
5
|
|
|
1
|
0
|
|
|
|
2
|
|
|
1
|
0
|
|
|
|
6
|
|
|
2
|
0
|
|
|
|
36
|
|
|
2
|
0
|
|
|
|
4
|
|
|
2
|
0
|
|
|
|
5
|
|
|
1
|
0
|
|
|
|
2
|
|
|
1
|
0
|
|
|
|
4
|
|
|
171
|
0
|
|
|
|
950
|
|
|
171
|
0
|
|
|
|
896
|
|
|
171
|
0
|
|
|
|
473
|
|
|
170
|
0
|
|
|
|
398
|
|
|
1
|
0
|
|
|
|
6
|
|
|
2
|
0
|
|
|
|
36
|
|
|
2
|
50
|
|
|
|
4
|
|
|
2
|
50
|
|
|
|
5
|
|
|
1
|
50
|
|
|
|
3
|
|
|
1
|
50
|
|
|
|
4
|
|
|
5
|
50
|
|
|
|
694
|
|
|
5
|
50
|
|
|
|
13
|
|
|
5
|
50
|
|
|
|
10
|
|
|
4
|
50
|
|
|
|
66
|
|
|
1
|
50
|
|
|
|
4
|
|
|
2
|
50
|
|
|
|
37
|
|
|
2
|
50
|
|
|
|
4
|
|
|
2
|
50
|
|
|
|
5
|
|
|
1
|
50
|
|
|
|
3
|
|
|
1
|
50
|
|
|
|
4
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
171
|
|
|
|
|
343
|
|
|
171
|
|
|
|
|
398
|
|
|
171
|
|
|
|
|
425
|
|
|
170
|
|
|
|
|
365
|
|
|
1
|
|
|
|
|
48
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
793
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
756
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
517
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
260
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
221
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
9
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
226
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
223
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
217
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
224
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
1App-Fetchware: internal operational error: _make_config_sub()'s internal eval() |
355
|
|
|
|
|
|
|
call failed with the exception [$@]. See perldoc App::Fetchware. |
356
|
|
|
|
|
|
|
EOD |
357
|
|
|
|
|
|
|
} elsif ($one_or_many_values eq 'ONEARRREF') { |
358
|
265
|
|
|
|
|
204
|
my $eval = <<'EOE'; |
359
|
|
|
|
|
|
|
package $package; |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub $name (@) { |
362
|
|
|
|
|
|
|
my $value = shift; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
die <
|
365
|
|
|
|
|
|
|
App-Fetchware: internal syntax error: $name was called more than once in this |
366
|
|
|
|
|
|
|
Fetchwarefile. Currently only mirror supports being used more than once in a |
367
|
|
|
|
|
|
|
Fetchwarefile, but you have used $name more than once. Please remove all calls |
368
|
|
|
|
|
|
|
to $name but one. See perldoc App::Fetchware. |
369
|
|
|
|
|
|
|
EOD |
370
|
|
|
|
|
|
|
unless (@_) { |
371
|
|
|
|
|
|
|
config('$name', $value); |
372
|
|
|
|
|
|
|
} else { |
373
|
|
|
|
|
|
|
config('$name', $value, @_); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
1; # return true from eval |
377
|
|
|
|
|
|
|
EOE |
378
|
265
|
|
|
|
|
1497
|
$eval =~ s/\$name/$name/g; |
379
|
265
|
|
|
|
|
706
|
$eval =~ s/\$package/$package/g; |
380
|
265
|
50
|
|
2
|
1
|
22657
|
eval $eval or die <
|
|
2
|
50
|
|
2
|
1
|
34
|
|
|
2
|
100
|
|
2
|
1
|
4
|
|
|
2
|
50
|
|
2
|
1
|
4
|
|
|
1
|
100
|
|
2
|
1
|
2
|
|
|
1
|
50
|
|
|
|
2
|
|
|
2
|
100
|
|
|
|
211
|
|
|
2
|
50
|
|
|
|
6
|
|
|
2
|
100
|
|
|
|
5
|
|
|
1
|
50
|
|
|
|
2
|
|
|
1
|
100
|
|
|
|
3
|
|
|
2
|
|
|
|
|
33
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
35
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
240
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
381
|
|
|
|
|
|
|
2App-Fetchware: internal operational error: _make_config_sub()'s internal eval() |
382
|
|
|
|
|
|
|
call failed with the exception [$@]. See perldoc App::Fetchware. |
383
|
|
|
|
|
|
|
EOD |
384
|
|
|
|
|
|
|
} elsif ($one_or_many_values eq 'MANY') { |
385
|
68
|
|
|
|
|
127
|
my $eval = <<'EOE'; |
386
|
|
|
|
|
|
|
package $package; |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub $name (@) { |
389
|
|
|
|
|
|
|
my $value = shift; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# Support multiple arguments specified on the same line. like: |
392
|
|
|
|
|
|
|
# mirror 'http://djfjf.com/a', 'ftp://kdjfjkl.net/b'; |
393
|
|
|
|
|
|
|
unless (@_) { |
394
|
|
|
|
|
|
|
config('$name', $value); |
395
|
|
|
|
|
|
|
} else { |
396
|
|
|
|
|
|
|
config('$name', $value, @_); |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
1; # return true from eval |
400
|
|
|
|
|
|
|
EOE |
401
|
68
|
|
|
|
|
290
|
$eval =~ s/\$name/$name/g; |
402
|
68
|
|
|
|
|
178
|
$eval =~ s/\$package/$package/g; |
403
|
68
|
50
|
|
176
|
1
|
4738
|
eval $eval or die <
|
|
176
|
100
|
|
|
|
1089
|
|
|
176
|
|
|
|
|
391
|
|
|
175
|
|
|
|
|
424
|
|
|
2
|
|
|
|
|
7
|
|
404
|
|
|
|
|
|
|
3App-Fetchware: internal operational error: _make_config_sub()'s internal eval() |
405
|
|
|
|
|
|
|
call failed with the exception [\$@]. See perldoc App::Fetchware. |
406
|
|
|
|
|
|
|
EOD |
407
|
|
|
|
|
|
|
} elsif ($one_or_many_values eq 'BOOLEAN') { |
408
|
219
|
|
|
|
|
218
|
my $eval = <<'EOE'; |
409
|
|
|
|
|
|
|
package $package; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub $name (@) { |
412
|
|
|
|
|
|
|
my $value = shift; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
die <
|
415
|
|
|
|
|
|
|
App-Fetchware: internal syntax error: $name was called more than once in this |
416
|
|
|
|
|
|
|
Fetchwarefile. Currently only mirror supports being used more than once in a |
417
|
|
|
|
|
|
|
Fetchwarefile, but you have used $name more than once. Please remove all calls |
418
|
|
|
|
|
|
|
to $name but one. See perldoc App::Fetchware. |
419
|
|
|
|
|
|
|
EOD |
420
|
|
|
|
|
|
|
# Make extra false values false (0). Not needed for true values, because |
421
|
|
|
|
|
|
|
# everything but 0, '', and undef are true values. |
422
|
|
|
|
|
|
|
if ($value =~ /false/i) { |
423
|
|
|
|
|
|
|
$value = 0; |
424
|
|
|
|
|
|
|
} elsif ($value =~ /off/i) { |
425
|
|
|
|
|
|
|
$value = 0; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
unless (@_) { |
429
|
|
|
|
|
|
|
config('$name', $value); |
430
|
|
|
|
|
|
|
} else { |
431
|
|
|
|
|
|
|
die <
|
432
|
|
|
|
|
|
|
App-Fetchware: internal syntax error. $name was called with more than one |
433
|
|
|
|
|
|
|
option. $name only supports just one option such as '$name 'option';'. It does |
434
|
|
|
|
|
|
|
not support more than one option such as '$name 'option', 'another option';'. |
435
|
|
|
|
|
|
|
Please chose one option not both, or combine both into one option. See perldoc |
436
|
|
|
|
|
|
|
App::Fetchware. |
437
|
|
|
|
|
|
|
EOD |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
1; # return true from eval |
441
|
|
|
|
|
|
|
EOE |
442
|
219
|
|
|
|
|
1667
|
$eval =~ s/\$name/$name/g; |
443
|
219
|
|
|
|
|
644
|
$eval =~ s/\$package/$package/g; |
444
|
219
|
50
|
|
7
|
1
|
26242
|
eval $eval or die <
|
|
6
|
100
|
|
4
|
1
|
935
|
|
|
7
|
50
|
|
4
|
1
|
233
|
|
|
7
|
100
|
|
4
|
1
|
25
|
|
|
1
|
100
|
|
|
|
4
|
|
|
1
|
100
|
|
|
|
3
|
|
|
6
|
50
|
|
|
|
14
|
|
|
6
|
100
|
|
|
|
228
|
|
|
2
|
100
|
|
|
|
7
|
|
|
4
|
100
|
|
|
|
254
|
|
|
4
|
100
|
|
|
|
10
|
|
|
3
|
100
|
|
|
|
12
|
|
|
1
|
100
|
|
|
|
216
|
|
|
1
|
100
|
|
|
|
3
|
|
|
4
|
100
|
|
|
|
10
|
|
|
3
|
100
|
|
|
|
7
|
|
|
1
|
100
|
|
|
|
4
|
|
|
4
|
|
|
|
|
469
|
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
16
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
256
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
11
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
445
|
|
|
|
|
|
|
4App-Fetchware: internal operational error: _make_config_sub()'s internal eval() |
446
|
|
|
|
|
|
|
call failed with the exception [\$@]. See perldoc App::Fetchware. |
447
|
|
|
|
|
|
|
EOD |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
sub new { |
457
|
2
|
|
|
1
|
1
|
437
|
my ($term, $program_name) = @_; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# Instantiate a new Fetchwarefile object for managing and generating a |
460
|
|
|
|
|
|
|
# Fetchwarefile, which we'll write to a file for the user or use to |
461
|
|
|
|
|
|
|
# build a associated Fetchware package. |
462
|
2
|
|
|
|
|
7
|
my $now = localtime; |
463
|
2
|
|
|
|
|
9
|
my $fetchwarefile = App::Fetchware::Fetchwarefile->new( |
464
|
|
|
|
|
|
|
header => <
|
465
|
|
|
|
|
|
|
use App::Fetchware; |
466
|
|
|
|
|
|
|
# Auto generated $now by fetchware's new command. |
467
|
|
|
|
|
|
|
# However, feel free to edit this file if fetchware's new command's |
468
|
|
|
|
|
|
|
# autoconfiguration is not enough. |
469
|
|
|
|
|
|
|
# |
470
|
|
|
|
|
|
|
# Please look up fetchware's documentation of its configuration file syntax at |
471
|
|
|
|
|
|
|
# perldoc App::Fetchware, and only if its configuration file syntax is not |
472
|
|
|
|
|
|
|
# malleable enough for your application should you resort to customizing |
473
|
|
|
|
|
|
|
# fetchware's behavior. For extra flexible customization see perldoc |
474
|
|
|
|
|
|
|
# App::Fetchware. |
475
|
|
|
|
|
|
|
EOF |
476
|
|
|
|
|
|
|
descriptions => { |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
program => <
|
479
|
|
|
|
|
|
|
program simply names the program the Fetchwarefile is responsible for |
480
|
|
|
|
|
|
|
downloading, building, and installing. |
481
|
|
|
|
|
|
|
EOA |
482
|
|
|
|
|
|
|
filter => <
|
483
|
|
|
|
|
|
|
filter specifies a program name and/or version number that tells fetchware |
484
|
|
|
|
|
|
|
which program and or which version of a program you want fetchware to install. |
485
|
|
|
|
|
|
|
This is *only* needed in cases where there are multiple programs and or |
486
|
|
|
|
|
|
|
multiple versions of the same program in the directory lookup_url specifies. |
487
|
|
|
|
|
|
|
EOA |
488
|
|
|
|
|
|
|
temp_dir => <
|
489
|
|
|
|
|
|
|
temp_dir specifies what temporary directory fetchware will use to download and |
490
|
|
|
|
|
|
|
build this program. |
491
|
|
|
|
|
|
|
EOA |
492
|
|
|
|
|
|
|
user => <
|
493
|
|
|
|
|
|
|
user specifes a user that fetchware will drop priviledges to when fetchware |
494
|
|
|
|
|
|
|
downloads and builds your software. It will then switch back to root privs, if |
495
|
|
|
|
|
|
|
run as root, and install your software system wide. This does not work on |
496
|
|
|
|
|
|
|
Windows. |
497
|
|
|
|
|
|
|
EOA |
498
|
|
|
|
|
|
|
fetchware_database_path => <
|
499
|
|
|
|
|
|
|
fetchware_database_path specifies an alternate path for fetchware to use to |
500
|
|
|
|
|
|
|
store the fetchware package that 'fetchware install' creates, and that |
501
|
|
|
|
|
|
|
'fetchware upgrade' uses to upgrade this fetchware package. |
502
|
|
|
|
|
|
|
EOA |
503
|
|
|
|
|
|
|
prefix => <
|
504
|
|
|
|
|
|
|
prefix specifies what base path your software will be installed under. This |
505
|
|
|
|
|
|
|
only works for software that uses GNU AutoTools to configure itself, it uses |
506
|
|
|
|
|
|
|
./configure. |
507
|
|
|
|
|
|
|
EOA |
508
|
|
|
|
|
|
|
configure_options => <
|
509
|
|
|
|
|
|
|
configure_options specifes what options fetchware should pass to ./configure |
510
|
|
|
|
|
|
|
when it configures your software. This option only works for software that |
511
|
|
|
|
|
|
|
uses GNU AutoTools. |
512
|
|
|
|
|
|
|
EOA |
513
|
|
|
|
|
|
|
make_options => <
|
514
|
|
|
|
|
|
|
make_options specifes what options fetchware should pass to make when make is |
515
|
|
|
|
|
|
|
run to build and install your software. |
516
|
|
|
|
|
|
|
EOA |
517
|
|
|
|
|
|
|
build_commands => <
|
518
|
|
|
|
|
|
|
build_commands specifies what commands fetchware should execute to build your |
519
|
|
|
|
|
|
|
software. |
520
|
|
|
|
|
|
|
EOA |
521
|
|
|
|
|
|
|
install_commands => <
|
522
|
|
|
|
|
|
|
install_commands specifies what commands fetchware should execute to install |
523
|
|
|
|
|
|
|
your software. |
524
|
|
|
|
|
|
|
EOA |
525
|
|
|
|
|
|
|
uninstall_commands => <
|
526
|
|
|
|
|
|
|
uninstall_commands specifies what commands fetchware should execute to uninstall |
527
|
|
|
|
|
|
|
your software. |
528
|
|
|
|
|
|
|
EOA |
529
|
|
|
|
|
|
|
lookup_url => <
|
530
|
|
|
|
|
|
|
lookup_url specifes the url that fetchware uses to determine what what |
531
|
|
|
|
|
|
|
versions of your program are available. It should point to a directory listing |
532
|
|
|
|
|
|
|
instead of a specific file. |
533
|
|
|
|
|
|
|
EOA |
534
|
|
|
|
|
|
|
lookup_method => <
|
535
|
|
|
|
|
|
|
lookup_method specifies how fetchware determines what version of your program |
536
|
|
|
|
|
|
|
to install. The default is the 'timestamp' algorithm, and then to try the |
537
|
|
|
|
|
|
|
'versionstring' algorithm if 'timestamp' fails. lookup_method specifies which |
538
|
|
|
|
|
|
|
one you would like to use. Only the strings 'timestamp' and 'versionstring' |
539
|
|
|
|
|
|
|
are allowed options. |
540
|
|
|
|
|
|
|
EOA |
541
|
|
|
|
|
|
|
gpg_keys_url => <
|
542
|
|
|
|
|
|
|
gpg_keys_url specifies the url that fetchware will use to download the author's |
543
|
|
|
|
|
|
|
KEYS file that it uses for gpg verification. |
544
|
|
|
|
|
|
|
EOA |
545
|
|
|
|
|
|
|
gpg_sig_url => <
|
546
|
|
|
|
|
|
|
gpg_sig_url specifies the url that fetchware uses to download digital |
547
|
|
|
|
|
|
|
signatures of this program. They're files that usually end .asc. |
548
|
|
|
|
|
|
|
EOA |
549
|
|
|
|
|
|
|
sha1_url => <
|
550
|
|
|
|
|
|
|
sha1_url specfies the url that fetchware uses to download sha1sum files of |
551
|
|
|
|
|
|
|
this program. This url should be the program's main download site instead of a |
552
|
|
|
|
|
|
|
mirror, because a hacked mirror could alter the sha1sum on that mirror. |
553
|
|
|
|
|
|
|
EOA |
554
|
|
|
|
|
|
|
md5_url => <
|
555
|
|
|
|
|
|
|
md5_url specfies the url that fetchware uses to download md5sum files of |
556
|
|
|
|
|
|
|
this program. This url should be the program's main download site instead of a |
557
|
|
|
|
|
|
|
mirror, because a hacked mirror could alter the md5sum on that mirror. |
558
|
|
|
|
|
|
|
EOA |
559
|
|
|
|
|
|
|
verify_method => <
|
560
|
|
|
|
|
|
|
verify_method specifes a specific method that fetchware should use to verify |
561
|
|
|
|
|
|
|
your program. This method can be 'gpg', 'sha1', or 'md5'. |
562
|
|
|
|
|
|
|
EOA |
563
|
|
|
|
|
|
|
no_install => <
|
564
|
|
|
|
|
|
|
no_install specifies that this software should not be installed. Instead, the |
565
|
|
|
|
|
|
|
install step is skipped, and fetchware prints to STDOUT where it downloaded, |
566
|
|
|
|
|
|
|
verified, and built your program. no_install must be a true or false value. |
567
|
|
|
|
|
|
|
EOA |
568
|
|
|
|
|
|
|
verify_failure_ok => <
|
569
|
|
|
|
|
|
|
verify_failure_ok specifies that fetchware should not stop installing your |
570
|
|
|
|
|
|
|
software and terminate with an error message if fetchware fails to verify your |
571
|
|
|
|
|
|
|
software. You should never set this to true. Doing so could cause fetchware to |
572
|
|
|
|
|
|
|
install software that may have been compromised, or had malware inserted into |
573
|
|
|
|
|
|
|
it. Never use this option unless the author or maintainer of this program does |
574
|
|
|
|
|
|
|
not gpg sign or checksum his software. |
575
|
|
|
|
|
|
|
EOA |
576
|
|
|
|
|
|
|
user_keyring => <
|
577
|
|
|
|
|
|
|
users_keyring if enabled causes fetchware to use the user's own gpg keyring |
578
|
|
|
|
|
|
|
instead of fetchware's own keyring. |
579
|
|
|
|
|
|
|
EOA |
580
|
|
|
|
|
|
|
mirror => <
|
581
|
|
|
|
|
|
|
The mirror configuration option provides fetchware with alternate servers to |
582
|
|
|
|
|
|
|
try to download this program from. This option is used when the server |
583
|
|
|
|
|
|
|
specified in the url options in this file is unavailable or times out. |
584
|
|
|
|
|
|
|
EOA |
585
|
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
); |
587
|
|
|
|
|
|
|
###INSANEFEATUREENHANCEMENT### Prompt for name of program, and do a fuzzy |
588
|
|
|
|
|
|
|
#search on CPAN for that program under |
589
|
|
|
|
|
|
|
#App::Fetchware::FetchwarefileX::UpCasedProgName. Consider using the meta |
590
|
|
|
|
|
|
|
#CPAN API. And if it exists ask user if they wanna use that one instead of |
591
|
|
|
|
|
|
|
#autogening one. |
592
|
|
|
|
|
|
|
# |
593
|
|
|
|
|
|
|
#Perhaps create a 'fetchwarefile' command to download and look at |
594
|
|
|
|
|
|
|
#fetchwarefiles from CPAN, and then install them, and/or perhaps upload |
595
|
|
|
|
|
|
|
#them pausing to ask for the user's PAUSE credentials!!!!!!!!! |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
|
598
|
0
|
|
|
|
|
0
|
extension_name(__PACKAGE__); |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
|
601
|
1
|
|
|
|
|
216
|
my $opening_message = <
|
602
|
|
|
|
|
|
|
Fetchware's new command is reasonably sophisticated, and is smart enough to |
603
|
|
|
|
|
|
|
determine based on the lookup_url you provide if it can autogenerate a |
604
|
|
|
|
|
|
|
Fetchwarefile for you. If Fetchware cannot, then it will ask you more |
605
|
|
|
|
|
|
|
questions regarding the information it requires to be able to build a |
606
|
|
|
|
|
|
|
installable fetchware package for you. After that, fetchware will ask you if |
607
|
|
|
|
|
|
|
you would like to edit the Fetchwarefile, fetchware has created for you in an |
608
|
|
|
|
|
|
|
editor. If you say yes, fetchware will open a editor for you, but if you say |
609
|
|
|
|
|
|
|
no, fetchware will skip the custom editing. Next, fetchware will create a test |
610
|
|
|
|
|
|
|
Fetchwarefile for you, and ask you if you would like to test it by trying to |
611
|
|
|
|
|
|
|
install it now. If you say yes, fetchware will install it, and if you say no, |
612
|
|
|
|
|
|
|
then fetchware will print the location of the Fetchwarefile it created for |
613
|
|
|
|
|
|
|
you to later use to install your application. |
614
|
|
|
|
|
|
|
EOM |
615
|
|
|
|
|
|
|
|
616
|
2
|
|
|
|
|
6
|
opening_message($opening_message); |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Ask user for name of program unless the user provided one at command |
619
|
|
|
|
|
|
|
# line such as fetchware new . |
620
|
2
|
|
|
|
|
6
|
$program_name = fetchwarefile_name(program => $program_name); |
621
|
0
|
|
|
|
|
0
|
vmsg "Determined name of your program to be [$program_name]"; |
622
|
|
|
|
|
|
|
|
623
|
2
|
|
|
|
|
434
|
$fetchwarefile->config_options(program => $program_name); |
624
|
2
|
|
|
|
|
7
|
vmsg "Appended program [$program_name] configuration option to Fetchwarefile"; |
625
|
|
|
|
|
|
|
|
626
|
2
|
|
|
|
|
8
|
my $lookup_url = get_lookup_url($term); |
627
|
0
|
|
|
|
|
0
|
vmsg "Asked user for lookup_url [$lookup_url] from user."; |
628
|
|
|
|
|
|
|
|
629
|
1
|
|
|
|
|
242
|
$fetchwarefile->config_options(lookup_url => $lookup_url); |
630
|
2
|
|
|
|
|
6
|
vmsg "Appended lookup_url [$lookup_url] configuration option to Fetchwarefile"; |
631
|
|
|
|
|
|
|
|
632
|
2
|
|
|
|
|
6
|
vmsg "Downloaded lookup_url [$lookup_url]"; |
633
|
0
|
|
|
|
|
0
|
my $filename_listing = download_lookup_url($term, $lookup_url); |
634
|
2
|
|
|
|
|
461
|
vmsg "Downloaded lookup_url's directory listing"; |
635
|
2
|
|
|
|
|
8
|
vmsg Dumper($filename_listing); |
636
|
|
|
|
|
|
|
|
637
|
2
|
|
|
|
|
8
|
my $mirrors_hashref = get_mirrors($term, $filename_listing); |
638
|
0
|
|
|
|
|
0
|
vmsg "Added mirrors to your Fetchwarefile."; |
639
|
1
|
|
|
|
|
217
|
vmsg Dumper($mirrors_hashref); |
640
|
|
|
|
|
|
|
|
641
|
2
|
|
|
|
|
7
|
my $verify_hashref = get_verification($term, $filename_listing, $lookup_url); |
642
|
2
|
|
|
|
|
5
|
vmsg "Added verification settings to Fetchwarefile."; |
643
|
0
|
|
|
|
|
0
|
vmsg Dumper($verify_hashref); |
644
|
|
|
|
|
|
|
|
645
|
2
|
|
|
|
|
427
|
my $filter_hashref = get_filter_option($term, $filename_listing); |
646
|
2
|
|
|
|
|
8
|
vmsg "Added [$filter_hashref->{filter}] filter setting to Fetchwarefile."; |
647
|
|
|
|
|
|
|
|
648
|
2
|
|
|
|
|
8
|
$fetchwarefile->config_options( |
649
|
|
|
|
|
|
|
%$mirrors_hashref, |
650
|
|
|
|
|
|
|
%$verify_hashref, |
651
|
|
|
|
|
|
|
%$filter_hashref |
652
|
|
|
|
|
|
|
); |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
###BUGALERT### Ask to parrallelize make with make_options??? |
655
|
|
|
|
|
|
|
###BUGALERT### Verify prefix is writable by current user, who will |
656
|
|
|
|
|
|
|
#presumably be the user who will install the package now and later. |
657
|
|
|
|
|
|
|
###BUGALERT### Ask user for a prefix if their running nonroot??? |
658
|
0
|
|
|
|
|
0
|
vmsg 'Prompting for other options that may be needed.'; |
659
|
1
|
|
|
|
|
216
|
my $other_options_hashref = prompt_for_other_options($term, |
660
|
|
|
|
|
|
|
temp_dir => { |
661
|
|
|
|
|
|
|
prompt => <
|
662
|
|
|
|
|
|
|
What temp_dir configuration option would you like? |
663
|
|
|
|
|
|
|
EOP |
664
|
|
|
|
|
|
|
print_me => <
|
665
|
|
|
|
|
|
|
temp_dir is the directory where fetchware creates a temporary directory that |
666
|
|
|
|
|
|
|
stores all of the temporary files it creates while it is building your software. |
667
|
|
|
|
|
|
|
The default directory is /tmp on Unix systems and C:\\temp on Windows systems. |
668
|
|
|
|
|
|
|
EOP |
669
|
|
|
|
|
|
|
}, |
670
|
|
|
|
|
|
|
user => { |
671
|
|
|
|
|
|
|
prompt => <
|
672
|
|
|
|
|
|
|
What user configuration option would you like? |
673
|
|
|
|
|
|
|
EOP |
674
|
|
|
|
|
|
|
print_me => <
|
675
|
|
|
|
|
|
|
user specifies what user fetchware will drop priveleges to on Unix systems |
676
|
|
|
|
|
|
|
capable of doing so. This allows fetchware to download files from the internet |
677
|
|
|
|
|
|
|
with user priveleges, and not do anything as the administrative root user until |
678
|
|
|
|
|
|
|
after the downloaded software package has been verified as exactly the same as |
679
|
|
|
|
|
|
|
the author of the package intended it to be. If you use this option, the only |
680
|
|
|
|
|
|
|
thing that is run as root is 'make install' or whatever this package's |
681
|
|
|
|
|
|
|
install_commands configuratio option is. |
682
|
|
|
|
|
|
|
EOP |
683
|
|
|
|
|
|
|
}, |
684
|
|
|
|
|
|
|
prefix => { |
685
|
|
|
|
|
|
|
prompt => <
|
686
|
|
|
|
|
|
|
What prefix configuration option would you like? |
687
|
|
|
|
|
|
|
EOP |
688
|
|
|
|
|
|
|
print_me => <
|
689
|
|
|
|
|
|
|
prefix specifies the base path that will be used to install this software. The |
690
|
|
|
|
|
|
|
default is /usr/local, which is acceptable for most unix users. Please note that |
691
|
|
|
|
|
|
|
this difective only works for software packages that use GNU AutoTools, software |
692
|
|
|
|
|
|
|
that uses ./configure --prefix= to change the prefix. |
693
|
|
|
|
|
|
|
EOP |
694
|
|
|
|
|
|
|
}, |
695
|
|
|
|
|
|
|
configure_options => { |
696
|
|
|
|
|
|
|
prompt => <
|
697
|
|
|
|
|
|
|
What configure_options configuration option would you like? |
698
|
|
|
|
|
|
|
EOP |
699
|
|
|
|
|
|
|
print_me => <
|
700
|
|
|
|
|
|
|
configure_options specifies what options fetchware should add when it configures |
701
|
|
|
|
|
|
|
this software package for you. A list of possible options can be obtained by |
702
|
|
|
|
|
|
|
running unarchiving the software package that corresponds to this Fetchwarefile, |
703
|
|
|
|
|
|
|
and running the command './configure --help'. These options vary from software |
704
|
|
|
|
|
|
|
package to software package. Please note that this option only works for GNU |
705
|
|
|
|
|
|
|
AutoTools based software distributions, ones that use ./configure to configure |
706
|
|
|
|
|
|
|
the software. |
707
|
|
|
|
|
|
|
EOP |
708
|
|
|
|
|
|
|
}, |
709
|
|
|
|
|
|
|
make_options => { |
710
|
|
|
|
|
|
|
prompt => <
|
711
|
|
|
|
|
|
|
What make_options configuration option would you like? |
712
|
|
|
|
|
|
|
EOP |
713
|
|
|
|
|
|
|
print_me => <
|
714
|
|
|
|
|
|
|
make_options specifies what options fetchware will pass to make when make is run |
715
|
|
|
|
|
|
|
to compile, perhaps test, and install your software package. They are simpley |
716
|
|
|
|
|
|
|
added after make is called. An example is '-j 4', which will cause make to |
717
|
|
|
|
|
|
|
execute 4 jobs simultaneously. A reasonable rule of thumb is to set make's -j |
718
|
|
|
|
|
|
|
argument to two times as many cpu cores your computer has as compiling programs |
719
|
|
|
|
|
|
|
is sometimes IO bound instead of CPU bound, so you can get away with running |
720
|
|
|
|
|
|
|
more jobs then you have cores. |
721
|
|
|
|
|
|
|
EOP |
722
|
|
|
|
|
|
|
}, |
723
|
|
|
|
|
|
|
###BUGALERT### Create a config sub called build_system that takes args like |
724
|
|
|
|
|
|
|
#AutoTools, cmake, MakeMaker, Module::Build, and so on that will use the default |
725
|
|
|
|
|
|
|
#build commands of whatever system this option specifies. |
726
|
|
|
|
|
|
|
build_commands => { |
727
|
|
|
|
|
|
|
prompt => <
|
728
|
|
|
|
|
|
|
What build_commands configuration option would you like? |
729
|
|
|
|
|
|
|
EOP |
730
|
|
|
|
|
|
|
print_me => <
|
731
|
|
|
|
|
|
|
build_commands specifies what commands fetchware will run to compile your |
732
|
|
|
|
|
|
|
software package. Fetchware's default is simply 'make', which is good for most |
733
|
|
|
|
|
|
|
programs. If you're software package uses something other than fetchware's |
734
|
|
|
|
|
|
|
default of GNU AutoTools, then you may need to change this configuration option |
735
|
|
|
|
|
|
|
to specify what you would like instead. Specify multiple build commands in |
736
|
|
|
|
|
|
|
single quotes with a comma between them: |
737
|
|
|
|
|
|
|
'./configure', 'make' |
738
|
|
|
|
|
|
|
EOP |
739
|
|
|
|
|
|
|
}, |
740
|
|
|
|
|
|
|
install_commands => { |
741
|
|
|
|
|
|
|
prompt => <
|
742
|
|
|
|
|
|
|
What install_commands configuration option would you like? |
743
|
|
|
|
|
|
|
EOP |
744
|
|
|
|
|
|
|
print_me => <
|
745
|
|
|
|
|
|
|
install_commands specifies what commands fetchware will run to install your |
746
|
|
|
|
|
|
|
software package. Fetchware's default is simply 'make install', which is good |
747
|
|
|
|
|
|
|
for most programs. If you're software package uses something other than |
748
|
|
|
|
|
|
|
fetchware's default of GNU AutoTools, then you may need to change this |
749
|
|
|
|
|
|
|
configuration option to specify what you would like instead. Specify multiple |
750
|
|
|
|
|
|
|
build commands in single quotes with a comma between them: |
751
|
|
|
|
|
|
|
'make test', 'make install' |
752
|
|
|
|
|
|
|
EOP |
753
|
|
|
|
|
|
|
}, |
754
|
|
|
|
|
|
|
uninstall_commands => { |
755
|
|
|
|
|
|
|
prompt => <
|
756
|
|
|
|
|
|
|
What uninstall_commands configuration option would you like? |
757
|
|
|
|
|
|
|
EOP |
758
|
|
|
|
|
|
|
print_me => <
|
759
|
|
|
|
|
|
|
uninstall_commands specifes what commands fetchware will run to uninstall your |
760
|
|
|
|
|
|
|
software pacakge. The default is 'make uninstall,' which works for some GNU |
761
|
|
|
|
|
|
|
AutoTools packages, but not all. If your software package does not have a 'make |
762
|
|
|
|
|
|
|
uninstall' make target, but it has some other command that can uninstall it, |
763
|
|
|
|
|
|
|
then please specify it using uninstall_commands so fetchware can uninstall it. |
764
|
|
|
|
|
|
|
EOP |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
}, |
767
|
|
|
|
|
|
|
lookup_method => { |
768
|
|
|
|
|
|
|
prompt => <
|
769
|
|
|
|
|
|
|
What lookup_method configuration option would you like? |
770
|
|
|
|
|
|
|
EOP |
771
|
|
|
|
|
|
|
print_me => <
|
772
|
|
|
|
|
|
|
lookup_method specifies what how fetchware determines if a new version of your |
773
|
|
|
|
|
|
|
software package is available. The available algorithms are 'timstamp' and |
774
|
|
|
|
|
|
|
'versionstring'. 'timestamp' uses the timestamp listed in the FTP or HTTP |
775
|
|
|
|
|
|
|
listing, and uses the software package that is the newest by filesystem |
776
|
|
|
|
|
|
|
timestamp. The 'versionstring' algorithm uses the filename of the files in the |
777
|
|
|
|
|
|
|
FTP or HTTP listing. It parses out the version information, sorts it highest to |
778
|
|
|
|
|
|
|
lowest, and then picks the highest version of your software package. The default |
779
|
|
|
|
|
|
|
is try 'timestamp' and if that doesn't work, then try 'versionstring'. |
780
|
|
|
|
|
|
|
EOP |
781
|
|
|
|
|
|
|
}, |
782
|
|
|
|
|
|
|
gpg_keys_url => { |
783
|
|
|
|
|
|
|
prompt => <
|
784
|
|
|
|
|
|
|
What gpg_keys_url configuration option would you like? |
785
|
|
|
|
|
|
|
EOP |
786
|
|
|
|
|
|
|
print_me => <
|
787
|
|
|
|
|
|
|
gpg_keys_url specifies a url similar to lookup_url in that it should specify a |
788
|
|
|
|
|
|
|
directory instead a specific file. It is used to download KEYS files, which |
789
|
|
|
|
|
|
|
contain your program author's gpg keys to import into gpg. |
790
|
|
|
|
|
|
|
EOP |
791
|
|
|
|
|
|
|
}, |
792
|
|
|
|
|
|
|
gpg_sig_url => { |
793
|
|
|
|
|
|
|
prompt => <
|
794
|
|
|
|
|
|
|
What gpg_sig_url configuration option would you like? |
795
|
|
|
|
|
|
|
EOP |
796
|
|
|
|
|
|
|
print_me => <
|
797
|
|
|
|
|
|
|
gpg_sig_url specifies a url similar to lookup_url in that it should specify a |
798
|
|
|
|
|
|
|
directory instead a specific file. It is used to download gpg signatures to |
799
|
|
|
|
|
|
|
verify your software package. |
800
|
|
|
|
|
|
|
EOP |
801
|
|
|
|
|
|
|
}, |
802
|
|
|
|
|
|
|
sha1_url => { |
803
|
|
|
|
|
|
|
prompt => <
|
804
|
|
|
|
|
|
|
What sha1_url configuration option would you like? |
805
|
|
|
|
|
|
|
EOP |
806
|
|
|
|
|
|
|
print_me => <
|
807
|
|
|
|
|
|
|
sha1_url specifies a url similar to lookup_url in that it should specify a |
808
|
|
|
|
|
|
|
directory instead of a specific file. It is separate from lookup_url, because |
809
|
|
|
|
|
|
|
you should download software from mirrors, but checksums from the original |
810
|
|
|
|
|
|
|
vendor's server, because checksums are easily replaced on a mirror by a hacker |
811
|
|
|
|
|
|
|
if the mirror gets hacked. |
812
|
|
|
|
|
|
|
EOP |
813
|
|
|
|
|
|
|
}, |
814
|
|
|
|
|
|
|
md5_url => { |
815
|
|
|
|
|
|
|
prompt => <
|
816
|
|
|
|
|
|
|
What md5_url configuration option would you like? |
817
|
|
|
|
|
|
|
EOP |
818
|
|
|
|
|
|
|
print_me => <
|
819
|
|
|
|
|
|
|
md5_url specifies a url similar to lookup_url in that it should specify a |
820
|
|
|
|
|
|
|
directory instead of a specific file. It is separate from lookup_url, because |
821
|
|
|
|
|
|
|
you should download software from mirrors, but checksums from the original |
822
|
|
|
|
|
|
|
vendor's server, because checksums are easily replaced on a mirror by a hacker |
823
|
|
|
|
|
|
|
if the mirror gets hacked. |
824
|
|
|
|
|
|
|
EOP |
825
|
|
|
|
|
|
|
}, |
826
|
|
|
|
|
|
|
verify_method => { |
827
|
|
|
|
|
|
|
prompt => <
|
828
|
|
|
|
|
|
|
What verify_method configuration option would you like? |
829
|
|
|
|
|
|
|
EOP |
830
|
|
|
|
|
|
|
print_me => <
|
831
|
|
|
|
|
|
|
verify_method specifies what method of verification fetchware should use to |
832
|
|
|
|
|
|
|
ensure the software you have downloaded has not been tampered with. The default |
833
|
|
|
|
|
|
|
is to try gpg verification, then sha1, and then finally md5, and if they all |
834
|
|
|
|
|
|
|
fail an error message is printed and fetchware exits, because if your software |
835
|
|
|
|
|
|
|
package cannot be verified, then it should not be installed. This configuration |
836
|
|
|
|
|
|
|
option allows you to remove the warnings by specifying a specific way of |
837
|
|
|
|
|
|
|
verifying your software has not been tampered with. To disable verification set |
838
|
|
|
|
|
|
|
the 'verify_failure_ok' configuration option to true. |
839
|
|
|
|
|
|
|
EOP |
840
|
|
|
|
|
|
|
}, |
841
|
|
|
|
|
|
|
###BUGALERT### replace no_install config su with a command line option that |
842
|
|
|
|
|
|
|
#would be the opposite of --force??? |
843
|
|
|
|
|
|
|
# Nah! Leave it! Just create a command line option for it too! |
844
|
|
|
|
|
|
|
no_install => { |
845
|
|
|
|
|
|
|
prompt => <
|
846
|
|
|
|
|
|
|
Would you like to enable the no_install configuration option? |
847
|
|
|
|
|
|
|
EOP |
848
|
|
|
|
|
|
|
###BUGALERT### no_install is not currently implemented properly!!! |
849
|
|
|
|
|
|
|
print_me => <
|
850
|
|
|
|
|
|
|
no_install is a true or false option, whoose acceptable values include 1 |
851
|
|
|
|
|
|
|
or 0, true or falue, On or Off. It's default value is false, but if you enable |
852
|
|
|
|
|
|
|
it, then fetchware will not install your software package, and instead it will |
853
|
|
|
|
|
|
|
simply download, verify, and build it. And then it will print out the full path |
854
|
|
|
|
|
|
|
of the directory it built your software package in. |
855
|
|
|
|
|
|
|
EOP |
856
|
|
|
|
|
|
|
###BUGALERT### Add support for a check regex, so that I can ensure |
857
|
|
|
|
|
|
|
#that what the user enters will be either true or false!!! |
858
|
|
|
|
|
|
|
}, |
859
|
|
|
|
|
|
|
verify_failure_ok => { |
860
|
|
|
|
|
|
|
prompt => <
|
861
|
|
|
|
|
|
|
Would you like to enable the verify_failure_ok configuration option? |
862
|
|
|
|
|
|
|
EOP |
863
|
|
|
|
|
|
|
print_me => <
|
864
|
|
|
|
|
|
|
verify_failure_ok is a true or false option, whoose acceptable values include 1 |
865
|
|
|
|
|
|
|
or 0, true or falue, On or Off. It's default value is false, but if you enable |
866
|
|
|
|
|
|
|
it, then fetchware will not print an error message and exit if verification |
867
|
|
|
|
|
|
|
fails for your software package. Please note that you should never use this |
868
|
|
|
|
|
|
|
option, because it makes it possible for fetchware to install source code that |
869
|
|
|
|
|
|
|
may have been tampered with. |
870
|
|
|
|
|
|
|
EOP |
871
|
|
|
|
|
|
|
}, |
872
|
|
|
|
|
|
|
users_keyring => { |
873
|
|
|
|
|
|
|
prompt => <
|
874
|
|
|
|
|
|
|
Would you like to enable users_keyring configuration option? |
875
|
|
|
|
|
|
|
EOP |
876
|
|
|
|
|
|
|
print_me => <
|
877
|
|
|
|
|
|
|
users_keyring when enabled causes fetchware to use the user who calls |
878
|
|
|
|
|
|
|
fetchware's gpg keyring instead of fetchware's own gpg keyring. Useful for |
879
|
|
|
|
|
|
|
source code distributions that do not provide an easily accessible KEYS file. |
880
|
|
|
|
|
|
|
Just remember to import the author's keys into your gpg keyring with gpg |
881
|
|
|
|
|
|
|
--import. |
882
|
|
|
|
|
|
|
EOP |
883
|
|
|
|
|
|
|
}, |
884
|
|
|
|
|
|
|
); |
885
|
2
|
|
|
|
|
8
|
vmsg 'User entered the following options.'; |
886
|
2
|
|
|
|
|
4
|
vmsg Dumper($other_options_hashref); |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
# Append all other options to the Fetchwarefile. |
889
|
0
|
|
|
|
|
0
|
$fetchwarefile->config_options(%$other_options_hashref); |
890
|
2
|
|
|
|
|
432
|
vmsg 'Appended all other options listed above to Fetchwarefile.'; |
891
|
|
|
|
|
|
|
|
892
|
2
|
|
|
|
|
6
|
my $edited_fetchwarefile = edit_manually($term, $fetchwarefile); |
893
|
2
|
|
|
|
|
10
|
vmsg <
|
894
|
|
|
|
|
|
|
Asked user if they would like to edit their generated Fetchwarefile manually. |
895
|
|
|
|
|
|
|
EOM |
896
|
|
|
|
|
|
|
# Generate Fetchwarefile. |
897
|
0
|
100
|
0
|
|
|
0
|
if (blessed($edited_fetchwarefile) |
898
|
|
|
|
|
|
|
and |
899
|
|
|
|
|
|
|
$edited_fetchwarefile->isa('App::Fetchware::Fetchwarefile')) { |
900
|
|
|
|
|
|
|
# If edit_manually() did not modify the Fetchwarefile, then generate |
901
|
|
|
|
|
|
|
# it. |
902
|
0
|
|
|
|
|
0
|
$fetchwarefile = $fetchwarefile->generate(); |
903
|
|
|
|
|
|
|
} else { |
904
|
|
|
|
|
|
|
# If edit_manually() modified the Fetchwarefile, then do not |
905
|
|
|
|
|
|
|
# generate it, and replace the Fetchwarefile object with the new |
906
|
|
|
|
|
|
|
# string that represents the user's edited Fetchwarefile. |
907
|
1
|
|
|
|
|
3
|
$fetchwarefile = $edited_fetchwarefile; |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
# Whatever variables the new() API subroutine returns are written via a pipe |
911
|
|
|
|
|
|
|
# back to the parent, and then the parent reads the variables back, and |
912
|
|
|
|
|
|
|
# makes then available to new_install(), back in the parent, as arguments. |
913
|
1
|
|
|
|
|
3
|
return $program_name, $fetchwarefile; |
914
|
|
|
|
|
|
|
} |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
sub extension_name { |
922
|
|
|
|
|
|
|
# Use a state variable to keep $extension_name's value between calls. |
923
|
4
|
|
|
5
|
1
|
467
|
state $extension_name; |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
# If $extension_name has never been touch and is still undef, then allow it |
926
|
|
|
|
|
|
|
# to be set. |
927
|
4
|
100
|
66
|
|
|
23
|
if (not defined $extension_name) { |
|
|
100
|
|
|
|
|
|
928
|
1
|
|
|
|
|
2
|
$extension_name = shift; |
929
|
|
|
|
|
|
|
# If $extension_name *is* set, and extension_name() was called with an |
930
|
|
|
|
|
|
|
# argument, which is what defined shift does (shift shifts the first value |
931
|
|
|
|
|
|
|
# off of @_ (the subroutine argument array), while defined checks to see if |
932
|
|
|
|
|
|
|
# one was actually defined and provided by the caller.) |
933
|
|
|
|
|
|
|
} elsif (defined $extension_name and defined shift) { |
934
|
1
|
|
|
|
|
6
|
die <
|
935
|
|
|
|
|
|
|
App-Fetchware: extension_name() was called more than once. It is a singleton, |
936
|
|
|
|
|
|
|
and therefore can only be called once. Please only call it once to set its |
937
|
|
|
|
|
|
|
value, and then call it repeatedly wherever you need that value. see perldoc |
938
|
|
|
|
|
|
|
App::Fetchware for more details. |
939
|
|
|
|
|
|
|
EOD |
940
|
|
|
|
|
|
|
} |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
# Return the singleton $extension_name. |
943
|
3
|
|
|
|
|
9
|
return $extension_name; |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
sub opening_message { |
949
|
0
|
|
|
1
|
1
|
0
|
my $opening_message = shift; |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
# Just print the opening message. |
952
|
0
|
|
|
|
|
0
|
print $opening_message; |
953
|
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
sub fetchwarefile_name { |
958
|
0
|
|
|
1
|
1
|
0
|
my ($term, $fetchwarefile_name, $fetchwarefile_name_value) = @_; |
959
|
0
|
|
|
|
|
0
|
my $what_a_fetchwarefile_name_is = <
|
960
|
|
|
|
|
|
|
Fetchware uses the $fetchwarefile_name configuration option to name this |
961
|
|
|
|
|
|
|
specific Fetchwarefile that Fetchware's new command is helping you create. |
962
|
|
|
|
|
|
|
Since, you did not provide a $fetchwarefile_name on the command line, please |
963
|
|
|
|
|
|
|
provide one below |
964
|
|
|
|
|
|
|
EOM |
965
|
0
|
50
|
|
|
|
0
|
die <
|
966
|
|
|
|
|
|
|
App-Fetchware: in your call to fetchwarefile_name() you failed to call it with a |
967
|
|
|
|
|
|
|
defined \$fetchwarefile_name option. The \$fetchwarefile_name option you |
968
|
|
|
|
|
|
|
specified is [$fetchwarefile_name]. Please specify this option, and try again. |
969
|
|
|
|
|
|
|
EOD |
970
|
|
|
|
|
|
|
|
971
|
0
|
50
|
|
|
|
0
|
if (not defined $fetchwarefile_name_value) { |
972
|
|
|
|
|
|
|
$fetchwarefile_name_value = $term->get_reply( |
973
|
|
|
|
|
|
|
prompt => q{What would you like to name this specific Fetchwarefile? }, |
974
|
|
|
|
|
|
|
print_me => $what_a_fetchwarefile_name_is, |
975
|
|
|
|
|
|
|
# This option requires a name, so just pressing return, which would |
976
|
|
|
|
|
|
|
# yield undef is not acceptable. We need an actual value, so check |
977
|
|
|
|
|
|
|
# the value to ensure that it is defined. |
978
|
0
|
50
|
|
2
|
|
0
|
allow => sub { defined shift @_ ? return 1 : return 0 } |
979
|
0
|
|
|
|
|
0
|
); |
980
|
|
|
|
|
|
|
} |
981
|
|
|
|
|
|
|
|
982
|
0
|
|
|
|
|
0
|
return $fetchwarefile_name, $fetchwarefile_name_value; |
983
|
|
|
|
|
|
|
} |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
sub get_lookup_url { |
988
|
0
|
|
|
1
|
1
|
0
|
my $term = shift; |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
# prompt for lookup_url. |
992
|
0
|
|
|
|
|
0
|
my $lookup_url = $term->get_reply( |
993
|
|
|
|
|
|
|
print_me => <
|
994
|
|
|
|
|
|
|
Fetchware's heart and soul is its lookup_url. This is the configuration option |
995
|
|
|
|
|
|
|
that tells fetchware where to check what the latest version of your program is. |
996
|
|
|
|
|
|
|
This version number is then parsed out of the HTTP/FTP/local directory listing, |
997
|
|
|
|
|
|
|
and compared against the latest installed version to determine when a new |
998
|
|
|
|
|
|
|
version of your program has been released. |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
How to determine your application's lookup_url: |
1001
|
|
|
|
|
|
|
1. Go to your application's Web site. |
1002
|
|
|
|
|
|
|
2. Determine the download link for the latest version and copy it with |
1003
|
|
|
|
|
|
|
CTRL-C or right-click it and select "copy". |
1004
|
|
|
|
|
|
|
3. Paste the download link into your browser's URL Location Bar. |
1005
|
|
|
|
|
|
|
4. Delete the filename from the location by starting at the end and deleting |
1006
|
|
|
|
|
|
|
everything to the left until you reach a slash '/'. |
1007
|
|
|
|
|
|
|
* ftp://a.url/downloads/program.tar.gz -> ftp://a.url/downloads/ |
1008
|
|
|
|
|
|
|
5. Press enter to access the directory listing on your Application's mirror |
1009
|
|
|
|
|
|
|
site. |
1010
|
|
|
|
|
|
|
6. If the directory listing in either FTP or HTTP format is displayed in |
1011
|
|
|
|
|
|
|
your browser, then Fetchware's default, built-in lookup fuctionality will |
1012
|
|
|
|
|
|
|
probably work properly. Copy and paste this URL into the prompt below, and |
1013
|
|
|
|
|
|
|
Fetchware will download and analyze your lookup_url to see if it will work |
1014
|
|
|
|
|
|
|
properly. If you do not end up with a browser directory listing, then |
1015
|
|
|
|
|
|
|
please see Fetchware's documentation using perldoc App::Fetchware. |
1016
|
|
|
|
|
|
|
EOP |
1017
|
|
|
|
|
|
|
prompt => q{What is your application's lookup_url? }, |
1018
|
|
|
|
|
|
|
allow => qr!(ftp|http|file)://!); |
1019
|
|
|
|
|
|
|
|
1020
|
0
|
|
|
|
|
0
|
return $lookup_url; |
1021
|
|
|
|
|
|
|
} |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
sub download_lookup_url { |
1026
|
0
|
|
|
1
|
1
|
0
|
my $term = shift; |
1027
|
0
|
|
|
|
|
0
|
my $lookup_url = shift; |
1028
|
|
|
|
|
|
|
|
1029
|
0
|
|
|
|
|
0
|
my $filename_listing; |
1030
|
|
|
|
|
|
|
eval { |
1031
|
|
|
|
|
|
|
# Use no_mirror_download_dirlist(), because the regular one uses |
1032
|
|
|
|
|
|
|
# config(qw(lookup_url mirror)), which is not known yet. |
1033
|
0
|
|
|
|
|
0
|
my $directory_listing = no_mirror_download_dirlist($lookup_url); |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
# Create a fake lookup_url, because parse_directory_listing() uses it to |
1036
|
|
|
|
|
|
|
# determine the type of *_filename_listing() subroutine to call. |
1037
|
0
|
|
|
|
|
0
|
config(lookup_url => $lookup_url); |
1038
|
|
|
|
|
|
|
|
1039
|
0
|
|
|
|
|
0
|
$filename_listing = parse_directory_listing($directory_listing); |
1040
|
|
|
|
|
|
|
|
1041
|
0
|
|
|
|
|
0
|
__clear_CONFIG(); |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
# Fix the most annoying bug that ever existed in perl. |
1044
|
|
|
|
|
|
|
# http://blog.twoshortplanks.com/2011/06/06/unexceptional-exceptions-in-perl-5-14/ |
1045
|
0
|
|
|
|
|
0
|
1; |
1046
|
0
|
50
|
|
|
|
0
|
} or do { |
1047
|
0
|
|
|
|
|
0
|
my $lookup_url_failed_try_again = <
|
1048
|
|
|
|
|
|
|
fetchware: the lookup_url you provided failed because of : |
1049
|
|
|
|
|
|
|
[$@] |
1050
|
|
|
|
|
|
|
Please try again. Try the steps outlined above to determine what your program's |
1051
|
|
|
|
|
|
|
lookup_url should be. If you cannot figure out what it should be please see |
1052
|
0
|
|
|
|
|
0
|
perldoc @{[extension_name()]} for additional hints on how to choose a lookup_url. |
1053
|
|
|
|
|
|
|
EOF |
1054
|
0
|
|
|
|
|
0
|
$lookup_url = get_lookup_url($term, $lookup_url_failed_try_again); |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
eval { |
1057
|
|
|
|
|
|
|
# Use no_mirror_download_dirlist(), because the regular one uses |
1058
|
|
|
|
|
|
|
# config(qw(lookup_url mirror)), which is not known yet. |
1059
|
0
|
|
|
|
|
0
|
my $dir_list = no_mirror_download_dirlist($lookup_url); |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
# Create a fake lookup_url, because parse_directory_listing() uses |
1062
|
|
|
|
|
|
|
# it to determine the type of *_filename_listing() subroutine to |
1063
|
|
|
|
|
|
|
# call. |
1064
|
0
|
|
|
|
|
0
|
config(lookup_url => $lookup_url); |
1065
|
|
|
|
|
|
|
|
1066
|
0
|
|
|
|
|
0
|
$filename_listing = parse_directory_listing($dir_list); |
1067
|
|
|
|
|
|
|
|
1068
|
0
|
|
|
|
|
0
|
__clear_CONFIG(); |
1069
|
|
|
|
|
|
|
# Fix the most annoying bug that ever existed in perl. |
1070
|
|
|
|
|
|
|
# http://blog.twoshortplanks.com/2011/06/06/unexceptional-exceptions-in-perl-5-14/ |
1071
|
0
|
|
|
|
|
0
|
1; |
1072
|
0
|
50
|
|
|
|
0
|
} or do { |
1073
|
0
|
|
|
|
|
0
|
die <
|
1074
|
|
|
|
|
|
|
fetchware: run-time error. The lookup_url you provided [$lookup_url] is not a |
1075
|
|
|
|
|
|
|
usable lookup_url because of the error below: |
1076
|
|
|
|
|
|
|
[$@] |
1077
|
0
|
|
|
|
|
0
|
Please see perldoc @{[extension_name()]} for troubleshooting tips and rerun |
1078
|
|
|
|
|
|
|
fetchware new. |
1079
|
|
|
|
|
|
|
EOD |
1080
|
|
|
|
|
|
|
}; |
1081
|
|
|
|
|
|
|
}; |
1082
|
|
|
|
|
|
|
|
1083
|
0
|
|
|
|
|
0
|
return $filename_listing; |
1084
|
|
|
|
|
|
|
} |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
###BUGALERT### Use the $filename_listing argument to search for a MIRRORS file |
1089
|
|
|
|
|
|
|
#that specifies this open source distribution's official listing of mirrors, |
1090
|
|
|
|
|
|
|
#parse it, and add them to the returned hash or mirrors. But, it'll probably |
1091
|
|
|
|
|
|
|
#need configuration. Use GeoIP? No options are avalable. Parse the list, and |
1092
|
|
|
|
|
|
|
#present it to the user, and ask him to pick some:) |
1093
|
|
|
|
|
|
|
sub get_mirrors { |
1094
|
0
|
|
|
1
|
1
|
0
|
my ($term, $filename_listing) = @_; |
1095
|
|
|
|
|
|
|
|
1096
|
0
|
|
|
|
|
0
|
my @mirrors; |
1097
|
|
|
|
|
|
|
|
1098
|
0
|
|
|
|
|
0
|
my $mirror = $term->get_reply( |
1099
|
|
|
|
|
|
|
print_me => <
|
1100
|
|
|
|
|
|
|
Fetchware requires you to please provide a mirror. This mirror is required, |
1101
|
|
|
|
|
|
|
because most software authors prefer users download their software packages from |
1102
|
|
|
|
|
|
|
a mirror instead of from the authors main download site, which your lookup_url |
1103
|
|
|
|
|
|
|
should point to. |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
The mirror should be a URL in standard browser format such as [ftp://a.mirror/]. |
1106
|
|
|
|
|
|
|
FTP, HTTP, and local file:// mirrors are supported. All other formats are not |
1107
|
|
|
|
|
|
|
supported. |
1108
|
|
|
|
|
|
|
EOP |
1109
|
|
|
|
|
|
|
prompt => 'Please enter the URL of your mirror: ', |
1110
|
|
|
|
|
|
|
allow => qr!^(ftp|http|file)://!, |
1111
|
|
|
|
|
|
|
); |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
# Append mirror to $fetchwarefile. |
1114
|
0
|
|
|
|
|
0
|
push @mirrors, $mirror; |
1115
|
|
|
|
|
|
|
|
1116
|
0
|
50
|
|
|
|
0
|
if ( |
1117
|
|
|
|
|
|
|
$term->ask_yn( |
1118
|
|
|
|
|
|
|
print_me => <
|
1119
|
|
|
|
|
|
|
In addition to the one required mirror that you must define in order for |
1120
|
|
|
|
|
|
|
fetchware to function properly, you may specify additonal mirros that fetchware |
1121
|
|
|
|
|
|
|
will use if the mirror you've already specified is unreachable or download |
1122
|
|
|
|
|
|
|
attempts using that mirror fail. |
1123
|
|
|
|
|
|
|
EOP |
1124
|
|
|
|
|
|
|
prompt => 'Would you like to add any additional mirrors? ', |
1125
|
|
|
|
|
|
|
default => 'n', |
1126
|
|
|
|
|
|
|
) |
1127
|
|
|
|
|
|
|
) { |
1128
|
|
|
|
|
|
|
# Prompt for first mirror outside loop, because if you just hit enter or |
1129
|
|
|
|
|
|
|
# type done, then the above text will be appended to your fetchwarefile, |
1130
|
|
|
|
|
|
|
# but you'll be able to skip actually adding a mirror. |
1131
|
0
|
|
|
|
|
0
|
my $first_mirror = $term->get_reply( |
1132
|
|
|
|
|
|
|
prompt => 'Type in URL of mirror or done to continue: ', |
1133
|
|
|
|
|
|
|
allow => qr!^(ftp|http|file)://!, |
1134
|
|
|
|
|
|
|
); |
1135
|
|
|
|
|
|
|
# Append $first_mirror to $fetchwarefile. |
1136
|
0
|
|
|
|
|
0
|
push @mirrors, $first_mirror; |
1137
|
|
|
|
|
|
|
|
1138
|
0
|
|
|
|
|
0
|
while (1) { |
1139
|
0
|
|
|
|
|
0
|
my $mirror_or_done = $term->get_reply( |
1140
|
|
|
|
|
|
|
prompt => 'Type in URL of mirror or done to continue: ', |
1141
|
|
|
|
|
|
|
default => 'done', |
1142
|
|
|
|
|
|
|
allow => qr!(^(ftp|http|file)://)|done!, |
1143
|
|
|
|
|
|
|
); |
1144
|
0
|
50
|
|
|
|
0
|
if ($mirror_or_done eq 'done') { |
1145
|
0
|
|
|
|
|
0
|
last; |
1146
|
|
|
|
|
|
|
} else { |
1147
|
|
|
|
|
|
|
# Append $mirror_or_done to $fetchwarefile. |
1148
|
0
|
|
|
|
|
0
|
push @mirrors, $mirror_or_done; |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
} |
1151
|
|
|
|
|
|
|
} |
1152
|
|
|
|
|
|
|
|
1153
|
0
|
|
|
|
|
0
|
return {mirror => \@mirrors}; |
1154
|
|
|
|
|
|
|
} |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
sub get_verification { |
1159
|
0
|
|
|
1
|
1
|
0
|
my ($term, $filename_listing, $lookup_url) = @_; |
1160
|
|
|
|
|
|
|
|
1161
|
0
|
|
|
|
|
0
|
my %options; |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
my %available_verify_methods; |
1164
|
|
|
|
|
|
|
# Determine what types of verification are available. |
1165
|
0
|
|
|
|
|
0
|
for my $file_and_timestamp (@$filename_listing) { |
1166
|
0
|
50
|
|
|
|
0
|
if ($file_and_timestamp->[0] =~ /\.(asc|sig|sign)$/) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1167
|
0
|
|
|
|
|
0
|
$available_verify_methods{gpg}++; |
1168
|
|
|
|
|
|
|
} elsif ($file_and_timestamp->[0] =~ /\.sha1?$/) { |
1169
|
0
|
|
|
|
|
0
|
$available_verify_methods{sha1}++; |
1170
|
|
|
|
|
|
|
} elsif ($file_and_timestamp->[0] =~ /\.md5$/) { |
1171
|
0
|
|
|
|
|
0
|
$available_verify_methods{md5}++; |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
} |
1174
|
|
|
|
|
|
|
|
1175
|
0
|
|
|
|
|
0
|
my $verify_configed_flag = 0; |
1176
|
|
|
|
|
|
|
#If gpg is available prefer it over the others. |
1177
|
0
|
50
|
0
|
|
|
0
|
if (exists $available_verify_methods{gpg} |
|
|
|
0
|
|
|
|
|
1178
|
|
|
|
|
|
|
and defined $available_verify_methods{gpg} |
1179
|
|
|
|
|
|
|
and $available_verify_methods{gpg} > 0 |
1180
|
|
|
|
|
|
|
) { |
1181
|
0
|
|
|
|
|
0
|
msg <
|
1182
|
|
|
|
|
|
|
gpg digital signatures found. Using gpg verification. |
1183
|
|
|
|
|
|
|
EOM |
1184
|
0
|
|
|
|
|
0
|
$options{verify_method} = 'gpg'; |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
# Search for a KEYS file to use to import the author's keys. |
1187
|
0
|
50
|
|
|
|
0
|
if (grep {$_->[0] eq 'KEYS'} @$filename_listing) { |
|
0
|
|
|
|
|
0
|
|
1188
|
0
|
|
|
|
|
0
|
msg <
|
1189
|
|
|
|
|
|
|
KEYS file found using lookup_url. Adding gpg_keys_url to your Fetchwarefile. |
1190
|
|
|
|
|
|
|
EOM |
1191
|
|
|
|
|
|
|
# Add 'KEYS' or '/KEYS' to $lookup_url's path. |
1192
|
0
|
|
|
|
|
0
|
my ($scheme, $auth, $path, $query, $fragment) = |
1193
|
|
|
|
|
|
|
uri_split($lookup_url); |
1194
|
0
|
|
|
|
|
0
|
$path = catfile($path, 'KEYS'); |
1195
|
0
|
|
|
|
|
0
|
$lookup_url = uri_join($scheme, $auth, $path, $query, $fragment); |
1196
|
|
|
|
|
|
|
|
1197
|
0
|
|
|
|
|
0
|
$options{gpg_keys_url} = $lookup_url; |
1198
|
0
|
|
|
|
|
0
|
$verify_configed_flag++; |
1199
|
|
|
|
|
|
|
} else { |
1200
|
0
|
|
|
|
|
0
|
msg <
|
1201
|
|
|
|
|
|
|
KEYS file *not* found! |
1202
|
|
|
|
|
|
|
EOM |
1203
|
|
|
|
|
|
|
# Since autoconfiguration of KEYS failed, try asking the user if |
1204
|
|
|
|
|
|
|
# they would like to import the author's key themselves into their |
1205
|
|
|
|
|
|
|
# own keyring and have fetchware use that. |
1206
|
0
|
50
|
|
|
|
0
|
if ( |
1207
|
|
|
|
|
|
|
$term->ask_yn(prompt => |
1208
|
|
|
|
|
|
|
q{Would you like to import the author's key yourself after fetchware completes? }, |
1209
|
|
|
|
|
|
|
default => 'n', |
1210
|
|
|
|
|
|
|
print_me => <
|
1211
|
|
|
|
|
|
|
Automatic KEYS file discovery failed. Fetchware needs the author's keys to |
1212
|
|
|
|
|
|
|
download and import into its own keyring, or you may specify the option |
1213
|
|
|
|
|
|
|
user_keyring, which if true will cause fetchware to use the user who runs |
1214
|
|
|
|
|
|
|
fetchware's keyring instead of fetchware's own keyring. But you, the user, needs |
1215
|
|
|
|
|
|
|
to import the author's keys into your own gpg keyring. You can do this now in a |
1216
|
|
|
|
|
|
|
separate shell, or after you finish configuring this Fetchwarefile. Just run the |
1217
|
|
|
|
|
|
|
command [gpg --import ]. |
1218
|
|
|
|
|
|
|
EOP |
1219
|
|
|
|
|
|
|
) |
1220
|
|
|
|
|
|
|
) { |
1221
|
0
|
|
|
|
|
0
|
$options{user_keyring} = 'On'; |
1222
|
|
|
|
|
|
|
|
1223
|
0
|
|
|
|
|
0
|
$verify_configed_flag++; |
1224
|
|
|
|
|
|
|
} |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
# And if the user does not want to, then fallback to sha1 and/or md5 |
1227
|
|
|
|
|
|
|
# if they're defined, which is done below. |
1228
|
|
|
|
|
|
|
} |
1229
|
|
|
|
|
|
|
} |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
# Only try sha1 and md5 if gpg failed. |
1233
|
0
|
50
|
|
|
|
0
|
unless ($verify_configed_flag == 1) { |
1234
|
0
|
50
|
0
|
|
|
0
|
if (exists $available_verify_methods{sha1} |
|
|
50
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
1235
|
|
|
|
|
|
|
and defined $available_verify_methods{sha1} |
1236
|
|
|
|
|
|
|
and $available_verify_methods{sha1} > 0 |
1237
|
|
|
|
|
|
|
) { |
1238
|
0
|
|
|
|
|
0
|
msg <
|
1239
|
|
|
|
|
|
|
SHA1 checksums found. Using SHA1 verification. |
1240
|
|
|
|
|
|
|
EOM |
1241
|
0
|
|
|
|
|
0
|
$options{verify_method} = 'sha1'; |
1242
|
|
|
|
|
|
|
} elsif (exists $available_verify_methods{md5} |
1243
|
|
|
|
|
|
|
and defined $available_verify_methods{md5} |
1244
|
|
|
|
|
|
|
and $available_verify_methods{md5} > 0 |
1245
|
|
|
|
|
|
|
) { |
1246
|
0
|
|
|
|
|
0
|
msg <
|
1247
|
|
|
|
|
|
|
MD5 checksums found. Using MD5 verification. |
1248
|
|
|
|
|
|
|
EOM |
1249
|
0
|
|
|
|
|
0
|
$options{verify_method} = 'md5'; |
1250
|
|
|
|
|
|
|
} else { |
1251
|
|
|
|
|
|
|
# Print a huge long nasty warning even include links to news stories |
1252
|
|
|
|
|
|
|
# of mirrors actually getting hacked and serving malware, which |
1253
|
|
|
|
|
|
|
# would be detected and prevented with proper verification enabled. |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
# Ask user if they would like to continue installing fetchware even if |
1256
|
|
|
|
|
|
|
# verification fails, and then enable the verify_failure_ok option. |
1257
|
0
|
50
|
|
|
|
0
|
if ( |
1258
|
|
|
|
|
|
|
$term->ask_yn(prompt => <
|
1259
|
|
|
|
|
|
|
Would you like fetchware to ignore the fact that it is unable to verify the |
1260
|
|
|
|
|
|
|
authenticity of any downloads it makes? Are you ok with possibly downloading |
1261
|
|
|
|
|
|
|
viruses, worms, rootkits, or any other malware, and installing it possibly even |
1262
|
|
|
|
|
|
|
as root? |
1263
|
|
|
|
|
|
|
EOP |
1264
|
|
|
|
|
|
|
default => 'n', |
1265
|
|
|
|
|
|
|
print_me => <
|
1266
|
|
|
|
|
|
|
Automatic verification of your fetchware package has failed! Fetchware is |
1267
|
|
|
|
|
|
|
capable of ignoring the error, and installing software packages anyway using its |
1268
|
|
|
|
|
|
|
verify_failure_ok configuration option. However, installing software packages |
1269
|
|
|
|
|
|
|
without verifying that they have not been tampered with could allow hackers to |
1270
|
|
|
|
|
|
|
potentially install malware onto your computer. Don't think this is *not* |
1271
|
|
|
|
|
|
|
possible or do you think its extremely unlikely? Well, it's actually |
1272
|
|
|
|
|
|
|
surprisingly common: |
1273
|
|
|
|
|
|
|
1. http://arstechnica.com/security/2012/09/questions-abound-as-malicious-phpmyadmin-backdoor-found-on-sourceforge-site/ |
1274
|
|
|
|
|
|
|
Discusses how a mirror for sourceforge was hacked, and the phpMyAdmin |
1275
|
|
|
|
|
|
|
software package on that mirror was modified to spread malware. |
1276
|
|
|
|
|
|
|
2. http://www.geek.com/news/major-open-source-code-repository-hacked-for-months-says-fsf-551344/ |
1277
|
|
|
|
|
|
|
Discusses how FSF's gnu.org ftp download site was hacked. |
1278
|
|
|
|
|
|
|
3. http://arstechnica.com/security/2012/11/malicious-code-added-to-open-source-piwik-following-website-compromise/ |
1279
|
|
|
|
|
|
|
Discusses how Piwiki's wordpress software was hacked, and downloads of |
1280
|
|
|
|
|
|
|
Piwiki had malicious code inserted into them. |
1281
|
|
|
|
|
|
|
4. http://www.theregister.co.uk/2011/03/21/php_server_hacked/ |
1282
|
|
|
|
|
|
|
Discusses how php's wiki.php.org server was hacked yielding credentials to |
1283
|
|
|
|
|
|
|
php's source code repository. |
1284
|
|
|
|
|
|
|
Download mirrors *do* get hacked. Do not make the mistake, and think that it is |
1285
|
|
|
|
|
|
|
not possible. It is possible, and it does happen, so please properly configure |
1286
|
|
|
|
|
|
|
your Fetchwarefile to enable fetchware to verify that the downloaded software is |
1287
|
|
|
|
|
|
|
the same what the author uploaded. |
1288
|
|
|
|
|
|
|
EOP |
1289
|
|
|
|
|
|
|
) |
1290
|
|
|
|
|
|
|
) { |
1291
|
|
|
|
|
|
|
# If the user is ok with not properly verifying downloads, then |
1292
|
|
|
|
|
|
|
# ignore the failure, and install anyway. |
1293
|
0
|
|
|
|
|
0
|
$options{verify_failure_ok} = 'On'; |
1294
|
|
|
|
|
|
|
} else { |
1295
|
|
|
|
|
|
|
# Otherwise, throw an exception. |
1296
|
0
|
|
|
|
|
0
|
die <
|
1297
|
|
|
|
|
|
|
fetchware: Fetchware *must* be able to verify any software packages that it |
1298
|
|
|
|
|
|
|
downloads. The Fetchwarefile that you were creating could not do this, because |
1299
|
|
|
|
|
|
|
you failed to specify how fetchware can verify its downloads. Please rerun |
1300
|
|
|
|
|
|
|
fetchware new again, and this time be sure to specify a gpg_keys_url, specify |
1301
|
|
|
|
|
|
|
user_keyring to use your own gpg keyring, or answer yes to the question |
1302
|
|
|
|
|
|
|
regarding adding verify_failure_ok to your Fetchwarefile to make failing |
1303
|
|
|
|
|
|
|
verificaton acceptable to fetchware. |
1304
|
|
|
|
|
|
|
EOD |
1305
|
|
|
|
|
|
|
} |
1306
|
|
|
|
|
|
|
} |
1307
|
|
|
|
|
|
|
} |
1308
|
|
|
|
|
|
|
|
1309
|
0
|
|
|
|
|
0
|
return \%options; |
1310
|
|
|
|
|
|
|
} |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
|
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
sub get_filter_option { |
1315
|
0
|
|
|
1
|
1
|
0
|
my $term = shift; |
1316
|
|
|
|
|
|
|
# $filename_listing is an array of [$filename, $timestamp] arrays. |
1317
|
0
|
|
|
|
|
0
|
my $filename_listing = shift; |
1318
|
0
|
|
|
|
|
0
|
msg <
|
1319
|
|
|
|
|
|
|
Analyzing the lookup_url you provided to determine if fetchware can use it to |
1320
|
|
|
|
|
|
|
successfully determine when new versions of your software are released. |
1321
|
|
|
|
|
|
|
EOS |
1322
|
|
|
|
|
|
|
|
1323
|
0
|
|
|
|
|
0
|
my $filter; |
1324
|
0
|
0
|
|
|
|
0
|
if (grep {$_->[0] =~ /^(CURRENT|LATEST)[_-]IS[_-].+/} @$filename_listing) { |
|
0
|
|
|
|
|
0
|
|
1325
|
|
|
|
|
|
|
# There is only one version in the lookup_url directory listing, so |
1326
|
|
|
|
|
|
|
# I do not need a filter option. |
1327
|
0
|
|
|
|
|
0
|
msg <
|
1328
|
|
|
|
|
|
|
* The lookup_url you gave fetchware includes a CURRENT_IS or a LATEST_IS file |
1329
|
|
|
|
|
|
|
that tells fetchware and regular users what the latest version is. Because of |
1330
|
|
|
|
|
|
|
this we can be reasonable sure that a filter option is not needed, so I'll skip |
1331
|
|
|
|
|
|
|
asking for one. You can provide one later if you need to provide one, when |
1332
|
|
|
|
|
|
|
fetchware prompts you for any custom options you may want to use. |
1333
|
|
|
|
|
|
|
EOS |
1334
|
|
|
|
|
|
|
} else { |
1335
|
|
|
|
|
|
|
# There is a CURRENT_IS_ or LATEST_IS_ file that tells |
1336
|
|
|
|
|
|
|
# you what the latest version is. |
1337
|
|
|
|
|
|
|
###BUGALERT### Why is this line in both sections of the if statement??? Inside |
1338
|
|
|
|
|
|
|
#this else block means that a CURRENT_IS or LATEST-IS was *not* found??? Fix |
1339
|
|
|
|
|
|
|
#this!!!!!! |
1340
|
0
|
|
|
|
|
0
|
msg <
|
1341
|
|
|
|
|
|
|
* The directory listing of your lookup_url has a CURRENT_IS_ or |
1342
|
|
|
|
|
|
|
LATEST_IS_ file that specifies the latest version, which means that |
1343
|
|
|
|
|
|
|
your program's corresponding Fetchwarefile does not need a filter option. If you |
1344
|
|
|
|
|
|
|
still would like to provide one, you can do so later on, when fetchware allows |
1345
|
|
|
|
|
|
|
you to define any additional configuration options. |
1346
|
|
|
|
|
|
|
EOS |
1347
|
0
|
|
|
|
|
0
|
my $what_a_filter_is = <
|
1348
|
|
|
|
|
|
|
Fetchware needs you to provide a filter option, which is a pattern that fetchware |
1349
|
|
|
|
|
|
|
compares each file in the directory listing of your lookup_url to to determine |
1350
|
|
|
|
|
|
|
which version of your program to install. |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
Directories will have other junk files in them or even completely different |
1353
|
|
|
|
|
|
|
programs that could confuse fetchware, and even potentially cause it to install |
1354
|
|
|
|
|
|
|
a different program. Therefore, you should also add the program name to the |
1355
|
|
|
|
|
|
|
begining of your filter. For example if you program is apache, then your filter |
1356
|
|
|
|
|
|
|
should include the name of apache on mirror sites, which is actually: |
1357
|
|
|
|
|
|
|
httpd |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
For example, Apache's lookup_url has three versions in the same lookup_url |
1360
|
|
|
|
|
|
|
directory listing. These are 2.4, 2.2, and 2.0. Without the filter option |
1361
|
|
|
|
|
|
|
fetchware would choose the highest, which would be 2.4, which is the latest |
1362
|
|
|
|
|
|
|
version. However, you may want to stick with the older and perhaps more stable |
1363
|
|
|
|
|
|
|
2.2 version of apache. Therefore, you'll need to tell fetchware this by using |
1364
|
|
|
|
|
|
|
by adding the version number to your filter: |
1365
|
|
|
|
|
|
|
httpd-2.2 |
1366
|
|
|
|
|
|
|
will result in fetchware filtering the results of its lookup check through your |
1367
|
|
|
|
|
|
|
filter of httpd-2.2 causing fetchware to choose the latest version from the 2.2 |
1368
|
|
|
|
|
|
|
stable branch instead of the higher version numbered 2.4 or 2.0 legacy releases. |
1369
|
|
|
|
|
|
|
Note the use of the dash, which is used in the filename to separate the 'httpd' |
1370
|
|
|
|
|
|
|
name part from the '2.2' version part. |
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
Note: fetchware accepts any valid perl regular expresion as an acceptable |
1373
|
|
|
|
|
|
|
filter option, but that should only be needed for advanced users. See perldoc |
1374
|
|
|
|
|
|
|
fetchware. |
1375
|
|
|
|
|
|
|
EOA |
1376
|
|
|
|
|
|
|
# Prompt for the needed filter option. |
1377
|
0
|
|
|
|
|
0
|
$filter = $term->get_reply( |
1378
|
|
|
|
|
|
|
prompt => <
|
1379
|
|
|
|
|
|
|
[Just press enter or return to skip adding a filter option] |
1380
|
|
|
|
|
|
|
What does fetchware need your filter option to be? |
1381
|
|
|
|
|
|
|
EOP |
1382
|
|
|
|
|
|
|
print_me => $what_a_filter_is, |
1383
|
|
|
|
|
|
|
); |
1384
|
|
|
|
|
|
|
###BUGALERT### Consider Adding a loop around checking the filter option |
1385
|
|
|
|
|
|
|
#that runs determine_lookup_url() using the provided filter option, and |
1386
|
|
|
|
|
|
|
#then asking the user if that is indeed the correct filter option, and |
1387
|
|
|
|
|
|
|
#if not ask again and try it again unit it succeeds or user presses |
1388
|
|
|
|
|
|
|
#ctrl-c|z. |
1389
|
|
|
|
|
|
|
} |
1390
|
|
|
|
|
|
|
|
1391
|
0
|
|
|
|
|
0
|
return {filter => $filter}; |
1392
|
|
|
|
|
|
|
} |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
|
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
sub prompt_for_other_options { |
1397
|
0
|
|
|
1
|
1
|
0
|
my $term = shift; |
1398
|
|
|
|
|
|
|
|
1399
|
0
|
|
|
|
|
0
|
my %option_description = @_; |
1400
|
|
|
|
|
|
|
|
1401
|
0
|
|
|
|
|
0
|
my %answered_option; |
1402
|
|
|
|
|
|
|
|
1403
|
0
|
0
|
|
|
|
0
|
if ( |
1404
|
|
|
|
|
|
|
$term->ask_yn(prompt => |
1405
|
|
|
|
|
|
|
q{Would you like to add extra configuration options to your fetchwarefile?}, |
1406
|
|
|
|
|
|
|
default => 'n', |
1407
|
|
|
|
|
|
|
print_me => <
|
1408
|
|
|
|
|
|
|
Fetchware has many different configuration options that allow you to control its |
1409
|
|
|
|
|
|
|
behavior, and even change its behavior if needed to customize fetchware for any |
1410
|
|
|
|
|
|
|
possible source code distribution. |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
If you think you need to add configuration options please check out perldoc |
1413
|
|
|
|
|
|
|
fetchware for more details on fetchware and its Fetchwarefile configuration |
1414
|
|
|
|
|
|
|
options. |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
If this is your first package your creating with Fetchware or you're creating a |
1417
|
|
|
|
|
|
|
package for a new program for the first time, you should skip messing with |
1418
|
|
|
|
|
|
|
fetchware's more flexible options, and just give the defaults a chance. |
1419
|
|
|
|
|
|
|
EOP |
1420
|
|
|
|
|
|
|
) |
1421
|
|
|
|
|
|
|
) { |
1422
|
0
|
|
|
|
|
0
|
my @options = keys %option_description; |
1423
|
0
|
|
|
|
|
0
|
my @config_file_options_to_provide = $term->get_reply( |
1424
|
|
|
|
|
|
|
print_me => <
|
1425
|
|
|
|
|
|
|
Below is a listing of Fetchware's available configuration options. |
1426
|
|
|
|
|
|
|
EOP |
1427
|
|
|
|
|
|
|
prompt => <
|
1428
|
|
|
|
|
|
|
Please answer with a space seperated list of the number before the configuration |
1429
|
|
|
|
|
|
|
file options that you would like to add to your configuration file? |
1430
|
|
|
|
|
|
|
EOP |
1431
|
|
|
|
|
|
|
choices => \@options, |
1432
|
|
|
|
|
|
|
multi => 1, |
1433
|
|
|
|
|
|
|
); |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
|
1436
|
0
|
|
|
|
|
0
|
for my $config_file_option (@config_file_options_to_provide) { |
1437
|
|
|
|
|
|
|
$answered_option{$config_file_option} = $term->get_reply( |
1438
|
|
|
|
|
|
|
print_me => $option_description{$config_file_option}->{print_me}, |
1439
|
|
|
|
|
|
|
prompt => $option_description{$config_file_option}->{prompt}, |
1440
|
0
|
|
|
|
|
0
|
); |
1441
|
|
|
|
|
|
|
} |
1442
|
|
|
|
|
|
|
} |
1443
|
0
|
|
|
|
|
0
|
return \%answered_option; |
1444
|
|
|
|
|
|
|
} |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
|
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
sub edit_manually { |
1449
|
0
|
|
|
1
|
1
|
0
|
my ($term, $fetchwarefile) = @_; |
1450
|
|
|
|
|
|
|
|
1451
|
0
|
0
|
|
|
|
0
|
if ( |
1452
|
|
|
|
|
|
|
$term->ask_yn( |
1453
|
|
|
|
|
|
|
print_me => <
|
1454
|
|
|
|
|
|
|
Fetchware has now asked you all of the needed questions to determine what it |
1455
|
|
|
|
|
|
|
thinks your new program's Fetchwarefile should look like. But it's not perfect, |
1456
|
|
|
|
|
|
|
and perhaps you would like to tweak it manually. If you would like to edit it |
1457
|
|
|
|
|
|
|
manually in your favorite editor, answer 'yes', and if you want to skip this just |
1458
|
|
|
|
|
|
|
answer 'no', or just press . |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
If you would like to cancel any edits you have made, and use the automagically |
1461
|
|
|
|
|
|
|
generated Fetchwarefile, just delete the entire contents of the file, and save |
1462
|
|
|
|
|
|
|
an empty file. |
1463
|
|
|
|
|
|
|
EOP |
1464
|
|
|
|
|
|
|
prompt => q{Would you like to edit your automagically generated Fetchwarefile manually? }, |
1465
|
|
|
|
|
|
|
default => 'n', |
1466
|
|
|
|
|
|
|
) |
1467
|
|
|
|
|
|
|
) { |
1468
|
0
|
|
|
|
|
0
|
my ($fh, $fetchwarefile_filename) = |
1469
|
|
|
|
|
|
|
tempfile('Fetchwarefile-XXXXXXXXX', TMPDIR => 1); |
1470
|
0
|
|
|
|
|
0
|
print $fh $fetchwarefile->generate(); |
1471
|
|
|
|
|
|
|
|
1472
|
0
|
|
|
|
|
0
|
close $fh; |
1473
|
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
# Ask what editor to use if EDITOR environment variable is not set. |
1475
|
0
|
|
0
|
|
|
0
|
my $editor = $ENV{EDITOR} || do { |
1476
|
|
|
|
|
|
|
$term->get_reply(prompt => <
|
1477
|
|
|
|
|
|
|
What text editor would you like to use? |
1478
|
|
|
|
|
|
|
EOP |
1479
|
|
|
|
|
|
|
print_me => <
|
1480
|
|
|
|
|
|
|
The Environment variable EDITOR is not set. This is used by fetchware and other |
1481
|
|
|
|
|
|
|
programs to determine what program fetchware should use to edit your |
1482
|
|
|
|
|
|
|
Fetchwarefile. Please enter what text editor you would like to use. Examples |
1483
|
|
|
|
|
|
|
include: vim, emacs, nano, pico, or notepad.exe (on Windows). |
1484
|
|
|
|
|
|
|
EOP |
1485
|
|
|
|
|
|
|
); |
1486
|
|
|
|
|
|
|
}; |
1487
|
|
|
|
|
|
|
|
1488
|
0
|
|
|
|
|
0
|
run_prog($editor, $fetchwarefile_filename); |
1489
|
|
|
|
|
|
|
# NOTE: fetchware will "block" during the above call to run_prog(), and |
1490
|
|
|
|
|
|
|
# wait for the user to close the editor program. |
1491
|
|
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
# If the edited Fetchwarefile does not have a file size of zero. |
1493
|
0
|
0
|
|
|
|
0
|
if (not -z $fetchwarefile_filename) { |
1494
|
0
|
|
|
|
|
0
|
my $fh = safe_open($fetchwarefile_filename, <
|
1495
|
|
|
|
|
|
|
fetchware: run-time error. fetchware can't open the fetchwarefile you edited |
1496
|
|
|
|
|
|
|
with your editor after you edited it. This just shouldn't happen. Possible race |
1497
|
|
|
|
|
|
|
condition or weird bug. See perldoc fetchware. |
1498
|
|
|
|
|
|
|
EOD |
1499
|
|
|
|
|
|
|
# Since the generated Fetchwarefile has been edited, because its |
1500
|
|
|
|
|
|
|
# size is nonzero, then replace the App::Fetchware::Fetchwarefile |
1501
|
|
|
|
|
|
|
# object with whatever text can be slurped from the file the user |
1502
|
|
|
|
|
|
|
# edited. Since it is now a scalar instead of an object, that is how |
1503
|
|
|
|
|
|
|
# Fetchware will tell if the user changed it or not. |
1504
|
0
|
|
|
|
|
0
|
$fetchwarefile = do { local $/; <$fh> }; # slurp fetchwarefile |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1505
|
|
|
|
|
|
|
} else { |
1506
|
0
|
|
|
|
|
0
|
msg <
|
1507
|
|
|
|
|
|
|
You canceled any custom editing of your fetchwarefile by writing an empty file |
1508
|
|
|
|
|
|
|
to disk. |
1509
|
|
|
|
|
|
|
EOM |
1510
|
|
|
|
|
|
|
} |
1511
|
|
|
|
|
|
|
} |
1512
|
0
|
|
|
|
|
0
|
return $fetchwarefile; |
1513
|
|
|
|
|
|
|
} |
1514
|
|
|
|
|
|
|
|
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
sub new_install { |
1520
|
0
|
|
|
1
|
1
|
0
|
my ($term, $program_name, $fetchwarefile) = @_; |
1521
|
|
|
|
|
|
|
|
1522
|
0
|
|
|
|
|
0
|
my $fetchware_package_path = |
1523
|
|
|
|
|
|
|
ask_to_install_now_to_test_fetchwarefile($term, \$fetchwarefile, |
1524
|
|
|
|
|
|
|
$program_name); |
1525
|
|
|
|
|
|
|
|
1526
|
0
|
|
|
|
|
0
|
return $fetchware_package_path; |
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
} |
1529
|
|
|
|
|
|
|
|
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
|
1532
|
|
|
|
|
|
|
|
1533
|
|
|
|
|
|
|
|
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
sub ask_to_install_now_to_test_fetchwarefile { |
1536
|
0
|
|
|
0
|
1
|
0
|
my ($term, $fetchwarefile, $program_name) = @_; |
1537
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
|
1539
|
0
|
|
|
|
|
0
|
vmsg <
|
1540
|
|
|
|
|
|
|
Determining if user wants to install now or just save their Fetchwarefile. |
1541
|
|
|
|
|
|
|
EOM |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
# If the user wants to install their new Fetchwarefile. |
1544
|
0
|
0
|
|
|
|
0
|
if ( |
1545
|
|
|
|
|
|
|
$term->ask_yn( |
1546
|
|
|
|
|
|
|
print_me => <
|
1547
|
|
|
|
|
|
|
It is recommended that fetchware go ahead and install the package based on the |
1548
|
|
|
|
|
|
|
Fetchwarefile that fetchware has created for you. If you don't want to install |
1549
|
|
|
|
|
|
|
it now, then enter 'no', but if you want to test your Fetchwarefile now, and |
1550
|
|
|
|
|
|
|
install it, then please enter 'yes' or just press . |
1551
|
|
|
|
|
|
|
EOP |
1552
|
|
|
|
|
|
|
prompt => q{Would you like to install the package you just created a Fetchwarefile for? }, |
1553
|
|
|
|
|
|
|
default => 'y', |
1554
|
|
|
|
|
|
|
) |
1555
|
|
|
|
|
|
|
) { |
1556
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
# Create a temp Fetchwarefile to store the autogenerated configuration. |
1558
|
0
|
|
|
|
|
0
|
my ($fh, $fetchwarefile_filename) |
1559
|
|
|
|
|
|
|
= |
1560
|
|
|
|
|
|
|
tempfile("fetchware-$$-XXXXXXXXXXXXXX", TMPDIR => 1, UNLINK => 1); |
1561
|
0
|
|
|
|
|
0
|
print $fh $$fetchwarefile; |
1562
|
|
|
|
|
|
|
# Close the temp file to ensure everything that was written to it gets |
1563
|
|
|
|
|
|
|
# flushed from caches and actually makes it to disk. |
1564
|
0
|
|
|
|
|
0
|
close $fh; |
1565
|
|
|
|
|
|
|
|
1566
|
0
|
|
|
|
|
0
|
vmsg <
|
1567
|
|
|
|
|
|
|
Saved Fetchwarefile temporarily to [$fetchwarefile_filename]. |
1568
|
|
|
|
|
|
|
EOM |
1569
|
|
|
|
|
|
|
|
1570
|
|
|
|
|
|
|
# Reach up bin/fetchware's skirt, and call cmd_install directly, because |
1571
|
|
|
|
|
|
|
# if I use system() and call fetchware again in a separate process using |
1572
|
|
|
|
|
|
|
# the install command, it will return a useless number indicating |
1573
|
|
|
|
|
|
|
# success instead of the $fetchware_package_path I want. I could parse |
1574
|
|
|
|
|
|
|
# the output, but that's a head ache I want to avoid. Instead, I'll just |
1575
|
|
|
|
|
|
|
# be a little frisky. |
1576
|
0
|
|
|
|
|
0
|
my $fetchware_package_path = fetchware::cmd_install($fetchwarefile_filename); |
1577
|
|
|
|
|
|
|
###BUGALERT### Call cmd_install() inside an eval that will catch any |
1578
|
|
|
|
|
|
|
#problems that come up, and suggest how to fix them??? |
1579
|
|
|
|
|
|
|
#Is that really doable??? |
1580
|
0
|
|
|
|
|
0
|
vmsg <
|
1581
|
|
|
|
|
|
|
Copied Fetchwarefile package to fetchware database [$fetchware_package_path]. |
1582
|
|
|
|
|
|
|
EOM |
1583
|
0
|
|
|
|
|
0
|
msg 'Installed Fetchware package to fetchware database.'; |
1584
|
0
|
|
|
|
|
0
|
return $fetchware_package_path; |
1585
|
|
|
|
|
|
|
# Else the user just wants to save the Fetchwarefile somewhere. |
1586
|
|
|
|
|
|
|
} else { |
1587
|
0
|
|
|
|
|
0
|
my $fetchwarefile_filename = $program_name . '.Fetchwarefile'; |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
# Get a name for the Fetchwarefile that does not already exist. |
1590
|
0
|
0
|
|
|
|
0
|
if (-e $fetchwarefile_filename) { |
1591
|
0
|
|
|
|
|
0
|
while (1) { |
1592
|
0
|
|
|
|
|
0
|
$fetchwarefile_filename = $term->get_reply( |
1593
|
|
|
|
|
|
|
prompt => <
|
1594
|
|
|
|
|
|
|
What would you like your new Fetchwarefile's filename to be? |
1595
|
|
|
|
|
|
|
EOP |
1596
|
|
|
|
|
|
|
print_me => <
|
1597
|
|
|
|
|
|
|
Fetchware by default uses the program name you specified at the beginning of |
1598
|
|
|
|
|
|
|
running fetchware new plus a '.Fetchwarefile' extension to name your |
1599
|
|
|
|
|
|
|
Fetchwarefile. But his file already exists, so you'll have to pick a new |
1600
|
|
|
|
|
|
|
filename that does not currently exist. |
1601
|
|
|
|
|
|
|
EOP |
1602
|
|
|
|
|
|
|
); |
1603
|
0
|
0
|
|
|
|
0
|
last unless -e $fetchwarefile_filename; |
1604
|
|
|
|
|
|
|
} |
1605
|
|
|
|
|
|
|
} |
1606
|
0
|
|
|
|
|
0
|
vmsg <
|
1607
|
|
|
|
|
|
|
Determine Fetchwarefile name to be [$fetchwarefile_filename]. |
1608
|
|
|
|
|
|
|
EOM |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
###BUGALERT### Replace >, create or delete whole file and replace it with |
1611
|
|
|
|
|
|
|
#what I write now, with >> for append to file if it already exists???? |
1612
|
|
|
|
|
|
|
###BUGALERT### Should safe_open() be moved into the loop above, and instead |
1613
|
|
|
|
|
|
|
#of checking for existence, open the file using safeopen as needed, but |
1614
|
|
|
|
|
|
|
#don't write to it just yet, and then test the open file handle if it's |
1615
|
|
|
|
|
|
|
#empty, and therefore presumable a new file, or an old file that no one |
1616
|
|
|
|
|
|
|
#cares about anymore, because it's empty? |
1617
|
0
|
|
|
|
|
0
|
my $fh = safe_open($fetchwarefile_filename, < '>'); |
1618
|
|
|
|
|
|
|
fetchware: failed to open your new fetchwarefile because of os error |
1619
|
|
|
|
|
|
|
[$!]. This really shouldn't happen in this case. Probably a bug, or a weird race |
1620
|
|
|
|
|
|
|
condition. |
1621
|
|
|
|
|
|
|
EOD |
1622
|
0
|
|
|
|
|
0
|
print $fh $$fetchwarefile; |
1623
|
|
|
|
|
|
|
|
1624
|
0
|
|
|
|
|
0
|
close $fh; |
1625
|
|
|
|
|
|
|
|
1626
|
0
|
|
|
|
|
0
|
msg "Saved Fetchwarefile to [$fetchwarefile_filename]."; |
1627
|
0
|
|
|
|
|
0
|
return $fetchwarefile_filename; |
1628
|
|
|
|
|
|
|
} |
1629
|
|
|
|
|
|
|
} |
1630
|
|
|
|
|
|
|
|
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
|
1633
|
|
|
|
|
|
|
|
1634
|
|
|
|
|
|
|
sub start { |
1635
|
173
|
|
|
173
|
1
|
1708
|
my %opts = @_; |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
# Add temp_dir config sub to create_tempdir()'s arguments. |
1638
|
173
|
50
|
|
|
|
669
|
if (config('temp_dir')) { |
1639
|
0
|
|
|
|
|
0
|
$opts{TempDir} = config('temp_dir'); |
1640
|
0
|
|
|
|
|
0
|
vmsg "Using user specified temporary directory [$opts{TempDir}]"; |
1641
|
|
|
|
|
|
|
} |
1642
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
# Add KeepTempDir option if no_install is set. That way user can still |
1644
|
|
|
|
|
|
|
# access the build directory to do the install themselves. |
1645
|
173
|
100
|
|
|
|
413
|
if (config('no_install')) { |
1646
|
1
|
|
|
|
|
3
|
$opts{KeepTempDir} = 1; |
1647
|
1
|
|
|
|
|
4
|
vmsg "no_install option enabled not deleting temporary directory."; |
1648
|
|
|
|
|
|
|
} |
1649
|
|
|
|
|
|
|
|
1650
|
|
|
|
|
|
|
# Forward opts to create_tempdir(), which does the heavy lifting. |
1651
|
173
|
|
|
|
|
735
|
my $temp_dir = create_tempdir(%opts); |
1652
|
173
|
|
|
|
|
1221
|
msg "Created fetchware temporary directory [$temp_dir]"; |
1653
|
|
|
|
|
|
|
|
1654
|
173
|
|
|
|
|
1433
|
return $temp_dir; |
1655
|
|
|
|
|
|
|
} |
1656
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
|
1658
|
|
|
|
|
|
|
|
1659
|
|
|
|
|
|
|
|
1660
|
|
|
|
|
|
|
sub lookup { |
1661
|
0
|
|
|
0
|
1
|
0
|
msg "Looking up download url using lookup_url [@{[config('lookup_url')]}]"; |
|
0
|
|
|
|
|
0
|
|
1662
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
# obtain directory listing for file, ftp, or http. (a sub for each.) |
1664
|
0
|
|
|
|
|
0
|
vmsg 'Downloading a directory listing using your lookup_url'; |
1665
|
0
|
|
|
|
|
0
|
my $directory_listing = get_directory_listing(); |
1666
|
0
|
|
|
|
|
0
|
vmsg 'Obtained the following directory listing:'; |
1667
|
0
|
|
|
|
|
0
|
vmsg Dumper($directory_listing); |
1668
|
|
|
|
|
|
|
# parse the directory listing's format based on ftp or http. |
1669
|
0
|
|
|
|
|
0
|
vmsg 'Parse directory listing into internal format.'; |
1670
|
0
|
|
|
|
|
0
|
my $filename_listing = parse_directory_listing($directory_listing); |
1671
|
0
|
|
|
|
|
0
|
vmsg 'Directory listing parsed as:'; |
1672
|
0
|
|
|
|
|
0
|
vmsg Dumper($filename_listing); |
1673
|
|
|
|
|
|
|
# Run those listings through lookup_by_timestamp() and/or |
1674
|
|
|
|
|
|
|
# lookup_by_versionstring() based on lookup_method, or first by timestamp, |
1675
|
|
|
|
|
|
|
# and then by versionstring if timestamp can't figure out the latest |
1676
|
|
|
|
|
|
|
# version (normally because everything in the directory listing has the |
1677
|
|
|
|
|
|
|
# same timestamp. |
1678
|
|
|
|
|
|
|
# return $download_url, which is lookup_url . |
1679
|
0
|
|
|
|
|
0
|
vmsg 'Using parsed directory listing to determine download url.'; |
1680
|
0
|
|
|
|
|
0
|
my $download_path = determine_download_path($filename_listing); |
1681
|
|
|
|
|
|
|
|
1682
|
0
|
|
|
|
|
0
|
vmsg "Download path determined to be [$download_path]"; |
1683
|
|
|
|
|
|
|
|
1684
|
0
|
|
|
|
|
0
|
return $download_path; |
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
|
1690
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
|
1692
|
|
|
|
|
|
|
sub get_directory_listing { |
1693
|
|
|
|
|
|
|
|
1694
|
0
|
|
|
0
|
1
|
0
|
return download_dirlist(config('lookup_url')); |
1695
|
|
|
|
|
|
|
} |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
|
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
sub parse_directory_listing { |
1700
|
0
|
|
|
0
|
1
|
0
|
my ($directory_listing) = @_; |
1701
|
|
|
|
|
|
|
|
1702
|
0
|
0
|
|
|
|
0
|
if (config('lookup_url') =~ m!^ftp://!) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
###BUGALERT### *_parse_filelist may not properly skip directories, so a |
1704
|
|
|
|
|
|
|
#directory could exist that could wind up being the "latest version" |
1705
|
0
|
|
|
|
|
0
|
return ftp_parse_filelist($directory_listing); |
1706
|
|
|
|
|
|
|
} elsif (config('lookup_url') =~ m!^http://!) { |
1707
|
0
|
|
|
|
|
0
|
return http_parse_filelist($directory_listing); |
1708
|
|
|
|
|
|
|
} elsif (config('lookup_url') =~ m!^file://!) { |
1709
|
0
|
|
|
|
|
0
|
return file_parse_filelist($directory_listing); |
1710
|
|
|
|
|
|
|
} |
1711
|
|
|
|
|
|
|
} |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
sub determine_download_path { |
1716
|
0
|
|
|
0
|
1
|
0
|
my $filename_listing = shift; |
1717
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
# Base lookup algorithm on lookup_method configuration sub if it was |
1719
|
|
|
|
|
|
|
# specified. |
1720
|
0
|
|
|
|
|
0
|
my $sorted_filename_listing; |
1721
|
0
|
0
|
0
|
|
|
0
|
if (defined config('lookup_method') |
|
|
0
|
0
|
|
|
|
|
1722
|
|
|
|
|
|
|
and config('lookup_method') eq 'timestamp' |
1723
|
|
|
|
|
|
|
) { |
1724
|
0
|
|
|
|
|
0
|
$sorted_filename_listing = lookup_by_timestamp($filename_listing); |
1725
|
|
|
|
|
|
|
} elsif (defined config('lookup_method') |
1726
|
|
|
|
|
|
|
and config('lookup_method') eq 'versionstring' |
1727
|
|
|
|
|
|
|
) { |
1728
|
0
|
|
|
|
|
0
|
$sorted_filename_listing = lookup_by_versionstring($filename_listing); |
1729
|
|
|
|
|
|
|
# Default is to just use timestamp although timestamp will call |
1730
|
|
|
|
|
|
|
# versionstring if it can't figure it out, because all of the timestamps |
1731
|
|
|
|
|
|
|
# are the same. |
1732
|
|
|
|
|
|
|
} else { |
1733
|
0
|
|
|
|
|
0
|
$sorted_filename_listing = lookup_by_timestamp($filename_listing); |
1734
|
|
|
|
|
|
|
} |
1735
|
|
|
|
|
|
|
|
1736
|
|
|
|
|
|
|
# Manage duplicate timestamps apropriately including .md5, .asc, .txt files. |
1737
|
|
|
|
|
|
|
# And support some hacks to make lookup() more robust. |
1738
|
0
|
|
|
|
|
0
|
return lookup_determine_downloadpath($sorted_filename_listing); |
1739
|
|
|
|
|
|
|
} |
1740
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
|
1742
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
{ # Bare block for holding %month {ftp,http}_parse_filelist() need. |
1745
|
|
|
|
|
|
|
my %month = ( |
1746
|
|
|
|
|
|
|
Jan => '01', |
1747
|
|
|
|
|
|
|
Feb => '02', |
1748
|
|
|
|
|
|
|
Mar => '03', |
1749
|
|
|
|
|
|
|
Apr => '04', |
1750
|
|
|
|
|
|
|
May => '05', |
1751
|
|
|
|
|
|
|
Jun => '06', |
1752
|
|
|
|
|
|
|
Jul => '07', |
1753
|
|
|
|
|
|
|
Aug => '08', |
1754
|
|
|
|
|
|
|
Sep => '09', |
1755
|
|
|
|
|
|
|
Oct => '10', |
1756
|
|
|
|
|
|
|
Nov => '11', |
1757
|
|
|
|
|
|
|
Dec => '12', |
1758
|
|
|
|
|
|
|
); |
1759
|
|
|
|
|
|
|
|
1760
|
|
|
|
|
|
|
my %num_month = ( |
1761
|
|
|
|
|
|
|
1 => '01', |
1762
|
|
|
|
|
|
|
2 => '02', |
1763
|
|
|
|
|
|
|
3 => '03', |
1764
|
|
|
|
|
|
|
4 => '04', |
1765
|
|
|
|
|
|
|
5 => '05', |
1766
|
|
|
|
|
|
|
6 => '06', |
1767
|
|
|
|
|
|
|
7 => '07', |
1768
|
|
|
|
|
|
|
8 => '08', |
1769
|
|
|
|
|
|
|
9 => '09', |
1770
|
|
|
|
|
|
|
10 => '10', |
1771
|
|
|
|
|
|
|
11 => '11', |
1772
|
|
|
|
|
|
|
12 => '12', |
1773
|
|
|
|
|
|
|
); |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
|
1776
|
|
|
|
|
|
|
sub ftp_parse_filelist { |
1777
|
0
|
|
|
0
|
1
|
0
|
my $ftp_listing = shift; |
1778
|
|
|
|
|
|
|
|
1779
|
0
|
|
|
|
|
0
|
my ($filename, $timestamp, @filename_listing); |
1780
|
|
|
|
|
|
|
|
1781
|
0
|
|
|
|
|
0
|
for my $listing (@$ftp_listing) { |
1782
|
|
|
|
|
|
|
# Example Net::FTP->dir() output. |
1783
|
|
|
|
|
|
|
#drwxrwsr-x 49 200 200 4096 Oct 05 14:27 patches |
1784
|
|
|
|
|
|
|
# 0 1 2 3 4 5 6 7 8 |
1785
|
0
|
|
|
|
|
0
|
my @fields = split /\s+/, $listing; |
1786
|
|
|
|
|
|
|
# Test & try it??? Probaby won't work. |
1787
|
|
|
|
|
|
|
#my ($month, $day, $year_or_time, $filename) = ( split /\s+/, $listing )[-4--1]; |
1788
|
0
|
|
|
|
|
0
|
$filename = $fields[-1]; |
1789
|
|
|
|
|
|
|
#month #day #year |
1790
|
|
|
|
|
|
|
#"$fields[6] $fields[7] $fields[8]"; |
1791
|
0
|
|
|
|
|
0
|
my $month = $fields[5]; |
1792
|
0
|
|
|
|
|
0
|
my $day = $fields[6]; |
1793
|
0
|
|
|
|
|
0
|
my $year_or_time = $fields[7]; |
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
# Normalize timestamp format. |
1796
|
|
|
|
|
|
|
# It's a time. |
1797
|
0
|
0
|
|
|
|
0
|
if ($year_or_time =~ /\d\d:\d\d/) { |
|
|
0
|
|
|
|
|
|
1798
|
|
|
|
|
|
|
# the $month{} hash access replaces text months with numerical |
1799
|
|
|
|
|
|
|
# ones. |
1800
|
0
|
|
|
|
|
0
|
$year_or_time =~ s/://; # Make 12:00 1200 for numerical sort. |
1801
|
0
|
|
|
|
|
0
|
$timestamp = "9999$month{$month}$day$year_or_time"; |
1802
|
|
|
|
|
|
|
# It's a year. |
1803
|
|
|
|
|
|
|
} elsif ($year_or_time =~ /\d\d\d\d/) { |
1804
|
|
|
|
|
|
|
# the $month{} hash access replaces text months with numerical |
1805
|
|
|
|
|
|
|
# ones. |
1806
|
0
|
|
|
|
|
0
|
$timestamp = "$year_or_time$month{$month}${day}0000"; |
1807
|
|
|
|
|
|
|
} |
1808
|
0
|
|
|
|
|
0
|
push @filename_listing, [$filename, $timestamp]; |
1809
|
|
|
|
|
|
|
} |
1810
|
|
|
|
|
|
|
|
1811
|
0
|
|
|
|
|
0
|
return \@filename_listing; |
1812
|
|
|
|
|
|
|
} |
1813
|
|
|
|
|
|
|
|
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
sub http_parse_filelist { |
1817
|
0
|
|
|
0
|
1
|
0
|
my $http_listing = shift; |
1818
|
|
|
|
|
|
|
|
1819
|
|
|
|
|
|
|
# Use HTML::TreeBuilder to parse the scalar of html into a tree of tags. |
1820
|
0
|
|
|
|
|
0
|
my $tree = HTML::TreeBuilder->new_from_content($http_listing); |
1821
|
|
|
|
|
|
|
|
1822
|
0
|
|
|
|
|
0
|
my @filename_listing; |
1823
|
|
|
|
|
|
|
my @matching_links = $tree->look_down( |
1824
|
|
|
|
|
|
|
_tag => 'a', |
1825
|
|
|
|
|
|
|
sub { |
1826
|
0
|
|
|
0
|
|
0
|
my $h = shift; |
1827
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
#parse out archive name. |
1829
|
0
|
|
|
|
|
0
|
my $link = $h->as_text(); |
1830
|
|
|
|
|
|
|
# NOTE: The weird alternations adding .asc, .md5, and .sha.?, |
1831
|
|
|
|
|
|
|
# and also a KEYS file are to allow fetchware new to also use |
1832
|
|
|
|
|
|
|
# this subroutine to parse http file listings to analyze the |
1833
|
|
|
|
|
|
|
# contents of the user's lookup_url. It does not make any sense |
1834
|
|
|
|
|
|
|
# to copy and paste this function or even add a callback argument |
1835
|
|
|
|
|
|
|
# allowing you to change the regex. |
1836
|
0
|
0
|
|
|
|
0
|
if ($link =~ |
1837
|
|
|
|
|
|
|
/(\.(tar\.(gz|bz2|xz)|(tgz|tbz2|txz))|(asc|md5|sha.?))|KEYS$/) { |
1838
|
|
|
|
|
|
|
# Should I strip out dirs just to be safe? |
1839
|
0
|
|
|
|
|
0
|
my $filename = $link; |
1840
|
|
|
|
|
|
|
# Obtain the tag to the right of the archive link to find the |
1841
|
|
|
|
|
|
|
# timestamp. |
1842
|
0
|
0
|
|
|
|
0
|
if (my $rh = $h->right()) { |
1843
|
0
|
|
|
|
|
0
|
my $listing_line; |
1844
|
0
|
0
|
|
|
|
0
|
if (blessed($rh)) { |
1845
|
0
|
|
|
|
|
0
|
$listing_line = $rh->as_text(); |
1846
|
|
|
|
|
|
|
} else { |
1847
|
0
|
|
|
|
|
0
|
$listing_line = $rh; |
1848
|
|
|
|
|
|
|
} |
1849
|
0
|
|
|
|
|
0
|
my @fields = split ' ', $listing_line; |
1850
|
|
|
|
|
|
|
###BUGALERT### Internationalization probably breaks this |
1851
|
|
|
|
|
|
|
#datetime parsing? Can a library do it? |
1852
|
|
|
|
|
|
|
# day-month-year time |
1853
|
|
|
|
|
|
|
# $fields[0] $fields[1] |
1854
|
|
|
|
|
|
|
# Normalize format for lookup algorithms . |
1855
|
0
|
|
|
|
|
0
|
my ($day, $month, $year) = split /-/, $fields[0]; |
1856
|
|
|
|
|
|
|
# Ditch the ':' in the time. |
1857
|
0
|
|
|
|
|
0
|
$fields[1] =~ s/://; |
1858
|
|
|
|
|
|
|
# Some dirlistings use string months Aug, Jun, etc... |
1859
|
0
|
0
|
|
|
|
0
|
if (looks_like_number($month)) { |
1860
|
|
|
|
|
|
|
# Strip leading 0 if it exists by converting the |
1861
|
|
|
|
|
|
|
# string with the useless leading 0 into an integer. |
1862
|
|
|
|
|
|
|
# The %num_month hash lookup will add back a leading |
1863
|
|
|
|
|
|
|
# 0 if there was one. This stupid roundabout code is |
1864
|
|
|
|
|
|
|
# to ensure that there always is a leading 0 if the |
1865
|
|
|
|
|
|
|
# number is less than 10 to ensure that all of the |
1866
|
|
|
|
|
|
|
# numbers this hacky datetime parser outputs all |
1867
|
|
|
|
|
|
|
# have the same length so that the numbers can |
1868
|
|
|
|
|
|
|
# easily be compared with each other. |
1869
|
0
|
|
|
|
|
0
|
$month = sprintf("%u", $month); |
1870
|
0
|
|
|
|
|
0
|
push @filename_listing, [$filename, |
1871
|
|
|
|
|
|
|
"$year$num_month{$month}$day$fields[1]"]; |
1872
|
|
|
|
|
|
|
# ...and some use numbers 8, 6, etc.... |
1873
|
|
|
|
|
|
|
} else { |
1874
|
0
|
|
|
|
|
0
|
push @filename_listing, [$filename, |
1875
|
|
|
|
|
|
|
"$year$month{$month}$day$fields[1]"]; |
1876
|
|
|
|
|
|
|
} |
1877
|
|
|
|
|
|
|
} else { |
1878
|
|
|
|
|
|
|
###BUGALERT### Add support for other http servers such as lighttpd, nginx, |
1879
|
|
|
|
|
|
|
#cherokee, starman?, AND use the Server: header to determine which algorithm to |
1880
|
|
|
|
|
|
|
#use. |
1881
|
0
|
|
|
|
|
0
|
die <
|
1882
|
|
|
|
|
|
|
App-Fetchware: run-time error. A hardcoded algorithm to parse HTML directory |
1883
|
|
|
|
|
|
|
listings has failed! Fetchware currently only supports parseing Apache HTML |
1884
|
|
|
|
|
|
|
directory listings. This is a huge limitation, but surprisingly pretty much |
1885
|
|
|
|
|
|
|
everyone who runs a mirror uses apache for http support. This is a bug so |
1886
|
|
|
|
|
|
|
please report it. Also, if you want to try a possible workaround, just use a ftp |
1887
|
|
|
|
|
|
|
mirror instead of a http one, because ftp directory listings are a easy to |
1888
|
|
|
|
|
|
|
parse. See perldoc App::Fetchware. |
1889
|
|
|
|
|
|
|
EOD |
1890
|
|
|
|
|
|
|
} |
1891
|
|
|
|
|
|
|
} |
1892
|
|
|
|
|
|
|
} |
1893
|
0
|
|
|
|
|
0
|
); |
1894
|
|
|
|
|
|
|
|
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
# Delete the $tree, so perl can garbage collect it. |
1897
|
0
|
|
|
|
|
0
|
$tree = $tree->delete; |
1898
|
|
|
|
|
|
|
|
1899
|
0
|
|
|
|
|
0
|
return \@filename_listing; |
1900
|
|
|
|
|
|
|
} |
1901
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
|
1903
|
|
|
|
|
|
|
} # end bare block for %month. |
1904
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
|
1908
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
sub file_parse_filelist { |
1910
|
1
|
|
|
1
|
1
|
1
|
my $file_listing = shift; |
1911
|
|
|
|
|
|
|
|
1912
|
1
|
|
|
|
|
2
|
for my $file (@$file_listing) { |
1913
|
45
|
50
|
|
|
|
2555
|
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime, |
1914
|
|
|
|
|
|
|
$blksize,$blocks) |
1915
|
|
|
|
|
|
|
= stat($file) or die <
|
1916
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to stat() the file [$file] while trying to parse |
1917
|
|
|
|
|
|
|
your local [file://] lookup_url. The OS error was [$!]. This should not happen, |
1918
|
|
|
|
|
|
|
and is either a bug in fetchware or some sort of race condition. |
1919
|
|
|
|
|
|
|
EOD |
1920
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
# Replace scalar filename with a arrayref of the filename with its |
1922
|
|
|
|
|
|
|
# assocated timestamp for later processing for lookup(). |
1923
|
|
|
|
|
|
|
# |
1924
|
|
|
|
|
|
|
# Use Path::Class's file() constructor & basename() method to strip out |
1925
|
|
|
|
|
|
|
# all unneeded directory information leaving just the file's name. |
1926
|
|
|
|
|
|
|
# Add all of the timestamp numbers together, so that only one numberical |
1927
|
|
|
|
|
|
|
# sort is needed instead of a descending list of numerical sorts. |
1928
|
45
|
|
|
|
|
88
|
$file = [file($file)->basename(), $mtime ]; |
1929
|
|
|
|
|
|
|
} |
1930
|
|
|
|
|
|
|
|
1931
|
1
|
|
|
|
|
47
|
return $file_listing; |
1932
|
|
|
|
|
|
|
} |
1933
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
sub lookup_by_timestamp { |
1937
|
1
|
|
|
1
|
1
|
77
|
my $file_listing = shift; |
1938
|
|
|
|
|
|
|
|
1939
|
|
|
|
|
|
|
# Sort the timstamps to determine the latest one. The one with the higher |
1940
|
|
|
|
|
|
|
# numbers, and put $b before $a to put the "bigger", later versions before |
1941
|
|
|
|
|
|
|
# the "lower" older versions. |
1942
|
|
|
|
|
|
|
# Sort based on timestamp, which is $file_listing->[0..*][1][0..6]. |
1943
|
|
|
|
|
|
|
# Note: the crazy || ors are to make perl sort each timestamp array first by |
1944
|
|
|
|
|
|
|
# year, then month, then day of the month, and so on. |
1945
|
1
|
|
|
|
|
5
|
my @sorted_listing = sort { $b->[1] <=> $a->[1] } @$file_listing; |
|
153
|
|
|
|
|
135
|
|
1946
|
|
|
|
|
|
|
|
1947
|
1
|
|
|
|
|
6
|
return \@sorted_listing; |
1948
|
|
|
|
|
|
|
} |
1949
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
|
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
sub lookup_by_versionstring { |
1953
|
9
|
|
|
9
|
1
|
38458
|
my $file_listing = shift; |
1954
|
|
|
|
|
|
|
|
1955
|
|
|
|
|
|
|
# Implement versionstring algorithm. |
1956
|
9
|
|
|
|
|
7
|
my @versionstrings; |
1957
|
9
|
|
|
|
|
12
|
for (my $i = 0; $i <= $#{$file_listing}; $i++) { |
|
85
|
|
|
|
|
119
|
|
1958
|
|
|
|
|
|
|
# Split the filename on "Not a numbers", so remove all "not |
1959
|
|
|
|
|
|
|
# numbers", but keep a list of things that actually are numbers. |
1960
|
76
|
|
|
|
|
174
|
my @iversionstring = split(/\D+/, $file_listing->[$i][0]); |
1961
|
|
|
|
|
|
|
|
1962
|
|
|
|
|
|
|
# Use grep to strip leading empty strings (eg: ''). |
1963
|
76
|
|
|
|
|
61
|
@iversionstring = grep {$_ ne ''} @iversionstring; |
|
248
|
|
|
|
|
275
|
|
1964
|
|
|
|
|
|
|
|
1965
|
76
|
100
|
|
|
|
103
|
if (@iversionstring == 0) { |
1966
|
|
|
|
|
|
|
# Let the usr know we're skipping this filename, but only if they |
1967
|
|
|
|
|
|
|
# really want to know (They turned on verbose output.). |
1968
|
10
|
|
|
|
|
24
|
vmsg <
|
1969
|
|
|
|
|
|
|
File [$file_listing->[$i][0]] has no version number in it. Ignoring. |
1970
|
|
|
|
|
|
|
EOM |
1971
|
|
|
|
|
|
|
# And also skip adding this @iversionstring to @versionstrings, |
1972
|
|
|
|
|
|
|
# because this @iversionstring is empty, and how do I sort an empty |
1973
|
|
|
|
|
|
|
# array? Return undef--nope causes "value undef in sort fatal errors |
1974
|
|
|
|
|
|
|
# and warnings." Return 0--nope causes a file with no version number |
1975
|
|
|
|
|
|
|
# at beginning of listing to stay at listing, and cause fetchware to |
1976
|
|
|
|
|
|
|
# fail picking the right version. Return -1--nope, because that's |
1977
|
|
|
|
|
|
|
# hackish and lame. Instead, just not include them in the lookup |
1978
|
|
|
|
|
|
|
# listing, and if that means that the lookup listing is empty throw |
1979
|
|
|
|
|
|
|
# an exception. |
1980
|
10
|
|
|
|
|
9
|
next; |
1981
|
|
|
|
|
|
|
} |
1982
|
|
|
|
|
|
|
# Add $i's version string to @versionstrings. |
1983
|
66
|
|
|
|
|
115
|
push @versionstrings, [$i, @iversionstring]; |
1984
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
# And the sort below sorts them into highest number first order. |
1986
|
|
|
|
|
|
|
} |
1987
|
|
|
|
|
|
|
|
1988
|
9
|
50
|
|
|
|
17
|
die <
|
1989
|
0
|
|
|
|
|
0
|
App-Fetchware: The lookup_url your provided [@{[config('lookup_url')]}] does not |
1990
|
|
|
|
|
|
|
have any filenames with detectable version numbers in them. Fetchware's |
1991
|
|
|
|
|
|
|
'versionstring' lookup algorithm depends on files having version numbers in them |
1992
|
|
|
|
|
|
|
such as [httpd-2.2.22.tar.gz] notice the [2.2.22] version number. Fetchware |
1993
|
|
|
|
|
|
|
failed to find any of those in the lookup_url you provided. Consider a different |
1994
|
|
|
|
|
|
|
lookup_url or try switching to the default 'timestamp' lookup algorithm adding |
1995
|
|
|
|
|
|
|
the "lookup_method" configuration option to your Fetchwarefile. |
1996
|
|
|
|
|
|
|
EOD |
1997
|
|
|
|
|
|
|
|
1998
|
|
|
|
|
|
|
# LIMITATION: The sort block below can not have any undef values in its |
1999
|
|
|
|
|
|
|
# input. If there are any, then perl will give a warning about a value being |
2000
|
|
|
|
|
|
|
# undef in a sort, if you are not lucky, then it will actually trigger a |
2001
|
|
|
|
|
|
|
# fatal error. There are CPAN Testers reports with this problem, so it really |
2002
|
|
|
|
|
|
|
# can happen. But you do not have to worry about this, because the for loop |
2003
|
|
|
|
|
|
|
# above that creates @versionstrings |
2004
|
|
|
|
|
|
|
@versionstrings = sort { |
2005
|
|
|
|
|
|
|
# Figure out whoose ($b or $a) is larger and set $last_index to it. |
2006
|
9
|
|
|
|
|
25
|
my $last_index; |
|
160
|
|
|
|
|
102
|
|
2007
|
160
|
100
|
|
|
|
87
|
if ($#{$b} > $#{$a}) { |
|
160
|
|
|
|
|
109
|
|
|
160
|
|
|
|
|
169
|
|
2008
|
56
|
|
|
|
|
33
|
$last_index = $#{$b}; |
|
56
|
|
|
|
|
48
|
|
2009
|
|
|
|
|
|
|
} else { |
2010
|
104
|
|
|
|
|
65
|
$last_index = $#{$a}; |
|
104
|
|
|
|
|
73
|
|
2011
|
|
|
|
|
|
|
} |
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
# Loop over the indexes of both $b and $a at the same time comparing |
2014
|
|
|
|
|
|
|
# them one by one with <=>... |
2015
|
|
|
|
|
|
|
# ...and be sure to start at index 1, because index 0 is the index of |
2016
|
|
|
|
|
|
|
# $file_listing that this entry in @versionstrings belongs to... |
2017
|
160
|
|
|
|
|
166
|
for my $x (1..$last_index) { |
2018
|
|
|
|
|
|
|
# If one of $b or $a has more numbers in it ($#{$a_or_b} is smaller than |
2019
|
|
|
|
|
|
|
# $x), then if it's $b we should return -1, because $b is smaller |
2020
|
|
|
|
|
|
|
# than $a, and if it's $a, we should return 1, because $b is bigger |
2021
|
|
|
|
|
|
|
# than $a. |
2022
|
395
|
100
|
|
|
|
233
|
return -1 if $x > $#{$b}; |
|
395
|
|
|
|
|
467
|
|
2023
|
386
|
100
|
|
|
|
213
|
return 1 if $x > $#{$a}; |
|
386
|
|
|
|
|
453
|
|
2024
|
|
|
|
|
|
|
|
2025
|
352
|
|
|
|
|
283
|
my $spaceship_result = $b->[$x] <=> $a->[$x]; |
2026
|
|
|
|
|
|
|
|
2027
|
|
|
|
|
|
|
# ...and as soon as they no longer equal each other return whatever |
2028
|
|
|
|
|
|
|
# result (-1 or 1) <=> gives. |
2029
|
352
|
100
|
|
|
|
427
|
return $spaceship_result if $spaceship_result != 0; |
2030
|
|
|
|
|
|
|
} |
2031
|
|
|
|
|
|
|
|
2032
|
|
|
|
|
|
|
# Return 0 for equal, because if the two versions were not equal, then |
2033
|
|
|
|
|
|
|
# the for loop above would have caught it, and returned the appropriate |
2034
|
|
|
|
|
|
|
# -1 or 1. |
2035
|
30
|
|
|
|
|
24
|
return 0; |
2036
|
|
|
|
|
|
|
} @versionstrings; |
2037
|
|
|
|
|
|
|
|
2038
|
|
|
|
|
|
|
# Now, "sort" $file_listing into the order @versionstrings was sorted into |
2039
|
|
|
|
|
|
|
# using the copy @sorted_file_listing. |
2040
|
9
|
|
|
|
|
8
|
my @sorted_file_listing; |
2041
|
9
|
|
|
|
|
11
|
for my $versionstring_arrayref (@versionstrings) { |
2042
|
66
|
|
|
|
|
61
|
push @sorted_file_listing, |
2043
|
|
|
|
|
|
|
# The $versionstring_arrayref->[0] part refers to the index that was |
2044
|
|
|
|
|
|
|
# saved first when @versionstrings was created. |
2045
|
|
|
|
|
|
|
$file_listing->[$versionstring_arrayref->[0]]; |
2046
|
|
|
|
|
|
|
} |
2047
|
|
|
|
|
|
|
|
2048
|
|
|
|
|
|
|
# Return the sorted $file_listing, @sorted_filename_listing. |
2049
|
9
|
|
|
|
|
32
|
return \@sorted_file_listing; |
2050
|
|
|
|
|
|
|
} |
2051
|
|
|
|
|
|
|
|
2052
|
|
|
|
|
|
|
|
2053
|
|
|
|
|
|
|
|
2054
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
sub lookup_determine_downloadpath { |
2056
|
0
|
|
|
0
|
1
|
0
|
my $file_listing = shift; |
2057
|
|
|
|
|
|
|
|
2058
|
|
|
|
|
|
|
# First grep @$file_listing for $CONFIG{filter} if $CONFIG{filter} is defined. |
2059
|
|
|
|
|
|
|
# This is done, because some distributions have multiple versions of the |
2060
|
|
|
|
|
|
|
# same program in one directory, so sorting by version numbers or |
2061
|
|
|
|
|
|
|
# timestamps, and then by filetype like below is not enough to determine, |
2062
|
|
|
|
|
|
|
# which file to download, so filter was invented to fix this problem by |
2063
|
|
|
|
|
|
|
# letting Fetchwarefile's specify which version of the software to download. |
2064
|
0
|
0
|
|
|
|
0
|
if (defined config('filter')) { |
2065
|
0
|
|
|
|
|
0
|
@$file_listing = grep { $_->[0] =~ /@{[config('filter')]}/ } @$file_listing; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
2066
|
|
|
|
|
|
|
} |
2067
|
|
|
|
|
|
|
|
2068
|
|
|
|
|
|
|
# Skip any filenames with win32 in them on non-Windows systems. |
2069
|
|
|
|
|
|
|
# Windows systems who may need to download the win32 version can just use |
2070
|
|
|
|
|
|
|
# filter 'win32' for that or maybe 'win32|http-2.2' if they need the other |
2071
|
|
|
|
|
|
|
# functionality of filter. |
2072
|
0
|
0
|
|
|
|
0
|
if ($^O ne 'MSWin32') { # $^O is what os I'm on, MSWin32, Linux, darwin, etc |
2073
|
0
|
|
|
|
|
0
|
@$file_listing = grep { $_->[0] !~ m/win32/i } @$file_listing; |
|
0
|
|
|
|
|
0
|
|
2074
|
|
|
|
|
|
|
} |
2075
|
|
|
|
|
|
|
|
2076
|
|
|
|
|
|
|
# Support 'LATEST{_,-}IS' and 'CURRENT{_,-}IS', which indicate what the |
2077
|
|
|
|
|
|
|
# latest version is. These files come from each software distributions |
2078
|
|
|
|
|
|
|
# mirror scripts, so they should be more accurate than either of my lookup |
2079
|
|
|
|
|
|
|
# algorithms. Both Apache and the Linux kernel maintain these files. |
2080
|
0
|
|
|
|
|
0
|
$_->[0] =~ /^(?:latest|current)[_-]is[_-](.*)$/i for @$file_listing; |
2081
|
0
|
|
|
|
|
0
|
my $latest_version = $1; |
2082
|
0
|
0
|
|
|
|
0
|
@$file_listing = grep { $_->[0] =~ /$latest_version/ } @$file_listing |
|
0
|
|
|
|
|
0
|
|
2083
|
|
|
|
|
|
|
if defined $latest_version; |
2084
|
|
|
|
|
|
|
|
2085
|
|
|
|
|
|
|
# Determine the $download_url based on the sorted @$file_listing by |
2086
|
|
|
|
|
|
|
# finding a downloadable file (a tarball or zip archive). |
2087
|
|
|
|
|
|
|
# Furthermore, choose them based on best compression to worst to save some |
2088
|
|
|
|
|
|
|
# bandwidth. |
2089
|
0
|
|
|
|
|
0
|
for my $fl (@$file_listing) { |
2090
|
0
|
0
|
|
|
|
0
|
if ($fl->[0] =~ /\.tar\.xz$/) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
2091
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2092
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2093
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.txz$/) { |
2094
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2095
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2096
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.tar\.bz2$/) { |
2097
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2098
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2099
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.tbz$/) { |
2100
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2101
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2102
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.tar\.gz$/) { |
2103
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2104
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2105
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.tgz$/) { |
2106
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2107
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2108
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.zip$/) { |
2109
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2110
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2111
|
|
|
|
|
|
|
} elsif ($fl->[0] =~ /\.fpkg$/) { |
2112
|
0
|
|
|
|
|
0
|
my $path = ( uri_split(config('lookup_url')) )[2]; |
2113
|
0
|
|
|
|
|
0
|
return "$path/$fl->[0]"; |
2114
|
|
|
|
|
|
|
} |
2115
|
|
|
|
|
|
|
##DELME## if (config('lookup_url') =~ m!^file://!) { |
2116
|
|
|
|
|
|
|
##DELME## # Must prepend scheme, so that download() knows how to retrieve this |
2117
|
|
|
|
|
|
|
##DELME## # file with download_file(), which requires a URL that must begin |
2118
|
|
|
|
|
|
|
##DELME## # with a scheme, and file:// is the scheme for local files. |
2119
|
|
|
|
|
|
|
##DELME## $fl->[0] =~ s/"file://$fl->[0]"; |
2120
|
|
|
|
|
|
|
} |
2121
|
0
|
|
|
|
|
0
|
die <
|
2122
|
|
|
|
|
|
|
App-Fetchware: run-time error. Fetchware failed to determine what URL it should |
2123
|
|
|
|
|
|
|
use to download your software. This URL is based on the lookup_url you |
2124
|
|
|
|
|
|
|
specified. See perldoc App::Fetchware. |
2125
|
|
|
|
|
|
|
EOD |
2126
|
|
|
|
|
|
|
} |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
|
2129
|
|
|
|
|
|
|
|
2130
|
|
|
|
|
|
|
|
2131
|
|
|
|
|
|
|
sub download { |
2132
|
1
|
|
|
1
|
1
|
8
|
my ($temp_dir, $download_path) = @_; |
2133
|
|
|
|
|
|
|
|
2134
|
|
|
|
|
|
|
# Ensure we're passed just a path, and *not* a full URL. |
2135
|
1
|
50
|
|
|
|
5
|
die <
|
2136
|
|
|
|
|
|
|
App-Fetchware: download() has been passed a full URL *not* only a path. |
2137
|
|
|
|
|
|
|
download() should only be called with a path never a full URL. The URL you |
2138
|
|
|
|
|
|
|
specified was [$download_path] |
2139
|
|
|
|
|
|
|
EOD |
2140
|
|
|
|
|
|
|
|
2141
|
1
|
|
|
|
|
7
|
vmsg <
|
2142
|
|
|
|
|
|
|
Using [$download_path] as basis for determined our download_url using the user |
2143
|
|
|
|
|
|
|
supplied mirrors. |
2144
|
|
|
|
|
|
|
EOM |
2145
|
|
|
|
|
|
|
|
2146
|
1
|
|
|
|
|
4
|
msg "Downloading from url [$download_path] to temp dir [$temp_dir]"; |
2147
|
|
|
|
|
|
|
|
2148
|
1
|
|
|
|
|
6
|
my $downloaded_file_path = download_file(PATH => $download_path); |
2149
|
1
|
|
|
|
|
6
|
vmsg "Downloaded file to [$downloaded_file_path]"; |
2150
|
|
|
|
|
|
|
|
2151
|
1
|
|
|
|
|
5
|
my $package_path = determine_package_path($temp_dir, $downloaded_file_path); |
2152
|
1
|
|
|
|
|
17
|
msg "Determined package path to be [$package_path]"; |
2153
|
|
|
|
|
|
|
|
2154
|
1
|
|
|
|
|
18
|
return $package_path; |
2155
|
|
|
|
|
|
|
} |
2156
|
|
|
|
|
|
|
|
2157
|
|
|
|
|
|
|
|
2158
|
|
|
|
|
|
|
|
2159
|
|
|
|
|
|
|
|
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
|
2162
|
|
|
|
|
|
|
sub determine_package_path { |
2163
|
2
|
|
|
2
|
1
|
4244
|
my ($tempdir, $filename) = @_; |
2164
|
|
|
|
|
|
|
|
2165
|
|
|
|
|
|
|
# return $package_path, which stores the full path of where the file |
2166
|
|
|
|
|
|
|
# HTTP::Tiny downloaded. |
2167
|
|
|
|
|
|
|
###BUGALERT### $tempdir is no longer used, so remove it from |
2168
|
|
|
|
|
|
|
#determine_package_path() and probably download() too. |
2169
|
2
|
|
|
|
|
5755
|
return catfile(cwd(), $filename) |
2170
|
|
|
|
|
|
|
} |
2171
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
|
2173
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
|
2175
|
|
|
|
|
|
|
sub verify { |
2176
|
0
|
|
|
0
|
1
|
0
|
my ($download_path, $package_path) = @_; |
2177
|
|
|
|
|
|
|
|
2178
|
0
|
|
|
|
|
0
|
msg "Verifying the downloaded package [$package_path]"; |
2179
|
|
|
|
|
|
|
|
2180
|
0
|
|
|
|
|
0
|
my $retval; |
2181
|
0
|
0
|
|
|
|
0
|
unless (defined(config('verify_method'))) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
2182
|
|
|
|
|
|
|
# if gpg fails try |
2183
|
|
|
|
|
|
|
# sha and if it fails try |
2184
|
|
|
|
|
|
|
# md5 and if it fails die |
2185
|
0
|
|
|
|
|
0
|
msg 'Trying to use gpg to cyptographically verify downloaded package.'; |
2186
|
0
|
|
|
|
|
0
|
my ($gpg_err, $sha_err, $md5_err); |
2187
|
0
|
|
|
|
|
0
|
eval {$retval = gpg_verify($download_path)}; |
|
0
|
|
|
|
|
0
|
|
2188
|
0
|
|
|
|
|
0
|
$gpg_err = $@; |
2189
|
0
|
0
|
|
|
|
0
|
if ($gpg_err) { |
2190
|
0
|
|
|
|
|
0
|
msg <
|
2191
|
|
|
|
|
|
|
Cyptographic verification using gpg failed! |
2192
|
|
|
|
|
|
|
GPG verification error [ |
2193
|
|
|
|
|
|
|
$@ |
2194
|
|
|
|
|
|
|
] |
2195
|
|
|
|
|
|
|
EOM |
2196
|
0
|
|
|
|
|
0
|
warn $gpg_err; |
2197
|
|
|
|
|
|
|
} |
2198
|
0
|
0
|
0
|
|
|
0
|
if (! $retval or $gpg_err) { |
2199
|
0
|
|
|
|
|
0
|
msg <
|
2200
|
|
|
|
|
|
|
Trying SHA1 verification of downloaded package. |
2201
|
|
|
|
|
|
|
EOM |
2202
|
0
|
|
|
|
|
0
|
eval {$retval = sha1_verify($download_path, $package_path)}; |
|
0
|
|
|
|
|
0
|
|
2203
|
0
|
|
|
|
|
0
|
$sha_err = $@; |
2204
|
0
|
0
|
|
|
|
0
|
if ($sha_err) { |
2205
|
0
|
|
|
|
|
0
|
msg <
|
2206
|
|
|
|
|
|
|
SHA1 verification failed! |
2207
|
|
|
|
|
|
|
SHA1 verificaton error [ |
2208
|
|
|
|
|
|
|
$@ |
2209
|
|
|
|
|
|
|
] |
2210
|
|
|
|
|
|
|
EOM |
2211
|
0
|
|
|
|
|
0
|
warn $sha_err; |
2212
|
|
|
|
|
|
|
} |
2213
|
0
|
0
|
0
|
|
|
0
|
if (! $retval or $sha_err) { |
2214
|
0
|
|
|
|
|
0
|
msg <
|
2215
|
|
|
|
|
|
|
Trying MD5 verification of downloaded package. |
2216
|
|
|
|
|
|
|
EOM |
2217
|
0
|
|
|
|
|
0
|
eval {$retval = md5_verify($download_path, $package_path)}; |
|
0
|
|
|
|
|
0
|
|
2218
|
0
|
|
|
|
|
0
|
$md5_err = $@; |
2219
|
0
|
0
|
|
|
|
0
|
if ($md5_err) { |
2220
|
0
|
|
|
|
|
0
|
msg <
|
2221
|
|
|
|
|
|
|
MD5 verification failed! |
2222
|
|
|
|
|
|
|
MD5 verificaton error [ |
2223
|
|
|
|
|
|
|
$@ |
2224
|
|
|
|
|
|
|
] |
2225
|
|
|
|
|
|
|
EOM |
2226
|
0
|
|
|
|
|
0
|
warn $md5_err; |
2227
|
|
|
|
|
|
|
} |
2228
|
|
|
|
|
|
|
} |
2229
|
0
|
0
|
0
|
|
|
0
|
if (! $retval or $md5_err) { |
2230
|
0
|
0
|
|
|
|
0
|
die <
|
2231
|
|
|
|
|
|
|
App-Fetchware: run-time error. Fetchware failed to verify your downloaded |
2232
|
|
|
|
|
|
|
software package. You can rerun fetchware with the --force option or add |
2233
|
|
|
|
|
|
|
[verify_failure_ok 'True';] to your Fetchwarefile. See the section VERIFICATION |
2234
|
|
|
|
|
|
|
FAILED in perldoc fetchware. |
2235
|
|
|
|
|
|
|
EOD |
2236
|
|
|
|
|
|
|
} |
2237
|
0
|
0
|
|
|
|
0
|
if (config('verify_failure_ok')) { |
2238
|
0
|
|
|
|
|
0
|
warn <
|
2239
|
|
|
|
|
|
|
App-Fetchware: run-time warning. Fetchware failed to verify the integrity of you |
2240
|
|
|
|
|
|
|
downloaded file [$package_path]. This is ok, because you asked Fetchware to |
2241
|
|
|
|
|
|
|
ignore its errors when it tries to verify the integrity of your downloaded file. |
2242
|
|
|
|
|
|
|
You can also ignore the errors Fetchware printed out abover where it tried to |
2243
|
|
|
|
|
|
|
verify your downloaded file. See perldoc App::Fetchware. |
2244
|
|
|
|
|
|
|
EOW |
2245
|
0
|
|
|
|
|
0
|
vmsg <
|
2246
|
|
|
|
|
|
|
Verification Failed! But you asked to ignore verification failures, so this |
2247
|
|
|
|
|
|
|
failure is not fatal. |
2248
|
|
|
|
|
|
|
EOM |
2249
|
0
|
|
|
|
|
0
|
return 'warned due to verify_failure_ok' |
2250
|
|
|
|
|
|
|
} |
2251
|
|
|
|
|
|
|
} |
2252
|
|
|
|
|
|
|
} elsif (config('verify_method') =~ /gpg/i) { |
2253
|
0
|
|
|
|
|
0
|
vmsg <
|
2254
|
|
|
|
|
|
|
You selected gpg cryptographic verification. Verifying now. |
2255
|
|
|
|
|
|
|
EOM |
2256
|
|
|
|
|
|
|
###BUGALERT### Should trap the exception {gpg,sha1,md5}_verify() |
2257
|
|
|
|
|
|
|
#throws, and then add that error to the one here, otherwise the |
2258
|
|
|
|
|
|
|
#error message here is never seen. |
2259
|
0
|
0
|
0
|
|
|
0
|
gpg_verify($download_path) |
2260
|
|
|
|
|
|
|
or die <
|
2261
|
|
|
|
|
|
|
App-Fetchware: run-time error. You asked fetchware to only try to verify your |
2262
|
|
|
|
|
|
|
package with gpg or openpgp, but they both failed. See the warning above for |
2263
|
|
|
|
|
|
|
their error message. See perldoc App::Fetchware. |
2264
|
|
|
|
|
|
|
EOD |
2265
|
|
|
|
|
|
|
} elsif (config('verify_method') =~ /sha1?/i) { |
2266
|
0
|
|
|
|
|
0
|
vmsg <
|
2267
|
|
|
|
|
|
|
You selected SHA1 checksum verification. Verifying now. |
2268
|
|
|
|
|
|
|
EOM |
2269
|
0
|
0
|
0
|
|
|
0
|
sha1_verify($download_path, $package_path) |
2270
|
|
|
|
|
|
|
or die <
|
2271
|
|
|
|
|
|
|
App-Fetchware: run-time error. You asked fetchware to only try to verify your |
2272
|
|
|
|
|
|
|
package with sha, but it failed. See the warning above for their error message. |
2273
|
|
|
|
|
|
|
See perldoc App::Fetchware. |
2274
|
|
|
|
|
|
|
EOD |
2275
|
|
|
|
|
|
|
} elsif (config('verify_method') =~ /md5/i) { |
2276
|
0
|
|
|
|
|
0
|
vmsg <
|
2277
|
|
|
|
|
|
|
You selected MD5 checksum verification. Verifying now. |
2278
|
|
|
|
|
|
|
EOM |
2279
|
0
|
0
|
0
|
|
|
0
|
md5_verify($download_path, $package_path) |
2280
|
|
|
|
|
|
|
or die <
|
2281
|
|
|
|
|
|
|
App-Fetchware: run-time error. You asked fetchware to only try to verify your |
2282
|
|
|
|
|
|
|
package with md5, but it failed. See the warning above for their error message. |
2283
|
|
|
|
|
|
|
See perldoc App::Fetchware. |
2284
|
|
|
|
|
|
|
EOD |
2285
|
|
|
|
|
|
|
} else { |
2286
|
0
|
|
|
|
|
0
|
die <
|
2287
|
|
|
|
|
|
|
App-Fetchware: run-time error. Your fetchware file specified a wrong |
2288
|
|
|
|
|
|
|
verify_method option. The only supported types are 'gpg', 'sha', 'md5', but you |
2289
|
0
|
|
|
|
|
0
|
specified [@{[config('verify_method')]}]. See perldoc App::Fetchware. |
2290
|
|
|
|
|
|
|
EOD |
2291
|
|
|
|
|
|
|
} |
2292
|
0
|
|
|
|
|
0
|
msg 'Verification succeeded.'; |
2293
|
|
|
|
|
|
|
} |
2294
|
|
|
|
|
|
|
|
2295
|
|
|
|
|
|
|
|
2296
|
|
|
|
|
|
|
|
2297
|
|
|
|
|
|
|
|
2298
|
|
|
|
|
|
|
|
2299
|
|
|
|
|
|
|
|
2300
|
|
|
|
|
|
|
sub gpg_verify { |
2301
|
0
|
|
|
0
|
1
|
0
|
my $download_path = shift; |
2302
|
|
|
|
|
|
|
|
2303
|
0
|
|
|
|
|
0
|
my $keys_file; |
2304
|
|
|
|
|
|
|
# Attempt to download KEYS file in lookup_url's containing directory. |
2305
|
|
|
|
|
|
|
# If that fails, try gpg_keys_url if defined. |
2306
|
|
|
|
|
|
|
# Import downloaded KEYS file into a local gpg keyring using gpg command. |
2307
|
|
|
|
|
|
|
# Determine what URL to use to download the signature file *only* from |
2308
|
|
|
|
|
|
|
# lookup_url's host, so that we only download the signature from the |
2309
|
|
|
|
|
|
|
# project's main mirror. |
2310
|
|
|
|
|
|
|
# Download it. |
2311
|
|
|
|
|
|
|
# gpg verify the sig using the downloaded and imported keys in our local |
2312
|
|
|
|
|
|
|
# keyring. |
2313
|
|
|
|
|
|
|
|
2314
|
|
|
|
|
|
|
# Skip downloading and importing keys if we're called from inside a |
2315
|
|
|
|
|
|
|
# fetchware package, which should already have a copy of our package's |
2316
|
|
|
|
|
|
|
# KEYS file. |
2317
|
0
|
0
|
0
|
|
|
0
|
unless (config('user_keyring') |
|
|
|
0
|
|
|
|
|
2318
|
|
|
|
|
|
|
or (-e './pubring.gpg' and -e './secring.gpg')) { |
2319
|
|
|
|
|
|
|
# Obtain a KEYS file listing everyone's key that signs this distribution. |
2320
|
0
|
0
|
|
|
|
0
|
if (defined config('gpg_keys_url')) { |
2321
|
0
|
|
|
|
|
0
|
$keys_file = no_mirror_download_file(config('gpg_keys_url')); |
2322
|
|
|
|
|
|
|
} else { |
2323
|
0
|
|
|
|
|
0
|
eval { |
2324
|
0
|
|
|
|
|
0
|
$keys_file = no_mirror_download_file(config('lookup_url'). '/KEYS'); |
2325
|
|
|
|
|
|
|
}; |
2326
|
0
|
0
|
|
|
|
0
|
die <
|
2327
|
|
|
|
|
|
|
App-Fetchware: Fetchware was unable to download the gpg_key_url you specified or |
2328
|
0
|
|
|
|
|
0
|
that fetchware tried appending asc, sig, or sign to [@{[config('lookup_url')]}]. |
2329
|
|
|
|
|
|
|
It needs to download this file to properly verify you software package. This is |
2330
|
|
|
|
|
|
|
a fatal error, because failing to verify packages is a perferable default over |
2331
|
|
|
|
|
|
|
potentially installing compromised ones. If failing to verify your software |
2332
|
|
|
|
|
|
|
package is ok to you, then you may disable verification by adding |
2333
|
|
|
|
|
|
|
verify_failure_ok 'On'; to your Fetchwarefile. See perldoc App::Fetchware. |
2334
|
|
|
|
|
|
|
EOD |
2335
|
|
|
|
|
|
|
} |
2336
|
|
|
|
|
|
|
|
2337
|
|
|
|
|
|
|
# Import downloaded KEYS file into a local gpg keyring using gpg |
2338
|
|
|
|
|
|
|
# command. |
2339
|
0
|
0
|
|
|
|
0
|
eval { |
2340
|
|
|
|
|
|
|
# Add --homedir option if needed. |
2341
|
0
|
0
|
|
|
|
0
|
if (config('user_keyring')) { |
2342
|
0
|
|
|
|
|
0
|
run_prog('gpg', '--import', $keys_file); |
2343
|
|
|
|
|
|
|
} else { |
2344
|
0
|
|
|
|
|
0
|
run_prog('gpg', '--homedir', '.', '--import', $keys_file); |
2345
|
|
|
|
|
|
|
} |
2346
|
0
|
|
|
|
|
0
|
1; |
2347
|
|
|
|
|
|
|
} or msg <
|
2348
|
|
|
|
|
|
|
App-Fetchware: Warning: gpg exits nonzero when importing large KEY files such as |
2349
|
|
|
|
|
|
|
Apache's. However, despite exiting nonzero gpg still manages to import most of |
2350
|
|
|
|
|
|
|
the keys into its keyring. It only exits nonzero, because some of the keys in |
2351
|
|
|
|
|
|
|
the KEYS file had errors, and these key's errors were enough to cause gpg to |
2352
|
|
|
|
|
|
|
exit nonzero, but not enough to cause it to completely fail importing the keys. |
2353
|
|
|
|
|
|
|
EOM |
2354
|
|
|
|
|
|
|
} |
2355
|
|
|
|
|
|
|
|
2356
|
|
|
|
|
|
|
# Download Signature using lookup_url. |
2357
|
0
|
|
|
|
|
0
|
my $sig_file; |
2358
|
0
|
|
|
|
|
0
|
my (undef, undef, $path, undef, undef) = uri_split($download_path); |
2359
|
0
|
|
|
|
|
0
|
my ($scheme, $auth, undef, undef, undef) = uri_split(config('lookup_url')); |
2360
|
0
|
|
|
|
|
0
|
my $sig_url; |
2361
|
0
|
|
|
|
|
0
|
for my $ext (qw(asc sig sign)) { |
2362
|
0
|
|
|
|
|
0
|
eval { |
2363
|
0
|
|
|
|
|
0
|
$sig_url = uri_join($scheme, $auth, "$path.$ext", undef, undef); |
2364
|
0
|
|
|
|
|
0
|
$sig_file = no_mirror_download_file($sig_url); |
2365
|
|
|
|
|
|
|
|
2366
|
|
|
|
|
|
|
}; |
2367
|
|
|
|
|
|
|
# If the file was downloaded stop trying other extensions. |
2368
|
0
|
0
|
|
|
|
0
|
last if defined $sig_file; |
2369
|
|
|
|
|
|
|
} |
2370
|
0
|
0
|
|
|
|
0
|
die <
|
2371
|
|
|
|
|
|
|
App-Fetchware: Fetchware was unable to download the gpg_sig_url you specified or |
2372
|
|
|
|
|
|
|
that fetchware tried appending asc, sig, or sign to [$sig_url]. It needs |
2373
|
|
|
|
|
|
|
to download this file to properly verify you software package. This is a fatal |
2374
|
|
|
|
|
|
|
error, because failing to verify packages is a perferable default over |
2375
|
|
|
|
|
|
|
potentially installing compromised ones. If failing to verify your software |
2376
|
|
|
|
|
|
|
package is ok to you, then you may disable verification by adding |
2377
|
|
|
|
|
|
|
verify_failure_ok 'On'; to your Fetchwarefile. See perldoc App::Fetchware. |
2378
|
|
|
|
|
|
|
EOD |
2379
|
|
|
|
|
|
|
|
2380
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
###BUGALERT### # Use Crypt::OpenPGP if its installed. |
2382
|
|
|
|
|
|
|
###BUGALERT### if (eval {use Crypt::OpenPGP}) { |
2383
|
|
|
|
|
|
|
##DOESNTWORK?? # Build a pubring needed for verify. |
2384
|
|
|
|
|
|
|
##DOESNTWORK?? my $pubring = Crypt::OpenPGP::KeyRing->new(); |
2385
|
|
|
|
|
|
|
##DOESNTWORK?? my $secring = Crypt::OpenPGP::KeyRing->new(); |
2386
|
|
|
|
|
|
|
##DOESNTWORK?? |
2387
|
|
|
|
|
|
|
##DOESNTWORK?? # Turn on gpg compatibility just in case its needed. |
2388
|
|
|
|
|
|
|
##DOESNTWORK?? my $pgp = Crypt::OpenPGP->new( |
2389
|
|
|
|
|
|
|
##DOESNTWORK?? Compat => 'GnuPG', |
2390
|
|
|
|
|
|
|
##DOESNTWORK?? PubRing => $pubring, |
2391
|
|
|
|
|
|
|
##DOESNTWORK?? SecRing => $secring, |
2392
|
|
|
|
|
|
|
##DOESNTWORK?? # Automatically download public keys as needed. |
2393
|
|
|
|
|
|
|
##DOESNTWORK?? AutoKeyRetrieve => 1, |
2394
|
|
|
|
|
|
|
##DOESNTWORK?? # Use this keyserver to download them from. |
2395
|
|
|
|
|
|
|
##DOESNTWORK?? KeyServer => 'pool.sks-keyservers.net', |
2396
|
|
|
|
|
|
|
##DOESNTWORK?? ); |
2397
|
|
|
|
|
|
|
##DOESNTWORK?? |
2398
|
|
|
|
|
|
|
##DOESNTWORK?? # Verify the downloaded file. |
2399
|
|
|
|
|
|
|
##DOESNTWORK?? my $retval = $pgp->verify(SigFile => $sig_file, Files => $CONFIG{PackagePath}); |
2400
|
|
|
|
|
|
|
##DOESNTWORK?? if ($retval == 0) { |
2401
|
|
|
|
|
|
|
##DOESNTWORK?? warn "Crypt::OpenPGP failed due to invalid signature."; |
2402
|
|
|
|
|
|
|
##DOESNTWORK?? # return failure, because Fetchware failed to verify the downloaded |
2403
|
|
|
|
|
|
|
##DOESNTWORK?? # file. |
2404
|
|
|
|
|
|
|
##DOESNTWORK?? return undef; |
2405
|
|
|
|
|
|
|
##DOESNTWORK?? } elsif ($retval) { |
2406
|
|
|
|
|
|
|
##DOESNTWORK?? return 'Package verified'; |
2407
|
|
|
|
|
|
|
##DOESNTWORK?? } else { |
2408
|
|
|
|
|
|
|
##DOESNTWORK?? # print warning about $pgp errstr message. |
2409
|
|
|
|
|
|
|
##DOESNTWORK?? my $errstr = $pgp->errstr(); |
2410
|
|
|
|
|
|
|
##DOESNTWORK?? warn "Crypt::OpenPGP failed with message: [$errstr]"; |
2411
|
|
|
|
|
|
|
##DOESNTWORK?? # return failure, because Fetchware failed to verify the downloaded |
2412
|
|
|
|
|
|
|
##DOESNTWORK?? # file. |
2413
|
|
|
|
|
|
|
##DOESNTWORK?? return undef; |
2414
|
|
|
|
|
|
|
##DOESNTWORK?? } |
2415
|
|
|
|
|
|
|
###BUGALERT### } else { |
2416
|
|
|
|
|
|
|
###BUGALERT### ###BUGALERT### eval the run_prog()'s below & add better error reporting in |
2417
|
|
|
|
|
|
|
###BUGALERT### ###BUGALERT### if Crypt::OpenPGP works ok remove gpg support & this if & |
2418
|
|
|
|
|
|
|
###BUGALERT### } |
2419
|
|
|
|
|
|
|
#IPC::System::Simple dependency. |
2420
|
|
|
|
|
|
|
#my standard format. |
2421
|
|
|
|
|
|
|
# Use automatic key retrieval & a cool pool of keyservers |
2422
|
|
|
|
|
|
|
###BUGALERT## Give Crypt::OpenPGP another try with |
2423
|
|
|
|
|
|
|
#pool.sks-keyservers.net |
2424
|
|
|
|
|
|
|
###BUGALERT### Should I cache the files gpg puts in its "homedir"? They |
2425
|
|
|
|
|
|
|
#are the public keys that verify this fetchware package. Or should they |
2426
|
|
|
|
|
|
|
#always be downloaded on demand as they are now??? But if verify() can |
2427
|
|
|
|
|
|
|
#have keys cached inside the fetchware package does that mean that I |
2428
|
|
|
|
|
|
|
#should open up this as an API for fetchware extensions????? I don't |
2429
|
|
|
|
|
|
|
#know. I'll have to think more about this issue. |
2430
|
|
|
|
|
|
|
#run_prog('gpg', '--keyserver', 'pool.sks-keyservers.net', |
2431
|
|
|
|
|
|
|
# '--keyserver-options', 'auto-key-retrieve=1', |
2432
|
|
|
|
|
|
|
# '--homedir', '.', "$sig_file"); |
2433
|
|
|
|
|
|
|
|
2434
|
|
|
|
|
|
|
# Verify sig. |
2435
|
|
|
|
|
|
|
# Add --homedir option if needed. |
2436
|
0
|
0
|
|
|
|
0
|
if (config('user_keyring')) { |
2437
|
0
|
|
|
|
|
0
|
run_prog('gpg', '--verify', $sig_file); |
2438
|
|
|
|
|
|
|
} else { |
2439
|
0
|
|
|
|
|
0
|
run_prog('gpg', '--homedir', '.', '--verify', $sig_file); |
2440
|
|
|
|
|
|
|
} |
2441
|
|
|
|
|
|
|
|
2442
|
|
|
|
|
|
|
# Return true indicating the package was verified. |
2443
|
0
|
|
|
|
|
0
|
return 'Package Verified'; |
2444
|
|
|
|
|
|
|
} |
2445
|
|
|
|
|
|
|
|
2446
|
|
|
|
|
|
|
|
2447
|
|
|
|
|
|
|
|
2448
|
|
|
|
|
|
|
sub sha1_verify { |
2449
|
0
|
|
|
0
|
1
|
0
|
my ($download_path, $package_path) = @_; |
2450
|
|
|
|
|
|
|
|
2451
|
0
|
|
|
|
|
0
|
return digest_verify('SHA-1', $download_path, $package_path); |
2452
|
|
|
|
|
|
|
} |
2453
|
|
|
|
|
|
|
|
2454
|
|
|
|
|
|
|
|
2455
|
|
|
|
|
|
|
|
2456
|
|
|
|
|
|
|
sub md5_verify { |
2457
|
0
|
|
|
0
|
1
|
0
|
my ($download_path, $package_path) = @_; |
2458
|
|
|
|
|
|
|
|
2459
|
0
|
|
|
|
|
0
|
return digest_verify('MD5', $download_path, $package_path); |
2460
|
|
|
|
|
|
|
} |
2461
|
|
|
|
|
|
|
|
2462
|
|
|
|
|
|
|
|
2463
|
|
|
|
|
|
|
|
2464
|
|
|
|
|
|
|
sub digest_verify { |
2465
|
0
|
|
|
0
|
1
|
0
|
my ($digest_type, $download_path, $package_path) = @_; |
2466
|
|
|
|
|
|
|
|
2467
|
|
|
|
|
|
|
# Turn SHA-1 into sha1 & MD5 into md5. |
2468
|
0
|
|
|
|
|
0
|
my $digest_ext = $digest_type; |
2469
|
0
|
|
|
|
|
0
|
$digest_ext = lc $digest_type; |
2470
|
0
|
|
|
|
|
0
|
$digest_ext =~ s/-//g; |
2471
|
|
|
|
|
|
|
##subify get_sha_sum() |
2472
|
0
|
|
|
|
|
0
|
my $digest_file; |
2473
|
|
|
|
|
|
|
# Obtain a sha sum file. |
2474
|
0
|
0
|
|
|
|
0
|
if (defined config("${digest_ext}_url")) { |
2475
|
0
|
|
|
|
|
0
|
my (undef, undef, $path, undef, undef) = uri_split($download_path); |
2476
|
0
|
|
|
|
|
0
|
my ($scheme, $auth, undef, undef, undef) = |
2477
|
|
|
|
|
|
|
uri_split(config("${digest_ext}_url")); |
2478
|
0
|
|
|
|
|
0
|
my $digest_url = uri_join($scheme, $auth, $path, undef, undef); |
2479
|
0
|
|
|
|
|
0
|
msg "Downloading $digest_ext digest using [$digest_url.$digest_ext]"; |
2480
|
0
|
|
|
|
|
0
|
$digest_file = no_mirror_download_file("$digest_url.$digest_ext"); |
2481
|
|
|
|
|
|
|
} else { |
2482
|
0
|
|
|
|
|
0
|
eval { |
2483
|
0
|
|
|
|
|
0
|
my (undef, undef, $path, undef, undef) = uri_split($download_path); |
2484
|
0
|
|
|
|
|
0
|
my ($scheme, $auth, undef, undef, undef) = |
2485
|
|
|
|
|
|
|
uri_split(config('lookup_url')); |
2486
|
0
|
|
|
|
|
0
|
my $digest_url = uri_join($scheme, $auth, $path, undef, undef); |
2487
|
0
|
|
|
|
|
0
|
msg "Downloading $digest_ext digest using [$digest_url.$digest_ext]"; |
2488
|
0
|
|
|
|
|
0
|
$digest_file = no_mirror_download_file("$digest_url.$digest_ext"); |
2489
|
|
|
|
|
|
|
}; |
2490
|
0
|
0
|
|
|
|
0
|
if ($@) { |
2491
|
0
|
|
|
|
|
0
|
die <
|
2492
|
|
|
|
|
|
|
App-Fetchware: Fetchware was unable to download the $digest_type sum it needs to |
2493
|
|
|
|
|
|
|
download to properly verify you software package. This is a fatal error, because |
2494
|
|
|
|
|
|
|
failing to verify packages is a perferable default over potentially installin |
2495
|
|
|
|
|
|
|
compromised ones. If failing to verify your software package is ok to you, then |
2496
|
|
|
|
|
|
|
you may disable verification by adding verify_failure_ok 'On'; to your |
2497
|
|
|
|
|
|
|
Fetchwarefile. See perldoc App::Fetchware. |
2498
|
|
|
|
|
|
|
EOD |
2499
|
|
|
|
|
|
|
} |
2500
|
|
|
|
|
|
|
} |
2501
|
|
|
|
|
|
|
|
2502
|
|
|
|
|
|
|
###BUGALERT###subify calc_sum() |
2503
|
|
|
|
|
|
|
# Open the downloaded software archive for reading. |
2504
|
0
|
|
|
|
|
0
|
my $package_fh = safe_open($package_path, <
|
2505
|
|
|
|
|
|
|
App-Fetchware: run-time error. Fetchware failed to open the file it downloaded |
2506
|
|
|
|
|
|
|
while trying to read it in order to check its MD5 sum. The file was |
2507
|
|
|
|
|
|
|
[$package_path]. See perldoc App::Fetchware. |
2508
|
|
|
|
|
|
|
EOD |
2509
|
|
|
|
|
|
|
|
2510
|
|
|
|
|
|
|
# Do Digest type checking myself, because until Digest.pm 1.17, |
2511
|
|
|
|
|
|
|
# Digest->new() could run any Perl code you specify or a user does causing |
2512
|
|
|
|
|
|
|
# the security hole. Instead of use Digest 1.17, just avoid it altogether. |
2513
|
0
|
|
|
|
|
0
|
my $digest; |
2514
|
0
|
0
|
|
|
|
0
|
if ($digest_type eq 'MD5') { |
|
|
0
|
|
|
|
|
|
2515
|
0
|
|
|
|
|
0
|
$digest = Digest::MD5->new(); |
2516
|
|
|
|
|
|
|
} elsif ($digest_type eq 'SHA-1') { |
2517
|
0
|
|
|
|
|
0
|
$digest = Digest::SHA->new(); |
2518
|
|
|
|
|
|
|
} else { |
2519
|
0
|
|
|
|
|
0
|
die <
|
2520
|
|
|
|
|
|
|
EOD |
2521
|
|
|
|
|
|
|
} |
2522
|
|
|
|
|
|
|
|
2523
|
|
|
|
|
|
|
# Digest requires the filehandle to have binmode set. |
2524
|
0
|
|
|
|
|
0
|
binmode $package_fh; |
2525
|
|
|
|
|
|
|
|
2526
|
0
|
|
|
|
|
0
|
my $calculated_digest; |
2527
|
0
|
|
|
|
|
0
|
eval { |
2528
|
|
|
|
|
|
|
# Add the file for digesting. |
2529
|
0
|
|
|
|
|
0
|
$digest->addfile($package_fh); |
2530
|
|
|
|
|
|
|
# Actually digest it. |
2531
|
0
|
|
|
|
|
0
|
$calculated_digest = $digest->hexdigest(); |
2532
|
|
|
|
|
|
|
}; |
2533
|
0
|
0
|
|
|
|
0
|
if ($@) { |
2534
|
0
|
|
|
|
|
0
|
die <
|
2535
|
|
|
|
|
|
|
App-Fetchware: run-time error. Digest::$digest_type croak()ed an error [$@]. |
2536
|
|
|
|
|
|
|
See perldoc App::Fetchware. |
2537
|
|
|
|
|
|
|
EOD |
2538
|
|
|
|
|
|
|
} |
2539
|
|
|
|
|
|
|
|
2540
|
0
|
0
|
|
|
|
0
|
close $package_fh or die <
|
2541
|
|
|
|
|
|
|
App-Fetchware: run-time error Fetchware failed to close the file |
2542
|
|
|
|
|
|
|
[$package_path] after opening it for reading. See perldoc App::Fetchware. |
2543
|
|
|
|
|
|
|
EOD |
2544
|
|
|
|
|
|
|
|
2545
|
|
|
|
|
|
|
###subify compare_sums(); |
2546
|
|
|
|
|
|
|
# Open the downloaded software archive for reading. |
2547
|
0
|
|
|
|
|
0
|
my $digest_fh = safe_open($digest_file, <
|
2548
|
|
|
|
|
|
|
App-Fetchware: run-time error. Fetchware failed to open the $digest_type file it |
2549
|
|
|
|
|
|
|
downloaded while trying to read it in order to check its $digest_type sum. The file was |
2550
|
|
|
|
|
|
|
[$digest_file]. See perldoc App::Fetchware. |
2551
|
|
|
|
|
|
|
EOD |
2552
|
|
|
|
|
|
|
# Will only check the first checksum it finds. |
2553
|
0
|
|
|
|
|
0
|
while (<$digest_fh>) { |
2554
|
0
|
0
|
|
|
|
0
|
next if /^\s+$/; # skip whitespace only lines just in case. |
2555
|
0
|
|
|
|
|
0
|
my @fields = split ' '; # Defaults to $_, which is filled in by <> |
2556
|
|
|
|
|
|
|
|
2557
|
|
|
|
|
|
|
# Search the @fields for a regex that is either 32 hex for md5 or 40 hex |
2558
|
|
|
|
|
|
|
# for sha1. |
2559
|
0
|
|
|
|
|
0
|
my ($checksum) = grep /^[0-9a-f]{32}(?:[0-9a-f]{8})?$/i, @fields; |
2560
|
|
|
|
|
|
|
|
2561
|
|
|
|
|
|
|
# Skip trying to verify the $checksum if we failed to find it in this |
2562
|
|
|
|
|
|
|
# line, and instead skip to the next line in the checksum file to try to |
2563
|
|
|
|
|
|
|
# find a $checksum. |
2564
|
0
|
0
|
|
|
|
0
|
next unless defined $checksum; |
2565
|
|
|
|
|
|
|
|
2566
|
0
|
0
|
|
|
|
0
|
if ($checksum eq $calculated_digest) { |
|
|
0
|
|
|
|
|
|
2567
|
0
|
|
|
|
|
0
|
return 'Package verified'; |
2568
|
|
|
|
|
|
|
# Sometimes a = is appended to make it 32bits. |
2569
|
|
|
|
|
|
|
} elsif ("$checksum=" eq $calculated_digest) { |
2570
|
0
|
|
|
|
|
0
|
return 'Package verified'; |
2571
|
|
|
|
|
|
|
} |
2572
|
|
|
|
|
|
|
} |
2573
|
0
|
|
|
|
|
0
|
close $digest_fh; |
2574
|
|
|
|
|
|
|
|
2575
|
|
|
|
|
|
|
# Return failure, because fetchware failed to verify by checksum |
2576
|
0
|
|
|
|
|
0
|
return undef; |
2577
|
|
|
|
|
|
|
} |
2578
|
|
|
|
|
|
|
|
2579
|
|
|
|
|
|
|
|
2580
|
|
|
|
|
|
|
|
2581
|
|
|
|
|
|
|
|
2582
|
|
|
|
|
|
|
sub unarchive { |
2583
|
49
|
|
|
49
|
1
|
124
|
my $package_path = shift; |
2584
|
|
|
|
|
|
|
|
2585
|
49
|
|
|
|
|
286
|
msg "Unarchiving the downloaded package [$package_path]"; |
2586
|
|
|
|
|
|
|
|
2587
|
|
|
|
|
|
|
|
2588
|
49
|
|
|
|
|
271
|
my ($format, $files) = list_files($package_path); |
2589
|
|
|
|
|
|
|
|
2590
|
|
|
|
|
|
|
{ # Encloseing block for $", which prints a \n between each array element. |
2591
|
49
|
|
|
|
|
70
|
local $" = "\n"; |
|
49
|
|
|
|
|
156
|
|
2592
|
49
|
|
|
|
|
320
|
vmsg <
|
2593
|
|
|
|
|
|
|
Files are: |
2594
|
|
|
|
|
|
|
[ |
2595
|
|
|
|
|
|
|
@$files |
2596
|
|
|
|
|
|
|
] |
2597
|
|
|
|
|
|
|
EOM |
2598
|
|
|
|
|
|
|
} # Enclosing block for $" |
2599
|
|
|
|
|
|
|
|
2600
|
|
|
|
|
|
|
# Ensure no files starting with an absolute path get extracted |
2601
|
|
|
|
|
|
|
# And determine $build_path. |
2602
|
49
|
|
|
|
|
325
|
my $build_path = check_archive_files($files); |
2603
|
|
|
|
|
|
|
|
2604
|
49
|
|
|
|
|
235
|
vmsg "Unarchiving $format archive [$package_path]."; |
2605
|
49
|
|
|
|
|
272
|
unarchive_package($format, $package_path); |
2606
|
|
|
|
|
|
|
|
2607
|
49
|
|
|
|
|
447
|
msg "Determined build path to be [$build_path]"; |
2608
|
49
|
|
|
|
|
485
|
return $build_path; |
2609
|
|
|
|
|
|
|
} |
2610
|
|
|
|
|
|
|
|
2611
|
|
|
|
|
|
|
|
2612
|
|
|
|
|
|
|
|
2613
|
|
|
|
|
|
|
|
2614
|
|
|
|
|
|
|
|
2615
|
|
|
|
|
|
|
|
2616
|
|
|
|
|
|
|
sub list_files { |
2617
|
49
|
|
|
49
|
1
|
90
|
my $package_path = shift; |
2618
|
|
|
|
|
|
|
|
2619
|
|
|
|
|
|
|
# List files based on archive format. |
2620
|
49
|
|
|
|
|
132
|
my $files; |
2621
|
|
|
|
|
|
|
my $format; |
2622
|
49
|
50
|
|
|
|
850
|
if ($package_path =~ /\.(t(gz|bz|xz|Z))|(tar\.(gz|bz2|xz|Z))|.fpkg$/) { |
|
|
0
|
|
|
|
|
|
2623
|
49
|
|
|
|
|
101
|
$format = 'tar'; |
2624
|
49
|
|
|
|
|
252
|
vmsg <
|
2625
|
|
|
|
|
|
|
Listing files in your tar format archive [$package_path]. |
2626
|
|
|
|
|
|
|
EOM |
2627
|
49
|
|
|
|
|
295
|
$files = list_files_tar($package_path); |
2628
|
|
|
|
|
|
|
} elsif ($package_path =~ /\.zip$/) { |
2629
|
0
|
|
|
|
|
0
|
$format = 'zip'; |
2630
|
0
|
|
|
|
|
0
|
vmsg <
|
2631
|
|
|
|
|
|
|
Listing files in your zip format archive [$package_path]. |
2632
|
|
|
|
|
|
|
EOM |
2633
|
0
|
|
|
|
|
0
|
$files = list_files_zip($package_path); |
2634
|
|
|
|
|
|
|
} else { |
2635
|
0
|
|
|
|
|
0
|
die <
|
2636
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to determine what type of archive your |
2637
|
|
|
|
|
|
|
downloaded package is [$package_path]. Fetchware only supports zip and tar |
2638
|
|
|
|
|
|
|
format archives. |
2639
|
|
|
|
|
|
|
EOD |
2640
|
|
|
|
|
|
|
} |
2641
|
|
|
|
|
|
|
|
2642
|
|
|
|
|
|
|
# unarchive_package() needs $format, so return that too. |
2643
|
49
|
|
|
|
|
149
|
return $format, $files; |
2644
|
|
|
|
|
|
|
} |
2645
|
|
|
|
|
|
|
|
2646
|
|
|
|
|
|
|
|
2647
|
|
|
|
|
|
|
|
2648
|
|
|
|
|
|
|
sub list_files_tar { |
2649
|
49
|
|
|
49
|
1
|
72
|
my $path_to_tar_archive = shift; |
2650
|
|
|
|
|
|
|
|
2651
|
49
|
|
|
|
|
489
|
my $tar_iter = Archive::Tar->iter($path_to_tar_archive, 1, ); |
2652
|
49
|
50
|
|
|
|
66557
|
die <
|
2653
|
|
|
|
|
|
|
App-Fetchware: fetchware failed to create a new Archive::Tar iterator. The |
2654
|
0
|
|
|
|
|
0
|
Archive::Tar error message was [@{[Archive::Tar->error()]}]. |
2655
|
|
|
|
|
|
|
EOD |
2656
|
|
|
|
|
|
|
|
2657
|
|
|
|
|
|
|
# Iterate over the the archive one file at a time to save memory on big |
2658
|
|
|
|
|
|
|
# archives suchs a say MariaDB or the Linux kernel. |
2659
|
49
|
|
|
|
|
95
|
my @files; |
2660
|
49
|
|
|
|
|
169
|
while (my $file = $tar_iter->() ) { |
2661
|
196
|
|
|
|
|
80924
|
push @files, $file->full_path(); |
2662
|
|
|
|
|
|
|
} |
2663
|
|
|
|
|
|
|
|
2664
|
49
|
|
|
|
|
29511
|
return \@files; |
2665
|
|
|
|
|
|
|
} |
2666
|
|
|
|
|
|
|
|
2667
|
|
|
|
|
|
|
|
2668
|
|
|
|
|
|
|
{ # Begin %zip_error_codes hash. |
2669
|
|
|
|
|
|
|
my %zip_error_codes = ( |
2670
|
|
|
|
|
|
|
AZ_OK => 'Everything is fine.', |
2671
|
|
|
|
|
|
|
AZ_STREAM_END => |
2672
|
|
|
|
|
|
|
'The read stream (or central directory) ended normally.', |
2673
|
|
|
|
|
|
|
AZ_ERROR => 'There was some generic kind of error.', |
2674
|
|
|
|
|
|
|
AZ_FORMAT_ERROR => 'There is a format error in a ZIP file being read.', |
2675
|
|
|
|
|
|
|
AZ_IO_ERROR => 'There was an IO error' |
2676
|
|
|
|
|
|
|
); |
2677
|
|
|
|
|
|
|
|
2678
|
|
|
|
|
|
|
|
2679
|
|
|
|
|
|
|
|
2680
|
|
|
|
|
|
|
sub list_files_zip { |
2681
|
0
|
|
|
0
|
1
|
0
|
my $path_to_zip_archive = shift; |
2682
|
|
|
|
|
|
|
|
2683
|
0
|
|
|
|
|
0
|
my $zip = Archive::Zip->new(); |
2684
|
|
|
|
|
|
|
|
2685
|
0
|
|
|
|
|
0
|
my $zip_error; |
2686
|
0
|
0
|
|
|
|
0
|
if(($zip_error = $zip->read($path_to_zip_archive)) ne AZ_OK) { |
2687
|
0
|
|
|
|
|
0
|
die <
|
2688
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to read in the zip file [$path_to_zip_archive]. |
2689
|
|
|
|
|
|
|
The zip error message was [$zip_error_codes{$zip_error}]. |
2690
|
|
|
|
|
|
|
EOD |
2691
|
|
|
|
|
|
|
} |
2692
|
|
|
|
|
|
|
|
2693
|
|
|
|
|
|
|
# List the zip files "members," which are annoying classes not just a list |
2694
|
|
|
|
|
|
|
# of file names. I could use the memberNames() method, but that method |
2695
|
|
|
|
|
|
|
# returns their "internal" names, but I want their external names, what |
2696
|
|
|
|
|
|
|
# their names will be on your file system. |
2697
|
0
|
|
|
|
|
0
|
my @members = $zip->members(); |
2698
|
|
|
|
|
|
|
|
2699
|
0
|
|
|
|
|
0
|
my @external_filenames; |
2700
|
0
|
|
|
|
|
0
|
for my $member (@members) { |
2701
|
0
|
|
|
|
|
0
|
push @external_filenames, $member->fileName(); |
2702
|
|
|
|
|
|
|
} |
2703
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
# Return list of "external" filenames. |
2705
|
0
|
|
|
|
|
0
|
return \@external_filenames; |
2706
|
|
|
|
|
|
|
} |
2707
|
|
|
|
|
|
|
|
2708
|
|
|
|
|
|
|
|
2709
|
|
|
|
|
|
|
|
2710
|
|
|
|
|
|
|
sub unarchive_package { |
2711
|
49
|
|
|
49
|
1
|
79
|
my ($format, $package_path) = @_; |
2712
|
|
|
|
|
|
|
|
2713
|
49
|
50
|
|
|
|
300
|
unarchive_tar($package_path) if $format eq 'tar'; |
2714
|
49
|
50
|
|
|
|
279
|
unarchive_zip($package_path) if $format eq 'zip'; |
2715
|
|
|
|
|
|
|
} |
2716
|
|
|
|
|
|
|
|
2717
|
|
|
|
|
|
|
|
2718
|
|
|
|
|
|
|
|
2719
|
|
|
|
|
|
|
sub unarchive_tar { |
2720
|
49
|
|
|
49
|
1
|
85
|
my $path_to_tar_archive = shift; |
2721
|
|
|
|
|
|
|
|
2722
|
49
|
|
|
|
|
252
|
my @extracted_files = Archive::Tar->extract_archive($path_to_tar_archive); |
2723
|
|
|
|
|
|
|
# extract_archive() returns false if the extraction failed, which will |
2724
|
|
|
|
|
|
|
# create an array with one false element, so I have test if tha one element |
2725
|
|
|
|
|
|
|
# is false not something like if (@extracted_files), because if |
2726
|
|
|
|
|
|
|
# extract_archive() returns undef on failure not empty list. |
2727
|
49
|
50
|
|
|
|
731483
|
unless ($extracted_files[0]) { |
2728
|
0
|
|
|
|
|
0
|
die <
|
2729
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to extract your archive [$path_to_tar_archive]. |
2730
|
0
|
|
|
|
|
0
|
The error message from Archive::Tar was [@{[Archive::Tar->error()]}]. |
2731
|
|
|
|
|
|
|
EOD |
2732
|
|
|
|
|
|
|
} else { |
2733
|
49
|
|
|
|
|
237
|
return @extracted_files; |
2734
|
|
|
|
|
|
|
} |
2735
|
|
|
|
|
|
|
} |
2736
|
|
|
|
|
|
|
|
2737
|
|
|
|
|
|
|
|
2738
|
|
|
|
|
|
|
|
2739
|
|
|
|
|
|
|
sub unarchive_zip { |
2740
|
0
|
|
|
0
|
1
|
0
|
my $path_to_zip_archive = shift; |
2741
|
|
|
|
|
|
|
|
2742
|
0
|
|
|
|
|
0
|
my $zip = Archive::Zip->new(); |
2743
|
|
|
|
|
|
|
|
2744
|
0
|
|
|
|
|
0
|
my $zip_error; |
2745
|
0
|
0
|
|
|
|
0
|
if(($zip_error = $zip->read($path_to_zip_archive)) ne AZ_OK) { |
2746
|
0
|
|
|
|
|
0
|
die <
|
2747
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to read in the zip file [$path_to_zip_archive]. |
2748
|
|
|
|
|
|
|
The zip error message was [$zip_error_codes{$zip_error}]. |
2749
|
|
|
|
|
|
|
EOD |
2750
|
|
|
|
|
|
|
} |
2751
|
|
|
|
|
|
|
|
2752
|
0
|
0
|
|
|
|
0
|
if (($zip_error = $zip->extractTree()) ne AZ_OK) { |
2753
|
0
|
|
|
|
|
0
|
die <
|
2754
|
|
|
|
|
|
|
App-Fetchware: Fetchware failed to extract the zip file [$path_to_zip_archive]. |
2755
|
|
|
|
|
|
|
The zip error message was [$zip_error_codes{$zip_error}]. |
2756
|
|
|
|
|
|
|
EOD |
2757
|
|
|
|
|
|
|
} else { |
2758
|
0
|
|
|
|
|
0
|
return 'Extraced files successfully.'; |
2759
|
|
|
|
|
|
|
} |
2760
|
|
|
|
|
|
|
} |
2761
|
|
|
|
|
|
|
|
2762
|
|
|
|
|
|
|
} # End %zip_error_codes |
2763
|
|
|
|
|
|
|
|
2764
|
|
|
|
|
|
|
|
2765
|
|
|
|
|
|
|
|
2766
|
|
|
|
|
|
|
|
2767
|
|
|
|
|
|
|
sub check_archive_files { |
2768
|
52
|
|
|
52
|
1
|
584
|
my $files = shift; |
2769
|
|
|
|
|
|
|
|
2770
|
|
|
|
|
|
|
|
2771
|
|
|
|
|
|
|
# Determine if *all* files are in the same directory. |
2772
|
52
|
|
|
|
|
59
|
my %dir; |
2773
|
52
|
|
|
|
|
162
|
for my $path (@$files) { |
2774
|
|
|
|
|
|
|
# Skip Fetchwarefiles. |
2775
|
210
|
100
|
|
|
|
425
|
next if $path eq './Fetchwarefile'; |
2776
|
161
|
100
|
|
|
|
419
|
if (file_name_is_absolute($path)) { |
2777
|
1
|
|
|
|
|
9
|
my $error = <
|
2778
|
|
|
|
|
|
|
App-Fetchware: run-time error. The archive you asked fetchware to download has |
2779
|
|
|
|
|
|
|
one or more files with an absolute path. Absolute paths in archives is |
2780
|
|
|
|
|
|
|
dangerous, because the files could potentially overwrite files anywhere in the |
2781
|
|
|
|
|
|
|
filesystem including important system files. That is why this is a fatal error |
2782
|
|
|
|
|
|
|
that cannot be ignored. See perldoc App::Fetchware. |
2783
|
|
|
|
|
|
|
Absolute path [$path]. |
2784
|
|
|
|
|
|
|
EOE |
2785
|
1
|
|
|
|
|
2
|
$error .= "[\n"; |
2786
|
1
|
|
|
|
|
4
|
$error .= join("\n", @$files); |
2787
|
1
|
|
|
|
|
2
|
$error .= "\n]\n"; |
2788
|
|
|
|
|
|
|
|
2789
|
1
|
|
|
|
|
5
|
die $error; |
2790
|
|
|
|
|
|
|
} |
2791
|
|
|
|
|
|
|
|
2792
|
160
|
|
|
|
|
1042
|
my ($volume,$directories,$file) = splitpath($path); |
2793
|
160
|
|
|
|
|
1394
|
my @dirs = splitdir($directories); |
2794
|
|
|
|
|
|
|
# Skip empty directories. |
2795
|
160
|
100
|
|
|
|
674
|
next unless @dirs; |
2796
|
|
|
|
|
|
|
|
2797
|
111
|
|
|
|
|
650
|
$dir{$dirs[0]}++; |
2798
|
|
|
|
|
|
|
} |
2799
|
|
|
|
|
|
|
|
2800
|
|
|
|
|
|
|
|
2801
|
51
|
|
|
|
|
117
|
my $i = 0; |
2802
|
51
|
|
|
|
|
157
|
for my $dir (keys %dir) { |
2803
|
51
|
|
|
|
|
68
|
$i++; |
2804
|
51
|
50
|
|
|
|
92
|
warn < 1; |
2805
|
|
|
|
|
|
|
App-Fetchware: run-time warning. The archive you asked Fetchware to download |
2806
|
|
|
|
|
|
|
does *not* have *all* of its files in one and only one containing directory. |
2807
|
|
|
|
|
|
|
This is not a problem for fetchware, because it does all of its downloading, |
2808
|
|
|
|
|
|
|
unarchive, and building in a temporary directory that makes it easy to |
2809
|
|
|
|
|
|
|
automatically delete all of the files when fetchware is done with them. See |
2810
|
|
|
|
|
|
|
perldoc App::Fetchware. |
2811
|
|
|
|
|
|
|
EOD |
2812
|
|
|
|
|
|
|
|
2813
|
|
|
|
|
|
|
# Return $build_path |
2814
|
51
|
|
|
|
|
74
|
my $build_path = $dir; |
2815
|
51
|
|
|
|
|
142
|
return $build_path; |
2816
|
|
|
|
|
|
|
} |
2817
|
|
|
|
|
|
|
} |
2818
|
|
|
|
|
|
|
|
2819
|
|
|
|
|
|
|
|
2820
|
|
|
|
|
|
|
|
2821
|
|
|
|
|
|
|
|
2822
|
|
|
|
|
|
|
sub build { |
2823
|
0
|
|
|
0
|
1
|
0
|
my $build_path = shift; |
2824
|
|
|
|
|
|
|
|
2825
|
0
|
|
|
|
|
0
|
msg "Building your package in [$build_path]"; |
2826
|
|
|
|
|
|
|
|
2827
|
0
|
|
|
|
|
0
|
vmsg "changing Directory to build path [$build_path]"; |
2828
|
0
|
0
|
|
|
|
0
|
chdir $build_path or die <
|
2829
|
|
|
|
|
|
|
App-Fetchware: run-time error. Failed to chdir to the directory fetchware |
2830
|
|
|
|
|
|
|
unarchived [$build_path]. OS error [$!]. |
2831
|
|
|
|
|
|
|
EOD |
2832
|
|
|
|
|
|
|
|
2833
|
|
|
|
|
|
|
|
2834
|
|
|
|
|
|
|
# If build_commands is set, then all other build config options are ignored. |
2835
|
0
|
0
|
0
|
|
|
0
|
if (defined config('build_commands')) { |
|
|
0
|
0
|
|
|
|
|
2836
|
0
|
|
|
|
|
0
|
vmsg 'Building your package using user specified build_commands.'; |
2837
|
0
|
|
|
|
|
0
|
run_star_commands(config('build_commands')); |
2838
|
|
|
|
|
|
|
# Otherwise handle the other options properly. |
2839
|
|
|
|
|
|
|
} elsif ( |
2840
|
|
|
|
|
|
|
defined config('configure_options') |
2841
|
|
|
|
|
|
|
or defined config('prefix') |
2842
|
|
|
|
|
|
|
or defined config('make_options') |
2843
|
|
|
|
|
|
|
) { |
2844
|
|
|
|
|
|
|
|
2845
|
|
|
|
|
|
|
# Set up configure_options and prefix, and then run ./configure. |
2846
|
0
|
0
|
|
|
|
0
|
vmsg "Running configure with options [@{[config('configure_options')]}]" |
|
0
|
|
|
|
|
0
|
|
2847
|
|
|
|
|
|
|
if defined config('configure_options'); |
2848
|
0
|
|
|
|
|
0
|
run_configure(); |
2849
|
|
|
|
|
|
|
|
2850
|
|
|
|
|
|
|
# Next, make. |
2851
|
0
|
0
|
|
|
|
0
|
if (defined config('make_options')) { |
2852
|
0
|
|
|
|
|
0
|
vmsg 'Executing make to build your package'; |
2853
|
0
|
|
|
|
|
0
|
run_prog('make', config('make_options')) |
2854
|
|
|
|
|
|
|
} else { |
2855
|
0
|
|
|
|
|
0
|
vmsg 'Executing make to build your package'; |
2856
|
0
|
|
|
|
|
0
|
run_prog('make'); |
2857
|
|
|
|
|
|
|
} |
2858
|
|
|
|
|
|
|
|
2859
|
|
|
|
|
|
|
# Execute the default commands. |
2860
|
|
|
|
|
|
|
} else { |
2861
|
0
|
|
|
|
|
0
|
vmsg 'Running default build commands [./configure] and [make]'; |
2862
|
0
|
|
|
|
|
0
|
run_prog($_) for qw(./configure make); |
2863
|
|
|
|
|
|
|
} |
2864
|
|
|
|
|
|
|
|
2865
|
|
|
|
|
|
|
# Return success. |
2866
|
0
|
|
|
|
|
0
|
msg 'The build was successful.'; |
2867
|
0
|
|
|
|
|
0
|
return 'build succeeded'; |
2868
|
|
|
|
|
|
|
} |
2869
|
|
|
|
|
|
|
|
2870
|
|
|
|
|
|
|
###BUGALERT### Add a *() API REFERENCE section for each fetchware API |
2871
|
|
|
|
|
|
|
#subroutine, and subify the API subs that aren't yet. |
2872
|
|
|
|
|
|
|
|
2873
|
|
|
|
|
|
|
|
2874
|
|
|
|
|
|
|
|
2875
|
|
|
|
|
|
|
|
2876
|
|
|
|
|
|
|
sub run_star_commands { |
2877
|
4
|
|
|
4
|
1
|
1690
|
my @star_commands = @_; |
2878
|
|
|
|
|
|
|
|
2879
|
|
|
|
|
|
|
# Support multiple options like star_command './configure', 'make'; |
2880
|
|
|
|
|
|
|
# Should be called like run_star_commands(config'*_commands')), and |
2881
|
|
|
|
|
|
|
# config('star_commands') returns a list of *all* star_commands. |
2882
|
4
|
|
|
|
|
10
|
for my $star_command (@star_commands) { |
2883
|
|
|
|
|
|
|
# If a /,\s+/ is present in a $star_command |
2884
|
|
|
|
|
|
|
# To support: star_commands './configure, make'; |
2885
|
6
|
100
|
|
|
|
38
|
if ($star_command =~ /,\s*/) { |
2886
|
|
|
|
|
|
|
# split on it, and run each resulting command. |
2887
|
3
|
|
|
|
|
19
|
my @star_commands = split /,\s*/, $star_command; |
2888
|
3
|
|
|
|
|
8
|
for my $split_star_command (@star_commands) { |
2889
|
6
|
|
|
|
|
39
|
run_prog($split_star_command); |
2890
|
|
|
|
|
|
|
} |
2891
|
|
|
|
|
|
|
# Or just run the one command. |
2892
|
|
|
|
|
|
|
} else { |
2893
|
3
|
|
|
|
|
14
|
run_prog($star_command); |
2894
|
|
|
|
|
|
|
} |
2895
|
|
|
|
|
|
|
} |
2896
|
|
|
|
|
|
|
} |
2897
|
|
|
|
|
|
|
|
2898
|
|
|
|
|
|
|
|
2899
|
|
|
|
|
|
|
|
2900
|
|
|
|
|
|
|
###BUGALERT### Add an uninstall() option to instead edit the AutoTools paths |
2901
|
|
|
|
|
|
|
#into relative ones. |
2902
|
|
|
|
|
|
|
|
2903
|
|
|
|
|
|
|
sub run_configure { |
2904
|
49
|
|
|
49
|
1
|
150
|
my $configure = './configure'; |
2905
|
49
|
50
|
|
|
|
221
|
if (config('configure_options')) { |
2906
|
|
|
|
|
|
|
# Support multiple options like configure_options '--prefix', '.'; |
2907
|
0
|
|
|
|
|
0
|
for my $configure_option (config('configure_options')) { |
2908
|
0
|
|
|
|
|
0
|
$configure .= " $configure_option"; |
2909
|
|
|
|
|
|
|
} |
2910
|
|
|
|
|
|
|
} |
2911
|
|
|
|
|
|
|
|
2912
|
49
|
50
|
|
|
|
170
|
if (config('prefix')) { |
2913
|
0
|
0
|
|
|
|
0
|
if ($configure =~ /--prefix/) { |
2914
|
0
|
|
|
|
|
0
|
die <
|
2915
|
|
|
|
|
|
|
App-Fetchware: run-time error. You specified both the --prefix option twice. |
2916
|
|
|
|
|
|
|
Once in 'prefix' and once in 'configure_options'. You may only specify prefix |
2917
|
|
|
|
|
|
|
once in either configure option. See perldoc App::Fetchware. |
2918
|
|
|
|
|
|
|
EOD |
2919
|
|
|
|
|
|
|
} else { |
2920
|
|
|
|
|
|
|
###BUGALERT## At least under AutoTools, --prefix needs to be a full |
2921
|
|
|
|
|
|
|
#path. Should I check for this here? Ignore this possible error, and |
2922
|
|
|
|
|
|
|
#just let ./configure check its own arguments. Or add syntax |
2923
|
|
|
|
|
|
|
#checking to configuration subroutines??? |
2924
|
0
|
|
|
|
|
0
|
$configure .= " --prefix=@{[config('prefix')]}"; |
|
0
|
|
|
|
|
0
|
|
2925
|
|
|
|
|
|
|
} |
2926
|
|
|
|
|
|
|
} |
2927
|
|
|
|
|
|
|
|
2928
|
|
|
|
|
|
|
# Finally run ./configure. |
2929
|
49
|
|
|
|
|
270
|
run_prog($configure); |
2930
|
|
|
|
|
|
|
|
2931
|
|
|
|
|
|
|
# Return success. |
2932
|
49
|
|
|
|
|
316
|
return 'Configure successful'; |
2933
|
|
|
|
|
|
|
} |
2934
|
|
|
|
|
|
|
|
2935
|
|
|
|
|
|
|
|
2936
|
|
|
|
|
|
|
|
2937
|
|
|
|
|
|
|
sub install { |
2938
|
88
|
|
|
88
|
1
|
277
|
my $build_path = shift; |
2939
|
|
|
|
|
|
|
|
2940
|
|
|
|
|
|
|
# Skip installation if the user requests it. |
2941
|
88
|
50
|
|
|
|
378
|
if (config('no_install')) { |
2942
|
0
|
|
|
|
|
0
|
msg <
|
2943
|
|
|
|
|
|
|
Installation skipped, because no_install is specified in your Fetchwarefile. |
2944
|
|
|
|
|
|
|
EOM |
2945
|
0
|
|
|
|
|
0
|
return 'installation skipped!' ; |
2946
|
|
|
|
|
|
|
} |
2947
|
|
|
|
|
|
|
|
2948
|
88
|
|
|
|
|
698
|
msg 'Installing your software package.'; |
2949
|
|
|
|
|
|
|
|
2950
|
88
|
|
|
|
|
544
|
chdir_unless_already_at_path($build_path); |
2951
|
|
|
|
|
|
|
|
2952
|
88
|
50
|
|
|
|
1036
|
if (defined config('install_commands')) { |
2953
|
0
|
|
|
|
|
0
|
vmsg 'Installing your package using user specified commands.'; |
2954
|
0
|
|
|
|
|
0
|
run_star_commands(config('install_commands')); |
2955
|
|
|
|
|
|
|
} else { |
2956
|
88
|
50
|
|
|
|
343
|
if (defined config('make_options')) { |
2957
|
0
|
|
|
|
|
0
|
vmsg <
|
2958
|
|
|
|
|
|
|
Installing package using default command [make] with user specified make options. |
2959
|
|
|
|
|
|
|
EOM |
2960
|
0
|
|
|
|
|
0
|
run_prog('make', config('make_options'), 'install', ); |
2961
|
|
|
|
|
|
|
} else { |
2962
|
88
|
|
|
|
|
335
|
vmsg <
|
2963
|
|
|
|
|
|
|
Installing package using default command [make]. |
2964
|
|
|
|
|
|
|
EOM |
2965
|
88
|
|
|
|
|
618
|
run_prog('make', 'install'); |
2966
|
|
|
|
|
|
|
} |
2967
|
|
|
|
|
|
|
} |
2968
|
|
|
|
|
|
|
|
2969
|
88
|
|
|
|
|
920
|
msg 'Installation succeeded'; |
2970
|
|
|
|
|
|
|
# Return success. |
2971
|
88
|
|
|
|
|
583
|
return 'install succeeded'; |
2972
|
|
|
|
|
|
|
} |
2973
|
|
|
|
|
|
|
|
2974
|
|
|
|
|
|
|
|
2975
|
|
|
|
|
|
|
|
2976
|
|
|
|
|
|
|
|
2977
|
|
|
|
|
|
|
|
2978
|
|
|
|
|
|
|
sub chdir_unless_already_at_path { |
2979
|
139
|
|
|
139
|
1
|
10618
|
my $path = shift; |
2980
|
|
|
|
|
|
|
|
2981
|
|
|
|
|
|
|
# chdir() to $path unless its already our cwd. |
2982
|
|
|
|
|
|
|
# This is needed, because we'll inherit the "child's" chdir if stay_root is |
2983
|
|
|
|
|
|
|
# turned on, because stay_root does *not* fork and drop privs, which |
2984
|
|
|
|
|
|
|
# typicially causes the child's chdir to be "inherited" by the parent, |
2985
|
|
|
|
|
|
|
# because there is no parent and there is no child due to *not* forking. |
2986
|
139
|
50
|
|
|
|
337228
|
unless ( dir(cwd())->dir_list(-1, 1) eq $path ) { |
2987
|
139
|
50
|
|
|
|
18875
|
chdir($path) or die <
|
2988
|
|
|
|
|
|
|
fetchware: fetchware failed to chdir to the build directory [$path]. It |
2989
|
|
|
|
|
|
|
needs to chdir() to this directory, so that it can finish your fetchware |
2990
|
|
|
|
|
|
|
command. |
2991
|
|
|
|
|
|
|
EOD |
2992
|
139
|
|
|
|
|
1303
|
vmsg "chdir()'d to the necessary path [$path]."; |
2993
|
|
|
|
|
|
|
} |
2994
|
|
|
|
|
|
|
} |
2995
|
|
|
|
|
|
|
|
2996
|
|
|
|
|
|
|
|
2997
|
|
|
|
|
|
|
|
2998
|
|
|
|
|
|
|
|
2999
|
|
|
|
|
|
|
|
3000
|
|
|
|
|
|
|
|
3001
|
|
|
|
|
|
|
###BUGALERT### Is uninstall() calling API subs a bug??? Should it just use the |
3002
|
|
|
|
|
|
|
#lower level library functions of these tools. Have it do this after I subify |
3003
|
|
|
|
|
|
|
#the rest of the API subs like I've done to lookup and download. |
3004
|
|
|
|
|
|
|
###BUGALERT### NOT TESTED!!! There is no t/App-Fetchware-uninstall.t test |
3005
|
|
|
|
|
|
|
#file!!! cmd_uninstall(), which uses uninstall(), is tested, but not uninstall() |
3006
|
|
|
|
|
|
|
#directly!!! |
3007
|
|
|
|
|
|
|
sub uninstall { |
3008
|
49
|
|
|
49
|
1
|
100
|
my $build_path = shift; |
3009
|
|
|
|
|
|
|
|
3010
|
49
|
|
|
|
|
282
|
msg "Uninstalling package unarchived at path [$build_path]"; |
3011
|
|
|
|
|
|
|
|
3012
|
49
|
|
|
|
|
239
|
chdir_unless_already_at_path($build_path); |
3013
|
|
|
|
|
|
|
|
3014
|
49
|
50
|
|
|
|
614
|
if (defined config('uninstall_commands')) { |
3015
|
0
|
|
|
|
|
0
|
vmsg 'Uninstalling using user specified uninstall commands.'; |
3016
|
0
|
|
|
|
|
0
|
run_star_commands(config('uninstall_commands')); |
3017
|
|
|
|
|
|
|
} else { |
3018
|
|
|
|
|
|
|
# Set up configure_options and prefix, and then run ./configure, because |
3019
|
|
|
|
|
|
|
# Autotools uses full paths that ./configure sets up, and these paths |
3020
|
|
|
|
|
|
|
# change from install time to uninstall time. |
3021
|
49
|
|
|
|
|
191
|
vmsg q{Uninstalling using AutoTool's default of make uninstall}; |
3022
|
|
|
|
|
|
|
|
3023
|
49
|
|
|
|
|
266
|
vmsg q{Running AutoTool's default ./configure}; |
3024
|
49
|
|
|
|
|
297
|
run_configure(); |
3025
|
49
|
50
|
|
|
|
437
|
if (defined config('make_options')) { |
3026
|
0
|
|
|
|
|
0
|
vmsg <
|
3027
|
|
|
|
|
|
|
Running AutoTool's default make uninstall with user specified make options. |
3028
|
|
|
|
|
|
|
EOM |
3029
|
0
|
|
|
|
|
0
|
run_prog('make', config('make_options'), 'uninstall'); |
3030
|
|
|
|
|
|
|
} else { |
3031
|
49
|
|
|
|
|
228
|
vmsg <
|
3032
|
|
|
|
|
|
|
Running AutoTool's default make uninstall. |
3033
|
|
|
|
|
|
|
EOM |
3034
|
49
|
|
|
|
|
310
|
run_prog('make', 'uninstall'); |
3035
|
|
|
|
|
|
|
} |
3036
|
|
|
|
|
|
|
} |
3037
|
|
|
|
|
|
|
|
3038
|
|
|
|
|
|
|
|
3039
|
49
|
|
|
|
|
609
|
msg <
|
3040
|
|
|
|
|
|
|
Package uninstalled from system, but still installed in Fetchware's database. |
3041
|
|
|
|
|
|
|
EOM |
3042
|
|
|
|
|
|
|
# Return success. |
3043
|
49
|
|
|
|
|
402
|
return 'uninstall succeeded'; |
3044
|
|
|
|
|
|
|
} |
3045
|
|
|
|
|
|
|
|
3046
|
|
|
|
|
|
|
|
3047
|
|
|
|
|
|
|
|
3048
|
|
|
|
|
|
|
|
3049
|
|
|
|
|
|
|
sub upgrade { |
3050
|
9
|
|
|
9
|
1
|
2874
|
my ($download_path, $fetchware_package_path) = @_; |
3051
|
|
|
|
|
|
|
|
3052
|
|
|
|
|
|
|
# I only need the basename. |
3053
|
9
|
|
|
|
|
21
|
my $download_path_basename = file($download_path)->basename(); |
3054
|
9
|
|
|
|
|
521
|
my $upgrade_name_basename = |
3055
|
|
|
|
|
|
|
file( $fetchware_package_path)->basename(); |
3056
|
9
|
|
|
|
|
320
|
vmsg <
|
3057
|
|
|
|
|
|
|
Shortened the new download url [$download_path_basename] and the installed |
3058
|
|
|
|
|
|
|
package's [$upgrade_name_basename] into just their basenames. |
3059
|
|
|
|
|
|
|
EOM |
3060
|
|
|
|
|
|
|
|
3061
|
|
|
|
|
|
|
# Strip trailing garbage to normalize their names, so that they can be |
3062
|
|
|
|
|
|
|
# compared to each other. |
3063
|
|
|
|
|
|
|
###BUGALERT### This comparision is quite fragile. Figure out a better way to |
3064
|
|
|
|
|
|
|
#do this!!! |
3065
|
9
|
|
|
|
|
20
|
$upgrade_name_basename =~ s/\.fpkg$//; |
3066
|
9
|
|
|
|
|
33
|
$download_path_basename |
3067
|
|
|
|
|
|
|
=~ s/(\.(?:zip|tgz|tbz|txz|fpkg)|(?:\.tar\.(gz|bz2|xz|Z)?))$//; |
3068
|
9
|
|
|
|
|
21
|
vmsg <
|
3069
|
|
|
|
|
|
|
Striped the new download url [$download_path_basename] and the installed |
3070
|
|
|
|
|
|
|
package's [$upgrade_name_basename] of their file extensions. |
3071
|
|
|
|
|
|
|
EOM |
3072
|
|
|
|
|
|
|
|
3073
|
|
|
|
|
|
|
# Check if $upgrade_name_basename and $download_path_basename are eq, and if |
3074
|
|
|
|
|
|
|
# they are return false indicating that this program should not be upgraded, |
3075
|
|
|
|
|
|
|
# because the version available for upgrading is the same as the currently |
3076
|
|
|
|
|
|
|
# installed version. |
3077
|
9
|
100
|
|
|
|
26
|
return 0 if $upgrade_name_basename eq $download_path_basename; |
3078
|
|
|
|
|
|
|
|
3079
|
|
|
|
|
|
|
# Transform both competing filenames into a string of version numbers. |
3080
|
|
|
|
|
|
|
|
3081
|
|
|
|
|
|
|
# Use lookup_by_versionstring() to determine which version of the same |
3082
|
|
|
|
|
|
|
# program is "newer." |
3083
|
6
|
|
|
|
|
16
|
my $sorted_file_names = lookup_by_versionstring( |
3084
|
|
|
|
|
|
|
[ |
3085
|
|
|
|
|
|
|
[$upgrade_name_basename, 'placeholder'], |
3086
|
|
|
|
|
|
|
[$download_path_basename, 'placeholder'], |
3087
|
|
|
|
|
|
|
] |
3088
|
|
|
|
|
|
|
); |
3089
|
|
|
|
|
|
|
|
3090
|
6
|
100
|
66
|
|
|
21
|
if ($sorted_file_names->[0][0] eq $download_path_basename |
3091
|
|
|
|
|
|
|
# Make sure cmd_upgrade() does not upgrade when the latest version is |
3092
|
|
|
|
|
|
|
# the same as the currently installed version ($upgrade_name_basename). |
3093
|
|
|
|
|
|
|
and $sorted_file_names->[0][0] ne $upgrade_name_basename) { |
3094
|
|
|
|
|
|
|
# The latest version we can download ($download_path_basename) is newer |
3095
|
|
|
|
|
|
|
# than the currently installed version ($upgrade_name_basename), so we |
3096
|
|
|
|
|
|
|
# should upgrade. |
3097
|
3
|
|
|
|
|
16
|
return 1; |
3098
|
|
|
|
|
|
|
} else { |
3099
|
|
|
|
|
|
|
# Currenlty installed version ($upgrade_name_basename) is equal to the |
3100
|
|
|
|
|
|
|
# latest version available for download ($download_path_basename), so |
3101
|
|
|
|
|
|
|
# return false indicating that we sould not upgrade. |
3102
|
3
|
|
|
|
|
18
|
return 0; |
3103
|
|
|
|
|
|
|
} |
3104
|
|
|
|
|
|
|
} |
3105
|
|
|
|
|
|
|
|
3106
|
|
|
|
|
|
|
|
3107
|
|
|
|
|
|
|
|
3108
|
|
|
|
|
|
|
|
3109
|
|
|
|
|
|
|
sub check_syntax { |
3110
|
|
|
|
|
|
|
|
3111
|
|
|
|
|
|
|
# Use check_config_options() to run config() a bunch of times to check the |
3112
|
|
|
|
|
|
|
# already parsed Fetchwarefile. |
3113
|
170
|
|
|
170
|
1
|
3194
|
return check_config_options( |
3114
|
|
|
|
|
|
|
BothAreDefined => [ [qw(build_commands)], |
3115
|
|
|
|
|
|
|
[qw(prefix configure_options make_options)] ], |
3116
|
|
|
|
|
|
|
Mandatory => [ 'program', <
|
3117
|
|
|
|
|
|
|
App-Fetchware: Your Fetchwarefile must specify a program configuration |
3118
|
|
|
|
|
|
|
option. Please add one, and try again. |
3119
|
|
|
|
|
|
|
EOM |
3120
|
|
|
|
|
|
|
Mandatory => [ 'mirror', <
|
3121
|
|
|
|
|
|
|
App-Fetchware: Your Fetchwarefile must specify a mirror configuration |
3122
|
|
|
|
|
|
|
option. Please add one, and try again. |
3123
|
|
|
|
|
|
|
EOM |
3124
|
|
|
|
|
|
|
Mandatory => [ 'lookup_url', <
|
3125
|
|
|
|
|
|
|
App-Fetchware: Your Fetchwarefile must specify a lookup_url configuration |
3126
|
|
|
|
|
|
|
option. Please add one, and try again. |
3127
|
|
|
|
|
|
|
EOM |
3128
|
|
|
|
|
|
|
ConfigOptionEnum => ['lookup_method', [qw(timestamp versionstring)] ], |
3129
|
|
|
|
|
|
|
ConfigOptionEnum => ['verify_method', [qw(gpg sha1 md5)] ], |
3130
|
|
|
|
|
|
|
); |
3131
|
|
|
|
|
|
|
} |
3132
|
|
|
|
|
|
|
|
3133
|
|
|
|
|
|
|
|
3134
|
|
|
|
|
|
|
|
3135
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
|
3137
|
|
|
|
|
|
|
sub check_config_options { |
3138
|
179
|
|
|
179
|
1
|
502
|
my @args = @_; |
3139
|
|
|
|
|
|
|
|
3140
|
179
|
|
|
|
|
263
|
my @both_are_defined; |
3141
|
|
|
|
|
|
|
my @mandatory; |
3142
|
0
|
|
|
|
|
0
|
my @config_option_enum; |
3143
|
|
|
|
|
|
|
|
3144
|
|
|
|
|
|
|
# Process arguments, and check that they were specified correctly. |
3145
|
|
|
|
|
|
|
# Loop over @args 2 at a time hence the $i += 2 instead of $i++. |
3146
|
179
|
|
|
|
|
636
|
for( my $i = 0; $i < @args; $i += 2 ) { |
3147
|
1034
|
|
|
|
|
1367
|
my( $type, $AnB ) = @args[ $i, $i+1 ]; |
3148
|
1034
|
100
|
|
|
|
1429
|
die <
|
3149
|
|
|
|
|
|
|
App-Fetchware: check_config_options()'s even arguments must be an array |
3150
|
|
|
|
|
|
|
reference. Please correct your arguments, and try again. |
3151
|
|
|
|
|
|
|
EOD |
3152
|
1033
|
100
|
|
|
|
1273
|
die <
|
3153
|
|
|
|
|
|
|
App-Fetchware: check_config_options()'s even arguments must be an array |
3154
|
|
|
|
|
|
|
reference with exactly two elements in it. Please correct and try again. |
3155
|
|
|
|
|
|
|
EOD |
3156
|
|
|
|
|
|
|
|
3157
|
1032
|
100
|
|
|
|
1698
|
if ($type eq 'BothAreDefined') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
3158
|
173
|
|
|
|
|
545
|
push @both_are_defined, $AnB; |
3159
|
|
|
|
|
|
|
} elsif ($type eq 'Mandatory') { |
3160
|
515
|
|
|
|
|
829
|
push @mandatory, $AnB; |
3161
|
|
|
|
|
|
|
} elsif ($type eq 'ConfigOptionEnum') { |
3162
|
344
|
|
|
|
|
643
|
push @config_option_enum, $AnB; |
3163
|
|
|
|
|
|
|
} else { |
3164
|
0
|
|
|
|
|
0
|
die <
|
3165
|
|
|
|
|
|
|
App-Fetchware: check_config_options() only supports types 'BothAreDefined', |
3166
|
|
|
|
|
|
|
'Mandatory', and 'ConfigOptionEnum.' Please specify one of these, and try again. |
3167
|
|
|
|
|
|
|
EOD |
3168
|
|
|
|
|
|
|
} |
3169
|
|
|
|
|
|
|
} |
3170
|
|
|
|
|
|
|
|
3171
|
|
|
|
|
|
|
# Process @both_are_defined by checking if both of the elements in the |
3172
|
|
|
|
|
|
|
# provided arrayrefs are "both defined", and if they are "both defined" |
3173
|
|
|
|
|
|
|
# throw an exception. |
3174
|
177
|
|
|
|
|
352
|
for my $AnB (@both_are_defined) { |
3175
|
173
|
|
|
|
|
261
|
my ($A, $B) = @$AnB; |
3176
|
|
|
|
|
|
|
|
3177
|
173
|
|
|
|
|
229
|
my @A_defined; |
3178
|
|
|
|
|
|
|
my @B_defined; |
3179
|
|
|
|
|
|
|
|
3180
|
|
|
|
|
|
|
# Check which ones are defined in both $A and $B |
3181
|
|
|
|
|
|
|
{ |
3182
|
|
|
|
|
|
|
# the config() call will call the specified strings of which many |
3183
|
|
|
|
|
|
|
# are expected to be uninitialized. Because we expect them to be |
3184
|
|
|
|
|
|
|
# uninitialized, we use that behavior to determine if they have been |
3185
|
|
|
|
|
|
|
# specified in the users Fetchwarefile, and if an option was not |
3186
|
|
|
|
|
|
|
# specified, then undef is returned by config(). Since, we expect |
3187
|
|
|
|
|
|
|
# lots of undef warnings, we'll disable them. |
3188
|
50
|
|
|
50
|
|
583
|
no warnings 'uninitialized'; |
|
50
|
|
|
|
|
103
|
|
|
50
|
|
|
|
|
8720
|
|
|
173
|
|
|
|
|
178
|
|
3189
|
173
|
|
|
|
|
314
|
@A_defined = grep {config($_)} @$A; |
|
173
|
|
|
|
|
410
|
|
3190
|
173
|
|
|
|
|
332
|
@B_defined = grep {config($_)} @$B; |
|
519
|
|
|
|
|
713
|
|
3191
|
|
|
|
|
|
|
} |
3192
|
|
|
|
|
|
|
|
3193
|
173
|
100
|
100
|
|
|
728
|
if (@A_defined > 0 and @B_defined > 0) { |
3194
|
1
|
|
|
|
|
34
|
die <
|
3195
|
|
|
|
|
|
|
App-Fetchware: Your Fetchwarefile has incompatible configuration options. |
3196
|
|
|
|
|
|
|
You specified configuration options [@$A] and [@$B], but these options are not |
3197
|
|
|
|
|
|
|
compatible with each other. Please specifiy either [@$A] or [@$B] not both. |
3198
|
|
|
|
|
|
|
EOD |
3199
|
|
|
|
|
|
|
} |
3200
|
|
|
|
|
|
|
} |
3201
|
|
|
|
|
|
|
|
3202
|
|
|
|
|
|
|
|
3203
|
|
|
|
|
|
|
# Process @mandatory options by checking if they're defined, and if not |
3204
|
|
|
|
|
|
|
# throwing the specified exception. |
3205
|
176
|
|
|
|
|
354
|
for my $AnB (@mandatory) { |
3206
|
515
|
|
|
|
|
720
|
my ($option, $error_message) = @$AnB; |
3207
|
|
|
|
|
|
|
|
3208
|
515
|
100
|
|
|
|
822
|
die $error_message if not defined config($option); |
3209
|
|
|
|
|
|
|
} |
3210
|
|
|
|
|
|
|
|
3211
|
|
|
|
|
|
|
|
3212
|
|
|
|
|
|
|
# Process @config_option_enum. |
3213
|
175
|
|
|
|
|
323
|
for my $AnB (@config_option_enum) { |
3214
|
344
|
|
|
|
|
464
|
my ($option, $enumerations) = @$AnB; |
3215
|
|
|
|
|
|
|
|
3216
|
|
|
|
|
|
|
# Ditch uninitialized warnings, because I'm using undef to mean |
3217
|
|
|
|
|
|
|
# unspecified, so undef is not something unexpected to bother warning |
3218
|
|
|
|
|
|
|
# about, but something that will happen all the time. |
3219
|
|
|
|
|
|
|
{ |
3220
|
50
|
|
|
50
|
|
262
|
no warnings 'uninitialized'; |
|
50
|
|
|
|
|
76
|
|
|
50
|
|
|
|
|
10369
|
|
|
344
|
|
|
|
|
386
|
|
3221
|
|
|
|
|
|
|
|
3222
|
|
|
|
|
|
|
# Only test the @enumerations if $option was specified in the |
3223
|
|
|
|
|
|
|
# Fetchwarefile. |
3224
|
344
|
100
|
|
|
|
506
|
if (config($option)) { |
3225
|
|
|
|
|
|
|
|
3226
|
|
|
|
|
|
|
# Only one @enumerations should equal $option not more than one, hence |
3227
|
|
|
|
|
|
|
# the == 1 part. |
3228
|
171
|
100
|
|
|
|
190
|
die <
|
|
513
|
|
|
|
|
755
|
|
3229
|
|
|
|
|
|
|
App-Fetchware: You specified the option [$option], but failed to specify only |
3230
|
|
|
|
|
|
|
one of its acceptable values [@$enumerations]. Please change the value you |
3231
|
1
|
|
|
|
|
2
|
specified [@{[config($option)]}] to one of the acceptable ones listed above, and try again. |
3232
|
|
|
|
|
|
|
EOD |
3233
|
|
|
|
|
|
|
} |
3234
|
|
|
|
|
|
|
|
3235
|
|
|
|
|
|
|
} |
3236
|
|
|
|
|
|
|
} |
3237
|
|
|
|
|
|
|
|
3238
|
174
|
|
|
|
|
455
|
return 'Syntax Ok'; |
3239
|
|
|
|
|
|
|
} |
3240
|
|
|
|
|
|
|
|
3241
|
|
|
|
|
|
|
|
3242
|
|
|
|
|
|
|
|
3243
|
|
|
|
|
|
|
|
3244
|
|
|
|
|
|
|
sub end { |
3245
|
|
|
|
|
|
|
# Use cleanup_tempdir() to cleanup your tempdir for us. |
3246
|
168
|
|
|
168
|
1
|
2222
|
cleanup_tempdir(); |
3247
|
|
|
|
|
|
|
} |
3248
|
|
|
|
|
|
|
|
3249
|
|
|
|
|
|
|
|
3250
|
|
|
|
|
|
|
|
3251
|
|
|
|
|
|
|
1; |
3252
|
|
|
|
|
|
|
|
3253
|
|
|
|
|
|
|
|
3254
|
|
|
|
|
|
|
|
3255
|
|
|
|
|
|
|
|
3256
|
|
|
|
|
|
|
|
3257
|
|
|
|
|
|
|
|
3258
|
|
|
|
|
|
|
|
3259
|
|
|
|
|
|
|
|
3260
|
|
|
|
|
|
|
|
3261
|
|
|
|
|
|
|
|
3262
|
|
|
|
|
|
|
|
3263
|
|
|
|
|
|
|
|
3264
|
|
|
|
|
|
|
|
3265
|
|
|
|
|
|
|
|
3266
|
|
|
|
|
|
|
|
3267
|
|
|
|
|
|
|
|
3268
|
|
|
|
|
|
|
|
3269
|
|
|
|
|
|
|
sub hook ($$) { |
3270
|
2
|
|
|
2
|
1
|
785
|
my ($sub_to_hook, $callback) = @_; |
3271
|
|
|
|
|
|
|
|
3272
|
2
|
100
|
|
|
|
24
|
die <can($sub_to_hook); |
3273
|
|
|
|
|
|
|
App-Fetchware: The subroutine [$sub_to_hook] you attempted to override does |
3274
|
|
|
|
|
|
|
not exist in this package. Perhaps you misspelled it, or it does not exist in |
3275
|
|
|
|
|
|
|
the current package. |
3276
|
|
|
|
|
|
|
EOD |
3277
|
|
|
|
|
|
|
|
3278
|
1
|
|
|
|
|
4
|
override $sub_to_hook => $callback; |
3279
|
|
|
|
|
|
|
|
3280
|
|
|
|
|
|
|
# Overriding the subroutine is not enough, because it is overriding it |
3281
|
|
|
|
|
|
|
# inside App::Fetchware, so I need to also override the subroutine inside |
3282
|
|
|
|
|
|
|
# hook()'s caller as done below. |
3283
|
|
|
|
|
|
|
{ |
3284
|
50
|
|
|
50
|
|
276
|
no warnings 'redefine'; |
|
50
|
|
|
|
|
79
|
|
|
50
|
|
|
|
|
5393
|
|
|
1
|
|
|
|
|
51
|
|
3285
|
1
|
|
|
|
|
5
|
clone($sub_to_hook => (from => 'App::Fetchware', to => caller())); |
3286
|
|
|
|
|
|
|
} |
3287
|
|
|
|
|
|
|
} |
3288
|
|
|
|
|
|
|
|
3289
|
|
|
|
|
|
|
|
3290
|
|
|
|
|
|
|
###BUGALERT### Add an section of use cases. You know explaing why you'd use |
3291
|
|
|
|
|
|
|
#no_install, or why'd you'd use look, or why And so on..... |
3292
|
|
|
|
|
|
|
|
3293
|
|
|
|
|
|
|
|
3294
|
|
|
|
|
|
|
|
3295
|
|
|
|
|
|
|
|
3296
|
|
|
|
|
|
|
###BUGALERT### Create a fetchware command to do this for users perhaps even |
3297
|
|
|
|
|
|
|
#plugin it into Module::Starter???? If possible. |
3298
|
|
|
|
|
|
|
####BUGALERT## Even have so that you can specify which API subs you want to |
3299
|
|
|
|
|
|
|
#override or avoid overriding, and then it will create the skelton with stubs |
3300
|
|
|
|
|
|
|
#for those API sub already having some empty POD crap and the correct |
3301
|
|
|
|
|
|
|
#prototypes. |
3302
|
|
|
|
|
|
|
|
3303
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
|
3305
|
|
|
|
|
|
|
|
3306
|
|
|
|
|
|
|
|
3307
|
|
|
|
|
|
|
|
3308
|
|
|
|
|
|
|
|
3309
|
|
|
|
|
|
|
|
3310
|
|
|
|
|
|
|
###BUGALERT### Actually implement croak or more likely confess() support!!! |
3311
|
|
|
|
|
|
|
|
3312
|
|
|
|
|
|
|
__END__ |