| <?php | |
| /******************************************************************************* | |
| * Copyright (c) 2010, 2017 Eclipse Foundation and others. | |
| * | |
| * This program and the accompanying materials are made available under the | |
| * terms of the Eclipse Public License v. 2.0 which is available at | |
| * http://www.eclipse.org/legal/epl-2.0. | |
| * | |
| * SPDX-License-Identifier: EPL-2.0 | |
| ********************************************************************************/ | |
| // TODO Merge with web-api/common.inc | |
| require_once (dirname(__FILE__) . "/debug.php"); | |
| trace_file_info(__FILE__); | |
| /* | |
| * The regular expression pattern that is used to determine whether | |
| * or not a project id is valid. | |
| * PRIVATE: THIS FIELD IS NOT API. | |
| */ | |
| $projectNameSegmentPattern = "[a-zA-Z0-9\\-]+"; | |
| $projectNamePattern = "$projectNameSegmentPattern(\\.$projectNameSegmentPattern){0,2}"; | |
| define('ProjectNamePattern', $projectNamePattern); | |
| /** | |
| * Answers <code>true</code> if $id represents a valid project id; | |
| * <code>false</code> otherwise. | |
| * | |
| * @param string $id | |
| * Must not be <code>null</code> | |
| * @return bool | |
| */ | |
| function isValidProjectId($id) { | |
| global $projectNamePattern; | |
| return preg_match("/^$projectNamePattern$/", $id); | |
| } | |
| /** | |
| * Answers <code>true</code> if $name represents a valid project name; | |
| * <code>false</code> otherwise. | |
| * | |
| * @deprecated use isValidProjectId($id) instead. | |
| * @param string $name | |
| * Must not be <code>null</code> | |
| * @return bool | |
| */ | |
| function isValidProjectName($name) { | |
| return isValidProjectId($name); | |
| } | |
| /** | |
| * Answers <code>true</code> if $name represents a valid project name; | |
| * <code>false</code> otherwise. | |
| * | |
| * @deprecated use isValidProjectId($id) instead. | |
| * @param string $name | |
| * Must not be <code>null</code> | |
| * @return bool | |
| */ | |
| function is_valid_project_name($name) { | |
| return isValidProjectId($name); | |
| } | |
| /** | |
| * Returns the name of the parent project, or <code>null</code> is there | |
| * is no parent project. | |
| * Current implementation infers the name of the parent | |
| * from the given name by lopping off the last segment. e.g. | |
| * | |
| * getParentProjectId('eclipse.jdt.debugging') return 'eclipse.jdt' | |
| * . | |
| * | |
| * @param string $name | |
| * Must not be <code>null</code> | |
| * @return string | |
| */ | |
| function getParentProjectId($name) { | |
| if (!$name) | |
| return null; | |
| global $projectNamePattern, $projectNameSegmentPattern; | |
| if (preg_match("/^($projectNamePattern)\\.$projectNameSegmentPattern$/", $name, $matches)) | |
| return $matches[1]; | |
| return null; | |
| } | |
| /** | |
| * | |
| * @deprecated | |
| * | |
| * @see getParentProjectId() | |
| * @param string $name | |
| */ | |
| function get_project_parent_id($name) { | |
| return getParentProjectId($name); | |
| } | |
| /** | |
| * Returns <code>true</code> if the second parameter represents a | |
| * valid subproject of the first parameter. | |
| * Note that this only checks | |
| * to see if the names are compatible; no check is done to confirm that | |
| * either parameter represents the name of an actual existing project. | |
| * | |
| * @param string $parent | |
| * Must not be <code>null</code> | |
| * @param string $name | |
| * Must not be <code>null</code> | |
| * @return bool | |
| */ | |
| function is_valid_subproject_id($parent, $name) { | |
| return preg_match("/^$parent\\./", $name); | |
| } | |
| /** | |
| * This function normalizes the provided URL to a valid 'eclipse.org' HTTP | |
| * form. | |
| * Input should be a valid eclipse.org URL or a relative URL | |
| * (with or without a leading slash). Note that URLs that do not correspond | |
| * to an eclipse.org addresses, will result in a <code>null</code> result. | |
| * | |
| * Note that this is more about normalization than actual full validation; | |
| * only the scheme and domain are considered. The current implementation | |
| * only supports the http/https schemes; the specification of a port | |
| * is not supported. This may change in the future. | |
| * | |
| * e.g. The following URLs are all considered valid and returned in the | |
| * the form they are provided. | |
| * - http://www.eclipse.org/woolsey/para.html | |
| * - http://eclipse.org/woolsey/para.html | |
| * - http://download.eclipse.org/woolsey/para.html | |
| * - | |
| * http://git.eclipse.org/c/jetty/org.eclipse.jetty.admin.git/plain/jetty-project-plan.xml | |
| * | |
| * e.g. The following URLs will be returned as | |
| * http://eclipse.org/woolsey/para.html | |
| * - woolsey/para.html | |
| * - /woolsey/para.html | |
| * | |
| * Usage: | |
| * | |
| * normalizeHttpUrl('http://www.eclipse.org/woolsey/para.html'); | |
| * | |
| * @param string $url | |
| * Must not be <code>null</code> | |
| * @return string | |
| */ | |
| function normalizeHttpUrl($url) { | |
| if (preg_match('/^https?:\/\/(\w+\.)?eclipse\.org(\/.*)?$/', $url)) | |
| return $url; | |
| if (preg_match('/^https?:\/\/(\w+\.)?locationtech\.org(\/.*)?$/', $url)) | |
| return $url; | |
| if (preg_match('/^https?:\/\/(\w+\.)?polarsys\.org(\/.*)?$/', $url)) | |
| return $url; | |
| $relative = normalizeRelativeUrl($url, 'www'); | |
| if ($relative) | |
| return 'http://www.eclipse.org' . $relative; | |
| return null; | |
| } | |
| /** | |
| * This function normalizes the provided URL to valid file path on the | |
| * eclipse.org web directory. | |
| * Input should be a valid eclipse.org URL | |
| * or a relative URL (with or without a leading slash). | |
| * | |
| * e.g. The following URLs will all normalize to | |
| * /home/local/data/httpd/www.eclipse.org/html/woolsey/para.html | |
| * | |
| * - http://www.eclipse.org/woolsey/para.html | |
| * - http://eclipse.org/woolsey/para.html | |
| * - http://localhost/woolsey/para.html | |
| * - woolsey/para.html | |
| * - /woolsey/para.html) | |
| * | |
| * Note that URLs that do not correspond to eclipse.org addresses, will | |
| * result in a <code>null</code> result. | |
| * | |
| * Usage: | |
| * | |
| * normalizeFilePathUrl('http://www.eclipse.org/woolsey/para.html'); | |
| * | |
| * @param string $url | |
| * Must not be <code>null</code> | |
| * @return string | |
| */ | |
| function normalizeFilePathUrl($url) { | |
| global $_SERVER; | |
| $relative = normalizeRelativeUrl($url); | |
| if (!$relative) | |
| return null; | |
| return $_SERVER['DOCUMENT_ROOT'] . $relative; | |
| } | |
| /** | |
| * This function normalizes the provided URL to a relative path. | |
| * Input should be a valid eclipse.org URL or a relative URL | |
| * (with or without a leading slash). | |
| * | |
| * e.g. The following URLs will all normalize to | |
| * /woolsey/para.html | |
| * | |
| * - http://www.eclipse.org/woolsey/para.html | |
| * - http://eclipse.org/woolsey/para.html | |
| * - http://localhost/woolsey/para.html | |
| * - woolsey/para.html | |
| * - /woolsey/para.html) | |
| * | |
| * Note that URLs that do not correspond to eclipse.org addresses, will | |
| * result in a <code>null</code> result. | |
| * | |
| * Usage: | |
| * | |
| * extractcRelativeUrl('http://www.eclipse.org/woolsey/para.html'); | |
| * | |
| * @param string $url | |
| * Must not be <code>null</code> | |
| * @return string | |
| */ | |
| function normalizeRelativeUrl($url) { | |
| if (!$url) | |
| return null; | |
| $url = trim($url); | |
| $pattern_word = '\w[\w-]*'; | |
| $pattern_segment = "$pattern_word(\\.$pattern_word)*"; | |
| $pattern_relative_part = "$pattern_segment(\\/$pattern_segment)*\\/?"; | |
| $pattern_relative_url = "/^\\/?($pattern_relative_part)$/"; | |
| $pattern_http_url = "/^http:\\/\\/(www\\.)?eclipse\\.org\\/($pattern_relative_part)$/"; | |
| $pattern_http_local_url = "/^http:\\/\\/localhost\\/($pattern_relative_part)$/"; | |
| if (preg_match($pattern_relative_url, $url, $matches1)) { | |
| return '/' . $matches1[1]; | |
| } | |
| else | |
| if (preg_match($pattern_http_url, $url, $matches2)) { | |
| return '/' . $matches2[2]; | |
| } | |
| else | |
| if (preg_match($pattern_http_local_url, $url, $matches3)) { | |
| return '/' . $matches3[1]; | |
| } | |
| else { | |
| trace("The url ($url) cannot be normalized."); | |
| return null; | |
| } | |
| } | |
| /** | |
| * | |
| * @deprecated use #mustBeCommitter() instead. | |
| * @return Friend | |
| */ | |
| function login_committer() { | |
| return mustBeCommitter(); | |
| } | |
| /** | |
| * This function forces a login event if the current user is not | |
| * already logged in or is logged in as a non-committer. | |
| * If the | |
| * logged in user is not a committer, they are redirected to the | |
| * /projects/ page. It must be called before any HTML is written to the | |
| * output stream. | |
| * | |
| * This function assumes that the $App variable exists and has been | |
| * assigned an instance of the App class (from app.class.php). | |
| * | |
| * @deprecated | |
| * @see Project::callIfNotCommitter() | |
| * | |
| * @param Tracer $trace | |
| * (optional) | |
| * @return Friend | |
| */ | |
| function mustBeCommitter($trace = null) { | |
| global $App; | |
| if ($App->devmode) | |
| return; | |
| require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/classes/friends/friend.class.php"); | |
| require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/eclipseenv.class.php"); | |
| $Session = $App->useSession("optional"); | |
| $friend = $Session->getFriend(); | |
| $EclipseEnv = new EclipseEnv(); | |
| $domain = $EclipseEnv->getEclipseEnv(); | |
| if (!$friend->getLDAPUID()) { | |
| header("Location: " . $domain["accounts"] . "/user/login?takemeback=" . $_SERVER['SCRIPT_URI']); | |
| exit(); | |
| } | |
| if (!$trace) | |
| $trace = trace("Must be committer"); | |
| $trace->trace("UUID: " . $friend->getLDAPUID()); | |
| if (!$friend->getIsCommitter()) { | |
| header("Location: /projects"); | |
| exit(); | |
| } | |
| $trace->trace("User is a committer."); | |
| return $friend; | |
| } | |
| /** | |
| * Test to see if the user is a committer, and execute | |
| * the callable if they are not. | |
| * | |
| * @param callable $function | |
| * @return Friend | |
| */ | |
| function callIfNotCommitter($function) { | |
| global $App; | |
| if ($App->devmode) { | |
| return; | |
| } | |
| require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/classes/friends/friend.class.php"); | |
| $Session = $App->useSession("required"); | |
| $friend = $Session->getFriend(); | |
| if (!$friend->getIsCommitter()) { | |
| call_user_func($function); | |
| return; | |
| } | |
| return $friend; | |
| } | |
| /** | |
| * This function forces a login event if the current user is not | |
| * logged in. | |
| * If the logged in user is not an Eclipse Foundation | |
| * employee, they are redirected to the /projects/ page. It must | |
| * be called before any HTML is written to the output stream. | |
| * | |
| * This function assumes that the $App variable exists and has been | |
| * assigned an instance of the App class (from app.class.php). | |
| * | |
| * @return Friend | |
| */ | |
| function mustBeFoundationEmployee() { | |
| global $App; | |
| if ($App->devmode) | |
| return; | |
| $trace = trace("Must be Foundation Employee"); | |
| $friend = mustBeCommitter($trace); | |
| // TODO There may be a better way to do this. | |
| if (!preg_match('/^.+@eclipse-foundation\.org$/', $friend->getEmail())) { | |
| header("Location: /projects"); | |
| exit(); | |
| } | |
| return $friend; | |
| } | |
| /** | |
| * This function basically throws a fit if the caller is | |
| * coming from anywhere outside of the EF. | |
| * It determines | |
| * whether or not to grant access based on the IP Address. | |
| */ | |
| function mustBeEclipseFoundationCaller() { | |
| $patterns = array( | |
| '198.41.30.', // 198.41.30.192/26 | |
| '99.240.80.', | |
| '172.25.', // 172.25.0.0/16 | |
| '172.30.', // 172.30.0.0/16 | |
| '127.0.0.1' | |
| ); | |
| $match = preg_replace('/\./', '\.', implode('|', $patterns)); | |
| if (preg_match("/^($match)/", $_SERVER['REMOTE_ADDR'])) | |
| return; | |
| // if(preg_match('/209\.217\.126\.125|206\.191\.52\.\d+|172\.25\.25\.\d+|172\.30\.206\.\d+|127\.0\.0\.1/', | |
| // $_SERVER['REMOTE_ADDR'])) return; | |
| // $log = fopen( $logfile, "a" ); | |
| // fwrite( $log, date('Y-m-d.H:i:s') . " " . $_SERVER['REMOTE_ADDR'] . " is | |
| // an invalid caller\n" ); | |
| // fclose( $log ); | |
| echo $_SERVER['REMOTE_ADDR'] . " is an invalid caller<br>\n"; | |
| exit(); | |
| } | |
| /** | |
| * This function returns an instance of Friend corresponding to the | |
| * currently logged in committer, or null if nobody is logged in or | |
| * the currently logged in user is not a committer. | |
| * Note that this | |
| * function may return a different instance of Friend on subsequent | |
| * calls (i.e. do not assume that the instance is cached; don't assume | |
| * that it isn't cached either, these things change). | |
| * | |
| * This function assumes that the $App variable exists and has been | |
| * assigned an instance of the App class (from app.class.php). | |
| * | |
| * @return Friend | |
| */ | |
| function get_committer() { | |
| global $App; | |
| require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/classes/friends/friend.class.php"); | |
| if ($App->devmode) { | |
| $friend = new Friend(); | |
| // $friend->setBugzillaID(12345); | |
| $friend->setFirstName("John"); | |
| $friend->setLastName("Smith"); | |
| return $friend; | |
| } | |
| $Session = $App->useSession("optional"); | |
| $friend = $Session->getFriend(); | |
| if (!$friend->getBugzillaID()) | |
| return null; | |
| if (!$friend->getIsCommitter()) | |
| return null; | |
| return $friend; | |
| } | |
| /** | |
| * This function returns a string that describes the current | |
| * "login" state, e.g. | |
| * "You are logged in as Wayne Beaton." | |
| * | |
| * @deprecated | |
| * @return string | |
| */ | |
| function user_info_html() { | |
| $friend = get_committer(); | |
| $login = "https://accounts.eclipse.org/user/login?takemeback=" . $_SERVER['SCRIPT_URI']; | |
| $logout = "https://accounts.eclipse.org/user/login?submit=Logout&takemeback=" . $_SERVER['SCRIPT_URI']; | |
| if (!$friend) | |
| return "You must <a href=\"$login\">log in</a> as a committer (using your Eclipse Foundation Account) to use these tools."; | |
| $first = $friend->getFirstName(); | |
| $last = $friend->getLastName(); | |
| $message = $friend->getIsCommitter() ? "<a href=\"$logout\">Log out</a>" : " You are not a committer; you must <a href=\"$login\">log in</a> as a committer to use these tools"; | |
| return "You are logged in as $first $last. $message."; | |
| } | |
| /** | |
| * This function extracts the bundle name from the provided file name. | |
| * | |
| * Example: | |
| * | |
| * extract_bundle_name_and_version('javax.persistence.source_2.0.1.v201006031150.jar') | |
| * returns 'javax.persistence.source_2.0.1' | |
| * | |
| * Returns <code>null</code> if the bundle name cannot be determined. | |
| * | |
| * @param string $name | |
| * name of the file to extract from | |
| * @return string | |
| */ | |
| function extract_bundle_name_and_version($name) { | |
| if (preg_match('/^([a-zA-Z0-9\.-_]+[_-](\d+\.){3}).*\\.jar/', $name, $matches)) { | |
| return $matches[1]; | |
| } | |
| if (preg_match('/^([a-zA-Z0-9\.-_]+[_-]([\d\.]*))[-_].*\\.jar/', $name, $matches)) { | |
| return $matches[1]; | |
| } | |
| return null; | |
| } | |
| /** | |
| * The xmlentities function performs a similar function to the | |
| * htmlentities function, but with XML in mind. | |
| * The current | |
| * implementation runs the string through htmlentities and-- | |
| * from the result--prunes out any entity that should no be | |
| * in the result. A future version of this function will be | |
| * smarter. | |
| * | |
| * @param string $string | |
| * @return string | |
| */ | |
| function xmlentities($string) { | |
| $html = htmlentities($string, ENT_QUOTES, 'UTF-8'); | |
| return preg_replace_callback('/&[\w]+;/', '_xmlentitiescallback', $html); | |
| } | |
| /** | |
| * | |
| * @internal | |
| * | |
| * @param string[] $matches | |
| */ | |
| function _xmlentitiescallback($matches) { | |
| if (in_array($matches[0], array( | |
| '&', | |
| '<', | |
| '>', | |
| '"', | |
| ''' | |
| ))) | |
| return $matches[0]; | |
| return ''; | |
| } | |
| function requiresGoogleChartsSupport() { | |
| require_once dirname(__FILE__) . '/util/google-charts.php'; | |
| } | |
| /** | |
| * This function tests the provided value to determine whether or | |
| * not is represents a well-formed project id. | |
| * If the value fails the | |
| * test, a ValidationException is thrown. Callers can use this method | |
| * to make sure that their parameter values are reasonable. | |
| * | |
| * @param string $id | |
| * @throws ValidationException | |
| * @return void | |
| */ | |
| function mustBeValidProjectId($id) { | |
| if (!is_valid_project_name($id)) | |
| throw new ValidationException("Valid project id expected."); | |
| } | |
| class ValidationException extends Exception { | |
| } | |
| /** | |
| * This function answers an array containing the base | |
| * URLs for all forges. | |
| * | |
| * @deprecated use Forge::getForges() | |
| * @return string[] | |
| */ | |
| function getForges() { | |
| $forges = array(); | |
| foreach (Forge::getForges() as $forge) { | |
| $forges[] = $forge->getUrl(); | |
| } | |
| return $forges; | |
| } | |
| function getUrlContents($url) { | |
| $ch = curl_init(); | |
| curl_setopt($ch, CURLOPT_URL, $url); | |
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
| $page = curl_exec($ch); | |
| curl_close($ch); | |
| return $page; | |
| } | |
| function findPreviousThursday($start = 'now') { | |
| $date = strtotime($start); | |
| $diff = date('w', $date) - 4; // 4 == Thursday | |
| if ($diff < 0) | |
| $diff += 7; | |
| $thursday = $date - ($diff * 24 * 60 * 60); | |
| return date('Y-m-d', $thursday); | |
| } | |
| function findNextWednesday($start = 'now') { | |
| $date = strtotime($start); | |
| $diff = 3 - date('w', $date); // 3 == Wednesday | |
| if ($diff < 0) | |
| $diff += 7; | |
| $wednesday = $date + ($diff * 24 * 60 * 60); | |
| return date('Y-m-d', $wednesday); | |
| } | |
| function implodeWithConjunction($values, $conjunction = 'and', $start = 0) { | |
| $end = count($values) - 1; | |
| if ($start > $end) { | |
| return; | |
| } elseif ($start == $end) { | |
| return $values[$start]; | |
| } elseif ($end - $start == 1) { | |
| return $values[$start] . ', ' . $conjunction . ' ' . $values[$end]; | |
| } else { | |
| return $values[$start] . ', ' . implodeWithConjunction($values, $conjunction, $start + 1); | |
| } | |
| } | |
| function renderAsHeaderComment($string, $length=80) { | |
| $output = array(); | |
| $output[] = '/' . str_repeat('*', $length); | |
| foreach(explode("\n", $string) as $line) { | |
| foreach(explode("\n", wordwrap($line, $length-5)) as $fragment) { | |
| $output[] = ' * ' . $fragment; | |
| } | |
| } | |
| $output[] = ' ' . str_repeat('*', $length) . '/'; | |
| return implode("\n", $output); | |
| } | |
| function compareSemanticVersion($a, $b) { | |
| $va = explode('.', $a); | |
| $vb = explode('.', $b); | |
| $max = 5; | |
| while ($max-- > 0) { | |
| $ca = current($va); | |
| $cb = current($vb); | |
| // FALSE means that we've run out of terms. If both numbers | |
| // run out of terms, then they're the same. It's unlikely | |
| // that either of the following two lines will ever evaluate | |
| // to true since the getVersion() method should always answer | |
| // a three-part version number. But, we'll leave it just in | |
| // case something changes later. | |
| if ($ca === FALSE && ($cb === FALSE)) { | |
| return 0; | |
| } elseif ($ca === FALSE) { | |
| return -1; | |
| } elseif ($cb === FALSE) { | |
| return 1; | |
| } else { | |
| // Compare as integers rather than strings. | |
| $ca = (int) $ca; | |
| $cb = (int) $cb; | |
| if ($ca > $cb) { | |
| return 1; | |
| } elseif ($cb > $ca) { | |
| return -1; | |
| } | |
| next($va); | |
| next($vb); | |
| } | |
| } | |
| return 0; | |
| } | |
| ?> |