SRL Archive - OSR Advanced Scripting Tutorials

How to make live stats images for your scripts


xtrapsp

2013-01-01 17:55:18

Original thread:

http://villavu.com/forum/showthread.php?t=83538

Recently a few members of Villavu have been trying to re-create signature which update to their server. Some have been having issues.

Myself, Kyle and [J]ustin have done this to test it and found a few twists and turns in the tutorials which can throw people off, so this is hopefully a full fix for that tutorial.

What will you learn?

You will be learning a little PHP (Enough to progress you into further projects I think). Pascal and some logical thinking :)


What will I need?


  • A Webhost with MYSQL Databasing
  • An Image

Ok, so first things first we need to create a website, Putonajonny suggested:


Steps from here:

  • Sign up using the registration, You don't want to pay so use a subdomain
  • Confirm your email
  • Go to the control panel of your selected sub domain, scroll or press CTRL + F to find Software / Services and click on the MYSQL icon (Should be a dolphin or something)
  • Create a new database and a user, SAVE THESE DETAILS. YOU WILL NEED THEM.
  • Now that you have a database and user, you need to manage it. So click on PHPMyAdmin and enter your database

So from this point we are inside the Database, this can get a little confusing so we will take baby steps!

The best way I can explain these databases is to imagine them like Excel spread sheets. The database is the document, the tables are the worksheets and all the parts inside is the data!

Firstly we will need to create a new database. If you are using 000webhost you will have a different PHPMyAdmin to most main hosts but have no fear! It's pretty much the same.

So following Putona's tutorial we will name the Table to be "Table1". (Case sensitive).
From here we need to create fields! So for now add 3-4 depending on how many variables you are using.
Here is an example of how the table details should look (I used Excel to explain it).


Putona used this explanation which is fairly good describing all of the options:


Your fields should now look like this:


So far so good? I hope so!

With my technique it doesn't matter what you use My Scripts name as, it's only for personal use so you can read it easier.

Eventually with more scripts it will do this:


What ID auto increment means is that each time you submit a new script name it will automatically add a new ID :spot:

Connecting our database up.

Ok, so now we need to create a PHP file! :stirthepot:
To do this, create a new file (Preferably a text file) and name it

Commit.php (or anything you want.php) but make sure to save it as a PHP file and not a text file ;)

Inside here you want to put your Database information!

[PHP]<?PHP

$user_name = "usename"; //Username for the account you created earlier
$pass_word = "password"; //Password for the account you created earlier
$database = "database"; //The name of the database you created earlier
$server = "MySQLServer"; //With 000webhost this can be found by going to your control panel then clicking MySQL
[/PHP]

We also need to actually connect the database…
[PHP] $db_handle = mysql_connect($server, $user_name, $pass_word); or die(mysql_error());
$db_found = mysql_select_db($database, $db_handle); or die(mysql_error());[/PHP]

What this does is check the database is connecting and if not it will tell you the error :)

Now we are going to check if the database is found and if it is then do the following!

[PHP]if ($db_found) {
$SQL = "SELECT * FROM `Table1` WHERE `ID` = 1";
$result = mysql_query($SQL);
if($result){
while ($db_field = mysql_fetch_assoc($result)){

$time = $db_field['Time'];
$tokens = $db_field['XP'];
}[/PHP]

Now there are two parts in this, the table and ID + the Variables.

$SQL = "SELECT * FROM `Table1` WHERE `ID` =1"; basically checks in Table1 and finds all of the information inside the row of ID1.

[PHP] $time = $db_field['Time'];
$tokens = $db_field['XP'];[/PHP]

Another image which will hopefully explain it!

[PHP]
header("Content-type: image/png");
putenv("GDFONTPATH=".realpath("."));

$img = imagecreatefrompng("signature.png");

$color["yellow"] = imagecolorallocate( $img, 255, 255, 0 );
$color["white"] = imagecolorallocate( $img, 255, 255, 255 );
$color["green"] = imagecolorallocate( $img, 0, 255, 0 );
$color["orange"] = imagecolorallocate( $img, 254, 179, 0 );
$color["purple"] = imagecolorallocate( $img, 128, 0, 128 );
$color["dblue"] = imagecolorallocate( $img, 37, 84, 199 );


[/PHP]
if you want to make it something other than a PNG, read this:
http://php.net/manual/en/function.header.php

$img = is the location of the background on your root.
putenv("GDFONTPATH=".realpath("."));
basically means the font should be in the root of the site :)


This section is a little more creative!

Now to change the text on the signature!
[PHP]
//size x y
imagettftextshadow($img, 20, 0, 25, 30, $color["dblue"], "font.ttf", "Script name");
imagettftextshadow($img, 12, 0, 10, 56, $color["orange"], "font.ttf", "XP Gained: ");
imagettftextshadow($img, 12, 0, 90, 56, $color["purple"], "font.ttf", number_format($XP));
imagettftextshadow($img, 12, 0, 10, 76, $color["orange"], "font.ttf", "Total Time: ");
imagettftextshadow($img, 12, 0, 120, 76, $color["purple"], "font.ttf", formatMilliseconds($time * 1000));

imagepng($img);
imagedestroy($img);
}[/PHP]

This is pretty much it, you have defined your color, the text and what its printing..

E.g the $ stuff ;)

SIMBA part:

Add this in the mainloop:

AddOnTerminate('SendData');//To make it send the data

Function SendData : Boolean;
Var
i : integer;
begin

i := InitializeHTTPClientWrap(False); //this creates a client

AddPostVariable(i, 'time', IntToStr(GetTimeRunning / 1000));//This adds our info to the client
AddPostVariable(i, 'runs', IntToStr(XPGained));

Result := Pos('true', Lowercase(PostHTTPPageEx(i, 'http://mywebsite.net/MyPage.php'))) <> 0;//Then this posts it

FreeHTTPClient(i);//Remember to free it

end;


Full PHP bit:

[PHP]

<?PHP //Milliseconds Function

function formatMilliseconds($milliseconds) {
$seconds = floor($milliseconds / 1000);
$minutes = floor($seconds / 60);
$hours = floor($minutes / 60);
$days = floor($hours / 24);
$milliseconds = $milliseconds % 1000;
$seconds = $seconds % 60;
$minutes = $minutes % 60;
$hours = $hours % 24;

if($days == 0){
$format = '%uhours, %02uminutes and %02u seconds';
$time = sprintf($format, $hours, $minutes, $seconds);
return rtrim($time, '0');
}else{
$format = 'Úys, %uhours, %02uminutes';
$time = sprintf($format, $days, $hours, $minutes, $seconds);
return rtrim($time, '0');
}

}

//imagettftext function
function imagettftextshadow($image, $size, $angle, $x, $y, $color, $fontfile, $text) {
imagettftext($image, $size, $angle, $x + 1, $y + 1, imagecolorallocate($image, 0, 0, 0), $fontfile, $text);
imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $text);
}
//Database

$user_name = "DBUsername"; //Username for the account you created earlier
$pass_word = "Password"; //Password for the account you created earlier
$database = "DBname"; //The name of the database you created earlier
$server = "localhost"; //With 000webhost this can be found by going to your control panel then clicking MySQL

$db_handle = mysql_connect($server, $user_name, $pass_word) or die(mysql_error());
$db_found = mysql_select_db($database, $db_handle) or die(mysql_error());

//Script
if ($db_found) {

$SQL = "SELECT * FROM `table1` WHERE `ID` = 1";
$result = mysql_query($SQL);
if($result){
while ($db_field = mysql_fetch_assoc($result)){

$time = $db_field['Time'];
$xp = $db_field['XP'];
}

header("Content-type: image/png");
putenv("GDFONTPATH=".realpath("."));

$img = imagecreatefrompng("sig.png");

$color["yellow"] = imagecolorallocate( $img, 255, 255, 0 );
$color["white"] = imagecolorallocate( $img, 255, 255, 255 );
$color["green"] = imagecolorallocate( $img, 0, 255, 0 );
$color["orange"] = imagecolorallocate( $img, 254, 179, 0 );
$color["purple"] = imagecolorallocate( $img, 128, 0, 128 );
$color["dblue"] = imagecolorallocate( $img, 37, 84, 199 );

imagettftextshadow($img, 12, 0, 10, 50, $color["orange"], "sans.ttf", "XP Gained: ");
imagettftextshadow($img, 12, 0, 90, 50, $color["purple"], "sans.ttf", number_format($xp));
imagettftextshadow($img, 12, 0, 10, 70, $color["white"], "sans.ttf", "Time Run: ");
imagettftextshadow($img, 12, 0, 90, 70, $color["purple"], "sans.ttf", formatMilliseconds($time * 1000));

imagepng($img);
imagedestroy($img);
}else
print "Not working";

}
else
print "DB not Found, please report this";


?> [/PHP]

SQL Injection:


[J]ustin reminded me of this ^^

SQL Injection can be a pain in the arse, they can find your details, put stuff onto your website etc. So you need protection!
This is the function:
[PHP]
mysql_real_escape_string();
[/PHP]

This is it in use:
[PHP]
mysql_real_escape_string($SQL);
[/PHP]

Tutorial:

http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php

Gucci

2013-01-01 19:44:54

nice tut man

Ian

2013-01-02 04:56:05

I may want to try this, could it work for avatars too?

Justin

2013-01-02 04:58:18

Wont work for avatars.

You might want to add some sql injection protection there Brad

xtrapsp

2013-01-02 04:58:26

From: BMWxi
I may want to try this, could it work for avatars too?


I don't believe so. It's worth a try :D

eska

2013-01-02 05:07:16

Disregard this post.

I didn't think before posting -.-

Justin

2013-01-02 05:08:18

From: xtrapsp
I don't believe so. It's worth a try :D


Don't forget to add that you will need to edit the script to calculate the 'XPGained' variable :)

litoris

2013-01-02 05:57:59

Nice tut, too bad stats has been down since March :(

Justin

2013-01-02 06:07:31

From: litoris
Nice tut, too bad stats has been down since March :(


This doesn't use SRL Stats.

xtrapsp

2013-01-02 06:07:58

From: litoris
Nice tut, too bad stats has been down since March :(


It doesn't use SRL stats, it uses your own ^^

Justin

2013-01-02 06:11:59

From: xtrapsp
It doesn't use SRL stats, it uses your own ^^


Feel the power of being ninja'd :D

Shatterhand

2013-01-03 12:01:18

There is a mistype at the part "Full PHP bit:".
[PHP]$format = 'Úys, %uhours, %02uminutes';[/PHP]

J J

2013-01-03 12:08:39

Might want to add error reporting
[PHP]error_reporting(-1);[/PHP]

Got everything working now thanks to Shatterhands tutorial and help on Skype. Hope this will work for anyone without help.

xtrapsp

2013-01-04 21:32:47

From: Shatterhand
There is a mistype at the part "Full PHP bit:".
[PHP]$format = 'Úys, %uhours, %02uminutes';[/PHP]


I think thats a format issue with the forum, it keeps changing it. I think the PHP tag isn't utf-8 or something ^^

J J

2013-01-06 08:48:21

Can you add information about adding caching to your images? Because my database is offline now because I put the image in my signature :stirthepot:

I think something like this (http://dtbaker.com.au/random-bits/how-to-cache-images-generated-by-php.html) will work? I'm not sure about PHP-related stuff and I don't want to overflow the site again. Thanks in advance :)

Shatterhand

2013-01-15 14:28:35

From: J J
Can you add information about adding caching to your images? Because my database is offline now because I put the image in my signature :stirthepot:

I think something like this (http://dtbaker.com.au/random-bits/how-to-cache-images-generated-by-php.html) will work? I'm not sure about PHP-related stuff and I don't want to overflow the site again. Thanks in advance :)

Didnt know about caching, thanks for the tip!
EDIT: Its not working nvm.
EDIT2: Googled a lot, here is what I found:
source ->
[PHP]function getRequestHeaders()
{
if (function_exists("apache_request_headers"))
{
if($headers = apache_request_headers())
{
return $headers;
}
}
$headers = array();
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
$headers['If-Modified-Since'] = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
}
return $headers;
}

// Return the requested graphic file to the browser
// or a 304 code to use the cached browser copy
function displayGraphicFile ($graphicFileName, $fileType='jpeg')
{
$fileModTime = filemtime($graphicFileName);
// Getting headers sent by the client.
$headers = getRequestHeaders();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) &&
(strtotime($headers['If-Modified-Since']) == $fileModTime))
{
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).
' GMT', true, 304);
}
else
{
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).
' GMT', true, 200);
header('Content-type: image/'.$fileType);
header('Content-transfer-encoding: binary');
//header('Content-length: '.filesize($graphicFileName));
//readfile($graphicFileName);
}
}
displayGraphicFile("image.png");[/PHP]
These functions will change the caching setting of the header.
Remove the line "header("Content-type: image/png"); " and put the code before it.
It works. :D
EDIT3: Just realized that texts dont get updated on the cached picture. :(

Olly

2013-01-15 23:43:15

Kyles your man for this ^ :p

xtrapsp

2013-01-16 05:05:03

From: Shatterhand
Didnt know about caching, thanks for the tip!
EDIT: Its not working nvm.
EDIT2: Googled a lot, here is what I found:
source ->
[PHP]function getRequestHeaders()
{
if (function_exists("apache_request_headers"))
{
if($headers = apache_request_headers())
{
return $headers;
}
}
$headers = array();
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
$headers['If-Modified-Since'] = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
}
return $headers;
}

// Return the requested graphic file to the browser
// or a 304 code to use the cached browser copy
function displayGraphicFile ($graphicFileName, $fileType='jpeg')
{
$fileModTime = filemtime($graphicFileName);
// Getting headers sent by the client.
$headers = getRequestHeaders();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) &&
(strtotime($headers['If-Modified-Since']) == $fileModTime))
{
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).
' GMT', true, 304);
}
else
{
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).
' GMT', true, 200);
header('Content-type: image/'.$fileType);
header('Content-transfer-encoding: binary');
//header('Content-length: '.filesize($graphicFileName));
//readfile($graphicFileName);
}
}
displayGraphicFile("image.png");[/PHP]
These functions will change the caching setting of the header.
Remove the line "header("Content-type: image/png"); " and put the code before it.
It works. :D
EDIT3: Just realized that texts dont get updated on the cached picture. :(


Try refreshing with CTRL + F5?

Shatterhand

2013-01-16 05:09:10

From: xtrapsp
Try refreshing with CTRL + F5?

Ye it works, but a normal user would not do CTRL + F5. This is not the best solution. :D

xtrapsp

2013-01-16 05:29:54

From: Shatterhand
Ye it works, but a normal user would not do CTRL + F5. This is not the best solution. :D


It simply means your not having your cache cleared regularly, I'l look into it when I have time ^^

Shatterhand

2013-01-16 05:40:39

From: xtrapsp
It simply means your not having your cache cleared regularly, I'l look into it when I have time ^^

Im not sure what you mean.
JJ and me wants our images (lot of Kb) not to load every time we load the page.
Normal images get cached by browser automatically, but .php images dont.
So we want our .php images to have cached, but ONLY the image, the text on should be up-to-date.

Here is an example:
not cached image, up-to-date text: ->
cahced image, not up-to-date text: ->

xtrapsp

2013-01-16 05:59:12

From: Shatterhand
Im not sure what you mean.
JJ and me wants our images (lot of Kb) not to load every time we load the page.
Normal images get cached by browser automatically, but .php images dont.
So we want our .php images to have cached, but ONLY the image, the text on should be up-to-date.

Here is an example:
not cached image, up-to-date text: ->
cahced image, not up-to-date text: ->


Hmm, the only thing that I question with that is that it's saving the text on the image isn't it? so surely it's a matter of detecting if the time is different from when u last cached it, deleting and reuploading?

@ Kyle

Shatterhand

2013-01-16 06:44:09

From: xtrapsp
Hmm, the only thing that I question with that is that it's saving the text on the image isn't it? so surely it's a matter of detecting if the time is different from when u last cached it, deleting and reuploading?
@ Kyle

What if the text changes every minute or so? It would force to load the image every time you load the page. We should separate the image and text somehow, but not sure how. This caching applies to the whole header.

xtrapsp

2013-01-16 07:42:19

From: Shatterhand
What if the text changes every minute or so? It would force to load the image every time you load the page. We should separate the image and text somehow, but not sure how. This caching applies to the whole header.


If we seperated the image to the text it wouldn't be an image format then surely?

Kyle Undefined

2013-01-16 10:11:44

You cannot "split" the text from the image. That's why you're printing out the text on top of the image, to make it a PHP image. It's either you cache everything, or you don't cache at all. Because even if the text changes, you'll have to create a whole new image, which defeats the purpose of caching.

I'd do an hour cache, that's the normal for these type of things.

xtrapsp

2013-01-16 10:34:40

From: Kyle Undefined
You cannot "split" the text from the image. That's why you're printing out the text on top of the image, to make it a PHP image. It's either you cache everything, or you don't cache at all. Because even if the text changes, you'll have to create a whole new image, which defeats the purpose of caching.

I'd do an hour cache, that's the normal for these type of things.


Thanks for confirming Kyle.

StickToTheScript

2013-03-30 17:02:41

Very useful in the future my friend! Good job.