Advertisement
Tuurlijk

Is Absolute Path Test

Jan 10th, 2014
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.57 KB | None | 0 0
  1. <?php
  2. error_reporting(E_ALL & ~E_NOTICE);
  3. /*****************************************************************************
  4.  *  Copyright notice
  5.  *
  6.  *  ⓒ 2013 Michiel Roos <michiel@maxserv.nl>
  7.  *  All rights reserved
  8.  *
  9.  *  This script is part of the TYPO3 project. The TYPO3 project is free
  10.  *  software; you can redistribute it and/or modify it under the terms of the
  11.  *  GNU General Public License as published by the Free Software Foundation;
  12.  *  either version 2 of the License, or (at your option) any later version.
  13.  *
  14.  *  The GNU General Public License can be found at
  15.  *  http://www.gnu.org/copyleft/gpl.html.
  16.  *
  17.  *  This script is distributed in the hope that it will be useful, but
  18.  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  19.  *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  20.  *  more details.
  21.  *
  22.  *  This copyright notice MUST APPEAR in all copies of the script!
  23.  ****************************************************************************/
  24.  
  25. // Setup
  26. $testName = 'isAbsPath()';
  27. $reverseExecutionOrder = 0;
  28. $runs = 100;
  29.  
  30. // Parameter Sets
  31. $parameterSets = array(
  32.     'set1' => array (
  33.         'description' => '*nix path',
  34.         'path' => '/var/www/htdocs',
  35.         'os' => 'nix'
  36.     ),
  37.     'set2' => array (
  38.         'description' => 'Windows path',
  39.         'path' => 'c:\var\www\htdocs',
  40.         'os' => 'WIN'
  41.     ),
  42.     'set3' => array (
  43.         'description' => 'Windows path with forward slash',
  44.         'path' => 'c:/var/www/htdocs',
  45.         'os' => 'WIN'
  46.     ),
  47.     'set4' => array (
  48.         'description' => 'Empty path on Windows',
  49.         'path' => '',
  50.         'os' => 'WIN'
  51.     ),
  52.     'set5' => array (
  53.         'description' => 'Empty path on *nix',
  54.         'path' => '',
  55.         'os' => 'nix'
  56.     ),
  57.     'set6' => array (
  58.         'description' => '*nix path on Windows',
  59.         'path' => '/var/www/htdocs',
  60.         'os' => 'WIN'
  61.     ),
  62.     'set7' => array (
  63.         'description' => 'Windows path on *nix',
  64.         'path' => 'c:/var/www/htdocs',
  65.         'os' => 'nix'
  66.     ),
  67. );
  68.  
  69. /*****************************************************************************
  70.  * Tests:
  71.  ****************************************************************************/
  72.  
  73. $descriptions['version1'] = 'Baseline isAbsPath';
  74. function version1($path, $os) {
  75.         // On Windows also a path starting with a drive letter is absolute: X:/
  76.         if ($os === 'WIN' && (substr($path, 1, 2) === ':/' || substr($path, 1, 2) === ':\\')) {
  77.             return TRUE;
  78.         }
  79.         // Path starting with a / is always absolute, on every system
  80.         return substr($path, 0, 1) === '/';
  81. }
  82.  
  83. $descriptions['version2'] = 'Optimized';
  84. function version2($path, $os) {
  85.     return $path{0} === '/' || $os === 'WIN' && (strpos($path, ':/') === 1 || strpos($path, ':\\') === 1);
  86. }
  87.  
  88. /*****************************************************************************
  89.  * Helper functions needed for test:
  90.  ****************************************************************************/
  91.  
  92.  
  93. /*****************************************************************************
  94.  * System (look, but don't touch ;-) . . . only touch if you must.
  95.  ****************************************************************************/
  96.  
  97. // Show source?
  98. if (isset($_GET['source']) && $_GET['source']) {
  99.     show_source(__FILE__);
  100.     exit;
  101. }
  102.  
  103. // How many runs?
  104. if (isset($_GET['runs'])) $runs = preg_replace('/[^0-9]/', '', $_GET['runs']);
  105.  
  106. // Execution order?
  107. if (isset($_GET['reverseExecutionOrder'])) $reverseExecutionOrder = intval($_GET['reverseExecutionOrder']);
  108.  
  109. // Prepare
  110. $baselineTimes = $functionsToCall = $times = array();
  111. $allFunctions = get_defined_functions();
  112. $functions = array_filter($allFunctions['user'], create_function('$a','return strpos($a, "version") === 0;'));
  113. if ($reverseExecutionOrder) arsort($functions);
  114. foreach ($functions as $function) {
  115.     $xAxis[] = $function;
  116.     $functionsToCall[$function] = new ReflectionFunction($function);
  117. }
  118.  
  119. // Execute
  120. foreach ($parameterSets as $setName => $parameters) {
  121.     // Description is used later on, so clone the parameters
  122.     $functionParameters = $parameters;
  123.     unset($functionParameters['description']);
  124.     for ($i = 0; $i < $runs; $i++) {
  125.         foreach ($functions as $function) {
  126.             $start = microtime(TRUE);
  127.             $result = $functionsToCall[$function]->invokeArgs($functionParameters);
  128.             $time = microtime(TRUE) - $start;
  129.             if ($function === 'version1') {
  130.                 $baselineTimes[$setName] += $time * 1000;
  131.             }
  132.             if (is_array($result)) {
  133.                 $resultObjects[$setName][$function] = array_slice($result, 0, 20, TRUE);
  134.             } else {
  135.                 $resultObjects[$setName][$function] = $result;
  136.             }
  137.             $times[$setName][$function] += $time * 1000;
  138.         }
  139.     }
  140. }
  141.  
  142. function findWinner($times) {
  143.     $cumulativeTimes = array();
  144.     foreach ($times as $setName => $timeData) {
  145.         foreach ($timeData as $functionName => $time) {
  146.             if (isset($cumulativeTimes[$functionName])) {
  147.                 $cumulativeTimes['overall'][$functionName] += $time;
  148.                 $cumulativeTimes[$setName][$functionName] += $time;
  149.             } else {
  150.                 $cumulativeTimes['overall'][$functionName] = $time;
  151.                 $cumulativeTimes[$setName][$functionName] = $time;
  152.             }
  153.         }
  154.     }
  155.     $cumulativeTimes = array_filter($cumulativeTimes, 'asort');
  156.     return $cumulativeTimes;
  157. }
  158.  
  159. $cumulativeTimes = (findWinner($times));
  160.  
  161. /**
  162.  * Format an integer as a time value
  163.  *
  164.  * @param integer $time The value to format
  165.  *
  166.  * @return string
  167.  */
  168. function printSeconds($time) {
  169.     $prefix = '';
  170.     $suffix = 'μs';
  171.     if ($time < 0) {
  172.         $time = abs($time);
  173.         $prefix = '-';
  174.     }
  175.     if ($time === 0) {
  176.         $suffix = '';
  177.     }
  178.     if ($time >= 1000) {
  179.         $time = $time / 1000;
  180.         $suffix = 'ms';
  181.     }
  182.     if ($time >= 1000) {
  183.         $time = $time / 1000;
  184.         $suffix = ' s';
  185.     }
  186.     if ($time >= 60 && $suffix === ' s') {
  187.         $time = $time / 60;
  188.         $suffix = 'min!';
  189.     }
  190.     return $prefix . sprintf("%.2f {$suffix}", $time);
  191. }
  192.  
  193. ?>
  194. <html>
  195. <head>
  196.     <title><?php  echo $testName ?> | TYPO3 Tiny Test Suite</title>
  197.     <link rel="stylesheet" href="http://wiki.typo3.org/wiki/load.php?debug=false&amp;lang=en&amp;modules=mediawiki.legacy.commonPrint%2Cshared%7Cskins.typo3vector&amp;only=styles&amp;skin=typo3vector&amp;*" />
  198.     <script src="http://code.jquery.com/jquery-2.0.3.min.js" type="text/javascript"></script>
  199.     <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js" type="text/javascript"></script>
  200.     <script src="http://code.highcharts.com/highcharts.js" type="text/javascript"></script>
  201.     <script src="http://code.highcharts.com/modules/exporting.js" type="text/javascript"></script>
  202. </head>
  203. <body>
  204. <div id="content" class="mw-body">
  205.     <h1 id="top"><?php echo $testName ?></h1>
  206.     <form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>">
  207.         <label for="runs">Run the tests how many times?</label>
  208.         <input name="runs" id="runs" value="<?php echo $runs ?>"/>
  209.         <label for="runs"><a href="#help">Reverse execution order?</a></label>
  210.         <input type="checkbox" name="reverseExecutionOrder" id="reverseExecutionOrder" value="1" <?php echo ($reverseExecutionOrder) ? 'checked="checked"' : '' ?>/>
  211.         <input class="submit" type="submit" value="Go!"/>
  212.     </form>
  213.     <p>The overall winning function is <strong><?php
  214.             $winner = array_slice($cumulativeTimes['overall'], 0, 1);
  215.             echo key($winner) ?></strong> <?php echo printSeconds(current($winner)) ?>.</p>
  216.     <?php
  217.         if (count($parameterSets) > 1) {
  218.             echo '<ul>';
  219.             foreach ($cumulativeTimes as $set => $functions) {
  220.                 if ($set !== 'overall') {
  221.                     echo '<li><b>' . $set . '</b>: ';
  222.                     $setWinner = array_slice($functions, 0, 1);
  223.                     echo key($setWinner) . ' ' . printSeconds(current($setWinner)) . '</li>';
  224.                 }
  225.             }
  226.             echo '</ul>';
  227.         }
  228.     ?>
  229.     <div id="resultGraph" style="min-width: 310px; min-height: 400px; margin: 0 auto"></div>
  230.     <?php
  231.         foreach ($times as $setName => $functionData) {
  232.             echo '<h2>' , ucfirst($setName) , '</h2>',
  233.                 '<p>' , $parameterSets[$setName]['description'] , '</p>',
  234.                 '<ul>';
  235.             foreach ($functionData as $function => $time) {
  236.                 $identifier = $setName . '-' . $function;
  237.                 echo '<li><a style="text-decoration: none" href="#', $identifier, '">',
  238.                     ucfirst($function),
  239.                     '</a> ',
  240.                     ': ',
  241.                     sprintf('<span style="min-width: 33px; display: inline-block; text-align: right; font-weight: bold;">%1.2d%%</span> ', $time * 100 / $baselineTimes[$setName]),
  242.                     sprintf('<span style="min-width: 50px; display: inline-block; text-align: right; margin: 0 10px;">%s</span> ', printSeconds($time)),
  243.                     $descriptions[$function],
  244.                     '</li>';
  245.             }
  246.             echo '</ul><h3>Parameters</h3><ul>';
  247.             foreach ($parameterSets[$setName] as $key => $value) {
  248.                 if ($key !== 'description') {
  249.                     if (is_array($value)) {
  250.                         echo '<li>' , $key , ':', '</li>'; var_dump($value);
  251.                     } else {
  252.                         echo '<li>' . $key . ' = "' . (string) $value . '"</li>';
  253.                     }
  254.                 } else {
  255.                     $setDescriptions[] = $value;
  256.                 }
  257.             }
  258.             echo '</ul>';
  259.         }
  260.     ?>
  261.     <script>
  262.         /**
  263.          * Format an integer as a time value
  264.          *
  265.          * @param {String} time The value to format in microseconds.
  266.          * @param {Number} decimals The amount of decimals
  267.          *
  268.          * @return string
  269.          */
  270.         function printSeconds(time, decimals) {
  271.            decimals = typeof decimals !== 'undefined' ? decimals : 2;
  272.             var prefix = '',
  273.                 suffix = 'μs';
  274.             if (time < 0) {
  275.                 time = Math.abs(time);
  276.                 prefix = '-';
  277.             }
  278.             if (time == 0) {
  279.                 suffix = '';
  280.             }
  281.             if (time >= 1000) {
  282.                 time = time / 1000;
  283.                 suffix = 'ms';
  284.             }
  285.             if (time >= 1000) {
  286.                 time = time / 1000;
  287.                 suffix = ' s';
  288.             }
  289.             if (time >= 60 && suffix == ' s') {
  290.                 time = time / 60;
  291.                 suffix = 'min!';
  292.             }
  293.             return prefix + Highcharts.numberFormat(time, decimals) + ' ' + suffix;
  294.         }
  295.  
  296.         var baseLineTimes = [<?php echo implode(',', $baselineTimes) ?>];
  297.         var descriptions = ['<?php echo implode("','", array_map('addslashes', $descriptions)) ?>'];
  298.         var setDescriptions = ['<?php echo implode("','", array_map('addslashes', $setDescriptions)) ?>'];
  299.         Highcharts.setOptions({
  300.             colors: ['#f58006', '#f50806', '#067bf5', '#f5bc06', '#8006f5']
  301.         });
  302.         jQuery(document).ready(function($) {
  303.             $('#resultGraph').highcharts({
  304.                 chart: {
  305. //                  type: 'bar'
  306.                     zoomType: 'y'
  307.                 },
  308.                 title: {
  309.                     text: '<?php echo $testName ?>'
  310.                 },
  311.                 xAxis: {
  312.                     categories: ['<?php echo implode("','", $xAxis)  ?>'],
  313.                     title: {
  314.                         text: null
  315.                     }
  316.                 },
  317.                 yAxis: {
  318.                     min: 0,
  319.                     title: {
  320.                         text: 'Time (milliseconds)',
  321.                         align: 'high'
  322.                     },
  323.                     labels: {
  324.                         overflow: 'justify',
  325.                         formatter: function() {
  326.                             return printSeconds(this.value);
  327.                         }
  328.                     }
  329.                 },
  330.                 tooltip: {
  331.                     useHTML: true,
  332.                     formatter: function() {
  333.                         return '<strong><a style="text-decoration: none" href="#' + this.point.series.name + '-' + this.point.category + '">' + descriptions[this.point.x] + '</a></strong><br/>' +
  334.                             setDescriptions[this.series.index] + '<br/>' +
  335.                             printSeconds(this.point.y) +
  336.                             ' (' + Math.ceil(this.point.y * 100 / baseLineTimes[this.point.series.index]) + '%)';
  337.                     }
  338.                 },
  339.                 legend: {
  340.                     enabled: true
  341.                 },
  342.                 credits: {
  343.                     enabled: false
  344.                 },
  345.                 series: [
  346.                     <?php
  347.                     foreach ($times as $setName => $setTimes) {
  348.                         $series[] = "{
  349.                             name: '" . $setName . "',
  350.                             data: [" . implode(',', $setTimes) . "]
  351.                         }";
  352.                     }
  353.                     echo implode(',', $series);
  354.                     ?>
  355.                 ]
  356.             });
  357.             $('#showSourceLink').on('click', function(e) {
  358.                 e.preventDefault();
  359.                 $.ajax({
  360.                     url: '<?php echo $_SERVER['SCRIPT_NAME'] ?>?source=1',
  361.                     cache: false
  362.                 })
  363.                 .done(function(html) {
  364.                     $('.loading').hide();
  365.                     $('#sourceCode').html(html);
  366.                     $('html, body').animate({
  367.                         scrollTop: $("#source").offset().top
  368.                     }, {
  369.                         duration: 2000,
  370.                         easing: 'easeOutBounce'
  371.                     });
  372.                 });
  373.             });
  374.             $('.top').on('click', function(e) {
  375.                 e.preventDefault();
  376.                 $('html, body').animate({
  377.                     scrollTop: $("#top").offset().top
  378.                 }, {
  379.                     duration: 2000,
  380.                     easing: 'easeOutBounce'
  381.                 });
  382.             });
  383.         });
  384.     </script>
  385.     <h2>Data results</h2>
  386.     <?php
  387.         foreach ($times as $setName => $functionData) {
  388.             echo '<h3>' . ucfirst($setName) . '</h3>';
  389.             echo '<p>' . $parameterSets[$setName]['description'] . '</p>';
  390.             echo '<ul>';
  391.             foreach ($parameterSets[$setName] as $key => $value) {
  392.                 if ($key !== 'description') {
  393.                     if (is_array($value)) {
  394.                         echo '<li>' , $key , ':', '</li>'; var_dump($value);
  395.                     } else {
  396.                         echo '<li>' . $key . ' = "' . (string) $value . '"</li>';
  397.                     }
  398.                 }
  399.             }
  400.             echo '</ul>';
  401.             foreach ($functionData as $function => $time) {
  402.                 echo '<h4 id="', $setName . '-' . $function, '">', ucfirst($function), '</h4>',
  403.                     '<p>', $descriptions[$function], '</p>';
  404.                 var_dump($resultObjects[$setName][$function]);
  405.                 echo '<a href="#top" class="top" style="color: #ddd; text-decoration: none;">^ top</a>';
  406.             }
  407.         }
  408.     ?>
  409.     <div id="p-personal" role="navigation" class="">
  410.         <ul>
  411.     <?php
  412.     foreach ($resultObjects as $setName => $functionData) {
  413.         foreach ($functionData as $function => $data) {
  414.             echo '<li><a href="#' . $setName . '-' . $function . '">' . ucfirst($setName) . ' ' . ucfirst($function)  . '</a></h3>';
  415.         }
  416.     }
  417.     ?>
  418.             <li><a href="#help">Help</a></li>
  419.             <li><a href="#source">Source Code</a></li>
  420.         </ul>
  421.     </div>
  422.     <div id="help">
  423.         <h2>Help</h2>
  424.         <h3>Execution Order</h3>
  425.         <p>In some cases, the second function (non baseline) always runs faster than the baseline. Even when switching the code around. This toggle enables you to reverse the running order to check for this behaviour. Your winning function should still win whatever the execution order. If that is not the case, then this test has failed to determine what code runs faster.</p>
  426.         <a href="#top" class="top" style="color: #ddd; text-decoration: none;">^ top</a>
  427.     </div>
  428.     <div id="source">
  429.         <h2>Source Code</h2>
  430.         <pre id="sourceCode"><a href="#source" id="showSourceLink">Show the sourcecode of this file.</a></pre>
  431.         <a href="#top" class="top" style="color: #ddd; text-decoration: none;">^ top</a>
  432.     </div>
  433.     <div id="logo" style="position: absolute; top: 60px; left: 60px;"><img alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAAiCAYAAACKuC3wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
  434. bWFnZVJlYWR5ccllPAAABzJJREFUeNrsWwlsFUUYHh4VkEMEKaACHmAV0KTENFxaiIqK1sQDNYIS
  435. UTQRDSlH1DSIBqSgAQVijGIEjdYDREXEIEo4LSiKgFgUMKCAIK1KFQoUSv1++y/v7zCzZ1/bkP2T
  436. Lztv59jd+Wb+a/c1qKysVLGcftLAb8PKfNUQh8sYRxrkqUWGNpNweBhoI06XAiXALuBnoBBYgv77
  437. 4umvA2JBEtVlATcA13K5KVf3ADEbtPadcdju87rHgY+BURhnd0xDzUuagdAMHIYDg4HzDX3+1kll
  438. 6RjwuoOAnrje5Rjvn5iKFBGLCSYV+yxwu4eKtpFwIMT1aTHcCMyNqUgBsSB1NA75QGMffc6xnP89
  439. 1XY+Fv+SAKmP4DjNJ6kkzdGnwyns5Kn9OISxl3/FNKSAWODREP36Wc5/FWKsXTENqSG2W4h+11jO
  440. Lwo4zkFga0xDamxsGBt3PYVDUL96duMToBxo5HOc7zHGCUtda2B8iHtbAXzEjmBzseC+8Og3Asgw
  441. tD8TmAq04nCvMZ+juSsD9gLLOHzz40CeAdxGcwhczOORQ7qZnch1Ln3p+rdQuAlcAqQL/2Y58BZw
  442. 6H/TCIIogXBWiAnsC1IKDeHSh3zjfuQJjPG8pe5CYEeI+5oB5DIZY/jcFqA73Z6lTyfgFyarAqCY
  443. /FeuO5tCPJ++wgPAApc2GbwAurq0IXIeAo4a6jJpM7j03QYMoHtPhJw8kiEuE+tXFqZQG01j7aF4
  444. InNc2o4Wod/bglSTlPAEbgQ2iGuQhvkA6GXp14q1gCSVHM4iNkmO3AfM8vF8tNh+4gXpCO3i2Y6N
  445. LQo5cXdidzYyeMekCtf76L8Obbe41JOHfZEBss89hvoJXEcqco7UDi4qf7ijcIApHvedzjsvk1Ui
  446. JXFWC9M23dLvKdYMzuIgP6Uda5J07f6GAlcZxvhNVWUC2/J90yLpwmq9Qvg/3YjYNSGJTefskUny
  447. fPR/2aOe0o47DSgXbfYZ6mX4NFU8cF+GLhQVNOPyXN4FQaSEiXB8hZ7CVjtCdvRB8fsxtsuOHAHI
  448. JL2v3ZdJ3S8BirXzpAnmi9/ZROzKCOou15hxyFOf47DYpR+tvHdqwTmk3PU8l11LTtBI8XtKyOvs
  449. YLXsiK6Os4QfU8wq22uxXxfwHr4W5S5E7KYIWaMsqOM+Ll7mQUvdOJBfXkue/2RRztHCu2Eq+SZq
  450. oUZOUNmqOX5Semtee4VLHuAYl9uwmg2T6GmR4JAlihMzzrJrd7AjoIczi9lBqS3ZJOJrCu3GCns4
  451. VrTLj3gdObEttbpLRflHlzEqNFOQEeD6zUW5PMGFeREeaCB2bbaFXHLt71JV72QV3/RQQ/ybapGk
  452. 3csOzx3sbJF8CayNeI2GoqyHKvItmZd23CPKHQJcXy6e3Q6xyyOoY1fbBBLJqF/ANuNK/C6ug0RM
  453. ofAlKEEwSrO3k2rgGvLjgkNaXVvLzvba+e18XrsZL1RHViV48iu00CCo9MauHeJCbimwFCirwyzb
  454. ZM3p68HlNbywo0qmxd6SNBHlfz3GKdOyVCZpz3a8M4c65KyeK+x0YUI0ft0lM+NHpoPc9qr+ymKR
  455. tZFqc0INjN2PJ9mRtYYdZVPTusjdbssIvsee+HYmta/wjO92EhTS2VkQURUVgNy0ekzuZO33Bp6Y
  456. sELzR58NFYhzpPLr6o1Ve8cDT2gVL0QcmLIec/jDt/oo87XgfkYILXVAoJwdL8c5olBlTA3er+0F
  457. yUvsJxCeFjEs+TLvUkiXptnCVSBlhbK/b/Uj5HV2wjjjeeUexbh76gmxJzQbFuZznpaW8/Ss9BLg
  458. W0NdqZaF8nKEHLF9hqQnOCaqqjdrORzGjTCpzWe0dFcYyWaHhB6oqzq95E1RPqyqEvmFPGe2pIs8
  459. 38Jj/KaWfm5CWmemSr7o6J9m8GCXY7d9huJNNTAJuRhv72lG7P0h+vwhyq092sr6IN9e/yDKXRKW
  460. RhTjHY9qz0DqGyoWPSlxnkdbmcwIsimqqfuEJe6kt/kvRniQnSr5KiyW6mnC7i7tyOnMsPTzkiO6
  461. u24TsrXbQjwExWG3YnEciPk8Kd+I8tUu895LOFclKthHEDL9WJpwyRaVsYd7LKDXOQR9N8ZcVpPv
  462. hIdLacKBlnbDRHlpwGsMEOVtbjuWyKWVNjIAqZTgXxDzeIoc5vjSkekGW3uz5pjNNoxDb3CaGM53
  463. ZA17MkmS8LojEPUKDs95NDvGpBbEHFplooib6T0rpQPpw79XgVXApyqZ6qRs2BLDGIPY1FHflRzP
  464. Ejar5H+nyOl9zVf6D4Q9iRCojFeF/rkqfZs0mJIbMXeuQkka+l8UvcqkHDB9vWH6mnM9m0Cb0Gbs
  465. rKrnpqU8Tk5Xwu9dgThKllPKcDUHxOTC0+u6K2qZVPqP7UbGwRD9i0T/Uh/tK0T7qL7DMvaKSRVv
  466. VcmUIanqNWz2+rDjZLPVs7jtfpVMh/6pqjJP/Z1o5j8BBgADhL1q2hRfzwAAAABJRU5ErkJggg==" /></div>
  467. </div>
  468. </body>
  469. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement