$v) { $exclude[$k] = '#(^|/)(' . str_replace( ['.', '*'], ['\.', '.*?'], trim($v) ) . ')(/|$)#'; } return $exclude; } public static function getPackages(string $root): array { $res = []; if (!is_dir($root) || !is_readable($root)) { return $res; } $files = Files::scanDir($root); $zip_files = []; foreach ($files as $file) { if (!preg_match('#(^|/)(.*?)\.zip(/|$)#', $file)) { continue; } $zip_files[] = $file; } if (empty($zip_files)) { return $res; } $sandboxes = [ 'theme' => clone dcCore::app()->themes, 'plugin' => clone dcCore::app()->plugins, ]; $i = 0; foreach ($zip_files as $zip_file) { $zip_file = $root . DIRECTORY_SEPARATOR . $zip_file; $zip = new Unzip($zip_file); $zip->getList(false, '#(^|/)(__MACOSX|\.svn|\.hg.*|\.git.*|\.DS_Store|\.directory|Thumbs\.db)(/|$)#'); $zip_root_dir = $zip->getRootDir(); if ($zip_root_dir != false) { $target = dirname($zip_file); $path = $target . DIRECTORY_SEPARATOR . $zip_root_dir; $define = $zip_root_dir . '/' . dcModules::MODULE_FILE_DEFINE; $init = $zip_root_dir . '/' . dcModules::MODULE_FILE_INIT; } else { $target = dirname($zip_file) . DIRECTORY_SEPARATOR . preg_replace('/\.([^.]+)$/', '', basename($zip_file)); $path = $target; $define = dcModules::MODULE_FILE_DEFINE; $init = dcModules::MODULE_FILE_INIT; } if ($zip->isEmpty()) { $zip->close(); continue; } if (!$zip->hasFile($define)) { $zip->close(); continue; } foreach ($sandboxes as $type => $sandbox) { try { Files::makeDir($path, true); // can't load twice _init.php file ! $unlink = false; if ($zip->hasFile($init)) { $unlink = true; $zip->unzip($init, $path); } $zip->unzip($define, $path); $sandbox->resetModulesList(); $sandbox->requireDefine($path, basename($path)); if ($unlink) { unlink($target . DIRECTORY_SEPARATOR . $init); } unlink($target . DIRECTORY_SEPARATOR . $define); if (!$sandbox->getErrors()) { $module = $sandbox->getDefine(basename($path)); if ($module->isDefined() && $module->get('type') == $type) { $res[$i] = $module; $res[$i]->set('root', $zip_file); $i++; } } } catch (Exception $e) { } Files::deltree($path); } $zip->close(); } return $res; } public static function pack(dcModuleDefine $define, string $root, array $files, bool $overwrite = false, array $exclude = [], bool $nocomment = false, bool $fixnewline = false): bool { // check define if (!$define->isDefined() || empty($define->get('root')) || !is_dir($define->get('root')) ) { throw new Exception(__('Failed to get module info')); } // check root $root = (string) Path::real($root); if (!is_dir($root) || !is_writable($root)) { throw new Exception(__('Directory is not writable')); } //set excluded $exclude = self::quote_exclude(array_merge(My::EXCLUDED_FILES, $exclude)); foreach ($files as $file) { if (empty($file)) { continue; } // check path $path = $root . DIRECTORY_SEPARATOR . self::getFile($file, $define); if (file_exists($path) && !$overwrite) { // don't break loop continue; } @set_time_limit(300); if ($nocomment) { Zip::$remove_comment = true; } if ($fixnewline) { Zip::$fix_newline = true; } $zip = new Zip($path); foreach ($exclude as $e) { $zip->addExclusion($e); } $zip->addDirectory( (string) Path::real($define->get('root'), false), $define->getId(), true ); $zip->close(); unset($zip); } return true; } private static function getFile(string $file, dcModuleDefine $define): string { $file = str_replace( [ '\\', '%type%', '%id%', '%version%', '%author%', '%time%', ], [ '/', $define->get('type'), $define->getId(), $define->get('version'), $define->get('author'), time(), ], $file ); $parts = explode('/', $file); foreach ($parts as $i => $part) { $parts[$i] = Files::tidyFileName($part); } return implode(DIRECTORY_SEPARATOR, $parts) . '.zip'; } }