public function createProfile($sProfileUrl, $sBaseDir, $sCurrentTheme) { parent::__construct(); // load global config $this->oCommonConfig = FileConfig::getInstance('common.cfg'); // load image config $oImageConfig = FileConfig::getInstance('image.cfg'); // set default theme $sDefaultTheme = $oImageConfig->getString('image.theme.default', 'default'); // set theme path $sDefaultThemePath = "{$sBaseDir}/themes/{$sDefaultTheme}"; $sCurrentThemePath = "{$sBaseDir}/themes/{$sCurrentTheme}"; if (!file_exists($sDefaultThemePath)) { throw new RuntimeException('Default theme folder not found'); } if (!file_exists($sCurrentThemePath)) { $sCurrentThemePath = $sDefaultThemePath; } // init cache $sCacheDir = $this->oCommonConfig->getString('cache.dir', 'cache'); $this->oJpgAssetCache = new Cache($sCacheDir, -1, 'jpg'); // the required files for the default theme $this->aThemeFiles = array('background' => 'background.png', 'background_fade' => 'background_fade.png', 'default_avatar' => 'default_av.jpg', 'error' => 'error.png', 'frame_avatar_ingame' => 'iconholder_ingame.png', 'frame_avatar_offline' => 'iconholder_offline.png', 'frame_avatar_online' => 'iconholder_online.png', 'frame_avatar_private' => 'iconholder_offline.png'); // check for existing theme files foreach ($this->aThemeFiles as $sKey => $sFile) { if (!file_exists("{$sDefaultThemePath}/{$sFile}")) { throw new RuntimeException("Missing default theme file '{$sDefaultThemePath}/{$sFile}'"); } if (file_exists("{$sCurrentThemePath}/{$sFile}")) { $this->aThemeFiles[$sKey] = "{$sCurrentThemePath}/{$sFile}"; } else { $this->aThemeFiles[$sKey] = "{$sDefaultThemePath}/{$sFile}"; } } // set theme config paths $sDefaultThemeConfigFile = "{$sDefaultThemePath}/theme.cfg"; $sCurrentThemeConfigFile = "{$sCurrentThemePath}/theme.cfg"; if (!file_exists($sDefaultThemeConfigFile)) { throw new RuntimeException('Default theme config not found'); } // load default config $this->oThemeConfig = FileConfig::getInstance($sDefaultThemeConfigFile); // merge default config with selected theme config, if existing if ($sCurrentTheme !== $sDefaultTheme && file_exists($sCurrentThemeConfigFile)) { $this->oThemeConfig->merge(FileConfig::getInstance($sCurrentThemeConfigFile)); } // init settings $iTextStatusX = $this->oThemeConfig->getInteger('theme.text.status.x'); $iTextStatusY = $this->oThemeConfig->getInteger('theme.text.status.y'); $iImageAvatarX = $this->oThemeConfig->getInteger('theme.image.avatar.x'); $iImageAvatarY = $this->oThemeConfig->getInteger('theme.image.avatar.y'); $bShowGameBG = $this->oThemeConfig->getBoolean('theme.background.game'); // load background $this->loadPng($this->aThemeFiles['background']); // enable alpha $this->setAlphaBlending(true); $this->setSaveFullAlpha(true); try { // load XML data $xmlData = $this->loadXmlData($sProfileUrl); } catch (Exception $e) { // that didn't work :( $this->drawErrorMessage($e->getMessage()); throw new SteamProfileImageException('Can\'t load XML data', 0, $e); } // check if the server has returned any errors if (count($xmlData->xpath('/response')) != 0) { $this->drawErrorMessage((string) $xmlData->error); throw new SteamProfileImageException('Steam server error: ' . (string) $xmlData->error); } // check for expected XML structure if (count($xmlData->xpath('/profile')) == 0) { $this->drawErrorMessage('Invalid Steam Community data'); throw new SteamProfileImageException('Invalid Steam Community data'); } $sStatusCode = 'offline'; // determinate status if ((string) $xmlData->privacyState != 'public') { $sStatusCode = 'private'; $sStatus = 'This profile is private'; } else { // get the player's status for text and color switch ((string) $xmlData->onlineState) { case 'in-game': $sStatusCode = 'ingame'; $sCurrentGame = $xmlData->inGameInfo == null ? '' : (string) $xmlData->inGameInfo->gameName; $sStatus = "In-Game\n{$sCurrentGame}"; break; case 'online': $sStatusCode = 'online'; $sStatus = 'Online'; break; case 'offline': $sStatus = (string) $xmlData->stateMessage; break; default: throw new RuntimeException('Unable to determinate player status.'); } } if ($bShowGameBG && $sStatusCode == 'ingame') { // game background $sGameBGUrl = (string) $xmlData->inGameInfo->gameLogoSmall; $this->drawGameBackground($sGameBGUrl); } // avatar image $sAvatarUrl = (string) $xmlData->avatarIcon; $this->drawAvatar($iImageAvatarX, $iImageAvatarY, $sAvatarUrl, $sStatusCode); // status text $sName = (string) $xmlData->steamID; $this->drawStatus($iTextStatusX, $iTextStatusY, $sName, $sStatus, $sStatusCode); }
public function run() { try { // load config $oProxyConfig = FileConfig::getInstance('xmlproxy.cfg'); $oCommonConfig = FileConfig::getInstance('common.cfg'); // load config vars $iCacheLifetime = $oCommonConfig->getInteger('cache.lifetime', 600); $sCacheDir = $oCommonConfig->getString('cache.dir', 'cache'); $iDownloaderTimeout = $oCommonConfig->getInteger('downloader.timeout', 10); $bXMLHttpRequestOnly = $oProxyConfig->getBoolean('proxy.check_header', true); $oHeader = new HTTPHeader(); // response to XMLHttpRequest only if ($bXMLHttpRequestOnly && !$oHeader->isXMLHttpRequest()) { $oHeader->setResponseCode(204); return; } // get profile URL $sXmlUrl = $this->getProfileUrl(); // init cache $oXmlCache = new Cache($sCacheDir, $iCacheLifetime, 'xml'); $oXmlFile = $oXmlCache->getFile($sXmlUrl); // do we have a cached version of the xml document? if (!$oXmlFile->isCached()) { try { // initialize the downloader $oProfileLoader = new SteamProfileLoader($sXmlUrl, SteamProfileApp::getUserAgent(), 'Ajax'); $oProfileLoader->setTimeout($iDownloaderTimeout); $oProfileLoader->setTrimExtra(true); $oProfileLoader->setFilterCtlChars(true); $sXml = ''; try { // try to download the XML file $sXml = $oProfileLoader->start(); } catch (Exception $e) { // didn't work, close cURL handle $oProfileLoader->close(); throw $e; } // close cURL handle $oProfileLoader->close(); // kill invalid characters $sXml = mb_convert_encoding($sXml, "UTF-8", "UTF-8"); // save document to cache $oXmlFile->writeString($sXml); // clear stat cache to ensure that the rest of the // script will notice the file modification clearstatcache(); } catch (Exception $e) { // downloading failed, but maybe we can redirect to the old file if (!$oXmlFile->exists()) { // no, we can't throw $e; } } } // use client cache, if possible if (!$oHeader->isModifiedSince($oXmlFile->lastModified())) { $oHeader->setResponseCode(304); return; } else { $oHeader->setResponse('Content-Type', 'application/xml'); $oXmlFile->readStdOut(); } } catch (Exception $e) { // print XML-formatted error $oError = new XMLError($e); $oError->build(); } }
public function run() { $bDebug = defined('DEBUG') && DEBUG; try { // get profile URL $sXmlUrl = $this->getProfileUrl(false); // load config $oCommonConfig = FileConfig::getInstance('common.cfg'); $oImageConfig = FileConfig::getInstance('image.cfg'); $oGPCConfig = GPCConfig::getInstance('get'); // load config vars $iCacheLifetime = $oCommonConfig->getInteger('cache.lifetime', 600); $sCacheDir = $oCommonConfig->getString('cache.dir', 'cache'); $bImageFallback = $oImageConfig->getString('image.fallback', true); $sDefaultLayout = $oImageConfig->getString('image.layout.default', 'small'); $sDefaultTheme = $oImageConfig->getString('image.theme.default', 'default'); $sLayout = $oGPCConfig->getStringAlnum('layout', $sDefaultLayout); $sTheme = $oGPCConfig->getStringAlnum('theme', $sDefaultTheme); // init cache $oImageCache = new Cache($sCacheDir, $iCacheLifetime, 'png'); $oImageFile = $oImageCache->getFile($_SERVER['QUERY_STRING']); $sImageBase = 'image/layouts'; if (!file_exists("{$sImageBase}/{$sLayout}")) { if (!file_exists("{$sImageBase}/{$sDefaultLayout}")) { throw new RuntimeException('Default layout folder not found'); } $sLayout = $sDefaultLayout; } $sLayoutDir = "{$sImageBase}/{$sLayout}"; include "{$sLayoutDir}/SteamProfileImage.php"; try { // do we have a cached version of the profile image? if (!$oImageFile->isCached()) { $oProfileImage = new SteamProfileImage(); // try to generate the profile image $oProfileImage->createProfile($sXmlUrl, $sLayoutDir, $sTheme); // save it to cache $oProfileImage->toPng($oImageFile->getPath()); // clear stat cache to ensure that the rest of the // script will notice the file modification clearstatcache(); } $this->displayImage($oImageFile); } catch (SteamProfileImageException $e) { // on debug mode, re-throw if ($bDebug) { $ep = $e->getPrevious(); throw $ep == null ? $e : $ep; } // an exception was thrown in SteamProfileImage, // but a themed error image could have been generated try { // try a fallback to the cached image first if ($bImageFallback && $oImageFile->exists()) { $this->displayImage($oImageFile); } else { // try to display the error image $oProfileImage->toPng(); } } catch (Exception $f) { // didn't work, re-throw the source exception throw $e; } } catch (Exception $e) { // on debug mode, re-throw if ($bDebug) { $ep = $e->getPrevious(); throw $ep == null ? $e : $ep; } // an exception was thrown in SteamProfileImage, // but we could try a fallback to the cached image if ($bImageFallback && $oImageFile->exists()) { // redirect to cached image file $this->displayImage($oImageFile); } else { // nothing cached, re-throw exception throw $e; } } } catch (Exception $e) { // quite fatal error, try to render a fail-safe error image if ($bDebug || !GDImage::isAvailable()) { $oHeader = new HTTPHeader(); $oHeader->setResponse('Content-Type', 'text/plain'); echo $bDebug ? "{$e}\n" : $e->getMessage(); } else { $ErrorImage = new ErrorImage($e->getMessage()); $ErrorImage->toPng(); } } }
public function createProfile($sProfileUrl, $sBaseDir, $sCurrentTheme) { parent::__construct(); // load global config $this->oCommonConfig = FileConfig::getInstance('common.cfg'); // load image config $oImageConfig = FileConfig::getInstance('image.cfg'); // set default theme $sDefaultTheme = $oImageConfig->getString('image.theme.default', 'default'); // set theme path $sDefaultThemePath = "{$sBaseDir}/themes/{$sDefaultTheme}"; $sCurrentThemePath = "{$sBaseDir}/themes/{$sCurrentTheme}"; if (!file_exists($sDefaultThemePath)) { throw new RuntimeException('Default theme folder not found'); } if (!file_exists($sCurrentThemePath)) { $sCurrentThemePath = $sDefaultThemePath; } // init cache $sCacheDir = $this->oCommonConfig->getString('cache.dir', 'cache'); $this->oJpgAssetCache = new Cache($sCacheDir, -1, 'jpg'); // the required files for the default theme $this->aThemeFiles = array('background' => 'background.png', 'default_avatar' => 'default_av.jpg', 'warning' => 'warning.png', 'error' => 'error.png', 'frame_avatar_ingame' => 'frame_avatar_ingame.png', 'frame_avatar_offline' => 'frame_avatar_offline.png', 'frame_avatar_online' => 'frame_avatar_online.png', 'frame_avatar_private' => 'frame_avatar_offline.png', 'frame_game' => 'frame_game.png', 'frame_icon' => 'frame_icon.png'); // check for existing theme files foreach ($this->aThemeFiles as $sKey => $sFile) { if (!file_exists("{$sDefaultThemePath}/{$sFile}")) { throw new RuntimeException("Missing default theme file '{$sDefaultThemePath}/{$sFile}'"); } if (file_exists("{$sCurrentThemePath}/{$sFile}")) { $this->aThemeFiles[$sKey] = "{$sCurrentThemePath}/{$sFile}"; } else { $this->aThemeFiles[$sKey] = "{$sDefaultThemePath}/{$sFile}"; } } // set theme config paths $sDefaultThemeConfigFile = "{$sDefaultThemePath}/theme.cfg"; $sCurrentThemeConfigFile = "{$sCurrentThemePath}/theme.cfg"; if (!file_exists($sDefaultThemeConfigFile)) { throw new RuntimeException('Default theme config not found'); } // load default config $this->oThemeConfig = FileConfig::getInstance($sDefaultThemeConfigFile); // merge default config with selected theme config, if existing if ($sCurrentTheme !== $sDefaultTheme && file_exists($sCurrentThemeConfigFile)) { $this->oThemeConfig->merge(FileConfig::getInstance($sCurrentThemeConfigFile)); } // init settings $iStatusTextX = $this->oThemeConfig->getInteger('theme.text.status.x'); $iStatusTextY = $this->oThemeConfig->getInteger('theme.text.status.y'); $iInfoTextX = $this->oThemeConfig->getInteger('theme.text.info.x'); $iInfoTextY = $this->oThemeConfig->getInteger('theme.text.info.y'); $iImageAvatarX = $this->oThemeConfig->getInteger('theme.image.avatar.x'); $iImageAvatarY = $this->oThemeConfig->getInteger('theme.image.avatar.y'); $iImageGameX = $this->oThemeConfig->getInteger('theme.image.game.x'); $iImageGameY = $this->oThemeConfig->getInteger('theme.image.game.y'); $iImageIconsGameX = $this->oThemeConfig->getInteger('theme.image.icon.games.x'); $iImageIconsGameY = $this->oThemeConfig->getInteger('theme.image.icon.games.y'); $iImageIconsGroupX = $this->oThemeConfig->getInteger('theme.image.icon.groups.x'); $iImageIconsGroupY = $this->oThemeConfig->getInteger('theme.image.icon.groups.y'); // load background $this->loadPng($this->aThemeFiles['background']); // enable alpha $this->setSaveAlpha(true); try { // load XML data $xmlData = $this->loadXmlData($sProfileUrl); } catch (Exception $e) { // that didn't work :( $this->drawErrorMessage($e->getMessage()); throw new SteamProfileImageException('Can\'t load XML data', 0, $e); } // check if the server has returned any errors if (count($xmlData->xpath('/response')) != 0) { $this->drawErrorMessage((string) $xmlData->error); throw new SteamProfileImageException('Steam server error: ' . (string) $xmlData->error); } // check for expected XML structure if (count($xmlData->xpath('/profile')) == 0) { $this->drawErrorMessage('Invalid Steam Community data'); throw new SteamProfileImageException('Invalid Steam Community data'); } $sStatusCode = 'offline'; // determinate status if ((string) $xmlData->privacyState != 'public') { $sStatusCode = 'private'; $sStatus = 'This profile is private'; } else { // get the player's status for text and color switch ((string) $xmlData->onlineState) { case 'in-game': $sStatusCode = 'ingame'; $sCurrentGame = $xmlData->inGameInfo == null ? '' : (string) $xmlData->inGameInfo->gameName; $sCurrentGame = wordwrap($sCurrentGame, 27); $sStatus = "In-Game\n{$sCurrentGame}"; break; case 'online': $sStatusCode = 'online'; $sStatus = 'Online'; break; case 'offline': $sStatus = str_replace(': ', ":\n", (string) $xmlData->stateMessage); break; default: throw new RuntimeException('Unable to determinate player status.'); } } // avatar image $sAvatarUrl = (string) $xmlData->avatarFull; $this->drawAvatar($iImageAvatarX, $iImageAvatarY, $sAvatarUrl, $sStatusCode); // status text $sName = (string) $xmlData->steamID; $this->drawStatus($iStatusTextX, $iStatusTextY, $sName, $sStatus, $sStatusCode); if ($sStatusCode == 'private') { // private profiles don't have anything of interest return; } else { if ($sStatusCode == 'ingame') { // game image $sGameImageUrl = (string) $xmlData->inGameInfo->gameLogo; $this->drawGame($iImageGameX, $iImageGameY, $sGameImageUrl); } else { // group icons if ($xmlData->groups->group != null) { $aGroupIcons = array(); foreach ($xmlData->groups->group as $group) { // add primary group icon as the first one if ($group['isPrimary'] == '1') { array_unshift($aGroupIcons, (string) $group->avatarIcon); continue; } // add three random group icons if (count($aGroupIcons) < 3) { array_push($aGroupIcons, (string) $group->avatarIcon); } } // remove last random icon, if the primary group was found later if (count($aGroupIcons) == 4) { array_pop($aGroupIcons); } $this->drawIconCluster($iImageIconsGroupX, $iImageIconsGroupY, $aGroupIcons, "Groups"); } } } // info text $iInfoStringLimit = 25; $sMemberSince = $this->limitString((string) $xmlData->memberSince, $iInfoStringLimit); $sPlayingTime = $this->limitString((string) $xmlData->hoursPlayed2Wk, $iInfoStringLimit); $sSteamRating = $this->limitString((string) $xmlData->steamRating, $iInfoStringLimit); $sLocation = (string) $xmlData->location; $aLocation = explode(',', $sLocation); $sCountry = $this->limitString(trim(array_pop($aLocation)), $iInfoStringLimit); // avoid blank lines if ($sCountry == '') { $sCountry = '---'; } $sInfoTextLeft = "Member since:\nPlaying time:\nSteam rating:\nCountry:"; $sInfoTextRight = "{$sMemberSince}\n{$sPlayingTime} past 2 weeks\n{$sSteamRating}\n{$sCountry}"; $this->drawInfo($iInfoTextX, $iInfoTextY, $sInfoTextLeft, $sInfoTextRight); // game icons if (count($xmlData->xpath('/profile/mostPlayedGames/mostPlayedGame')) != 0) { $aGameIcons = array(); foreach ($xmlData->mostPlayedGames->mostPlayedGame as $mostPlayedGame) { $aGameIcons[] = (string) $mostPlayedGame->gameIcon; } $this->drawIconCluster($iImageIconsGameX, $iImageIconsGameY, $aGameIcons, "Games"); } }