| <?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; |
| } |
| |
| $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; |
| } |
| ?> |