50% OFF!!!

Tuesday, December 6, 2022

MySQL: SUBSTRING_INDEX vs MID+INSTR (which is better)

Hello there.


SUBSTRING_INDEX vs MID+INSTR

I wanted to pull from domain name out of an email (or just remove the username part of an email).

There are two simple functions (and even more...) to do it:

1] SUBSTRING_INDEX('testuser@domain.com','@',-1)

use built in function SUBSTRING_INDEX to explode the string by '@' and get the last element.

 

2] MID('testuser@domain.com', INSTR('testuser@domain.com','@')+1, 999)

find '@' position using INSTR and get all string from that position until the end of string by MID function. 

 

But which one of them have better performance?

Using BENCHMARK function for Measuring the Speed of Expressions and Functions.

1] SELECT  BENCHMARK(100000000, SUBSTRING_INDEX('testuser@domain.com','@',-1))

/* Affected rows: 0  Found rows: 1  Warnings: 0  Duration for 1 query: 12.625 sec. */


2] SELECT  BENCHMARK(100000000, MID('testuser@domain.com', INSTR('testuser@domain.com','@')+1, 999))

/* Affected rows: 0  Found rows: 1  Warnings: 0  Duration for 1 query: 19.157 sec. */


BENCHMARK function results may vary between different devices, but on the same device can give quite clear results.

 

Summary:

SUBSTRING_INDEX won and have better results than MID + INSTR


Monday, July 11, 2022

JQuery serialize on form is EMPTY (ajax/post/get)

 Hi All,


I had several times a problem, that the collected data by jQuery API's serialize() or serializeArray() was empty, although the inputs were not empty.

Follow these checkups to by pass the problem.

1] when the input don't name attribute the result will be empty.

<form id="form1">
        <input type="text" value="test value">
        <button>submit</button>
</form>
//$('#form1').serialize()  ==> "" (empty)
 
 
SOLUTION:
<form id="form1">
        <input type="text" value="test value" value="ANYNAME">
        <button>submit</button>
</form>
//$('#form1').serialize()  ==> "ANYNAME=test+value" 
 

Sunday, December 12, 2021

using FontAwesome in PHP FPDF

Hi All,

I found it impossible to use FontAwesome 4.7.0 Free version, inside FPDF PHP engine.

When trying to upload the FontAwesome.4.7.full.otf into FPDF's Font File Generation, I'm getting an error:

Error: OpenType fonts based on PostScript outlines are not supported


So my solution, 

to re-build the FontAwesome font 4.7 free version (under same license!),

with mapping of regular characters to icons HEX CODES: 0x21 to 0xFF. 

So for example, 

character code 0x21 is now mapped to * (FontAwesome's asterisk)


And then, just use it inside PHP FPDF as follows:

// Import and prepare font for usage by engine:

$pdf->AddFont('FontAwesome47-P1','','FontAwesome47-P1.php');

...

// print FontAwesome's asterisk

$pdf->SetFont('FontAwesome47-P1' '', 14);

$pdf->Text($x, $y, chr(0x21));


Note:

Remember to upload the files FontAwesome47-P1.php + FontAwesome47-P1.z,
that generated on FPDF's Font File Generation to the FPDF's font folder.

Characters code MAP of new fonts exists as preview when opening the google-drive links below.


View MAP + DOWNLOAD: FontAwesome47-P1.otf (google drive)

View MAP + DOWNLOADFontAwesome47-P2.otf (google drive)

View MAP + DOWNLOADFontAwesome47-P3.otf (google drive)

View MAP + DOWNLOADFontAwesome47-P4.otf (google drive)


PHP+Z Files ready-to-use for PHP FPDF (with ISO-8859-1 encoding):

FontAwesome47-P1-4 (php+z files) DOWNLOAD (google drive)



Best regards!

Please write comments...


Sunday, October 17, 2021

MySQL | join/combine 2 SMALLINT/TINYINT into 1 INT

Hi All.

Today we will try to combine two MYSQL small integer values into one integer value.
Obviously, there is limit for the size of integer.
We will discuss only UNSIGNED integer column types (non negative values).

2 Solutions are suggested below:
Solution-1: concatenate base-9 value of each number with '9' separator.
Solution-2: concatenate the original values with padding (left) zeros.
[Note: if the values allowed to be NULL, solution-2 is not supported!].

# LIMITS #

First, lets learn about the range limits of each data-type:
DatatypeTypeUNSIGNED RangeMax value (base9)
INTA normal-size integer0 to 4294967295-
SMALLINTA small integer0 to 65535CONV(65535, 10, 9) = 108806
TINYINTA very small integer0 to 255CONV(255, 10, 9) = 313

# SOLUTION-1 (Support NULL values) #

Combine and merge two small integers,
into 1 integer by converting each number to base-9 integer,
and then concatenate with the digit '9' as separator.

Two SMALLINTs cannot be saved inside INT value:
1088069108806 > 4294967295.
But combining SMALLINT with TINYINT is possible (and aswell two TINYINT).

MYSQL CODE:
############ TABLE DEFINITION:
CREATE TABLE `table_test` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`sint1` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
`tint2` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE);

############ SELECT:
SELECT  T.*, 
        CONV(SUBSTRING_INDEX(combined,'9',1), 9,10) as _sint1, 
        CONV(SUBSTRING_INDEX(combined,'9',-1),9,10) as _tint2
FROM (
	SELECT 	id, sint1, tint2, 
                CONCAT( IFNULL(CONV(sint1, 10, 9),''), 
                        '9', 
                        IFNULL(CONV(tint2, 10, 9),'')
                ) AS combined
	FROM table_test
) AS T

            

And output will be:
idsint1tint2>combined>_sint1>_tint2
1NULLNULL9NULLNULL
21234NULL162191234NULL
3NULL2559313NULL255
43123384250942312338
53410243460893003410243
62685207361392502685207
71327224173492681327224
82047102272491232047102
92953189404192302953189
103686117504591403686117
114455186100920445518
122482663357973248266
133072744183982307274
142036422712946203642
152047139272491642047139
161573236213792821573236
172464173333792122464173
183656155501291823656155
193305120447291433305120
205894121806891445894121

# SOLUTION-2 (NULLS not supported) #

Here we just merge the original values with LEFT-PADDING of zeros.

MYSQL CODE:
############ TABLE DEFINITION:
CREATE TABLE `table_test` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`sint1` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
`tint2` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE);

############ SELECT:
SELECT  T.*, 
        SUBSTR(combined,1,LENGTH(combined)-3)+0 AS _sint1,
        RIGHT(combined,3)+0 AS _tint2
FROM (
	SELECT 	id, sint1, tint2, 
                CONCAT(sint1, LPAD(tint2,3,0)) AS combined
	FROM table_test
) AS T
            
And output will be:
idsint1tint2>combined>_sint1>_tint2
43123383123038312338
5341024334102433410243
6268520726852072685207
7132722413272241327224
8204710220471022047102
9295318929531892953189
10368611736861173686117
114455184455018445518
122482662482066248266
133072743072074307274
142036422036042203642
15204713920471392047139
16157323615732361573236
17246417324641732464173
18365615536561553656155
19330512033051203305120
20589412158941215894121

This solution can work with two SMALLINT,
if one of them limited up to 42949,
and it will be the left operand.


Thursday, December 3, 2020

php merge dateranges code algorithm


Here is a code for merging date-ranges in array. The method gives new array, with the maximum mergining between the date-ranges, meaning if there is a date-range that already exists with-in other, it can just skip, so just if two or more dates can be combined into one big date-range - it will be made :) . 
 
-------------------------------Example #1:
  array 
  0 => 's' => '2020-01-06' 'e' => '2020-01-10'
  1 => 's' => '2020-01-07' 'e' => '2020-01-12'
  2 => 's' => '2020-01-13' 'e' => '2020-01-16'
  3 => 's' => '2020-01-22' 'e' => '2020-01-24'

RESULT:
array 
  0 => 's' => '2020-01-06' 'e' => '2020-01-16'
  1 => 's' => '2020-01-22' 'e' => '2020-01-24'
 
-------------------------------Example #2:
array (size=8)
  0 => 's' => '2020-01-01' 'e' => '2020-01-01'
  1 => 's' => '2020-01-03' 'e' => '2020-01-03'
  2 => 's' => '2020-01-09' 'e' => '2020-01-10'
  3 => 's' => '2020-01-11' 'e' => '2020-01-22'
  4 => 's' => '2020-01-14' 'e' => '2020-02-02'
  5 => 's' => '2020-02-02' 'e' => '2020-02-03'
  6 => 's' => '2020-02-04' 'e' => '2020-02-04'
  7 => 's' => '2020-02-05' 'e' => '2020-02-07'

RESULT:
array (size=3)           
  0 => 's' => '2020-01-01' 'e' => '2020-01-01'
  1 => 's' => '2020-01-03' 'e' => '2020-01-03'
  2 => 's' => '2020-01-09' 'e' => '2020-02-07'
 
 
And here is the CODE:

$arrDateranges = array(
    array('s' => '2020-01-22', 'e' => '2020-01-24'),
    array('s' => '2020-01-06', 'e' => '2020-01-10'),
    array('s' => '2020-01-07', 'e' => '2020-01-12'),
    array('s' => '2020-01-13', 'e' => '2020-01-16'),
);
$arrMerged = mergeDateRanges($arrDateranges);
var_dump($arrDateranges);
var_dump($arrMerged);

//---------------------------------------------------------

// helper funciton to get NEXT date (or any modified date)
function getRelativeDate($p_sDate, $p_sModify, $p_sFormatIn = 'Y-m-d', $p_sFormatOut = 'Y-m-d') {
    $oDT = DateTime::createFromFormat($p_sFormatIn, $p_sDate);
    $oDT->modify($p_sModify);
    return $oDT->format($p_sFormatOut);
}

function mergeDateRanges($p_arrDateranges) {
    // sort by start date
    usort($p_arrDateranges, function($a1, $a2) {
        return $a1['s'] === $a2['s'] ? 0 : ($a1['s'] < $a2['s'] ? -1 : 1);
    });
    
    $arrMerged = array();
    $arrLastDR = null;
    foreach ($p_arrDateranges as $arrDR) {
        if ($arrLastDR === null) {
            $arrLastDR = $arrDR;
            continue;
        }
        //
        // NOTE: dateS is sorted thus $sDateS >= $arrLastDR['s']
        //
        if ($arrDR['e'] <= $arrLastDR['e']) {
            continue; // already in the range.
        }
        // --- [e] > lastDR[e] ---
        $sLastDateE_1 = getRelativeDate($arrLastDR['e'], '+1 day');
        if ($arrDR['s'] <= $sLastDateE_1) { // lapping date-range until day+1
            $arrLastDR['e'] = $arrDR['e'];
            continue;
        }

        // there is gap, so need to create new date-range
        array_push($arrMerged, $arrLastDR);
        $arrLastDR = $arrDR;
    }

    if ($arrLastDR === null) {
        array_push($arrMerged, $arrLastDR);
    }
    return $arrMerged;
}


Monday, February 24, 2020

Skype | stuck on loading screen [SOLVED] [SOLUTION]

Hello!

This thread is about a sign-in problem of SKYPE version 8.56.0.103,
where the application is stuck on loading screen.
here:


Here is how I've solved the problem!

I'm working at the moment with windows7,
but i assume that the solution will work for any windows version.

Step1:
make sure you have your Skype username/password saved,
as you will need to re-login later on.

Step2:
Make sure Skype on your desktop is closed. (if not - close/quit)

Step3:
Open your appdata Local folder:
C:\Users\YourUserNameHere\AppData\Roaming

alternative for opening the folder:
- search on windows start search for %appdata%
- click on Roaming 

  




Step4:
On the Roaming folder, Enter Microsoft folder,
Find Skype for Desktop folder, and rename it to "___skype"
(just to have backup)
Step5:
Just restart your skype and everything works :)

Let me know. 
:)
:)







Thursday, December 22, 2016

c# | WebBrowser control - programmatically select item on html `select`

Hi There,

As many times, we need to interact with the C# (.Net) Webbrowser Control, 
it is useful to be able to interact and programmatically change the selected item 
on an HTML select control.

I don't know, why it is hard to find this easy solution, but the code is as follow:


HtmlElementCollection col = webBrowser1.Document.GetElementsByTagName("select") 
foreach (HtmlElement heItem in col) 
{ 
  if (heItem.GetAttribute("className").Contains("exampleClassName") == true) 
  { 
    heItem.SetAttribute("selectedIndex", "3"); // select value at #3
    break; // incase of needed... 
  } 
}  


And finally, just easy as u code...


If you need change by value and not by index,
I assume you can check the values of the select control (sometimes called: dropdown),
and once you find the correct index of the desired value,
use the code above.



MDB-BLOG :)

Monday, October 31, 2016

List of country flags (png) by ISO3

As I needed a list of country flag images named with ISO3, and couldn't find,
I uploaded my version free (see license on bottom).


Above there are two ZIP containing country flags images (PNG format)
sizes of 64x64  and  128x128 
of the ~250 countries
as the file name is ISO3 standard
and not two letter (ISO 3166-2) or full name as most flags out there...


Download flags_iso3_128x128.rar
Example:
Download flags_iso3_64x64.rar
Example:



license and images are all taken from:





Saturday, February 13, 2016

Free Javascript Obfuscator Online

Protects JavaScript code from stealing/reading and shrinks its size.
Free Javascript Obfuscator is a professional tool for obfuscation of javascript. It Converts JavaScript source code into scrambled and completely unreadable form, preventing it from analyzing and theft.
Visit: http://freejsobfuscator.com/

u can choose if to process by your will: parameters / functions / strings / new lines / indentations and it is 100% free!

Sunday, November 22, 2015

How to install php imap extension on Centos (or any)

The php package (extension) for IMAP is usually:
php-imap

Sometimes, for example on amazon ec2, when installing PHP ver. 5.5 or 5.6,
In order to install this (or any other) PHP extension,
that not come with the default PHP,
You should installed the one related to your PHP version.

For example,
one of my servers have PHP 5.6 installed on it,
but when running 
 yum install php-imap 
which gives:
Error: php56-imap conflicts with php-imap-5.3.29-1.8.amzn1.x86_64
Error: php56-common conflicts with php-common-5.3.29-1.8.amzn1.x86_64
Error: php55-common conflicts with php-common-5.3.29-1.8.amzn1.x86_64
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest 


so instead, check first which version currently installed:
yum list installed | grep php
 which gives:
php56.x86_64                          5.6.14-1.119.amzn1           @amzn-updates
php56-cli.x86_64                      5.6.14-1.119.amzn1           @amzn-updates
php56-common.x86_64                   5.6.14-1.119.amzn1           @amzn-updates
php56-imap.x86_64                     5.6.14-1.119.amzn1           @amzn-updates
php56-jsonc.x86_64                    1.3.6-1.19.amzn1             @amzn-main
php56-mbstring.x86_64                 5.6.14-1.119.amzn1           @amzn-updates
php56-mysqlnd.x86_64                  5.6.14-1.119.amzn1           @amzn-updates
php56-pdo.x86_64                      5.6.14-1.119.amzn1           @amzn-updates
php56-process.x86_64                  5.6.14-1.119.amzn1           @amzn-updates
php56-xml.x86_64                      5.6.14-1.119.amzn1           @amzn-updates 
 

Which means that your PHP version is 5.6 (you can also run php -v)
php -v
 which gives:
PHP 5.6.14 (cli) (built: Oct 16 2015 22:58:32)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies

All needed now is to install the correct version.
If you install php55-imap (or any other package) it won't work!
Some have several PHP versions installed.
command:
 
yum install php56-imap

 
don't forget to restart your apache after that.
service httpd restart


and done... :)
Hope it helps.

Friday, November 13, 2015

PHP | XML to Html Table elment convertion

In this thread,
I will show generic & universal function that
gets XML string,
convert it,
and display it as an HTML table.
(you can add any css style to design your table later on of course)


The following code is using XML example from http://www.w3schools.com/xml/simple.xml.
The XML looks like that:
<breakfast_menu>
  <food>
    <name>Belgian Waffles</name>
    <price>$5.95</price>
    <description>Two of our famous...</description>
    <calories>650</calories>
  </food>
  <food>
    <name>Strawberry Belgian Waffles</name>
    <price>$7.95</price>
    <description>Light Belgian waffles...</description>
    <calories>900</calories>
  </food>
  <food>
    <name>Berry-Berry Belgian Waffles</name>
    <price>$8.95</price>
    <description>Light Belgian....</description>
    <calories>900</calories>
  </food>
  <food>
    <name>French Toast</name>
    <price>$4.50</price>
    <description>Thick slices made....</description>
    <calories>600</calories>
  </food>
  <food>
    <name>Homestyle Breakfast</name>
    <price>$6.95</price>
    <description>Two eggs, bacon...</description>
    <calories>950</calories>
  </food>
</breakfast_menu>



The function xmlToHtmlTable 
gets a SimpleXMLElement parameter which points to main parent for which will print all his children,
and returns html table representing the XML as string.

The Code:
 <?php  
   
 // get XML remotely / locally / or / just set it as string '<root>...</root>'  
 $sXml = file_get_contents('http://www.w3schools.com/xml/simple.xml');  
   
 // parse XML  
 $oXML = simplexml_load_string($sXml);  
 if (!$oXML) {  
      die('xml format not valid or simplexml module missing.');  
 }  
   
 // assuming running the root  
 $oXmlRoot = $oXML; // or can be [$oXML->food]  
   
 //echo '<pre>'; print_r( $oXmlRoot ); echo '</pre>';  
 echo xmlToHtmlTable($oXmlRoot);  
   
   
 function xmlToHtmlTable($p_oXmlRoot) {  
      $bIsHeaderProceessed = false;  
        
      $sTHead = '';  
      $sTBody = '';       
      foreach ($p_oXmlRoot as $oNode) {  
           $sTBody .= '<tr>';  
           foreach ($oNode as $sName => $oValue){  
                if (!$bIsHeaderProceessed) {  
                     $sTHead .= "<th>{$sName}</th>";  
                }  
                $sValue = (string)$oValue;  
                $sTBody .= "<td>{$sValue}</td>";                 
           }  
           $bIsHeaderProceessed = true;  
           $sTBody .= '</tr>';  
      }  
        
      $sHTML = "<table border=1>  
                     <thead><tr>{$sTHead}</tr></thead>  
                     <tbody>{$sTBody}</tbody>  
                </table>";  
      return $sHTML;  
 }  

This will output:

 
Hope it helps!
MDB BLOG!




 

Friday, June 19, 2015

MySQL | find median (Nth element) without join!

This is my suggestion to find on mysql select command
the Median (Nth element) without joining the table to itself (or to new custom one).

My method, uses string manipulation
so I'm not sure it is good for big tables.
(I tested it with medium size tables on Mysql 5.5.28)

The advantage of this method, 
that it works also if we need to find the MEDIAN for each group in the select query.

the code is using: SUBSTRING_INDEX and GROUP_CONCAT methods.


Here is test code for test table:
DROP TABLE test.test_median
CREATE TABLE test.test_median AS
SELECT 'book' AS grp, 4 AS val UNION ALL
SELECT 'book', 7 UNION ALL
SELECT 'book', 2 UNION ALL
SELECT 'book', 2 UNION ALL
SELECT 'book', 9 UNION ALL
SELECT 'book', 8 UNION ALL
SELECT 'book', 3 UNION ALL

SELECT 'note', 11 UNION ALL

SELECT 'bike', 22 UNION ALL
SELECT 'bike', 26 



and the code for finding the median for each group:
SELECT grp,
         SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT(val ORDER BY val), ',', COUNT(*)/2 ), ',', -1) as the_median,
         GROUP_CONCAT(val ORDER BY val) as all_vals_for_debug
FROM test.test_median
GROUP BY grp

The output:

grp the_median all_vals_for_debug
bike 22 22,26
book 4 2,2,3,4,7,8,9
note 11 11


Hope it helps you there...


Wednesday, May 27, 2015

php | destroy/delete all sessions

I recently searched for an option deleting all running/active sessions,
for changing some important logic on my server.

Important:
just restarting apache won't help!
because php handles php-sessions by itself.

now,
I wonder how to make it, without changing php code.
The solution, is to delete the PHP session files created by PHP engine.

Step #1 - find where PHP store php files
on php.ini there is configured session.save_path 
which points to the correct path.
by default, it configured to "" (empty), and it is:



  • On Ubuntu or Debian machines: saved on /var/lib/php5
  • On RHEL and CentOS systems: saved on /var/lib/php/session
  • If you need to find it: print session_save_path() on your php file.    You may run from command line:  php -r 'echo session_save_path(), "\n";'

Step #2 - just delete the files
Execute the following bash script:
rm  -f   /var/lib/php/session/*
or
rm  -f   /var/lib/php5/sess*
(-f will force delete without prompting!!) 



And that's it...
Now when a user will execute web-request, 
his session will be considered empty, 
and will be re-generated (under the same session name)




Thursday, December 25, 2014

NSIS | create CENTER aligned text control

I searched on the internet for CENTER LABEL on NSIS,
but didn't find.

I saw that the ${SS_CENTER} style, not working with ${NSD_CreateLabel}
So I build my own code, using the STATIC control.


nsDialogs::CreateControl STATIC ${WS_VISIBLE}|${WS_CHILD}|${SS_CENTER} 0 29 180 439 60 "WELCOME TEXT"
Pop $0
CreateFont $1 "Arial" 9
SendMessage $0 ${WM_SETFONT} $1 1
SetCtlColors $0 0x000000 '0xff0000'


Hope it help...
 

Wednesday, February 13, 2013

c# Winforms WebBrowser - Clear all cookies

Hello,
I recently search for a method to delete all cookies from the build in .NET WinForms WebBrowser control.
I didn't found any working solution for it, nor working example.
It being told to use InternetSetOption, but nothing found about it.
So, i will write here my solution for clearing and deleting all cookies.
My solution using InternetSetOption with the option flag: INTERNET_OPTION_SUPPRESS_BEHAVIOR, which described as:

A general purpose option that is used to suppress behaviors on a process-wide basis. The lpBuffer parameter of the function must be a pointer to a DWORD containing the specific behavior to suppress. This option cannot be queried with InternetQueryOption.

This option flag should be used together with INTERNET_SUPPRESS_COOKIE_PERSIST options, which means:

Suppresses the persistence of cookies, even if the server has specified them as persistent.


So the example code for it will be:
static void Main()
{
    SuppressWininetBehavior();

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
public static extern bool InternetSetOption(int hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);

private static unsafe void SuppressWininetBehavior()
{
    /* SOURCE: http://msdn.microsoft.com/en-us/library/windows/desktop/aa385328%28v=vs.85%29.aspx
        * INTERNET_OPTION_SUPPRESS_BEHAVIOR (81):
        *      A general purpose option that is used to suppress behaviors on a process-wide basis. 
        *      The lpBuffer parameter of the function must be a pointer to a DWORD containing the specific behavior to suppress. 
        *      This option cannot be queried with InternetQueryOption. 
        *      
        * INTERNET_SUPPRESS_COOKIE_PERSIST (3):
        *      Suppresses the persistence of cookies, even if the server has specified them as persistent.
        *      Version:  Requires Internet Explorer 8.0 or later.
        */

    int option = (int)3/* INTERNET_SUPPRESS_COOKIE_PERSIST*/;
    int* optionPtr = &option;

    bool success = InternetSetOption(0, 81/*INTERNET_OPTION_SUPPRESS_BEHAVIOR*/, new IntPtr(optionPtr), sizeof(int));
    if (!success)
    {
        MessageBox.Show("Something went wrong !>?");
    }
}

Please make sure your project is allows unsafe code. (under Properties => Build Tab)

This code is deleting the COOKIES per PROCESS on startup ONLY.
[tested on WIN-7 and working great]


Best Regards,
MDB-BLOG :)