348 lines
26 KiB
PHP
348 lines
26 KiB
PHP
<?php
|
|
/***********************************************************************
|
|
* Script (c) Kubwa (https://kubwa.de)
|
|
*
|
|
* This script was release under BSD license.
|
|
* You are free to use, share or change this code as you wish. This
|
|
* header must be kept intact.
|
|
***********************************************************************/
|
|
|
|
class GridUser
|
|
{
|
|
//Predfined images
|
|
private $ErrorImage = "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQubmV0IDQuMi4xMAAA/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgBAAEAAwEhAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+y6KACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACkoAhmvre3VmlnjjCjJLMBgVjy+PvDUDbZNf01G9GukH9aALVn4r0XUmAtdVs7g+kU6t/I1pJKkn3HVvoc0APooAKKACigAooAKKACigAooAKKACigAooAKKACigAqC8vrfT7d57qaO3hQZaSRgoH4mgDxzxl+05o2jtJb6LA2qzrkeafliB/ma8X8SfHTxd4klctqJsYWGPJsxsUfj1/WgDiLvVLy/kMlzdTTuerSSFj+tVtxPU5oAVZGXoxH0NbGk+NNd0Jw1jqt1b46BZTj8qAPTvCP7Tuu6SyRazDHqtv0MgGyUD6jg/lXvPgj4seHvHkYFjeLFdgZa1n+WQfQd/woA7KigAooAKKACigAooAKKACigAooAKKACigAooA5L4hfErSfh5prT30u+6YfubVOXkP9B7mvkvx/wDFTW/iBeM95OYbMH93aQkhFHv6mgDjaKACigAooAKkt7mWzmWWCRopVOVdDgigD3r4U/tFzWbQaX4mczQZ2pffxL/v+o96+kLW6hvbeOeCRZoZBuV0OQR6g0AS0UAFFABRQAUUAFFABRQAUUAFFABRQAVyPxK+IVl8PPDst7OyvdMNtvb55kb/AAHU0AfGHibxNf8Ai3V59R1Gdpp5GzyeFHYAdhWTQA+GGS4lWOJGkkY4CqMk16t4J/Zz8Q+Jo1ub8ro9o3K+cMyN9F7fjQB63on7MfhTTwpvWudScdQ8mxT+C4P610sPwQ8EwLtXQoSP9pmY/qaAKl/+z/4Ivo2A0n7O5GBJDM4I/DOP0rhPEn7KdpIrPomqSQvj5YrobgTj1H+FAHh/i74e674JuDFqtjJEmcLMvzRt9GFc5QAV7H8DvjNN4UvYtG1aYvpEzbUkfnyGPv8A3aAPq2ORZo1dGDowyGU5BFPoAKKACigAooAKKACigAooAKKACigCvfX0Om2U91cOI4IUMjs3QADJNfEnxR8f3PxB8UT3sjMLSMmO2i7IgPH4mgDj61PDXhu+8Waxb6bp0Xm3EzYHoo7knsKAPrf4X/Bb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";
|
|
private $BlockedImage = "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQubmV0IDQuMi4xMAAA/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgBAAEAAwEhAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+y6KACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACig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/wCIL/wvq1vqWm3DW13C25XXv6gjuD6V9kfCr4qWHxK0jeu221WAf6TaE8j/AGl9VP6dKAO0vFVrOcP9wowb6Yr89rjH2iXHTcf50AfaXwJZm+E3h4v18qQfh5r4/Su9oAKKACigAooAKKACigAryf8AaY1E2fwzlhBwbq5ii+oBLf8AstAHyJRQAUUAFFABRQB97eA4/J8DeHYx0XTrdfyiWue+OujtrXwu1qNF3PCi3C/8AYMf0BoA+KqKACigArR8P+IL/wALavb6lps7W13Ccq46H1BHcH0oA+nl+PWl678LNX1IutrrENv5L2eeTK42qU9Vyc+2DmvlHlm9SaAPvH4e6QdB8D6HYMNrw2kYcf7RGW/UmuhoAKKACigAooAKKACigArwj9rO6KeG9Cts8SXbyf8AfKY/9moA+Y6KACigAooAKKAPvP4e3kV/4E8PTwtujawgA+oQAj8CCK3Li3jureSCZBJFIpR0YcMpGCDQB8L/ABI8FzeA/F19pUit5Ct5ls7fxxEnaff0+oNcxQAUUAFFABXoPwR8CN448cWqyxF9OsSLm6OPlIB+VD/vEfkDQB9pUUAFFABRQAUUAFFABRQAV89/tcZ+x+GPTzLj+UdAHzhRQAUUAFFABRQB9L/sxfEOG40x/Ct5JsuYC0tpuPDoTllHuDk/Q+1e+UAcH8XPhdbfErQhGrLb6pbZa1uCOM90b/ZP6HmvjfXNCv8Aw3qc2n6lbSWl3CcNHIP1HqPcUAUKKACigDa8J+EdT8a6xFp2l27TzOfmbHyRr3Zj2Ar7P+HHgCy+HXhyLTbU+bM3z3FwRgyv3P0HQD0oA6qigAooAKKACigAooAKKACqmoaRY6sEF9ZW94EyUFxEsm3PXGRxQBS/4Q/Qf+gJpv8A4CR/4Uf8IfoP/QE03/wEj/woAP8AhD9B/wCgJpv/AICR/wCFH/CH6D/0BNN/8BI/8KAD/hD9B/6Amm/+Akf+FH/CH6D/ANATTf8AwEj/AMKAD/hD9B/6Amm/+Akf+FH/AAh+g/8AQE03/wABI/8ACgCS38L6NaTJNBpFjDMhyskdsisp9QQOK1KACuZ8bfDvQ/iBZiDVrQPIgPlXMfyyx/RvT2PFAHz94q/Zb17TppH0S6h1W26qkh8qUexzwfrn8BXAX3wk8Z6fIUl8Nak5H/PCAyj80zQBJp/we8aanIFi8N38ee9xF5I/8fxXovhH9ljU7yZJfEN9HYWw5a3tT5kre27ov15oA+gfCfgvR/BOmiy0izS2j6u/V5D6s3UmtygAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooA//9k=";
|
|
|
|
private $Uuid;
|
|
private $HomeUri;
|
|
private $FirstName;
|
|
private $LastName;
|
|
private $HomeGrid;
|
|
private $BirthUnix;
|
|
private $ServiceUris;
|
|
private $ProfileImageUuid;
|
|
private $ProfileImageBlob;
|
|
private $ProfileAbout;
|
|
private $LastRequest;
|
|
private $LastUpdate;
|
|
private $UserTitle;
|
|
private $HomeRegionUuid;
|
|
private $HomeRegionName;
|
|
private $HomeRegionUri;
|
|
private $HomeRegionPos;
|
|
private $OSHeaders = array();
|
|
|
|
private $MySql;
|
|
|
|
public function __construct($Uuid, $HomeUri)
|
|
{
|
|
if (empty($Uuid) || empty($HomeUri))
|
|
{return;}
|
|
$this->Uuid = $Uuid;
|
|
$this->HomeUri = $HomeUri;
|
|
$this->MySql = new MySql($GLOBALS["CONFIG"]["mysql"]["user"], $GLOBALS["CONFIG"]["mysql"]["pass"], $GLOBALS["CONFIG"]["mysql"]["db"], $GLOBALS["CONFIG"]["mysql"]["server"]);
|
|
|
|
//Process OpenSim header fields
|
|
foreach ($_SERVER as $k => $v)
|
|
{
|
|
if (substr($k, 5, 13) == "X_SECONDLIFE_")
|
|
{$this->OSHeaders[substr($k, 18)] = $v;}
|
|
}
|
|
|
|
//Remove cached profile images after 60 days but process this cleanup every 5 days only
|
|
if ($this->HelpValue("IMAGE.LAST.CLEANTIME") + 86400 * 5 < time())
|
|
{
|
|
//Delete the cached metadata
|
|
$this->MySql->query("DELETE FROM userdata WHERE lastreq < {0}", array(time() - 86400 * 60));
|
|
}
|
|
|
|
//Do the magic
|
|
$this->LastRequest = time();
|
|
if ($this->ExistsInCache()) //User exists in cache?
|
|
{
|
|
$this->GetFromCache(); //Load everything from cache
|
|
if ($this->LastUpdate + 3600 * 4 < time())
|
|
{
|
|
$this->GetFromInternet(); //Get all the data from the users grid
|
|
if ($this->HomeGrid == "Unknown" &&
|
|
$this->FirstName == "Unknown" &&
|
|
$this->LastName == "User")
|
|
{$this->GetFromCache();}
|
|
}
|
|
}
|
|
else
|
|
{$this->GetFromInternet();}
|
|
}
|
|
|
|
//The user might be unwanted in our system. See mysql table "bans"
|
|
private function IsUnwanted($CheckList)
|
|
{
|
|
$AllBans = $this->MySql->query("SELECT * FROM bans");
|
|
while ($Ban = $AllBans->fetch())
|
|
{
|
|
for ($i = 0; $i < count($CheckList); ++$i)
|
|
{
|
|
if (stripos($CheckList[$i], $Ban["banvalue"]) !== false)
|
|
{
|
|
$this->MySql->query("UPDATE bans SET nums = {1}, lastseen = {2} WHERE banvalue = {0} LIMIT 1", array($Ban["banvalue"], $Ban["nums"] + 1, $this->OSHeaders["OBJECT_KEY"]));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private function ExistsInCache()
|
|
{
|
|
$InCache = $this->MySql->query("SELECT * FROM userdata WHERE id = {0} LIMIT 1", array($this->Uuid))->fetch();
|
|
return !empty($InCache["id"]);
|
|
}
|
|
|
|
private function GetFromCache()
|
|
{
|
|
$Cache = $this->MySql->query("SELECT * FROM userdata WHERE id = {0} LIMIT 1", array($this->Uuid))->fetch();
|
|
$this->FromJson($Cache["userdata"]);
|
|
$this->LastUpdate = $Cache["lastreq"];
|
|
$this->ProfileImageBlob = $Cache["image"];
|
|
}
|
|
|
|
//Magic function
|
|
private function GetFromInternet()
|
|
{
|
|
//First of all, we need to find out what uris the gridservices are having for this user (might be different for each user)
|
|
$this->ServiceUris = $this->RequestUserSeviceUris();
|
|
if ($this->ServiceUris !== false)
|
|
{
|
|
//IF this was successfull, we are requesting all required user info from the services
|
|
$UserInfo = $this->RequestUserInfo();
|
|
if ($UserInfo !== false)
|
|
{
|
|
$this->FirstName = $UserInfo["user_firstname"];
|
|
$this->LastName = $UserInfo["user_lastname"];
|
|
|
|
/* Ungewollte User in der Auflistung ausschließen */
|
|
if ($this->IsUnwanted(array($this->Uuid, $this->HomeUri, $this->FirstName." ".$this->LastName)))
|
|
{
|
|
$this->BirthUnix = 0;
|
|
$this->UserTitle = "Blacklisted";
|
|
$this->HomeGrid = "Somewhere";
|
|
$this->ProfileImageUuid = "00000000-0000-0000-0000-000000000001";
|
|
$this->ProfileAbout = "";
|
|
$this->HomeRegionUuid = "00000000-0000-0000-0000-000000000000";
|
|
$this->HomeRegionName = "";
|
|
$this->HomeRegionUri = "";
|
|
$this->HomeRegionPos = "";
|
|
$this->HomeRegionUuid = "00000000-0000-0000-0000-000000000000";
|
|
$this->HomeRegionName = "Unknown";
|
|
$this->HomeRegionUri = "";
|
|
$this->HomeRegionPos = "<0, 0, 0>";
|
|
$this->ProfileImageBlob = base64_decode($this->BlockedImage);
|
|
$this->AddToCache();
|
|
return;
|
|
}
|
|
|
|
//We can do more magic: Request the entire user profile, its image and all other cool stuff
|
|
$ProfileData = $this->RequestUserProfile();
|
|
$GridInfo = $this->RequestHomeGrid();
|
|
$this->BirthUnix = $UserInfo["user_created"];
|
|
$this->UserTitle = $UserInfo["user_title"];
|
|
if (empty($this->UserTitle))
|
|
{$this->UserTitle = "Unknown";}
|
|
$this->HomeGrid = $GridInfo["gridname"];
|
|
$this->ProfileImageUuid = $ProfileData["result"]["ImageId"];
|
|
$this->ProfileAbout = $ProfileData["result"]["AboutText"];
|
|
$HomeRegion = $this->RequestHomeRegion();
|
|
$this->HomeRegionUuid = $HomeRegion["uuid"];
|
|
$this->HomeRegionName = $HomeRegion["region_name"];
|
|
$this->HomeRegionUri = $HomeRegion["server_uri"];
|
|
$this->HomeRegionPos = $HomeRegion["position"];
|
|
$this->ProfileImageBlob = $this->RequestUserImageBlob();
|
|
$this->AddToCache();
|
|
return;
|
|
}
|
|
}
|
|
$this->FirstName = "Unknown";
|
|
$this->LastName = "User";
|
|
$this->BirthUnix = 0;
|
|
$this->UserTitle = "Wrong configured grid";
|
|
$this->HomeGrid = "Unknown";
|
|
$this->ProfileImageUuid = "00000000-0000-0000-0000-000000000000";
|
|
$this->ProfileAbout = "";
|
|
$this->HomeRegionUuid = "00000000-0000-0000-0000-000000000000";
|
|
$this->HomeRegionName = "";
|
|
$this->HomeRegionUri = "";
|
|
$this->HomeRegionPos = "";
|
|
$this->HomeRegionUuid = "00000000-0000-0000-0000-000000000000";
|
|
$this->HomeRegionName = "Unknown";
|
|
$this->HomeRegionUri = "";
|
|
$this->HomeRegionPos = "<0, 0, 0>";
|
|
$this->ProfileImageBlob = base64_decode($this->ErrorImage);
|
|
}
|
|
|
|
private function RequestUserSeviceUris()
|
|
{
|
|
$Res = HttpRequest($this->HomeUri, "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodCall><methodName>get_server_urls</methodName><params><param><value><struct><member><name>userID</name><value><string>".$this->Uuid."</string></value></member></struct></value></param></params></methodCall>", "", 3, "application/xml");
|
|
if (strlen($Res) < 200)
|
|
{return false;}
|
|
$ServiceURLs = ParseXml($Res);
|
|
$ServiceURLList = array();
|
|
for ($i = 0; $i < count($ServiceURLs["params"]["param"]["value"]["struct"]["member"]); ++$i)
|
|
{
|
|
$ServiceURL = $ServiceURLs["params"]["param"]["value"]["struct"]["member"][$i];
|
|
$ServiceURLList[$ServiceURL["name"]] = $ServiceURL["value"]["string"];
|
|
}
|
|
if (count($ServiceURLList) < 7)
|
|
{return false;}
|
|
return $ServiceURLList;
|
|
}
|
|
|
|
private function RequestUserProfile()
|
|
{return json_decode(HttpRequest($this->ServiceUris["SRV_ProfileServerURI"], "{\"jsonrpc\":\"2.0\",\"id\":\"00000000-0000-0000-0000-000000000000\",\"method\":\"avatar_properties_request\",\"params\":{\"UserId\":\"".$this->Uuid."\"}}", "", 3, "application/json-rpc"), true);}
|
|
|
|
private function RequestUserInfo()
|
|
{
|
|
$UserInfos = ParseXml(HttpRequest($this->HomeUri, "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodCall><methodName>get_user_info</methodName><params><param><value><struct><member><name>userID</name><value><string>".$this->Uuid."</string></value></member></struct></value></param></params></methodCall>", "", 3, "application/xml"));
|
|
$UserInfosList = array();
|
|
for ($i = 0; $i < count($UserInfos["params"]["param"]["value"]["struct"]["member"]); ++$i)
|
|
{
|
|
$UserInfo = $UserInfos["params"]["param"]["value"]["struct"]["member"][$i];
|
|
$UserInfosList[$UserInfo["name"]] = $UserInfo["value"]["string"]?$UserInfo["value"]["string"]:$UserInfo["value"]["i4"];
|
|
}
|
|
if (count($UserInfosList) < 6)
|
|
{return false;}
|
|
return $UserInfosList;
|
|
}
|
|
|
|
private function RequestHomeGrid()
|
|
{return ParseXml(HttpRequest($this->HomeUri.((substr($this->HomeUri, -1, 1) == "/")?"":"/")."get_grid_info", "", "", 3), true);}
|
|
|
|
private function RequestHomeRegion()
|
|
{
|
|
$HomeInfos = ParseXml(HttpRequest($this->HomeUri, "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodCall><methodName>get_home_region</methodName><params><param><value><struct><member><name>userID</name><value><string>".$this->Uuid."</string></value></member></struct></value></param></params></methodCall>", "", 3, "application/xml"));
|
|
$HomeInfosList = array();
|
|
for ($i = 0; $i < count($HomeInfos["params"]["param"]["value"]["struct"]["member"]); ++$i)
|
|
{
|
|
$HomeInfo = $HomeInfos["params"]["param"]["value"]["struct"]["member"][$i];
|
|
$HomeInfosList[$HomeInfo["name"]] = $HomeInfo["value"]["string"];
|
|
}
|
|
if (count($HomeInfosList) < 13)
|
|
{return false;}
|
|
return $HomeInfosList;
|
|
}
|
|
|
|
private function RequestUserImageBlob()
|
|
{
|
|
if (!empty($this->ProfileImageUuid) && $this->ProfileImageUuid != "00000000-0000-0000-0000-000000000000")
|
|
{
|
|
$AssetURI = $this->ServiceUris["SRV_AssetServerURI"].((substr($this->ServiceUris["SRV_AssetServerURI"], -1, 1) == "/")?"":"/")."assets/".$this->ProfileImageUuid."/data";
|
|
$AssetImageData = HttpRequest($AssetURI, "", "", 3);
|
|
$TempName = $this->MySql->id(8);
|
|
file_put_contents("binary_helper/".$TempName.".jp2", $AssetImageData);
|
|
if (extension_loaded("imagick"))
|
|
{
|
|
$Image = new Imagick(realpath("./binary_helper/".$TempName.".jp2"));
|
|
$Image->setImageFormat("jpg");
|
|
$Image->writeImage(realpath("./binary_helper/".$TempName.".jpg"));
|
|
}
|
|
else
|
|
{shell_exec("binary_helper".DIRECTORY_SEPARATOR."magick convert binary_helper/".$TempName.".jp2 binary_helper/".$TempName.".jpg");}
|
|
$AssetImageData = file_get_contents("binary_helper/".$TempName.".jpg");
|
|
@unlink("binary_helper/".$TempName.".jp2");
|
|
@unlink("binary_helper/".$TempName.".jpg");
|
|
if (strlen($AssetImageData) < 512)
|
|
{return base64_decode($this->ErrorImage);}
|
|
$SrcImg = imagecreatefromstring($AssetImageData);
|
|
$DstImg = ImageCreateTrueColor(200, 200);
|
|
imagecopyresampled($DstImg, $SrcImg, 0, 0, 0, 0, 200, 200, imageSX($SrcImg), imageSY($SrcImg));
|
|
ob_start();
|
|
imagejpeg($DstImg, null, 90);
|
|
$Res = ob_get_contents();
|
|
ob_end_clean();
|
|
}
|
|
else
|
|
{$Res = base64_decode($this->ErrorImage);}
|
|
return $Res;
|
|
}
|
|
|
|
private function AddToCache()
|
|
{$this->MySql->query("REPLACE INTO userdata(id, userdata, lastreq, image)VALUES({0}, {1}, {2}, {3})", array($this->Uuid, $this->ToJson(), $this->LastRequest, $this->ProfileImageBlob));}
|
|
|
|
public function ToArray($ExportImage = true)
|
|
{
|
|
if (!empty($this->FirstName))
|
|
{
|
|
$Export = array("uuid" => $this->Uuid,
|
|
"firstname" => $this->FirstName,
|
|
"lastname" => $this->LastName,
|
|
"homegrid" => $this->HomeGrid,
|
|
"birthunix" => $this->BirthUnix,
|
|
"profileimage" => $this->ProfileImageUuid,
|
|
"about" => $this->ProfileAbout,
|
|
"title" => $this->UserTitle,
|
|
"home" => $this->HomeRegionName,
|
|
"homelocation" => $this->HomeRegionPos,
|
|
"homeuri" => $this->HomeRegionUri);
|
|
if ($ExportImage)
|
|
{$Export["img"] = $this->ProfileImageBlob;}
|
|
return $Export;
|
|
}
|
|
else
|
|
{return false;}
|
|
}
|
|
|
|
public function ToJson()
|
|
{
|
|
if (!empty($this->FirstName))
|
|
{return json_encode($this->ToArray(false));}
|
|
else
|
|
{return false;}
|
|
}
|
|
|
|
public function FromJson($Json)
|
|
{
|
|
$Json = json_decode($Json, true);
|
|
$this->Uuid = $Json["uuid"];
|
|
$this->FirstName = $Json["firstname"];
|
|
$this->LastName = $Json["lastname"];
|
|
$this->HomeGrid = $Json["homegrid"];
|
|
$this->BirthUnix = $Json["birthunix"];
|
|
$this->ProfileImageUuid = $Json["profileimage"];
|
|
$this->ProfileAbout = $Json["about"];
|
|
$this->UserTitle = $Json["title"];
|
|
$this->HomeRegionName = $Json["home"];
|
|
$this->HomeRegionPos = $Json["homelocation"];
|
|
$this->HomeRegionUri = $Json["homeuri"];
|
|
}
|
|
|
|
public function ToLsl($Glue)
|
|
{
|
|
if (!empty($this->FirstName))
|
|
{
|
|
return implode($Glue, array($this->Uuid,
|
|
$this->FirstName,
|
|
$this->LastName,
|
|
($this->HomeGrid==null)?"Unknown":$this->HomeGrid,
|
|
($this->BirthUnix==null)?"0":$this->BirthUnix,
|
|
($this->ProfileImageUuid==null)?"00000000-0000-0000-0000-000000000000":$this->ProfileImageUuid,
|
|
base64_encode($this->ProfileAbout),
|
|
($this->UserTitle==null)?"":(is_array($this->UserTitle)?"":$this->UserTitle),
|
|
($this->HomeRegionName==null)?"":$this->HomeRegionName,
|
|
($this->HomeRegionPos==null)?"<0, 0, 0>":$this->HomeRegionPos,
|
|
($this->HomeRegionUri==null)?"":$this->HomeRegionUri));
|
|
}
|
|
else
|
|
{return false;}
|
|
}
|
|
|
|
private function HelpValue($Name, $Value = null)
|
|
{
|
|
if ($Value === null)
|
|
{
|
|
$Res = $this->MySql->query("SELECT * FROM helpvals WHERE name = {0} LIMIT 1", array($Name))->fetch();
|
|
return $Res["val"];
|
|
}
|
|
else
|
|
{$this->MySql->query("REPLACE INTO helpvals (name, val)VALUES({0}, {1})", array($Name, $Value));}
|
|
}
|
|
}
|
|
?>
|