blob: 8f2c06044681da5beec0980a352790b8b500e80d [file] [log] [blame]
<?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(
'&amp;',
'&lt;',
'&gt;',
'&quot;',
'&apos;'
)))
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;
}
?>