From 095ca15093c07a9c2f3c768eb43313978b01d6d7 Mon Sep 17 00:00:00 2001 From: Shavitush Date: Sun, 1 Nov 2015 05:34:06 +0200 Subject: [PATCH] Added a (really ugly) web interface that shows records in maps. Configure using config.php --- webserver/config.php | 19 ++ webserver/functions.php | 77 +++++++ webserver/steamid.php | 457 ++++++++++++++++++++++++++++++++++++++++ webserver/timer.php | 184 ++++++++++++++++ 4 files changed, 737 insertions(+) create mode 100644 webserver/config.php create mode 100644 webserver/functions.php create mode 100644 webserver/steamid.php create mode 100644 webserver/timer.php diff --git a/webserver/config.php b/webserver/config.php new file mode 100644 index 00000000..d6ecec0b --- /dev/null +++ b/webserver/config.php @@ -0,0 +1,19 @@ + diff --git a/webserver/functions.php b/webserver/functions.php new file mode 100644 index 00000000..9fc00b8d --- /dev/null +++ b/webserver/functions.php @@ -0,0 +1,77 @@ + 3600) + { + $iHours = floor($iTemp / 3600.0); + $iTemp %= 3600; + } + + $sHours = ""; + + if($iHours < 10) + { + $sHours = "0" . $iHours; + } + + else + { + $sHours = $iHours; + } + + $iMinutes = 0; + + if($iTemp >= 60) + { + $iMinutes = floor($iTemp / 60.0); + $iTemp %= 60; + } + + $sMinutes = ""; + + if($iMinutes < 10) + { + $sMinutes = "0" . $iMinutes; + } + + else + { + $sMinutes = $iMinutes; + } + + $fSeconds = (($iTemp) + $time - floor($time)); + + $sSeconds = ""; + + if($fSeconds < 10) + { + $sSeconds = "0" . number_format($fSeconds, 3); + } + + else + { + $sSeconds = number_format($fSeconds, 3); + } + + if($iHours > 0) + { + $newtime = $sHours . ":" . $sMinutes . ":" . $sSeconds . "s"; + } + + else if($iMinutes > 0) + { + $newtime = $sMinutes . ":" . $sSeconds . "s"; + } + + else + { + $newtime = number_format($fSeconds, 3) . "s"; + } + + return $newtime; +} +?> diff --git a/webserver/steamid.php b/webserver/steamid.php new file mode 100644 index 00000000..82c91cb8 --- /dev/null +++ b/webserver/steamid.php @@ -0,0 +1,457 @@ +reason = $reason; + parent::__construct( $text ); + } +} + +/** --------------------------------------------------------------------------- + * SteamID + * + * Contains a User Steam ID. + * + * @author Mukunda Johnson + */ +class SteamID { + + // RAW Steam ID value as a string. (a plain number.) + public $value; + + // Array of converted values. Indexed by FORMAT_xxx + // this is a cache of formatted values, filled in + // by Format or Parse. + public $formatted; + + const FORMAT_AUTO = 0; // Auto-detect format --- this also supports + // other unlisted formats such as + // full profile URLs. + const FORMAT_STEAMID32 = 1; // Classic STEAM_x:y:zzzzzz | x = 0/1 + const FORMAT_STEAMID64 = 2; // SteamID64: 7656119xxxxxxxxxx + const FORMAT_STEAMID3 = 3; // SteamID3 format: [U:1:xxxxxx] + const FORMAT_S32 = 4; // Raw 32-bit SIGNED format. + // this is a raw steamid index that overflows + // into negative bitspace. + // This is the format that SourceMod returns + // with GetSteamAccountID, and will always + // fit into a 32-bit signed variable. (e.g. + // a 32-bit PHP integer). + const FORMAT_RAW = 5; // Raw index. like 64-bit minus the base value. + const FORMAT_VANITY = 6; // Vanity URL name. Forward conversion only. + + + const STEAMID64_BASE = '76561197960265728'; + + // max allowed value. (sanity check) + // 2^36; update this in approx 2,400,000 years + const MAX_VALUE = '68719476736'; + + private static $steam_api_key = FALSE; + private static $default_detect_raw = FALSE; + private static $default_resolve_vanity = FALSE; + + /** ----------------------------------------------------------------------- + * Set an API key to use for resolving Custom URLs. If this isn't set + * custom URL resolution will be done by parsing the profile XML. + * + * @param string $key API Key + * @see http://steamcommunity.com/dev/apikey + */ + public static function SetSteamAPIKey( $key ) { + if( empty($key) ) self::$steam_api_key = FALSE; + self::$steam_api_key = $key; + } + + /** ----------------------------------------------------------------------- + * Set the default setting for $detect_raw for Parse() + * + * @param bool $parseraw Default $detect_raw value, see Parse function. + */ + public static function SetParseRawDefault( $parseraw ) { + self::$default_detect_raw = $parseraw; + } + + /** ----------------------------------------------------------------------- + * Set the default setting for $resolve_vanity for Parse() + * + * @param bool $resolve_vanity Default $resolve_vanity value, + * see Parse function. + */ + public static function SetResolveVanityDefault( $resolve_vanity ) { + self::$default_resolve_vanity = $resolve_vanity; + } + + /** ----------------------------------------------------------------------- + * Construct an instance. + * + * @param string $raw Raw value of Steam ID. + */ + private function __construct( $raw ) { + $this->value = $raw; + $this->formatted[ self::FORMAT_RAW ] = $raw; + } + + /** ----------------------------------------------------------------------- + * Make a cURL request and return the contents. + * + * @param string $url URL to request. + * @return string|false Contents of result or FALSE if the request failed. + */ + private static function Curl( $url ) { + + $ch = curl_init(); + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 ); + + $data = curl_exec($ch); + curl_close($ch); + + return $data; + } + + /** ----------------------------------------------------------------------- + * Parse a Steam ID. + * + * @param string $input Input to parse. + * @param int $format Input formatting, see FORMAT_ constants. + * Defaults to FORMAT_AUTO which detects the format. + * @param bool $resolve_vanity Detect and resolve vanity URLs. (only used + * with FORMAT_AUTO. Default option set with + * SetResolveVanityDefault. + * @param bool $detect_raw Detect and parse RAW values. (only used with + * FORMAT_AUTO. e.g "123" will resolve to the + * SteamID with the raw value 123, and not a + * vanity-url named "123". Default option set with + * SetParseRawDefault. + * + * @return SteamID|false SteamID instance or FALSE if the input is invalid + * or unsupported. + */ + public static function Parse( $input, + $format = self::FORMAT_AUTO, + $resolve_vanity = null, + $detect_raw = null ) { + + if( $detect_raw === null ) + $detect_raw = self::$default_detect_raw; + if( $resolve_vanity === null ) + $resolve_vanity = self::$default_resolve_vanity; + + switch( $format ) { + + case self::FORMAT_STEAMID32: + + // validate STEAM_0/1:y:zzzzzz + if( !preg_match( + '/^STEAM_[0-1]:([0-1]):([0-9]+)$/', + $input, $matches ) ) { + + return FALSE; + } + + // convert to raw. + $a = bcmul( $matches[2], '2', 0 ); + $a = bcadd( $a, $matches[1], 0 ); + + $result = new self( $a ); + $result->formatted[ self::FORMAT_STEAMID32 ] = $input; + return $result; + + case self::FORMAT_STEAMID64: + + // allow digits only + if( !preg_match( '/^[0-9]+$/', $input ) ) return FALSE; + + // convert to raw (subtract base) + $a = bcsub( $input, self::STEAMID64_BASE, 0 ); + + // sanity range check. + if( bccomp( $a, '0', 0 ) < 0 ) return FALSE; + if( bccomp( $a, self::MAX_VALUE, 0 ) > 0 ) return FALSE; + + $result = new self( $a ); + $result->formatted[ self::FORMAT_STEAMID64 ] = $input; + return $result; + + case self::FORMAT_STEAMID3: + + // validate [U:1:xxxxxx] + if( !preg_match( '/^\[U:1:([0-9]+)\]$/', $input, $matches ) ) { + return FALSE; + } + + $a = $matches[1]; + + // sanity range check. + if( bccomp( $a, self::MAX_VALUE, 0 ) > 0 ) return FALSE; + $result = new self( $a ); + $result->formatted[ self::FORMAT_STEAMID3 ] = $input; + return $result; + + case self::FORMAT_S32: + + // validate signed 32-bit format + if( !preg_match( '/^(-?[0-9]+)$/', $input ) ) { + return FALSE; + } + + $a = $input; + + // 32-bit range check + if( bccomp( $a, '2147483647', 0 ) > 0 ) return FALSE; + if( bccomp( $a, '-2147483648', 0 ) < 0 ) return FALSE; + if( bccomp( $a, '0', 0 ) < 0 ) { + $a = bcadd( $a, '4294967296', 0 ); + } + $result = new self( $a ); + $result->formatted[ self::FORMAT_S32 ] = $input; + return $result; + + case self::FORMAT_RAW: + + // validate digits only + if( !preg_match( '/^[0-9]+$/', $input ) ) { + return FALSE; + } + + // sanity range check + if( bccomp( $input, self::MAX_VALUE, 0 ) > 0 ) return FALSE; + return new self( $input ); + + case self::FORMAT_VANITY: + + // validate characters. + if( !preg_match( '/^[a-zA-Z0-9_-]{2,}$/', $input ) ) return FALSE; + + $result = self::ConvertVanityURL( $input ); + if( $result !== FALSE ) { + $result->formatted[ self::FORMAT_VANITY ] = $input; + return $result; + } + } + + // Auto detect format: + + $input = trim( $input ); + $result = self::Parse( $input, self::FORMAT_STEAMID32 ); + if( $result !== FALSE ) return $result; + $result = self::Parse( $input, self::FORMAT_STEAMID64 ); + if( $result !== FALSE ) return $result; + $result = self::Parse( $input, self::FORMAT_STEAMID3 ); + if( $result !== FALSE ) return $result; + + if( preg_match( + '/^(?:https?:\/\/)?(?:www.)?steamcommunity.com\/profiles\/([0-9]+)\/*$/', + $input, $matches ) ) { + + $result = self::Parse( $matches[1], self::FORMAT_STEAMID64 ); + if( $result !== FALSE ) return $result; + } + + if( $resolve_vanity ) { + + // try the name directly + $result = self::Parse( $input, self::FORMAT_VANITY ); + if( $result !== FALSE ) return $result; + + // try a full URL. + if( preg_match( + '/^(?:https?:\/\/)?(?:www.)?steamcommunity.com\/id\/([a-zA-Z0-9_-]{2,})\/*$/', + $input, $matches ) ) { + + $result = self::ConvertVanityURL( $matches[1] ); + if( $result !== FALSE ) return $result; + } + } + + if( $detect_raw ) { + $result = self::Parse( $input, self::FORMAT_S32 ); + if( $result !== FALSE ) return $result; + $result = self::Parse( $input, self::FORMAT_RAW ); + if( $result !== FALSE ) return $result; + } + + // unknown stem + return FALSE; + } + + /** ----------------------------------------------------------------------- + * Convert a vanity URL into a SteamID instance. + * + * @param string $vanity_url_name The text part of the person's vanity URL. + * e.g http://steamcommunity.com/id/gabelogannewell + * would use "gabelogannewell" + * @return SteamID|false SteamID instance or FALSE on failure. + */ + public static function ConvertVanityURL( $vanity_url_name ) { + if( empty($vanity_url_name) ) return FALSE; + + if( self::$steam_api_key !== FALSE ) { + $response = self::Curl( + "http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=" + .self::$steam_api_key + ."&vanityurl=$vanity_url_name" ); + if( $response === FALSE ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::CURL_FAILURE, + 'CURL Request Failed.' ); + } + + if( $response == "" ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_FAILED, + 'Steam failure.' ); + } + + $response = json_decode( $response ); + if( $response === FALSE ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_FAILED, + 'Steam failure.' ); + } + + $response = $response->response; + + if( $response->success == 42 ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_NOTFOUND, + 'Vanity URL doesn\'t exist.' ); + + } + + if( $response->success != 1 ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_FAILED, + 'Steam failure.' ); + + } + + $steamid = $response->steamid; + + } else { + // fallback to xml parsing method. + + $result = self::Curl( "http://steamcommunity.com/id/$vanity_url_name?xml=1" ); + if( $result === FALSE ) { + throw new SteamIDResolutionException( + SteamIDResolutionException::CURL_FAILURE, + 'CURL Request Failed.' ); + } + + $parser = xml_parser_create(''); + $values = array(); + $indexes = array(); + xml_parse_into_struct( $parser, $result, $values, $indexes ); + xml_parser_free($parser); + if( !isset( $indexes['STEAMID64'] ) || is_null( $indexes['STEAMID64'] ) ) { + + if( isset( $indexes['ERROR'] ) && + trim($values[ $indexes['ERROR'][0] ]['value']) == + 'The specified profile could not be found.' ) { + + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_NOTFOUND, + 'Vanity URL doesn\'t exist.' ); + } + + throw new SteamIDResolutionException( + SteamIDResolutionException::VANITYURL_FAILED, + 'Invalid Vanity URL or Steam failure.' ); + } + $steamid = $indexes['STEAMID64']; + $steamid = $values[ $steamid[0] ]['value']; + } + + return self::Parse( $steamid, self::FORMAT_STEAMID64 ); + } + + /** ----------------------------------------------------------------------- + * Format this SteamID to a string. + * + * @param int $format Output format. See FORMAT_xxx constants. + * @return string|false Formatted Steam ID. FALSE if an invalid format is + * given or the desired format cannot contain the + * SteamID. + */ + public function Format( $format ) { + if( isset( $this->formatted[$format] ) ) { + return $this->formatted[$format]; + } + + switch( $format ) { + case self::FORMAT_STEAMID32: + $z = bcdiv( $this->value, '2', 0 ); + $y = bcmul( $z, '2', 0 ); + $y = bcsub( $this->value, $y, 0 ); + $formatted = "STEAM_1:$y:$z"; + $this->formatted[$format] = $formatted; + return $formatted; + + case self::FORMAT_STEAMID64: + $formatted = bcadd( $this->value, self::STEAMID64_BASE, 0 ); + $this->formatted[$format] = $formatted; + return $formatted; + + case self::FORMAT_STEAMID3: + $formatted = "[U:1:$this->value]"; + $this->formatted[$format] = $formatted; + return $formatted; + + case self::FORMAT_S32: + if( bccomp( $this->value, '4294967296', 0 ) >= 0 ) { + return FALSE; // too large for s32. + } + + if( bccomp( $this->value, '2147483648', 0 ) >= 0 ) { + $formatted = bcsub( $this->value, '4294967296', 0 ); + } else { + $formatted = $this->value; + } + $this->formatted[$format] = $formatted; + return $formatted; + + // (raw is always cached) + } + return FALSE; + } + +} + +?> diff --git a/webserver/timer.php b/webserver/timer.php new file mode 100644 index 00000000..a66f42a8 --- /dev/null +++ b/webserver/timer.php @@ -0,0 +1,184 @@ +set_charset("utf8"); + +$map = isset($_GET["map"]); + +function removeworkshop($mapname) +{ + if(strpos($mapname, "workshop/") !== false) + { + $pieces = explode("/", $mapname); + + return $pieces[2]; + } + + return $mapname; +} + +$style = 0; + +if(isset($_GET["style"])) +{ + $style = $_GET["style"]; +} +?> + + + + + + + + " . HOMEPAGE_TITLE . ""); + } + + else + { + echo("[" . ($style == 0? "NM":"SW") . " Records] " . removeworkshop($_GET["map"]) . ""); + } ?> + + + +

Home

+ +

+ "); + } + + else + { + echo(""); + } + ?> + + + + +

+ + prepare("SELECT p.id, p.map, u.auth, u.name, p.time, p.jumps FROM playertimes p JOIN users u ON p.auth = u.auth WHERE map = ? AND style = ? ORDER BY time ASC LIMIT " . RECORD_LIMIT . ";")) + { + $stmt->bind_param("ss", $_GET["map"], $_GET["style"]); + $stmt->execute(); + + $stmt->store_result(); + + $rows = $stmt->num_rows; + + $stmt->bind_result($id, $map, $auth, $name, $time, $jumps); + + echo "

Number of records: " . number_format($rows) . ".

"; + + if($rows > 0) + { + $first = true; + + $rank = 1; + + while($row = $stmt->fetch()) + { + if($first) + { + echo("

[" . ($style == 0? "Forwards":"Sideways") . " Records] " . removeworkshop($_GET["map"]) . "

"); + + ?> + + + + + + + + + + + + + + + + + + "); + } + } + + else + { + echo "

No results. Press Home to get the map list.

"; + } + + $stmt->close(); + } + + else + { + $result = mysqli_query($connection, "SELECT DISTINCT map FROM mapzones ORDER BY map ASC;"); + + if($result->num_rows > 0) + { + echo '

Click a map name in order to auto-fill the form.

'; + + while($row = $result->fetch_assoc()) + { + echo "" . removeworkshop($row["map"]) . "
"; + } + } + + else + { + echo "No results"; + } + } + ?> + + +close(); ?>
RankRecord IDSteamID3PlayerTimeJumps
#Format(SteamID::FORMAT_STEAMID64) . "/\">" . $auth . ""); ?> + +