function main($args = array()) { global $_opts, $verbose; // Read arguments and options $optParser = new OptParser(array('create-torrent=sURLs' => 'Create torrent with given tracker URLs (comma separates groups, space separates group members: "t1, t2a t2b")', 'overwrite' => 'Overwrite existing files (otherwise append .new)', 'template|t=sFILE' => 'Metalink template file', 'url-prefix=sURL' => 'URL prefix (where metalink should be placed online)', 'verbose|v' => 'Verbose output', 'V' => 'Show program version and exit', 'help|h' => 'Print this message and exit' . PHP_EOL . PHP_EOL . "Metalink options:", 'changelog=sTEXT' => 'Changelog', 'copyright=sTEXT' => 'Copyright', 'description=sTEXT' => 'Description', 'identity=sTEXT' => 'Identity', 'license-name=sTEXT' => 'Name of the license', 'license-url=sURL' => 'URL of the license', 'logo=sURL' => 'Logo URL', 'origin=sURL' => 'Absolute or relative URL to this metalink file (online)', 'publisher-name=sTEXT' => 'Name of the publisher', 'publisher-url=sURL' => 'URL of the publisher', 'refreshdate=sDATE' => 'RFC 822 date of refresh (for type "dynamic")', 'releasedate=sDATE' => 'RFC 822 date of release', 'screenshot=sURL' => 'Screenshot(s) URL', 'tags=sTEXT' => 'Comma-separated list of tags', 'type=sTEXT' => 'Type of this metalink file ("dynamic" or "static")', 'upgrade=sTYPE' => 'Upgrade type ("install", "uninstall, reboot, install" or "uninstall, install")', 'version=sTEXT' => 'Version of the file')); $_args = array_slice($_SERVER['argv'], 1); # array_merge(array_slice($_SERVER['argv'], 1), $args); list($_opts, $args, $stdin, $errors) = $optParser->parse($_args); if ($_opts['verbose'] !== null) { $verbose = $_opts['verbose']; } if ($_opts['help'] || $errors) { usage_and_exit(join(PHP_EOL, $errors), $optParser->getHelp()); } if ($_opts['V']) { usage_and_exit(false); } // Sanitize options $_opts['tags'] = split_values($_opts['tags'], false); $new_version = ''; $url_prefix = ''; $files = array(); $files_skipped = array(); $m = new Metalink(); $_files = array(); $_hashes = array(); $_hashes_general = new Hashes(); $_metalinks = array(); $_metalink_general = ''; $_mirrors = array(); $_mirrors_general = new Mirrors(); $_signatures = array(); $_torrents = array(); if ($_opts['template'] && is_file($_opts['template'])) { $_files[] = $_opts['template']; } if ($_opts['url_prefix']) { $url_prefix = $_opts['url_prefix']; } if ($_opts['version']) { $new_version = $_opts['version']; } if ($_opts['create_torrent']) { $_opts['create_torrent'] = split_values($_opts['create_torrent'], true, ',', ' '); } // Search files and url_prefix foreach ($args as $arg) { if (is_dir($arg)) { foreach (glob(sprintf('%s%s*', realpath($arg), DIRECTORY_SEPARATOR)) as $file) { if (is_file($file)) { $_files[] = $file; // Search parallel helper files array_merge($_files, $m->find_helper_files($file)); } } } elseif (is_file($arg)) { $file = realpath($arg); $_files[] = $file; // Search parallel helper files $_files = array_merge($_files, $m->find_helper_files($file)); } elseif (is_url($arg)) { if (1 == is_url($arg)) { $url_prefix = $arg; } else { // Add mirror $_mirrors_general->parse('', $arg); } } else { // Try glob expression (wildcards) foreach (glob($arg) as $file) { if (is_file($file)) { $_files[] = $file; // Search parallel helper $files $_files = array_merge($_files, $m->find_helper_files($file)); } } } } $_files = array_unique($_files); // Categorize and filter files (hashes, mirrors, torrents, signatures) foreach ($_files as $file) { $_file = basename($file); if (substr($_file, -9) == '.metalink') { $_metalinks[substr($_file, 0, -9)] = $file; } elseif (substr($_file, -8) == '.torrent') { $_torrents[substr($_file, 0, -8)] = $file; } elseif (substr($_file, -8) == '.mirrors' || strtolower($_file) == 'mirrors') { $key = strtolower($_file) == 'mirrors' ? $_file : substr($_file, 0, -8); $_mirrors[$key] = $file; } elseif ($m->hashes->is_hash_file($_file)) { $hash_file = $m->hashes->last_hash_file; if (!in_array($hash_file, $_hashes)) { $_hashes[$hash_file] = array(); } if ($hash_file == $_file) { $key = dirname($file); } else { $key = substr($_file, strlen($hash_file) + 1); } $_hashes[$hash_file][$key] = $file; } elseif ($m->hashes->is_signature_file($_file)) { $hash_file = $m->hashes->last_hash_file; if (!in_array($hash_file, $_signatures)) { $_signatures[$hash_file] = array(); } $_signatures[$hash_file][substr($_file, strlen($hash_file) + 1)] = $file; $_signatures[$m->hashes->last_hash_file] = $file; } elseif (filesize($file) > 1000000) { $files[$_file] = $file; } else { $files_skipped[] = $file; } } if ($files_skipped && $GLOBALS['verbose']) { sort($files_skipped); fwrite(STDERR, sprintf("Skipped the following {$files}:%s%s", PHP_EOL, join(PHP_EOL, $files_skipped))); } // Metalink update mode if (!$files && sizeof($_metalinks)) { print 'Metalink update mode (apply options and create torrents)' . PHP_EOL; foreach ($_metalinks as $filename => $file) { $m = new Metalink(false); $m->load_file($file, false); if ($m->version && $m->version != $new_version) { $m->change_filename($new_version, $m->version); $new_file = dirname($file) . DIRECTORY_SEPARATOR . str_replace($m->version, $new_version, $filename) . '.metalink'; } else { $new_file = $file; } // Parse parallel files $local_file = substr($new_file, 0, -9); $torrent = $local_file . '.torrent'; if (is_file($torrent)) { $m->parse_torrent($torrent); } if (is_file($local_file)) { $m->scan_file($local_file); } // Force current creation date (may be overwritten by command-line option afterwards) $m->pubdate = ''; $m->apply_command_line_options(); if (is_file($new_file) && !$_opts['overwrite']) { $new_file .= '.new'; } $m->generate($new_file); } return; } // Mirror update mode if (!$files && sizeof($_metalinks) == 1 && sizeof($_mirrors) == 1) { $files[key($_metalinks)] = key($_metalinks); } // Filter general help files foreach (array_diff(array_keys($_metalinks), array_keys($files)) as $filename) { // TODO: Parse general metalink only once $_metalink_general = $_metalinks[$filename]; unset($_metalinks[$filename]); break; } foreach (array_diff(array_keys($_mirrors), array_keys($files)) as $filename) { $_mirrors_general->parse($_mirrors[$filename]); unset($_mirrors[$filename]); } foreach (array_diff(array_keys($_hashes), array_keys($files)) as $filename) { foreach ($_hashes[$filename] as $file) { $_hashes_general->parse($file); } } if (!$files) { usage_and_exit(null, $optParser->getHelp()); } // 'No $files to process' foreach ($files as $filename => $file) { print sprintf('Processing %s', $file) . PHP_EOL; $m = new Metalink(); // Parse metalink template if (isset($_metalinks[$filename])) { $m->load_file($_metalinks[$filename]); } elseif ($_metalink_general) { $m->load_file($_metalink_general); } // Force pubdate to be the current timestamp $m->pubdate = ''; // Overwrite old mirror filenames from template $m->change_filename($filename); if (isset($_mirrors[$filename])) { $m->clear_res('http ftp https ftps'); $m->parse_mirrors($_mirrors[$filename], '', '', true, true); // $m->file->mirrors->change_filename($filename); } elseif ($_mirrors_general->mirrors) { $_mirrors_general->change_filename($filename); $m->file->mirrors->add($_mirrors_general, true); } // Parse torrent files if (isset($_torrents[$filename])) { $m->parse_torrent($_torrents[$filename]); } elseif (sizeof($_torrents) == sizeof($files) && sizeof($_torrents) == 1) { $m->parse_torrent(current($_torrents)); } // Parse signature file if (isset($_signatures[$filename])) { $m->import_signature($_signatures[$filename]); } // Parse hash files $_hashes_general->set_file($file); $m->file->hashes->update($_hashes_general); if (isset($_hashes[$filename])) { $m->file->hashes->files = array_values($_hashes[$filename]); $m->file->hashes->parse_files(); } $m->file->hashes->set_file($file); if (is_file($file)) { // Scan file for remaining hashes $m->scan_file($file); } $m->url_prefix = $url_prefix; $m->generate(true); } }