| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package App::Fetchware; | 
| 2 |  |  |  |  |  |  | $App::Fetchware::VERSION = '1.014'; | 
| 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 | 46 |  |  | 46 |  | 708247 | use strict; | 
|  | 46 |  |  |  |  | 136 |  | 
|  | 46 |  |  |  |  | 2611 |  | 
| 8 | 46 |  |  | 46 |  | 415 | use warnings; | 
|  | 46 |  |  |  |  | 145 |  | 
|  | 46 |  |  |  |  | 2168 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | # CPAN modules making Fetchwarefile better. | 
| 11 | 46 |  |  | 46 |  | 5166 | use File::Spec::Functions qw(catfile splitpath splitdir file_name_is_absolute); | 
|  | 46 |  |  |  |  | 2544 |  | 
|  | 46 |  |  |  |  | 3911 |  | 
| 12 | 46 |  |  | 46 |  | 2121 | use Path::Class; | 
|  | 46 |  |  |  |  | 189270 |  | 
|  | 46 |  |  |  |  | 2489 |  | 
| 13 | 46 |  |  | 46 |  | 4134 | use Data::Dumper; | 
|  | 46 |  |  |  |  | 20447 |  | 
|  | 46 |  |  |  |  | 2240 |  | 
| 14 | 46 |  |  | 46 |  | 262 | use File::Copy 'cp'; | 
|  | 46 |  |  |  |  | 111 |  | 
|  | 46 |  |  |  |  | 2084 |  | 
| 15 | 46 |  |  | 46 |  | 61338 | use HTML::TreeBuilder; | 
|  | 46 |  |  |  |  | 2249083 |  | 
|  | 46 |  |  |  |  | 772 |  | 
| 16 | 46 |  |  | 46 |  | 5707 | use Scalar::Util qw(blessed looks_like_number); | 
|  | 46 |  |  |  |  | 129 |  | 
|  | 46 |  |  |  |  | 4015 |  | 
| 17 | 46 |  |  | 46 |  | 58225 | use Digest::SHA; | 
|  | 46 |  |  |  |  | 180015 |  | 
|  | 46 |  |  |  |  | 2898 |  | 
| 18 | 46 |  |  | 46 |  | 503 | use Digest::MD5; | 
|  | 46 |  |  |  |  | 137 |  | 
|  | 46 |  |  |  |  | 1681 |  | 
| 19 |  |  |  |  |  |  | #use Crypt::OpenPGP::KeyRing; | 
| 20 |  |  |  |  |  |  | #use Crypt::OpenPGP; | 
| 21 | 46 |  |  | 46 |  | 3124 | use Archive::Tar; | 
|  | 46 |  |  |  |  | 312944 |  | 
|  | 46 |  |  |  |  | 7205 |  | 
| 22 | 46 |  |  | 46 |  | 89900 | use Archive::Zip qw(:ERROR_CODES :CONSTANTS); | 
|  | 46 |  |  |  |  | 2499696 |  | 
|  | 46 |  |  |  |  | 9595 |  | 
| 23 | 46 |  |  | 46 |  | 545 | use Cwd 'cwd'; | 
|  | 46 |  |  |  |  | 266 |  | 
|  | 46 |  |  |  |  | 2125 |  | 
| 24 | 46 |  |  | 46 |  | 11214 | use Sub::Mage; | 
|  | 46 |  |  |  |  | 29704 |  | 
|  | 46 |  |  |  |  | 576 |  | 
| 25 | 46 |  |  | 46 |  | 13584 | use URI::Split qw(uri_split uri_join); | 
|  | 46 |  |  |  |  | 6023 |  | 
|  | 46 |  |  |  |  | 3746 |  | 
| 26 | 46 |  |  | 46 |  | 2040 | use Text::ParseWords 'quotewords'; | 
|  | 46 |  |  |  |  | 2946 |  | 
|  | 46 |  |  |  |  | 2206 |  | 
| 27 | 46 |  |  | 46 |  | 265 | use File::Temp 'tempfile'; | 
|  | 46 |  |  |  |  | 88 |  | 
|  | 46 |  |  |  |  | 2090 |  | 
| 28 | 46 |  |  | 46 |  | 53042 | use Term::ReadLine; | 
|  | 46 |  |  |  |  | 229931 |  | 
|  | 46 |  |  |  |  | 1937 |  | 
| 29 | 46 |  |  | 46 |  | 49185 | use Term::UI; | 
|  | 46 |  |  |  |  | 1856907 |  | 
|  | 46 |  |  |  |  | 2351 |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 46 |  |  | 46 |  | 3530 | use App::Fetchware::Util ':UTIL'; | 
|  | 46 |  |  |  |  | 134 |  | 
|  | 46 |  |  |  |  | 15957 |  | 
| 32 | 46 |  |  | 46 |  | 332 | use App::Fetchware::Config ':CONFIG'; | 
|  | 46 |  |  |  |  | 106 |  | 
|  | 46 |  |  |  |  | 7123 |  | 
| 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 | 46 |  |  | 46 |  | 6299 | use 5.010001; | 
|  | 46 |  |  |  |  | 220 |  | 
|  | 46 |  |  |  |  | 2086 |  | 
| 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 | 46 |  |  | 46 |  | 5581 | use Exporter qw( import ); | 
|  | 46 |  |  |  |  | 93 |  | 
|  | 46 |  |  |  |  | 715413 |  | 
| 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 | 1180 |  |  | 1180 |  | 5954 | 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 | 1180 |  | 66 |  |  | 4842 | my $package = $callers_package // caller; | 
| 306 |  |  |  |  |  |  |  | 
| 307 | 1180 | 50 |  |  |  | 2777 | 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 | 1180 | 50 | 100 |  |  | 5347 | 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 | 1180 | 100 |  |  |  | 3411 | if ($one_or_many_values eq 'ONE') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 325 | 668 |  |  |  |  | 989 | 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 | 668 |  |  |  |  | 7232 | $eval =~ s/\$name/$name/g; | 
| 352 | 668 |  |  |  |  | 2779 | $eval =~ s/\$package/$package/g; | 
| 353 | 668 | 50 |  | 2 | 1 | 104044 | eval $eval or die < | 
|  | 2 | 50 |  | 152 | 1 | 63 |  | 
|  | 2 | 100 |  | 2 | 1 | 8 |  | 
|  | 2 | 50 |  | 2 | 1 | 9 |  | 
|  | 1 | 100 |  | 2 | 1 | 8 |  | 
|  | 1 | 50 |  | 152 | 1 | 7 |  | 
|  | 152 | 100 |  | 2 | 1 | 532 |  | 
|  | 152 | 50 |  | 2 | 1 | 649 |  | 
|  | 152 | 100 |  | 152 | 1 | 710 |  | 
|  | 151 | 50 |  | 2 | 1 | 623 |  | 
|  | 1 | 100 |  | 5 | 1 | 8 |  | 
|  | 2 | 50 |  | 2 | 1 | 57 |  | 
|  | 2 | 100 |  | 0 | 1 | 6 |  | 
|  | 2 | 50 |  | 152 | 1 | 7 |  | 
|  | 1 | 100 |  | 0 | 1 | 4 |  | 
|  | 1 | 50 |  | 0 | 1 | 7 |  | 
|  | 2 | 100 |  | 0 |  | 52 |  | 
|  | 2 | 50 |  | 0 |  | 6 |  | 
|  | 2 | 100 |  | 0 |  | 5 |  | 
|  | 1 | 50 |  | 0 |  | 4 |  | 
|  | 1 | 100 |  | 0 |  | 5 |  | 
|  | 2 | 50 |  | 0 |  | 57 |  | 
|  | 2 | 100 |  | 0 |  | 8 |  | 
|  | 2 | 50 |  | 1 |  | 9 |  | 
|  | 1 | 100 |  | 1 |  | 3 |  | 
|  | 1 | 0 |  | 1 |  | 7 |  | 
|  | 152 | 0 |  | 1 |  | 548 |  | 
|  | 152 | 50 |  | 1 |  | 614 |  | 
|  | 152 | 100 |  | 1 |  | 601 |  | 
|  | 151 | 0 |  | 1 |  | 525 |  | 
|  | 1 | 0 |  | 1 |  | 7 |  | 
|  | 2 | 0 |  | 1 |  | 55 |  | 
|  | 2 | 0 |  |  |  | 8 |  | 
|  | 2 | 0 |  |  |  | 6 |  | 
|  | 1 | 0 |  |  |  | 3 |  | 
|  | 1 | 0 |  |  |  | 7 |  | 
|  | 2 | 0 |  |  |  | 66 |  | 
|  | 2 | 0 |  |  |  | 8 |  | 
|  | 2 | 0 |  |  |  | 8 |  | 
|  | 1 | 0 |  |  |  | 4 |  | 
|  | 1 | 0 |  |  |  | 8 |  | 
|  | 152 | 0 |  |  |  | 2763 |  | 
|  | 152 | 0 |  |  |  | 5521 |  | 
|  | 152 | 0 |  |  |  | 632 |  | 
|  | 151 | 0 |  |  |  | 537 |  | 
|  | 1 | 0 |  |  |  | 13 |  | 
|  | 2 | 0 |  |  |  | 53 |  | 
|  | 2 | 50 |  |  |  | 6 |  | 
|  | 2 | 50 |  |  |  | 6 |  | 
|  | 1 | 50 |  |  |  | 4 |  | 
|  | 1 | 50 |  |  |  | 5 |  | 
|  | 5 | 50 |  |  |  | 1678 |  | 
|  | 5 | 50 |  |  |  | 22 |  | 
|  | 5 | 50 |  |  |  | 21 |  | 
|  | 4 | 50 |  |  |  | 15 |  | 
|  | 1 | 50 |  |  |  | 9 |  | 
|  | 2 | 50 |  |  |  | 65 |  | 
|  | 2 | 50 |  |  |  | 9 |  | 
|  | 2 | 50 |  |  |  | 8 |  | 
|  | 1 | 50 |  |  |  | 4 |  | 
|  | 1 | 50 |  |  |  | 7 |  | 
|  | 0 | 50 |  |  |  | 0 |  | 
|  | 0 | 50 |  |  |  | 0 |  | 
|  | 0 | 50 |  |  |  | 0 |  | 
|  | 0 | 50 |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 152 |  |  |  |  | 802 |  | 
|  | 152 |  |  |  |  | 634 |  | 
|  | 152 |  |  |  |  | 622 |  | 
|  | 151 |  |  |  |  | 1428 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 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 |  |  |  |  | 1922 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 14409 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 1230 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 588 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 19 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 487 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 457 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 561 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 497 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 445 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 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 | 245 |  |  |  |  | 386 | 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 | 245 |  |  |  |  | 2014 | $eval =~ s/\$name/$name/g; | 
| 379 | 245 |  |  |  |  | 944 | $eval =~ s/\$package/$package/g; | 
| 380 | 245 | 50 |  | 2 | 1 | 34070 | eval $eval or die < | 
|  | 2 | 50 |  | 2 | 1 | 59 |  | 
|  | 2 | 100 |  | 2 | 1 | 6 |  | 
|  | 2 | 50 |  | 2 | 1 | 7 |  | 
|  | 1 | 100 |  | 2 | 1 | 3 |  | 
|  | 1 | 50 |  |  |  | 5 |  | 
|  | 2 | 100 |  |  |  | 457 |  | 
|  | 2 | 50 |  |  |  | 8 |  | 
|  | 2 | 100 |  |  |  | 9 |  | 
|  | 1 | 50 |  |  |  | 5 |  | 
|  | 1 | 100 |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 57 |  | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 75 |  | 
|  | 2 |  |  |  |  | 9 |  | 
|  | 2 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 18 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 537 |  | 
|  | 2 |  |  |  |  | 11 |  | 
|  | 2 |  |  |  |  | 15 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 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 | 64 |  |  |  |  | 203 | 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 | 64 |  |  |  |  | 497 | $eval =~ s/\$name/$name/g; | 
| 402 | 64 |  |  |  |  | 378 | $eval =~ s/\$package/$package/g; | 
| 403 | 64 | 50 |  | 157 | 1 | 7260 | eval $eval or die < | 
|  | 157 | 100 |  |  |  | 2045 |  | 
|  | 157 |  |  |  |  | 565 |  | 
|  | 156 |  |  |  |  | 524 |  | 
|  | 2 |  |  |  |  | 10 |  | 
| 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 | 203 |  |  |  |  | 2991 | 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 | 203 |  |  |  |  | 3267 | $eval =~ s/\$name/$name/g; | 
| 443 | 203 |  |  |  |  | 1006 | $eval =~ s/\$package/$package/g; | 
| 444 | 203 | 50 |  | 7 | 1 | 95048 | eval $eval or die < | 
|  | 6 | 100 |  | 4 | 1 | 2059 |  | 
|  | 7 | 50 |  | 4 | 1 | 446 |  | 
|  | 7 | 100 |  | 4 | 1 | 48 |  | 
|  | 1 | 100 |  |  |  | 6 |  | 
|  | 1 | 100 |  |  |  | 3 |  | 
|  | 6 | 50 |  |  |  | 21 |  | 
|  | 6 | 100 |  |  |  | 561 |  | 
|  | 2 | 100 |  |  |  | 11 |  | 
|  | 4 | 100 |  |  |  | 526 |  | 
|  | 4 | 100 |  |  |  | 16 |  | 
|  | 3 | 100 |  |  |  | 28 |  | 
|  | 1 | 100 |  |  |  | 422 |  | 
|  | 1 | 100 |  |  |  | 5 |  | 
|  | 4 | 100 |  |  |  | 17 |  | 
|  | 3 | 100 |  |  |  | 11 |  | 
|  | 1 | 100 |  |  |  | 5 |  | 
|  | 4 |  |  |  |  | 1109 |  | 
|  | 4 |  |  |  |  | 17 |  | 
|  | 4 |  |  |  |  | 30 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 3 |  |  |  |  | 15 |  | 
|  | 2 |  |  |  |  | 10 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 581 |  | 
|  | 3 |  |  |  |  | 11 |  | 
|  | 3 |  |  |  |  | 22 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 3 |  |  |  |  | 11 |  | 
|  | 2 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 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 | 958 | 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 |  |  |  |  | 10 | my $now = localtime; | 
| 463 | 2 |  |  |  |  | 14 | 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 |  |  |  |  | 436 | 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 |  |  |  |  | 10 | 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 |  |  |  |  | 9 | $program_name = fetchwarefile_name(program => $program_name); | 
| 621 | 0 |  |  |  |  | 0 | vmsg "Determined name of your program to be [$program_name]"; | 
| 622 |  |  |  |  |  |  |  | 
| 623 | 2 |  |  |  |  | 932 | $fetchwarefile->config_options(program => $program_name); | 
| 624 | 2 |  |  |  |  | 8 | vmsg "Appended program [$program_name] configuration option to Fetchwarefile"; | 
| 625 |  |  |  |  |  |  |  | 
| 626 | 2 |  |  |  |  | 12 | my $lookup_url = get_lookup_url($term); | 
| 627 | 0 |  |  |  |  | 0 | vmsg "Asked user for lookup_url [$lookup_url] from user."; | 
| 628 |  |  |  |  |  |  |  | 
| 629 | 1 |  |  |  |  | 487 | $fetchwarefile->config_options(lookup_url => $lookup_url); | 
| 630 | 2 |  |  |  |  | 11 | vmsg "Appended lookup_url [$lookup_url] configuration option to Fetchwarefile"; | 
| 631 |  |  |  |  |  |  |  | 
| 632 | 2 |  |  |  |  | 9 | vmsg "Downloaded lookup_url [$lookup_url]"; | 
| 633 | 0 |  |  |  |  | 0 | my $filename_listing = download_lookup_url($term, $lookup_url); | 
| 634 | 2 |  |  |  |  | 915 | vmsg "Downloaded lookup_url's directory listing"; | 
| 635 | 2 |  |  |  |  | 10 | vmsg Dumper($filename_listing); | 
| 636 |  |  |  |  |  |  |  | 
| 637 | 2 |  |  |  |  | 13 | my $mirrors_hashref = get_mirrors($term, $filename_listing); | 
| 638 | 0 |  |  |  |  | 0 | vmsg "Added mirrors to your Fetchwarefile."; | 
| 639 | 1 |  |  |  |  | 514 | vmsg Dumper($mirrors_hashref); | 
| 640 |  |  |  |  |  |  |  | 
| 641 | 2 |  |  |  |  | 9 | my $verify_hashref = get_verification($term, $filename_listing, $lookup_url); | 
| 642 | 2 |  |  |  |  | 8 | vmsg "Added verification settings to Fetchwarefile."; | 
| 643 | 0 |  |  |  |  | 0 | vmsg Dumper($verify_hashref); | 
| 644 |  |  |  |  |  |  |  | 
| 645 | 2 |  |  |  |  | 977 | my $filter_hashref = get_filter_option($term, $filename_listing); | 
| 646 | 2 |  |  |  |  | 10 | vmsg "Added [$filter_hashref->{filter}] filter setting to Fetchwarefile."; | 
| 647 |  |  |  |  |  |  |  | 
| 648 | 2 |  |  |  |  | 14 | $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 |  |  |  |  | 485 | 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 |  |  |  |  | 9 | vmsg 'User entered the following options.'; | 
| 886 | 2 |  |  |  |  | 8 | 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 |  |  |  |  | 993 | vmsg 'Appended all other options listed above to Fetchwarefile.'; | 
| 891 |  |  |  |  |  |  |  | 
| 892 | 2 |  |  |  |  | 10 | my $edited_fetchwarefile = edit_manually($term, $fetchwarefile); | 
| 893 | 2 |  |  |  |  | 15 | 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 |  |  |  |  | 5 | $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 |  |  |  |  | 4 | 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 | 1051 | 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 |  |  | 31 | if (not defined $extension_name) { | 
|  |  | 100 |  |  |  |  |  | 
| 928 | 1 |  |  |  |  | 3 | $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 |  |  |  |  | 10 | 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 |  |  |  |  | 14 | 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 | 0 |  |  |  |  | 0 | [$@] | 
| 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 |  |  |  |  |  |  | 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 | 0 |  |  |  |  | 0 | 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 |  |  |  |  |  |  | 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 | 0 |  |  |  |  | 0 | $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 |  |  |  |  |  |  | ); | 
| 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 | 154 |  |  | 154 | 1 | 2626 | my %opts = @_; | 
| 1636 |  |  |  |  |  |  |  | 
| 1637 |  |  |  |  |  |  | # Add temp_dir config sub to create_tempdir()'s arguments. | 
| 1638 | 154 | 50 |  |  |  | 793 | 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 | 154 | 100 |  |  |  | 529 | if (config('no_install')) { | 
| 1646 | 1 |  |  |  |  | 13 | $opts{KeepTempDir} = 1; | 
| 1647 | 1 |  |  |  |  | 6 | vmsg "no_install option enabled not deleting temporary directory."; | 
| 1648 |  |  |  |  |  |  | } | 
| 1649 |  |  |  |  |  |  |  | 
| 1650 |  |  |  |  |  |  | # Forward opts to create_tempdir(), which does the heavy lifting. | 
| 1651 | 154 |  |  |  |  | 5463 | my $temp_dir = create_tempdir(%opts); | 
| 1652 | 154 |  |  |  |  | 3098 | msg "Created fetchware temporary directory [$temp_dir]"; | 
| 1653 |  |  |  |  |  |  |  | 
| 1654 | 154 |  |  |  |  | 6901 | 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 | 2 | my $file_listing = shift; | 
| 1911 |  |  |  |  |  |  |  | 
| 1912 | 1 |  |  |  |  | 2 | for my $file (@$file_listing) { | 
| 1913 | 46 | 50 |  |  |  | 4481 | 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 | 46 |  |  |  |  | 139 | $file = [file($file)->basename(), $mtime ]; | 
| 1929 |  |  |  |  |  |  | } | 
| 1930 |  |  |  |  |  |  |  | 
| 1931 | 1 |  |  |  |  | 76 | return $file_listing; | 
| 1932 |  |  |  |  |  |  | } | 
| 1933 |  |  |  |  |  |  |  | 
| 1934 |  |  |  |  |  |  |  | 
| 1935 |  |  |  |  |  |  |  | 
| 1936 |  |  |  |  |  |  | sub  lookup_by_timestamp { | 
| 1937 | 1 |  |  | 1 | 1 | 133 | 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 |  |  |  |  | 8 | my @sorted_listing = sort { $b->[1] <=> $a->[1] } @$file_listing; | 
|  | 153 |  |  |  |  | 222 |  | 
| 1946 |  |  |  |  |  |  |  | 
| 1947 | 1 |  |  |  |  | 7 | return \@sorted_listing; | 
| 1948 |  |  |  |  |  |  | } | 
| 1949 |  |  |  |  |  |  |  | 
| 1950 |  |  |  |  |  |  |  | 
| 1951 |  |  |  |  |  |  |  | 
| 1952 |  |  |  |  |  |  | sub  lookup_by_versionstring { | 
| 1953 | 9 |  |  | 9 | 1 | 72056 | my $file_listing = shift; | 
| 1954 |  |  |  |  |  |  |  | 
| 1955 |  |  |  |  |  |  | # Implement versionstring algorithm. | 
| 1956 | 9 |  |  |  |  | 14 | my @versionstrings; | 
| 1957 | 9 |  |  |  |  | 16 | for (my $i = 0; $i <= $#{$file_listing}; $i++) { | 
|  | 85 |  |  |  |  | 198 |  | 
| 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 |  |  |  |  | 1028 | my @iversionstring = split(/\D+/, $file_listing->[$i][0]); | 
| 1961 |  |  |  |  |  |  |  | 
| 1962 |  |  |  |  |  |  | # Use grep to strip leading empty strings (eg: ''). | 
| 1963 | 76 |  |  |  |  | 121 | @iversionstring = grep {$_ ne ''} @iversionstring; | 
|  | 248 |  |  |  |  | 514 |  | 
| 1964 |  |  |  |  |  |  |  | 
| 1965 | 76 | 100 |  |  |  | 351 | 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 |  |  |  |  | 41 | 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 |  |  |  |  | 23 | next; | 
| 1981 |  |  |  |  |  |  | } | 
| 1982 |  |  |  |  |  |  | # Add $i's version string to @versionstrings. | 
| 1983 | 66 |  |  |  |  | 222 | push @versionstrings, [$i, @iversionstring]; | 
| 1984 |  |  |  |  |  |  |  | 
| 1985 |  |  |  |  |  |  | # And the sort below sorts them into highest number first order. | 
| 1986 |  |  |  |  |  |  | } | 
| 1987 |  |  |  |  |  |  |  | 
| 1988 | 9 | 50 |  |  |  | 28 | 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 | 160 |  |  |  |  | 192 | @versionstrings = sort { | 
| 2005 |  |  |  |  |  |  | # Figure out whoose ($b or $a) is larger and set $last_index to it. | 
| 2006 | 9 |  |  |  |  | 37 | my $last_index; | 
| 2007 | 160 | 100 |  |  |  | 177 | if ($#{$b} > $#{$a}) { | 
|  | 160 |  |  |  |  | 230 |  | 
|  | 160 |  |  |  |  | 296 |  | 
| 2008 | 56 |  |  |  |  | 63 | $last_index = $#{$b}; | 
|  | 56 |  |  |  |  | 95 |  | 
| 2009 |  |  |  |  |  |  | } else { | 
| 2010 | 104 |  |  |  |  | 142 | $last_index = $#{$a}; | 
|  | 104 |  |  |  |  | 153 |  | 
| 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 |  |  |  |  | 290 | 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 |  |  |  | 445 | return -1 if $x > $#{$b}; | 
|  | 395 |  |  |  |  | 843 |  | 
| 2023 | 386 | 100 |  |  |  | 460 | return 1 if $x > $#{$a}; | 
|  | 386 |  |  |  |  | 903 |  | 
| 2024 |  |  |  |  |  |  |  | 
| 2025 | 352 |  |  |  |  | 686 | 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 |  |  |  | 789 | 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 |  |  |  |  | 44 | 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 |  |  |  |  | 13 | my @sorted_file_listing; | 
| 2041 | 9 |  |  |  |  | 17 | for my $versionstring_arrayref (@versionstrings) { | 
| 2042 | 66 |  |  |  |  | 112 | 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 |  |  |  |  | 61 | 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 | 19 | my ($temp_dir, $download_path) = @_; | 
| 2133 |  |  |  |  |  |  |  | 
| 2134 |  |  |  |  |  |  | # Ensure we're passed just a path, and *not* a full URL. | 
| 2135 | 1 | 50 |  |  |  | 14 | 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 |  |  |  |  | 8 | vmsg < | 
| 2142 |  |  |  |  |  |  | Using [$download_path] as basis for determined our download_url using the user | 
| 2143 |  |  |  |  |  |  | supplied mirrors. | 
| 2144 |  |  |  |  |  |  | EOM | 
| 2145 |  |  |  |  |  |  |  | 
| 2146 | 1 |  |  |  |  | 8 | msg "Downloading from url [$download_path] to temp dir [$temp_dir]"; | 
| 2147 |  |  |  |  |  |  |  | 
| 2148 | 1 |  |  |  |  | 16 | my $downloaded_file_path = download_file(PATH => $download_path); | 
| 2149 | 1 |  |  |  |  | 9 | vmsg "Downloaded file to [$downloaded_file_path]"; | 
| 2150 |  |  |  |  |  |  |  | 
| 2151 | 1 |  |  |  |  | 18 | my $package_path = determine_package_path($temp_dir, $downloaded_file_path); | 
| 2152 | 1 |  |  |  |  | 125 | msg "Determined package path to be [$package_path]"; | 
| 2153 |  |  |  |  |  |  |  | 
| 2154 | 1 |  |  |  |  | 50 | return $package_path; | 
| 2155 |  |  |  |  |  |  | } | 
| 2156 |  |  |  |  |  |  |  | 
| 2157 |  |  |  |  |  |  |  | 
| 2158 |  |  |  |  |  |  |  | 
| 2159 |  |  |  |  |  |  |  | 
| 2160 |  |  |  |  |  |  |  | 
| 2161 |  |  |  |  |  |  |  | 
| 2162 |  |  |  |  |  |  | sub determine_package_path { | 
| 2163 | 2 |  |  | 2 | 1 | 13611 | 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 |  |  |  |  | 36589 | 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 | 31 |  |  | 31 | 1 | 166 | my $package_path = shift; | 
| 2584 |  |  |  |  |  |  |  | 
| 2585 | 31 |  |  |  |  | 303 | msg "Unarchiving the downloaded package [$package_path]"; | 
| 2586 |  |  |  |  |  |  |  | 
| 2587 |  |  |  |  |  |  |  | 
| 2588 | 31 |  |  |  |  | 334 | my ($format, $files) = list_files($package_path); | 
| 2589 |  |  |  |  |  |  |  | 
| 2590 |  |  |  |  |  |  | { # Encloseing block for $", which prints a \n between each array element. | 
| 2591 | 31 |  |  |  |  | 76 | local $" = "\n"; | 
|  | 31 |  |  |  |  | 136 |  | 
| 2592 | 31 |  |  |  |  | 421 | 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 | 31 |  |  |  |  | 620 | my $build_path = check_archive_files($files); | 
| 2603 |  |  |  |  |  |  |  | 
| 2604 | 31 |  |  |  |  | 224 | vmsg "Unarchiving $format archive [$package_path]."; | 
| 2605 | 31 |  |  |  |  | 248 | unarchive_package($format, $package_path); | 
| 2606 |  |  |  |  |  |  |  | 
| 2607 | 31 |  |  |  |  | 812 | msg "Determined build path to be [$build_path]"; | 
| 2608 | 31 |  |  |  |  | 701 | return $build_path; | 
| 2609 |  |  |  |  |  |  | } | 
| 2610 |  |  |  |  |  |  |  | 
| 2611 |  |  |  |  |  |  |  | 
| 2612 |  |  |  |  |  |  |  | 
| 2613 |  |  |  |  |  |  |  | 
| 2614 |  |  |  |  |  |  |  | 
| 2615 |  |  |  |  |  |  |  | 
| 2616 |  |  |  |  |  |  | sub list_files { | 
| 2617 | 31 |  |  | 31 | 1 | 142 | my $package_path = shift; | 
| 2618 |  |  |  |  |  |  |  | 
| 2619 |  |  |  |  |  |  | # List files based on archive format. | 
| 2620 | 31 |  |  |  |  | 114 | my $files; | 
| 2621 |  |  |  |  |  |  | my $format; | 
| 2622 | 31 | 50 |  |  |  | 767 | if ($package_path =~ /\.(t(gz|bz|xz|Z))|(tar\.(gz|bz2|xz|Z))|.fpkg$/) { | 
|  |  | 0 |  |  |  |  |  | 
| 2623 | 31 |  |  |  |  | 168 | $format = 'tar'; | 
| 2624 | 31 |  |  |  |  | 272 | vmsg < | 
| 2625 |  |  |  |  |  |  | Listing files in your tar format archive [$package_path]. | 
| 2626 |  |  |  |  |  |  | EOM | 
| 2627 | 31 |  |  |  |  | 149 | $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 | 31 |  |  |  |  | 186 | return $format, $files; | 
| 2644 |  |  |  |  |  |  | } | 
| 2645 |  |  |  |  |  |  |  | 
| 2646 |  |  |  |  |  |  |  | 
| 2647 |  |  |  |  |  |  |  | 
| 2648 |  |  |  |  |  |  | sub list_files_tar { | 
| 2649 | 31 |  |  | 31 | 1 | 497 | my $path_to_tar_archive = shift; | 
| 2650 |  |  |  |  |  |  |  | 
| 2651 | 31 |  |  |  |  | 670 | my $tar_iter = Archive::Tar->iter($path_to_tar_archive, 1, ); | 
| 2652 | 31 | 50 |  |  |  | 132658 | 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 | 31 |  |  |  |  | 216 | my @files; | 
| 2660 | 31 |  |  |  |  | 174 | while (my $file = $tar_iter->() ) { | 
| 2661 | 124 |  |  |  |  | 119046 | push @files, $file->full_path(); | 
| 2662 |  |  |  |  |  |  | } | 
| 2663 |  |  |  |  |  |  |  | 
| 2664 | 31 |  |  |  |  | 52316 | 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 | 31 |  |  | 31 | 1 | 86 | my ($format, $package_path) = @_; | 
| 2712 |  |  |  |  |  |  |  | 
| 2713 | 31 | 50 |  |  |  | 244 | unarchive_tar($package_path) if $format eq 'tar'; | 
| 2714 | 31 | 50 |  |  |  | 662 | unarchive_zip($package_path) if $format eq 'zip'; | 
| 2715 |  |  |  |  |  |  | } | 
| 2716 |  |  |  |  |  |  |  | 
| 2717 |  |  |  |  |  |  |  | 
| 2718 |  |  |  |  |  |  |  | 
| 2719 |  |  |  |  |  |  | sub unarchive_tar { | 
| 2720 | 31 |  |  | 31 | 1 | 80 | my $path_to_tar_archive = shift; | 
| 2721 |  |  |  |  |  |  |  | 
| 2722 | 31 |  |  |  |  | 335 | 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 | 31 | 50 |  |  |  | 1969395 | unless ($extracted_files[0]) { | 
| 2728 | 0 |  |  |  |  | 0 | die < | 
| 2729 | 0 |  |  |  |  | 0 | App-Fetchware: Fetchware failed to extract your archive [$path_to_tar_archive]. | 
| 2730 |  |  |  |  |  |  | The error message from Archive::Tar was [@{[Archive::Tar->error()]}]. | 
| 2731 |  |  |  |  |  |  | EOD | 
| 2732 |  |  |  |  |  |  | } else { | 
| 2733 | 31 |  |  |  |  | 323 | 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 | 34 |  |  | 34 | 1 | 1577 | my $files = shift; | 
| 2769 |  |  |  |  |  |  |  | 
| 2770 |  |  |  |  |  |  |  | 
| 2771 |  |  |  |  |  |  | # Determine if *all* files are in the same directory. | 
| 2772 | 34 |  |  |  |  | 93 | my %dir; | 
| 2773 | 34 |  |  |  |  | 285 | for my $path (@$files) { | 
| 2774 |  |  |  |  |  |  | # Skip Fetchwarefiles. | 
| 2775 | 138 | 100 |  |  |  | 563 | next if $path eq './Fetchwarefile'; | 
| 2776 | 107 | 100 |  |  |  | 651 | if (file_name_is_absolute($path)) { | 
| 2777 | 1 |  |  |  |  | 20 | 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 |  |  |  |  | 3 | $error .= "[\n"; | 
| 2786 | 1 |  |  |  |  | 11 | $error .= join("\n", @$files); | 
| 2787 | 1 |  |  |  |  | 2 | $error .= "\n]\n"; | 
| 2788 |  |  |  |  |  |  |  | 
| 2789 | 1 |  |  |  |  | 8 | die $error; | 
| 2790 |  |  |  |  |  |  | } | 
| 2791 |  |  |  |  |  |  |  | 
| 2792 | 106 |  |  |  |  | 1399 | my ($volume,$directories,$file) = splitpath($path); | 
| 2793 | 106 |  |  |  |  | 1680 | my @dirs = splitdir($directories); | 
| 2794 |  |  |  |  |  |  | # Skip empty directories. | 
| 2795 | 106 | 100 |  |  |  | 860 | next unless @dirs; | 
| 2796 |  |  |  |  |  |  |  | 
| 2797 | 75 |  |  |  |  | 486 | $dir{$dirs[0]}++; | 
| 2798 |  |  |  |  |  |  | } | 
| 2799 |  |  |  |  |  |  |  | 
| 2800 |  |  |  |  |  |  |  | 
| 2801 | 33 |  |  |  |  | 143 | my $i = 0; | 
| 2802 | 33 |  |  |  |  | 144 | for my $dir (keys %dir) { | 
| 2803 | 33 |  |  |  |  | 68 | $i++; | 
| 2804 | 33 | 50 |  |  |  | 120 | 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 | 33 |  |  |  |  | 88 | my $build_path = $dir; | 
| 2815 | 33 |  |  |  |  | 148 | 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 | vmsg "Running configure with options [@{[config('configure_options')]}]"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2847 | 0 |  |  |  |  | 0 | run_configure(); | 
| 2848 |  |  |  |  |  |  |  | 
| 2849 |  |  |  |  |  |  | # Next, make. | 
| 2850 | 0 | 0 |  |  |  | 0 | if (defined config('make_options')) { | 
| 2851 | 0 |  |  |  |  | 0 | vmsg 'Executing make to build your package'; | 
| 2852 | 0 |  |  |  |  | 0 | run_prog('make', config('make_options')) | 
| 2853 |  |  |  |  |  |  | } else { | 
| 2854 | 0 |  |  |  |  | 0 | vmsg 'Executing make to build your package'; | 
| 2855 | 0 |  |  |  |  | 0 | run_prog('make'); | 
| 2856 |  |  |  |  |  |  | } | 
| 2857 |  |  |  |  |  |  |  | 
| 2858 |  |  |  |  |  |  | # Execute the default commands. | 
| 2859 |  |  |  |  |  |  | } else { | 
| 2860 | 0 |  |  |  |  | 0 | vmsg 'Running default build commands [./configure] and [make]'; | 
| 2861 | 0 |  |  |  |  | 0 | run_prog($_) for qw(./configure make); | 
| 2862 |  |  |  |  |  |  | } | 
| 2863 |  |  |  |  |  |  |  | 
| 2864 |  |  |  |  |  |  | # Return success. | 
| 2865 | 0 |  |  |  |  | 0 | msg 'The build was successful.'; | 
| 2866 | 0 |  |  |  |  | 0 | return 'build succeeded'; | 
| 2867 |  |  |  |  |  |  | } | 
| 2868 |  |  |  |  |  |  |  | 
| 2869 |  |  |  |  |  |  | ###BUGALERT### Add a *() API REFERENCE section for each fetchware API | 
| 2870 |  |  |  |  |  |  | #subroutine, and subify the API subs that aren't yet. | 
| 2871 |  |  |  |  |  |  |  | 
| 2872 |  |  |  |  |  |  |  | 
| 2873 |  |  |  |  |  |  |  | 
| 2874 |  |  |  |  |  |  |  | 
| 2875 |  |  |  |  |  |  | sub run_star_commands { | 
| 2876 | 4 |  |  | 4 | 1 | 3773 | my @star_commands = @_; | 
| 2877 |  |  |  |  |  |  |  | 
| 2878 |  |  |  |  |  |  | # Support multiple options like star_command './configure', 'make'; | 
| 2879 |  |  |  |  |  |  | # Should be called like run_star_commands(config'*_commands')), and | 
| 2880 |  |  |  |  |  |  | # config('star_commands') returns a list of *all* star_commands. | 
| 2881 | 4 |  |  |  |  | 29 | for my $star_command (@star_commands) { | 
| 2882 |  |  |  |  |  |  | # If a /,\s+/ is present in a $star_command | 
| 2883 |  |  |  |  |  |  | # To support: star_commands './configure, make'; | 
| 2884 | 6 | 100 |  |  |  | 101 | if ($star_command =~ /,\s*/) { | 
| 2885 |  |  |  |  |  |  | # split on it, and run each resulting command. | 
| 2886 | 3 |  |  |  |  | 46 | my @star_commands = split /,\s*/, $star_command; | 
| 2887 | 3 |  |  |  |  | 14 | for my $split_star_command (@star_commands) { | 
| 2888 | 6 |  |  |  |  | 84 | run_prog($split_star_command); | 
| 2889 |  |  |  |  |  |  | } | 
| 2890 |  |  |  |  |  |  | # Or just run the one command. | 
| 2891 |  |  |  |  |  |  | } else { | 
| 2892 | 3 |  |  |  |  | 35 | run_prog($star_command); | 
| 2893 |  |  |  |  |  |  | } | 
| 2894 |  |  |  |  |  |  | } | 
| 2895 |  |  |  |  |  |  | } | 
| 2896 |  |  |  |  |  |  |  | 
| 2897 |  |  |  |  |  |  |  | 
| 2898 |  |  |  |  |  |  |  | 
| 2899 |  |  |  |  |  |  | ###BUGALERT### Add an uninstall() option to instead edit the AutoTools paths | 
| 2900 |  |  |  |  |  |  | #into relative ones. | 
| 2901 |  |  |  |  |  |  |  | 
| 2902 |  |  |  |  |  |  | sub run_configure { | 
| 2903 | 31 |  |  | 31 | 1 | 233 | my $configure = './configure'; | 
| 2904 | 31 | 50 |  |  |  | 234 | if (config('configure_options')) { | 
| 2905 |  |  |  |  |  |  | # Support multiple options like configure_options '--prefix', '.'; | 
| 2906 | 0 |  |  |  |  | 0 | for my $configure_option (config('configure_options')) { | 
| 2907 | 0 |  |  |  |  | 0 | $configure .= " $configure_option"; | 
| 2908 |  |  |  |  |  |  | } | 
| 2909 |  |  |  |  |  |  | } | 
| 2910 |  |  |  |  |  |  |  | 
| 2911 | 31 | 50 |  |  |  | 264 | if (config('prefix')) { | 
| 2912 | 0 | 0 |  |  |  | 0 | if ($configure =~ /--prefix/) { | 
| 2913 | 0 |  |  |  |  | 0 | die < | 
| 2914 |  |  |  |  |  |  | App-Fetchware: run-time error. You specified both the --prefix option twice. | 
| 2915 |  |  |  |  |  |  | Once in 'prefix' and once in 'configure_options'. You may only specify prefix | 
| 2916 |  |  |  |  |  |  | once in either configure option. See perldoc App::Fetchware. | 
| 2917 |  |  |  |  |  |  | EOD | 
| 2918 |  |  |  |  |  |  | } else { | 
| 2919 |  |  |  |  |  |  | ###BUGALERT## At least under AutoTools, --prefix needs to be a full | 
| 2920 |  |  |  |  |  |  | #path. Should I check for this here? Ignore this possible error, and | 
| 2921 |  |  |  |  |  |  | #just let ./configure check its own arguments. Or add syntax | 
| 2922 |  |  |  |  |  |  | #checking to configuration subroutines??? | 
| 2923 | 0 |  |  |  |  | 0 | $configure .= " --prefix=@{[config('prefix')]}"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2924 |  |  |  |  |  |  | } | 
| 2925 |  |  |  |  |  |  | } | 
| 2926 |  |  |  |  |  |  |  | 
| 2927 |  |  |  |  |  |  | # Finally run ./configure. | 
| 2928 | 31 |  |  |  |  | 444 | run_prog($configure); | 
| 2929 |  |  |  |  |  |  |  | 
| 2930 |  |  |  |  |  |  | # Return success. | 
| 2931 | 31 |  |  |  |  | 872 | return 'Configure successful'; | 
| 2932 |  |  |  |  |  |  | } | 
| 2933 |  |  |  |  |  |  |  | 
| 2934 |  |  |  |  |  |  |  | 
| 2935 |  |  |  |  |  |  |  | 
| 2936 |  |  |  |  |  |  | sub install { | 
| 2937 | 87 |  |  | 87 | 1 | 256 | my $build_path = shift; | 
| 2938 |  |  |  |  |  |  |  | 
| 2939 |  |  |  |  |  |  | # Skip installation if the user requests it. | 
| 2940 | 87 | 50 |  |  |  | 1896 | if (config('no_install')) { | 
| 2941 | 0 |  |  |  |  | 0 | msg < | 
| 2942 |  |  |  |  |  |  | Installation skipped, because no_install is specified in your Fetchwarefile. | 
| 2943 |  |  |  |  |  |  | EOM | 
| 2944 | 0 |  |  |  |  | 0 | return 'installation skipped!' ; | 
| 2945 |  |  |  |  |  |  | } | 
| 2946 |  |  |  |  |  |  |  | 
| 2947 | 87 |  |  |  |  | 1066 | msg 'Installing your software package.'; | 
| 2948 |  |  |  |  |  |  |  | 
| 2949 | 87 |  |  |  |  | 703 | chdir_unless_already_at_path($build_path); | 
| 2950 |  |  |  |  |  |  |  | 
| 2951 | 87 | 50 |  |  |  | 2494 | if (defined config('install_commands')) { | 
| 2952 | 0 |  |  |  |  | 0 | vmsg 'Installing your package using user specified commands.'; | 
| 2953 | 0 |  |  |  |  | 0 | run_star_commands(config('install_commands')); | 
| 2954 |  |  |  |  |  |  | } else { | 
| 2955 | 87 | 50 |  |  |  | 647 | if (defined config('make_options')) { | 
| 2956 | 0 |  |  |  |  | 0 | vmsg < | 
| 2957 |  |  |  |  |  |  | Installing package using default command [make] with user specified make options. | 
| 2958 |  |  |  |  |  |  | EOM | 
| 2959 | 0 |  |  |  |  | 0 | run_prog('make', config('make_options'), 'install', ); | 
| 2960 |  |  |  |  |  |  | } else { | 
| 2961 | 87 |  |  |  |  | 744 | vmsg < | 
| 2962 |  |  |  |  |  |  | Installing package using default command [make]. | 
| 2963 |  |  |  |  |  |  | EOM | 
| 2964 | 87 |  |  |  |  | 1248 | run_prog('make', 'install'); | 
| 2965 |  |  |  |  |  |  | } | 
| 2966 |  |  |  |  |  |  | } | 
| 2967 |  |  |  |  |  |  |  | 
| 2968 | 87 |  |  |  |  | 3301 | msg 'Installation succeeded'; | 
| 2969 |  |  |  |  |  |  | # Return success. | 
| 2970 | 87 |  |  |  |  | 1866 | return 'install succeeded'; | 
| 2971 |  |  |  |  |  |  | } | 
| 2972 |  |  |  |  |  |  |  | 
| 2973 |  |  |  |  |  |  |  | 
| 2974 |  |  |  |  |  |  |  | 
| 2975 |  |  |  |  |  |  |  | 
| 2976 |  |  |  |  |  |  |  | 
| 2977 |  |  |  |  |  |  | sub chdir_unless_already_at_path { | 
| 2978 | 120 |  |  | 120 | 1 | 344706 | my $path = shift; | 
| 2979 |  |  |  |  |  |  |  | 
| 2980 |  |  |  |  |  |  | # chdir() to $path unless its already our cwd. | 
| 2981 |  |  |  |  |  |  | # This is needed, because we'll inherit the "child's" chdir if stay_root is | 
| 2982 |  |  |  |  |  |  | # turned on, because stay_root does *not* fork and drop privs, which | 
| 2983 |  |  |  |  |  |  | # typicially causes the child's chdir to be "inherited" by the parent, | 
| 2984 |  |  |  |  |  |  | # because there is no parent and there is no child due to *not* forking. | 
| 2985 | 120 | 50 |  |  |  | 1394455 | unless ( dir(cwd())->dir_list(-1, 1) eq $path ) { | 
| 2986 | 120 | 50 |  |  |  | 56364 | chdir($path) or die < | 
| 2987 |  |  |  |  |  |  | fetchware: fetchware failed to chdir to the build directory [$path]. It | 
| 2988 |  |  |  |  |  |  | needs to chdir() to this directory, so that it can finish your fetchware | 
| 2989 |  |  |  |  |  |  | command. | 
| 2990 |  |  |  |  |  |  | EOD | 
| 2991 | 120 |  |  |  |  | 3597 | vmsg "chdir()'d to the necessary path [$path]."; | 
| 2992 |  |  |  |  |  |  | } | 
| 2993 |  |  |  |  |  |  | } | 
| 2994 |  |  |  |  |  |  |  | 
| 2995 |  |  |  |  |  |  |  | 
| 2996 |  |  |  |  |  |  |  | 
| 2997 |  |  |  |  |  |  |  | 
| 2998 |  |  |  |  |  |  |  | 
| 2999 |  |  |  |  |  |  |  | 
| 3000 |  |  |  |  |  |  | ###BUGALERT### Is uninstall() calling API subs a bug??? Should it just use the | 
| 3001 |  |  |  |  |  |  | #lower level library functions of these tools. Have it do this after I subify | 
| 3002 |  |  |  |  |  |  | #the rest of the API subs like I've done to lookup and download. | 
| 3003 |  |  |  |  |  |  | ###BUGALERT### NOT TESTED!!! There is no t/App-Fetchware-uninstall.t test | 
| 3004 |  |  |  |  |  |  | #file!!! cmd_uninstall(), which uses uninstall(), is tested, but not uninstall() | 
| 3005 |  |  |  |  |  |  | #directly!!! | 
| 3006 |  |  |  |  |  |  | sub uninstall { | 
| 3007 | 31 |  |  | 31 | 1 | 315 | my $build_path = shift; | 
| 3008 |  |  |  |  |  |  |  | 
| 3009 | 31 |  |  |  |  | 368 | msg "Uninstalling package unarchived at path [$build_path]"; | 
| 3010 |  |  |  |  |  |  |  | 
| 3011 | 31 |  |  |  |  | 175 | chdir_unless_already_at_path($build_path); | 
| 3012 |  |  |  |  |  |  |  | 
| 3013 | 31 | 50 |  |  |  | 1049 | if (defined config('uninstall_commands')) { | 
| 3014 | 0 |  |  |  |  | 0 | vmsg 'Uninstalling using user specified uninstall commands.'; | 
| 3015 | 0 |  |  |  |  | 0 | run_star_commands(config('uninstall_commands')); | 
| 3016 |  |  |  |  |  |  | } else { | 
| 3017 |  |  |  |  |  |  | # Set up configure_options and prefix, and then run ./configure, because | 
| 3018 |  |  |  |  |  |  | # Autotools uses full paths that ./configure sets up, and these paths | 
| 3019 |  |  |  |  |  |  | # change from install time to uninstall time. | 
| 3020 | 31 |  |  |  |  | 385 | vmsg q{Uninstalling using AutoTool's default of make uninstall}; | 
| 3021 |  |  |  |  |  |  |  | 
| 3022 | 31 |  |  |  |  | 312 | vmsg q{Running AutoTool's default ./configure}; | 
| 3023 | 31 |  |  |  |  | 332 | run_configure(); | 
| 3024 | 31 | 50 |  |  |  | 1131 | if (defined config('make_options')) { | 
| 3025 | 0 |  |  |  |  | 0 | vmsg < | 
| 3026 |  |  |  |  |  |  | Running AutoTool's default make uninstall with user specified make options. | 
| 3027 |  |  |  |  |  |  | EOM | 
| 3028 | 0 |  |  |  |  | 0 | run_prog('make', config('make_options'), 'uninstall'); | 
| 3029 |  |  |  |  |  |  | } else { | 
| 3030 | 31 |  |  |  |  | 621 | vmsg < | 
| 3031 |  |  |  |  |  |  | Running AutoTool's default make uninstall. | 
| 3032 |  |  |  |  |  |  | EOM | 
| 3033 | 31 |  |  |  |  | 550 | run_prog('make', 'uninstall'); | 
| 3034 |  |  |  |  |  |  | } | 
| 3035 |  |  |  |  |  |  | } | 
| 3036 |  |  |  |  |  |  |  | 
| 3037 |  |  |  |  |  |  |  | 
| 3038 | 31 |  |  |  |  | 1722 | msg < | 
| 3039 |  |  |  |  |  |  | Package uninstalled from system, but still installed in Fetchware's database. | 
| 3040 |  |  |  |  |  |  | EOM | 
| 3041 |  |  |  |  |  |  | # Return success. | 
| 3042 | 31 |  |  |  |  | 601 | return 'uninstall succeeded'; | 
| 3043 |  |  |  |  |  |  | } | 
| 3044 |  |  |  |  |  |  |  | 
| 3045 |  |  |  |  |  |  |  | 
| 3046 |  |  |  |  |  |  |  | 
| 3047 |  |  |  |  |  |  |  | 
| 3048 |  |  |  |  |  |  | sub upgrade { | 
| 3049 | 9 |  |  | 9 | 1 | 5320 | my ($download_path, $fetchware_package_path) = @_; | 
| 3050 |  |  |  |  |  |  |  | 
| 3051 |  |  |  |  |  |  | # I only need the basename. | 
| 3052 | 9 |  |  |  |  | 30 | my $download_path_basename = file($download_path)->basename(); | 
| 3053 | 9 |  |  |  |  | 6770 | my $upgrade_name_basename = | 
| 3054 |  |  |  |  |  |  | file( $fetchware_package_path)->basename(); | 
| 3055 | 9 |  |  |  |  | 604 | vmsg < | 
| 3056 |  |  |  |  |  |  | Shortened the new download url [$download_path_basename] and the installed | 
| 3057 |  |  |  |  |  |  | package's [$upgrade_name_basename] into just their basenames. | 
| 3058 |  |  |  |  |  |  | EOM | 
| 3059 |  |  |  |  |  |  |  | 
| 3060 |  |  |  |  |  |  | # Strip trailing garbage to normalize their names, so that they can be | 
| 3061 |  |  |  |  |  |  | # compared to each other. | 
| 3062 |  |  |  |  |  |  | ###BUGALERT### This comparision is quite fragile. Figure out a better way to | 
| 3063 |  |  |  |  |  |  | #do this!!! | 
| 3064 | 9 |  |  |  |  | 28 | $upgrade_name_basename =~ s/\.fpkg$//; | 
| 3065 | 9 |  |  |  |  | 50 | $download_path_basename | 
| 3066 |  |  |  |  |  |  | =~ s/(\.(?:zip|tgz|tbz|txz|fpkg)|(?:\.tar\.(gz|bz2|xz|Z)?))$//; | 
| 3067 | 9 |  |  |  |  | 36 | vmsg < | 
| 3068 |  |  |  |  |  |  | Striped the new download url [$download_path_basename] and the installed | 
| 3069 |  |  |  |  |  |  | package's [$upgrade_name_basename] of their file extensions. | 
| 3070 |  |  |  |  |  |  | EOM | 
| 3071 |  |  |  |  |  |  |  | 
| 3072 |  |  |  |  |  |  | # Check if $upgrade_name_basename and $download_path_basename are eq, and if | 
| 3073 |  |  |  |  |  |  | # they are return false indicating that this program should not be upgraded, | 
| 3074 |  |  |  |  |  |  | # because the version available for upgrading is the same as the currently | 
| 3075 |  |  |  |  |  |  | # installed version. | 
| 3076 | 9 | 100 |  |  |  | 35 | return if $upgrade_name_basename eq $download_path_basename; | 
| 3077 |  |  |  |  |  |  |  | 
| 3078 |  |  |  |  |  |  | # Transform both competing filenames into a string of version numbers. | 
| 3079 |  |  |  |  |  |  |  | 
| 3080 |  |  |  |  |  |  | # Use lookup_by_versionstring() to determine which version of the same | 
| 3081 |  |  |  |  |  |  | # program is "newer." | 
| 3082 | 6 |  |  |  |  | 30 | my $sorted_file_names = lookup_by_versionstring( | 
| 3083 |  |  |  |  |  |  | [ | 
| 3084 |  |  |  |  |  |  | [$upgrade_name_basename, 'placeholder'], | 
| 3085 |  |  |  |  |  |  | [$download_path_basename, 'placeholder'], | 
| 3086 |  |  |  |  |  |  | ] | 
| 3087 |  |  |  |  |  |  | ); | 
| 3088 |  |  |  |  |  |  |  | 
| 3089 | 6 | 100 | 66 |  |  | 33 | if ($sorted_file_names->[0][0] eq $download_path_basename | 
| 3090 |  |  |  |  |  |  | # Make sure cmd_upgrade() does not upgrade when the latest version is | 
| 3091 |  |  |  |  |  |  | # the same as the currently installed version ($upgrade_name_basename). | 
| 3092 |  |  |  |  |  |  | and $sorted_file_names->[0][0] ne $upgrade_name_basename) { | 
| 3093 |  |  |  |  |  |  | # The latest version we can download ($download_path_basename) is newer | 
| 3094 |  |  |  |  |  |  | # than the currently installed version ($upgrade_name_basename), so we | 
| 3095 |  |  |  |  |  |  | # should upgrade. | 
| 3096 | 3 |  |  |  |  | 27 | return 1; | 
| 3097 |  |  |  |  |  |  | } else { | 
| 3098 |  |  |  |  |  |  | # Currenlty installed version ($upgrade_name_basename) is equal to the | 
| 3099 |  |  |  |  |  |  | # latest version available for download ($download_path_basename), so | 
| 3100 |  |  |  |  |  |  | # return false indicating that we sould not upgrade. | 
| 3101 | 3 |  |  |  |  | 21 | return; | 
| 3102 |  |  |  |  |  |  | } | 
| 3103 |  |  |  |  |  |  | } | 
| 3104 |  |  |  |  |  |  |  | 
| 3105 |  |  |  |  |  |  |  | 
| 3106 |  |  |  |  |  |  |  | 
| 3107 |  |  |  |  |  |  |  | 
| 3108 |  |  |  |  |  |  | sub check_syntax { | 
| 3109 |  |  |  |  |  |  |  | 
| 3110 |  |  |  |  |  |  | # Use check_config_options() to run config() a bunch of times to check the | 
| 3111 |  |  |  |  |  |  | # already parsed Fetchwarefile. | 
| 3112 | 151 |  |  | 151 | 1 | 6110 | return check_config_options( | 
| 3113 |  |  |  |  |  |  | BothAreDefined => [ [qw(build_commands)], | 
| 3114 |  |  |  |  |  |  | [qw(prefix configure_options make_options)] ], | 
| 3115 |  |  |  |  |  |  | Mandatory => [ 'program', < | 
| 3116 |  |  |  |  |  |  | App-Fetchware: Your Fetchwarefile must specify a program configuration | 
| 3117 |  |  |  |  |  |  | option. Please add one, and try again. | 
| 3118 |  |  |  |  |  |  | EOM | 
| 3119 |  |  |  |  |  |  | Mandatory => [ 'mirror', < | 
| 3120 |  |  |  |  |  |  | App-Fetchware: Your Fetchwarefile must specify a mirror configuration | 
| 3121 |  |  |  |  |  |  | option. Please add one, and try again. | 
| 3122 |  |  |  |  |  |  | EOM | 
| 3123 |  |  |  |  |  |  | Mandatory => [ 'lookup_url', < | 
| 3124 |  |  |  |  |  |  | App-Fetchware: Your Fetchwarefile must specify a lookup_url configuration | 
| 3125 |  |  |  |  |  |  | option. Please add one, and try again. | 
| 3126 |  |  |  |  |  |  | EOM | 
| 3127 |  |  |  |  |  |  | ConfigOptionEnum => ['lookup_method', [qw(timestamp versionstring)] ], | 
| 3128 |  |  |  |  |  |  | ConfigOptionEnum => ['verify_method', [qw(gpg sha1 md5)] ], | 
| 3129 |  |  |  |  |  |  | ); | 
| 3130 |  |  |  |  |  |  | } | 
| 3131 |  |  |  |  |  |  |  | 
| 3132 |  |  |  |  |  |  |  | 
| 3133 |  |  |  |  |  |  |  | 
| 3134 |  |  |  |  |  |  |  | 
| 3135 |  |  |  |  |  |  |  | 
| 3136 |  |  |  |  |  |  | sub check_config_options { | 
| 3137 | 160 |  |  | 160 | 1 | 1667 | my @args = @_; | 
| 3138 |  |  |  |  |  |  |  | 
| 3139 | 160 |  |  |  |  | 435 | my @both_are_defined; | 
| 3140 |  |  |  |  |  |  | my @mandatory; | 
| 3141 | 0 |  |  |  |  | 0 | my @config_option_enum; | 
| 3142 |  |  |  |  |  |  |  | 
| 3143 |  |  |  |  |  |  | # Process arguments, and check that they were specified correctly. | 
| 3144 |  |  |  |  |  |  | # Loop over @args 2 at a time hence the $i += 2 instead of $i++. | 
| 3145 | 160 |  |  |  |  | 745 | for( my $i = 0; $i < @args; $i += 2 ) { | 
| 3146 | 920 |  |  |  |  | 1900 | my( $type, $AnB ) = @args[ $i, $i+1 ]; | 
| 3147 | 920 | 100 |  |  |  | 2490 | die < | 
| 3148 |  |  |  |  |  |  | App-Fetchware: check_config_options()'s even arguments must be an array | 
| 3149 |  |  |  |  |  |  | reference. Please correct your arguments, and try again. | 
| 3150 |  |  |  |  |  |  | EOD | 
| 3151 | 919 | 100 |  |  |  | 1979 | die < | 
| 3152 |  |  |  |  |  |  | App-Fetchware: check_config_options()'s even arguments must be an array | 
| 3153 |  |  |  |  |  |  | reference with exactly two elements in it. Please correct and try again. | 
| 3154 |  |  |  |  |  |  | EOD | 
| 3155 |  |  |  |  |  |  |  | 
| 3156 | 918 | 100 |  |  |  | 2871 | if ($type eq 'BothAreDefined') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 3157 | 154 |  |  |  |  | 664 | push @both_are_defined, $AnB; | 
| 3158 |  |  |  |  |  |  | } elsif ($type eq 'Mandatory') { | 
| 3159 | 458 |  |  |  |  | 2635 | push @mandatory, $AnB; | 
| 3160 |  |  |  |  |  |  | } elsif ($type eq 'ConfigOptionEnum') { | 
| 3161 | 306 |  |  |  |  | 1366 | push @config_option_enum, $AnB; | 
| 3162 |  |  |  |  |  |  | } else { | 
| 3163 | 0 |  |  |  |  | 0 | die < | 
| 3164 |  |  |  |  |  |  | App-Fetchware: check_config_options() only supports types 'BothAreDefined', | 
| 3165 |  |  |  |  |  |  | 'Mandatory', and 'ConfigOptionEnum.' Please specify one of these, and try again. | 
| 3166 |  |  |  |  |  |  | EOD | 
| 3167 |  |  |  |  |  |  | } | 
| 3168 |  |  |  |  |  |  | } | 
| 3169 |  |  |  |  |  |  |  | 
| 3170 |  |  |  |  |  |  | # Process @both_are_defined by checking if both of the elements in the | 
| 3171 |  |  |  |  |  |  | # provided arrayrefs are "both defined", and if they are "both defined" | 
| 3172 |  |  |  |  |  |  | # throw an exception. | 
| 3173 | 158 |  |  |  |  | 1137 | for my $AnB (@both_are_defined) { | 
| 3174 | 154 |  |  |  |  | 349 | my ($A, $B) = @$AnB; | 
| 3175 |  |  |  |  |  |  |  | 
| 3176 | 154 |  |  |  |  | 296 | my @A_defined; | 
| 3177 |  |  |  |  |  |  | my @B_defined; | 
| 3178 |  |  |  |  |  |  |  | 
| 3179 |  |  |  |  |  |  | # Check which ones are defined in both $A and $B | 
| 3180 |  |  |  |  |  |  | { | 
| 3181 |  |  |  |  |  |  | # the config() call will call the specified strings of which many | 
| 3182 |  |  |  |  |  |  | # are expected to be uninitialized. Because we expect them to be | 
| 3183 |  |  |  |  |  |  | # uninitialized, we use that behavior to determine if they have been | 
| 3184 |  |  |  |  |  |  | # specified in the users Fetchwarefile, and if an option was not | 
| 3185 |  |  |  |  |  |  | # specified, then undef is returned by config(). Since, we expect | 
| 3186 |  |  |  |  |  |  | # lots of undef warnings, we'll disable them. | 
| 3187 | 46 |  |  | 46 |  | 816 | no warnings 'uninitialized'; | 
|  | 46 |  |  |  |  | 122 |  | 
|  | 46 |  |  |  |  | 11326 |  | 
|  | 154 |  |  |  |  | 314 |  | 
| 3188 | 154 |  |  |  |  | 362 | @A_defined = grep {config($_)} @$A; | 
|  | 154 |  |  |  |  | 704 |  | 
| 3189 | 154 |  |  |  |  | 405 | @B_defined = grep {config($_)} @$B; | 
|  | 462 |  |  |  |  | 1175 |  | 
| 3190 |  |  |  |  |  |  | } | 
| 3191 |  |  |  |  |  |  |  | 
| 3192 | 154 | 100 | 100 |  |  | 915 | if (@A_defined > 0 and @B_defined > 0) { | 
| 3193 | 1 |  |  |  |  | 13 | die < | 
| 3194 |  |  |  |  |  |  | App-Fetchware: Your Fetchwarefile has incompatible configuration options. | 
| 3195 |  |  |  |  |  |  | You specified configuration options [@$A] and [@$B], but these options are not | 
| 3196 |  |  |  |  |  |  | compatible with each other. Please specifiy either [@$A] or [@$B] not both. | 
| 3197 |  |  |  |  |  |  | EOD | 
| 3198 |  |  |  |  |  |  | } | 
| 3199 |  |  |  |  |  |  | } | 
| 3200 |  |  |  |  |  |  |  | 
| 3201 |  |  |  |  |  |  |  | 
| 3202 |  |  |  |  |  |  | # Process @mandatory options by checking if they're defined, and if not | 
| 3203 |  |  |  |  |  |  | # throwing the specified exception. | 
| 3204 | 157 |  |  |  |  | 410 | for my $AnB (@mandatory) { | 
| 3205 | 458 |  |  |  |  | 825 | my ($option, $error_message) = @$AnB; | 
| 3206 |  |  |  |  |  |  |  | 
| 3207 | 458 | 100 |  |  |  | 1174 | die $error_message if not defined config($option); | 
| 3208 |  |  |  |  |  |  | } | 
| 3209 |  |  |  |  |  |  |  | 
| 3210 |  |  |  |  |  |  |  | 
| 3211 |  |  |  |  |  |  | # Process @config_option_enum. | 
| 3212 | 156 |  |  |  |  | 387 | for my $AnB (@config_option_enum) { | 
| 3213 | 306 |  |  |  |  | 560 | my ($option, $enumerations) = @$AnB; | 
| 3214 |  |  |  |  |  |  |  | 
| 3215 |  |  |  |  |  |  | # Ditch uninitialized warnings, because I'm using undef to mean | 
| 3216 |  |  |  |  |  |  | # unspecified, so undef is not something unexpected to bother warning | 
| 3217 |  |  |  |  |  |  | # about, but something that will happen all the time. | 
| 3218 |  |  |  |  |  |  | { | 
| 3219 | 46 |  |  | 46 |  | 282 | no warnings 'uninitialized'; | 
|  | 46 |  |  |  |  | 103 |  | 
|  | 46 |  |  |  |  | 12427 |  | 
|  | 306 |  |  |  |  | 442 |  | 
| 3220 |  |  |  |  |  |  |  | 
| 3221 |  |  |  |  |  |  | # Only test the @enumerations if $option was specified in the | 
| 3222 |  |  |  |  |  |  | # Fetchwarefile. | 
| 3223 | 306 | 100 |  |  |  | 788 | if (config($option)) { | 
| 3224 |  |  |  |  |  |  |  | 
| 3225 |  |  |  |  |  |  | # Only one @enumerations should equal $option not more than one, hence | 
| 3226 |  |  |  |  |  |  | # the == 1 part. | 
| 3227 | 152 | 100 |  |  |  | 265 | die < | 
|  | 456 |  |  |  |  | 1208 |  | 
| 3228 | 1 |  |  |  |  | 4 | App-Fetchware: You specified the option [$option], but failed to specify only | 
| 3229 |  |  |  |  |  |  | one of its acceptable values [@$enumerations]. Please change the value you | 
| 3230 |  |  |  |  |  |  | specified [@{[config($option)]}] to one of the acceptable ones listed above, and try again. | 
| 3231 |  |  |  |  |  |  | EOD | 
| 3232 |  |  |  |  |  |  | } | 
| 3233 |  |  |  |  |  |  |  | 
| 3234 |  |  |  |  |  |  | } | 
| 3235 |  |  |  |  |  |  | } | 
| 3236 |  |  |  |  |  |  |  | 
| 3237 | 155 |  |  |  |  | 1284 | return 'Syntax Ok'; | 
| 3238 |  |  |  |  |  |  | } | 
| 3239 |  |  |  |  |  |  |  | 
| 3240 |  |  |  |  |  |  |  | 
| 3241 |  |  |  |  |  |  |  | 
| 3242 |  |  |  |  |  |  |  | 
| 3243 |  |  |  |  |  |  | sub end { | 
| 3244 |  |  |  |  |  |  | # Use cleanup_tempdir() to cleanup your tempdir for us. | 
| 3245 | 149 |  |  | 149 | 1 | 14483 | cleanup_tempdir(); | 
| 3246 |  |  |  |  |  |  | } | 
| 3247 |  |  |  |  |  |  |  | 
| 3248 |  |  |  |  |  |  |  | 
| 3249 |  |  |  |  |  |  |  | 
| 3250 |  |  |  |  |  |  | 1; | 
| 3251 |  |  |  |  |  |  |  | 
| 3252 |  |  |  |  |  |  |  | 
| 3253 |  |  |  |  |  |  |  | 
| 3254 |  |  |  |  |  |  |  | 
| 3255 |  |  |  |  |  |  |  | 
| 3256 |  |  |  |  |  |  |  | 
| 3257 |  |  |  |  |  |  |  | 
| 3258 |  |  |  |  |  |  |  | 
| 3259 |  |  |  |  |  |  |  | 
| 3260 |  |  |  |  |  |  |  | 
| 3261 |  |  |  |  |  |  |  | 
| 3262 |  |  |  |  |  |  |  | 
| 3263 |  |  |  |  |  |  |  | 
| 3264 |  |  |  |  |  |  |  | 
| 3265 |  |  |  |  |  |  |  | 
| 3266 |  |  |  |  |  |  |  | 
| 3267 |  |  |  |  |  |  |  | 
| 3268 |  |  |  |  |  |  | sub hook ($$) { | 
| 3269 | 2 |  |  | 2 | 1 | 1616 | my ($sub_to_hook, $callback) = @_; | 
| 3270 |  |  |  |  |  |  |  | 
| 3271 | 2 | 100 |  |  |  | 31 | die <can($sub_to_hook); | 
| 3272 |  |  |  |  |  |  | App-Fetchware: The subroutine [$sub_to_hook] you attempted to override does | 
| 3273 |  |  |  |  |  |  | not exist in this package. Perhaps you misspelled it, or it does not exist in | 
| 3274 |  |  |  |  |  |  | the current package. | 
| 3275 |  |  |  |  |  |  | EOD | 
| 3276 |  |  |  |  |  |  |  | 
| 3277 | 1 |  |  |  |  | 7 | override $sub_to_hook => $callback; | 
| 3278 |  |  |  |  |  |  |  | 
| 3279 |  |  |  |  |  |  | # Overriding the subroutine is not enough, because it is overriding it | 
| 3280 |  |  |  |  |  |  | # inside App::Fetchware, so I need to also override the subroutine inside | 
| 3281 |  |  |  |  |  |  | # hook()'s caller as done below. | 
| 3282 |  |  |  |  |  |  | { | 
| 3283 | 46 |  |  | 46 |  | 358 | no warnings 'redefine'; | 
|  | 46 |  |  |  |  | 106 |  | 
|  | 46 |  |  |  |  | 5589 |  | 
|  | 1 |  |  |  |  | 63 |  | 
| 3284 | 1 |  |  |  |  | 6 | clone($sub_to_hook => (from => 'App::Fetchware', to => caller())); | 
| 3285 |  |  |  |  |  |  | } | 
| 3286 |  |  |  |  |  |  | } | 
| 3287 |  |  |  |  |  |  |  | 
| 3288 |  |  |  |  |  |  |  | 
| 3289 |  |  |  |  |  |  | ###BUGALERT### Add an section of use cases. You know explaing why you'd use | 
| 3290 |  |  |  |  |  |  | #no_install, or why'd you'd use look, or why And so on..... | 
| 3291 |  |  |  |  |  |  |  | 
| 3292 |  |  |  |  |  |  |  | 
| 3293 |  |  |  |  |  |  |  | 
| 3294 |  |  |  |  |  |  |  | 
| 3295 |  |  |  |  |  |  | ###BUGALERT### Create a fetchware command to do this for users perhaps even | 
| 3296 |  |  |  |  |  |  | #plugin it into Module::Starter???? If possible. | 
| 3297 |  |  |  |  |  |  | ####BUGALERT## Even have so that you can specify which API subs you want to | 
| 3298 |  |  |  |  |  |  | #override or avoid overriding, and then it will create the skelton with stubs | 
| 3299 |  |  |  |  |  |  | #for those API sub already having some empty POD crap and the correct | 
| 3300 |  |  |  |  |  |  | #prototypes. | 
| 3301 |  |  |  |  |  |  |  | 
| 3302 |  |  |  |  |  |  |  | 
| 3303 |  |  |  |  |  |  |  | 
| 3304 |  |  |  |  |  |  |  | 
| 3305 |  |  |  |  |  |  |  | 
| 3306 |  |  |  |  |  |  |  | 
| 3307 |  |  |  |  |  |  |  | 
| 3308 |  |  |  |  |  |  |  | 
| 3309 |  |  |  |  |  |  | ###BUGALERT### Actually implement croak or more likely confess() support!!! | 
| 3310 |  |  |  |  |  |  |  | 
| 3311 |  |  |  |  |  |  | __END__ |