/** * Returns whether the specified URL is a valid Github URL. * Used for validating the input of the app/theme installer. * Also returns true if it's a link to a zip file. */ function github_is_valid_url($url) { if (github_parse_url($url) === false) { if (github_is_zip($url)) { return true; } return false; } return true; }
/** * Requires the Github reponsitory link (e.g., git://github.com/user/project.git). */ public static function install($source) { list($user, $project) = github_parse_url($source); $github = new GithubFetcher($user, $project); $tree = $github->tree(); // Get config and verify it $found = false; $conf = false; foreach ($tree as $item) { if ($item->path === 'elefant.json') { $data = $github->get($item); if (!$data) { self::$error = i18n_get('Unable to fetch configuration file.'); return false; } $conf = json_decode($data); if (!$conf) { self::$error = i18n_get('Verification failed: Invalid configuration file.'); return false; } if (!self::verify($conf)) { // self::$error already set by verify() return false; } $found = true; break; } } if (!$found) { self::$error = i18n_get('Configuration file not found.'); return false; } // Create new install folder if ($conf->type === 'app') { $dest = 'apps/' . $conf->folder; if (!mkdir($dest)) { self::$error = i18n_get('Unable to write to apps folder.'); return false; } } else { $dest = 'layouts/' . $conf->folder; if (!mkdir($dest)) { self::$error = i18n_get('Unable to write to layouts folder.'); return false; } } // This may take some time for larger apps set_time_limit(120); // Build files from tree foreach ($tree as $n => $item) { if ($item->type === 'tree') { mkdir($dest . '/' . $item->path); } else { $data = $github->get($item); if ($data === false) { self::$error = i18n_get('Unable to fetch file') . ' ' . $item->path; rmdir_recursive($dest); return false; } file_put_contents($dest . '/' . $item->path, $data); // Create our own rate-limiting to be nice with Github $data = null; if ($n % 20 === 0) { sleep(1); } } } chmod_recursive($dest, 0777); return $conf; }