diff options
Diffstat (limited to 'tests')
30 files changed, 1665 insertions, 0 deletions
diff --git a/tests/abstract.php b/tests/abstract.php new file mode 100755 index 0000000..2b085a4 --- /dev/null +++ b/tests/abstract.php @@ -0,0 +1,46 @@ +<?php + +abstract class abs { + + public static $abs = [ + 'one' => 10, + 'to' => [20, 220], + 'tree' => [30, [330, 3330]] + ]; + + public static function foo($who) { + print_r(static::$abs[$who]); + } + +} + +class Xtra extends abs { + + public static $abs = [ + 'Oh' => 'Yoo hoo!', + 'my' => ['babe', 'be', 'mine'] + ]; + + // overide method + public static function foo($who) { + print_r(['overiding', $who, 'my']); + } + +} + +class Repo extends abs { + public static $abs = [ + 'one' => 1, + 'to' => [2, 22], + 'tree' => [3, [33, 333]] + ]; +} + +class Neva extends abs { + // use abstract's (default) array +} + +Xtra::foo('Oh'); +Repo::foo('to'); +Neva::foo('tree'); + diff --git a/tests/algo-hashes.php b/tests/algo-hashes.php new file mode 100755 index 0000000..8457949 --- /dev/null +++ b/tests/algo-hashes.php @@ -0,0 +1,52 @@ +<?php +$userManager = new UserManager(); + +$password = $userManager->cryptPassword('102030!!!'); + +$user = (new User()) + ->setUserName('geo@roptron.gr') + ->setPassword($password) + ->setRoles([1]); + +$userManager->createUserToken($user); + + +$algos = [ + [ PASSWORD_DEFAULT, 10 ], + [ PASSWORD_ARGON2I, 10 ], + [ CRYPT_BLOWFISH, 10 ], + [ PASSWORD_DEFAULT, 9 ], + [ PASSWORD_ARGON2I, 9 ], + [ CRYPT_BLOWFISH, 9 ], + [ PASSWORD_DEFAULT, 11 ], + [ PASSWORD_ARGON2I, 11 ], + [ CRYPT_BLOWFISH, 11 ], + [ PASSWORD_DEFAULT, 12 ], + [ PASSWORD_ARGON2I, 12 ], + [ CRYPT_BLOWFISH, 12 ], + [ PASSWORD_DEFAULT, 8 ], + [ PASSWORD_ARGON2I, 8 ], + [ CRYPT_BLOWFISH, 8 ], + [ PASSWORD_DEFAULT, 7 ], + [ PASSWORD_ARGON2I, 7 ], + [ CRYPT_BLOWFISH, 7] +] +?> +<html> + <head> + <style>pre{ font: 400 14px/18px 'JetBrains Mono NL', 'Ununtu Mono', Consolas, Monaco; }</style> + <body> + <pre> + +<?php +foreach($algos as $algo) { + echo "\n\nalgo= {$algo[0]}, cost={$algo[1]}" + ."\nhash= ". ( $x = password_hash('102030', $algo[0], ['cost' => $algo[1]]) ) + ."\nbase64=". base64_encode($x); +} + +?> + + </pre> + </body> +</html> diff --git a/tests/auth.php b/tests/auth.php new file mode 100755 index 0000000..26c057a --- /dev/null +++ b/tests/auth.php @@ -0,0 +1,58 @@ +<?php + +class Pass_test +{ + use PasswordTrait; + + + public function isTextPasswordValid($plain, $hash): bool + { + return password_verify($plain, $hash); + } +} + + +$pass = new Pass_test(); + +$password = [ + '102030!!!', + '1234', + 'password' +]; + + +$hash = []; +$verify = []; + + +// create pass hashes +foreach($password as $val) +{ + $x = $pass->cryptPassword($val); + $hash[] = $x; +} +?> +<html> + <head> + <title>Dev Tools</title> + </head> + <body> + <h2>crypt passwords; then...</h2> + <h2>check password validation</h2> +<pre> +<?php + + +for($i=0 ; $i < 3 ; $i++) { + echo $i ."> ". $password[$i] ." -> ". $hash[$i]. "\n"; + $verify[$i] = ($pass->isTextPasswordValid($password[$i], $hash[$i])) ? 'valid' : 'not-match'; +} + +?> +</pre> + <?php print_r( $hash ); ?> + + <?php print_r( $verify ); ?> + </pre> + </body> +</html>
\ No newline at end of file diff --git a/tests/code/abstract.php b/tests/code/abstract.php new file mode 100755 index 0000000..b153816 --- /dev/null +++ b/tests/code/abstract.php @@ -0,0 +1,46 @@ +<?php + +abstract class abs { + + public static $abs = [ + 'one' => 10, + 'to' => [20, 220], + 'tree' => [30, [330, 3330]] + ]; + + public static function foo($who) { + print_r(static::$abs[$who]); + } + +} + +class Xtra extends abs { + + public static $abs = [ + 'Oh' => 'Yoo hoo!', + 'my' => ['babe', 'be', 'mine'] + ]; + + // overide method + public static function foo($who) { + print_r(['overiding', $who, 'my']); + } + +} + +class Repo extends abs { + public static $abs = [ + 'one' => 1, + 'to' => [2, 22], + 'tree' => [3, [33, 333]] + ]; +} + +class Neva extends abs { + // use abstract's +} + +Xtra::foo('Oh'); +Repo::foo('to'); +Neva::foo('tree'); + diff --git a/tests/code/bits.php b/tests/code/bits.php new file mode 100755 index 0000000..1ee1826 --- /dev/null +++ b/tests/code/bits.php @@ -0,0 +1,51 @@ +<?php +echo '<pre>'; + + +$a = 1; +$b = 2; +$c = 4; + +echo "\n\n(a|b)&...\n---\n"; +echo ($a|$b)&$a; +echo "\n"; +echo ($a|$b)&$b; +echo "\n"; +echo ($a|$b)&$c; + +echo "\n\n(b|c)&...\n---\n"; +echo ($b|$c)&$a; +echo "\n"; +echo ($b|$c)&$b; +echo "\n"; +echo ($b|$c)&$c; + +echo "\n\n(a|b|c)&...\n---\n"; +echo ($a|$b|$c)&$a; +echo "\n"; +echo ($a|$b|$c)&$b; +echo "\n"; +echo ($a|$b|$c)&$c; +echo "\n"; + + +/* + +3 +--- +%2 = 1 then a +/2 = 1 + +%2 = 1 then b +0 end + + +6 +--- +%2 = 0 NOT A +/2 = 3 + +%2 = + + +*/
\ No newline at end of file diff --git a/tests/code/echo.php b/tests/code/echo.php new file mode 100755 index 0000000..b8b0c34 --- /dev/null +++ b/tests/code/echo.php @@ -0,0 +1,43 @@ +<?php +echo "<h3>Lorem Ipsum</h3> +<blockquote>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...<br/> +<i>There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain...</i></blockquote> +<br/> +<br/> +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sit amet hendrerit mauris. Donec fringilla, lorem vel sagittis interdum, est ligula ornare arcu, non imperdiet tellus nibh vitae ante. Aliquam non elit pellentesque tortor porttitor rutrum. Quisque at vestibulum est. Fusce ut rutrum lacus. Maecenas aliquet mauris odio, vel sollicitudin justo eleifend nec. Integer varius, mi et ultricies faucibus, turpis lectus fermentum tortor, eu auctor enim tortor ut diam. Pellentesque lobortis feugiat lorem, in blandit massa sodales sed. Ut id dui elit. Proin rutrum sagittis metus quis varius. +<br/> +<br/> +Nam interdum nec nulla non elementum. Donec id erat venenatis, convallis lacus eu, faucibus justo. Donec nec pellentesque enim, a placerat ante. Integer vehicula mauris tellus, id luctus sem venenatis eleifend. Donec iaculis neque nisl, sit amet consectetur est viverra non. Quisque imperdiet nunc quam, vitae facilisis ligula vulputate quis. Vivamus feugiat odio sed facilisis auctor. Curabitur ullamcorper bibendum dui, quis rhoncus risus fermentum id. Donec efficitur augue at pharetra interdum. +<br/> +<br/> +Ut nec sagittis odio, sit amet condimentum mi. Morbi in fermentum lacus. Praesent lectus nibh, fringilla eu malesuada lobortis, pulvinar non leo. Aenean nec lectus at dui sodales accumsan. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed ligula libero, tincidunt ut aliquet in, laoreet eu nunc. Maecenas et leo dolor. Etiam at est et metus luctus malesuada. Donec pellentesque quam id tellus rutrum, vitae hendrerit lacus maximus. Vestibulum facilisis euismod mollis. Sed venenatis tincidunt lorem, et sodales sapien facilisis et. Praesent facilisis varius orci eu finibus. Fusce convallis magna ac lacinia ultricies. Mauris a finibus dolor. +<br/> +<br/> +Quisque volutpat turpis eget condimentum efficitur. Donec metus sapien, tincidunt ac felis vitae, facilisis lacinia risus. Pellentesque tempor orci eu massa porttitor, at malesuada dolor accumsan. Maecenas sit amet maximus ex. Ut non faucibus leo. Pellentesque quis rhoncus arcu. Donec id sodales metus. Ut fermentum arcu in ex vestibulum, in tempor nisi consequat. In in interdum sem. Phasellus vulputate enim vitae augue commodo, in ultrices ante placerat. +<br/> +<br/> +Vestibulum a ex dictum, efficitur nibh eget, viverra purus. Phasellus hendrerit eros suscipit lacus posuere, sit amet fringilla eros faucibus. Praesent porta gravida leo non mattis. In pretium sapien sed neque suscipit, sed mollis augue lobortis. Cras eleifend, ex vitae ornare aliquet, nunc urna bibendum tellus, sit amet vulputate elit quam ac lorem. Sed velit tortor, posuere et venenatis nec, mattis mattis diam. Nam commodo et enim ut tristique. +<br/> +<br/> +Etiam quam diam, aliquet eget placerat vel, sagittis semper nisi. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam suscipit dolor ut fringilla laoreet. Vivamus bibendum elit sit amet condimentum hendrerit. Phasellus vehicula pulvinar rhoncus. Maecenas diam nisl, lacinia in leo ac, convallis cursus tellus. Quisque suscipit varius consectetur. Morbi semper lorem non nulla imperdiet pharetra. Cras viverra sapien nec orci malesuada elementum. Proin vel ante orci. Integer sodales, nibh fermentum molestie tempor, justo eros scelerisque enim, vitae pellentesque risus erat ac erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas erat dolor, feugiat sodales ligula id, porttitor laoreet mi. Vivamus luctus diam ante, volutpat tincidunt magna dictum blandit. Nunc tristique elementum interdum. +<br/> +<br/> +Donec eget lorem id enim blandit facilisis. Donec vel elit ut urna vestibulum faucibus et ac nisl. Cras vestibulum accumsan nibh, quis gravida urna iaculis placerat. Vestibulum eleifend, augue quis sodales iaculis, turpis arcu molestie nibh, sit amet interdum mauris neque at lacus. Vivamus non tortor sed mauris suscipit eleifend. Mauris ornare quam et ex vehicula, eu tincidunt urna convallis. Suspendisse malesuada eu justo in cursus. Maecenas risus nunc, consectetur vitae est vel, dapibus volutpat tortor. Morbi est nulla, mollis pellentesque tempor id, ullamcorper et risus. Mauris mattis nunc eu dolor gravida aliquam. Duis condimentum id mauris in malesuada. Suspendisse ex ligula, vulputate eu tincidunt sed, tincidunt sit amet mi. In non libero nec ligula convallis ultrices. Nullam scelerisque quam massa, ut condimentum diam pharetra sit amet. Quisque placerat erat nec sapien rhoncus, vel pretium sem viverra. Maecenas condimentum, neque a interdum efficitur, eros dolor tincidunt ipsum, id imperdiet quam quam sit amet ex. +<br/> +<br/> +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent rhoncus odio vitae metus ultricies, ac fermentum velit blandit. Praesent sodales dictum mollis. Maecenas vehicula venenatis risus sollicitudin pretium. Sed varius, lorem et scelerisque finibus, tellus nisl tincidunt eros, id cursus urna velit consectetur nulla. Praesent finibus vel elit eget convallis. Maecenas auctor lorem eu ex sodales, at tincidunt turpis porta. Phasellus purus justo, mattis at gravida et, tempor eget metus. +<br/> +<br/> +Vestibulum eu maximus augue. Aenean augue enim, condimentum et nisi id, tempus cursus mi. Curabitur consectetur mauris molestie tellus dictum porta. Donec fringilla justo eget massa laoreet pellentesque. Donec aliquet semper dui. Praesent ante augue, rhoncus eget consequat ac, bibendum eu nulla. Proin et erat dignissim, laoreet odio sed, gravida eros. Maecenas quis rutrum metus. Sed rutrum rutrum lacus, sed scelerisque dolor porta eget. Praesent porttitor diam sit amet ante congue, nec dictum nunc laoreet. Morbi iaculis nisl in aliquam malesuada. +<br/> +<br/> +Nullam odio urna, tristique non odio sed, tempus sodales velit. Duis vel lobortis enim, mollis placerat diam. Aliquam venenatis erat sapien, sit amet laoreet lacus rhoncus quis. Nulla neque lorem, pellentesque eget iaculis eu, ultrices at augue. Nulla feugiat elementum eros, id maximus purus. Integer porttitor blandit rutrum. Donec placerat elit magna, a bibendum lorem gravida lacinia. Vestibulum aliquet vestibulum mauris at pulvinar. Nam sollicitudin purus est, nec commodo risus sollicitudin lobortis. Interdum et malesuada fames ac ante ipsum primis in faucibus. +<br/> +<br/> +Etiam eu iaculis augue. Phasellus dapibus nec orci sed fermentum. Fusce nisi tortor, rhoncus lacinia pellentesque id, egestas et leo. Curabitur maximus vulputate leo id dapibus. Quisque pretium, metus lobortis tristique rutrum, massa mauris dapibus magna, ornare consequat risus metus sit amet diam. Mauris vitae turpis ac lorem vehicula mattis. Sed convallis neque augue, eu ultrices dolor fringilla et. Donec eu sapien congue dui sollicitudin auctor. Nam accumsan ullamcorper erat nec varius. Quisque vehicula consequat metus nec porttitor. Nulla euismod vehicula massa nec finibus. Aenean venenatis, lacus eget ornare imperdiet, lectus ligula porta purus, in imperdiet urna quam eu mi. Aenean efficitur ligula nec augue cursus auctor. Aenean iaculis tristique tincidunt. Etiam commodo bibendum odio. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. +<br/> +<br/> +Duis sed tincidunt augue, et posuere tortor. Ut facilisis eros id lacus luctus finibus. Duis a libero tristique, viverra enim id, fermentum sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas a posuere magna. Fusce maximus nibh sit amet dignissim suscipit. Maecenas lacinia purus vel sapien tempor, at suscipit ipsum finibus. Vestibulum varius, metus eu scelerisque cursus, massa magna scelerisque nunc, nec venenatis lacus augue vitae ante. Phasellus massa lacus, lacinia condimentum dui in, porttitor aliquam sapien. In placerat auctor gravida. Phasellus sit amet justo in ipsum tristique laoreet quis ac mi. Pellentesque tincidunt dignissim ligula, et finibus nisl interdum quis. Mauris rhoncus arcu dignissim, interdum odio vestibulum, rutrum mi. Donec consectetur volutpat justo eget feugiat. Phasellus enim enim, hendrerit nec tempus ac, ornare vitae quam. +"; +Benchmark::add_spot('end'); // request ended +Benchmark::render_report();
\ No newline at end of file diff --git a/tests/code/exceptions.php b/tests/code/exceptions.php new file mode 100755 index 0000000..d60fc4f --- /dev/null +++ b/tests/code/exceptions.php @@ -0,0 +1,73 @@ +<?php +echo '<pre>'; + +if (!function_exists('interface_exists')) { + die('PHP version too old'); +} +$throwables = listThrowableClasses(); +$throwablesPerParent = splitInParents($throwables); +printTree($throwablesPerParent); +if (count($throwablesPerParent) !== 0) { + die('ERROR!!!'); +} + +function listThrowableClasses() +{ + $result = []; + if (interface_exists('Throwable')) { + foreach (get_declared_classes() as $cn) { + $implements = class_implements($cn); + if (isset($implements['Throwable'])) { + $result[] = $cn; + } + } + } else { + foreach (get_declared_classes() as $cn) { + if ($cn === 'Exception' || is_subclass_of($cn, 'Exception')) { + $result[] = $cn; + } + } + } + + return $result; +} + +function splitInParents($classes) +{ + $result = []; + foreach ($classes as $cn) { + $parent = (string) get_parent_class($cn); + if (isset($result[$parent])) { + $result[$parent][] = $cn; + } else { + $result[$parent] = [$cn]; + } + } + + return $result; +} + +function printTree(&$tree) +{ + if (!isset($tree[''])) { + die('No root classes!!!'); + } + printLeaves($tree, '', 0); +} +function printLeaves(&$tree, $parent, $level) +{ + if (isset($tree[$parent])) { + $leaves = $tree[$parent]; + unset($tree[$parent]); + natcasesort($leaves); + $leaves = array_values($leaves); + $count = count($leaves); + for ($i = 0; $i < $count; ++$i) { + $leaf = $leaves[$i]; + echo str_repeat(' ', $level), $leaf, "\n"; + printLeaves($tree, $leaf, $level + 1); + } + } +} + +echo "</pre>";
\ No newline at end of file diff --git a/tests/code/interface.php b/tests/code/interface.php new file mode 100755 index 0000000..3a06718 --- /dev/null +++ b/tests/code/interface.php @@ -0,0 +1,31 @@ +<?php + +interface moving +{ + public function go(); +} + +class walking implements moving +{ + public function go() { echo 'i walk'; } +} + +class driving implements moving +{ + public function go() { echo 'i drive my car'; } +} + + +class flying implements moving +{ + public function go() { echo 'i got my airplane tickets'; } +} + + +// $driver = DRIVER; +// $ready = new $driver(); + +define('DRIVER', 'flying'); +$ready = new (DRIVER)(); + +$ready->go(); diff --git a/tests/code/login.php b/tests/code/login.php new file mode 100755 index 0000000..0842c74 --- /dev/null +++ b/tests/code/login.php @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,minimum-scale=1"> + <title>Login</title> + </html> + <body> + <div class="login"> + <h1>Login</h1> + <form action="authenticate.php" method="post"> + <label for="username"> + <i class="fas fa-user"></i> + </label> + <input type="text" name="username" placeholder="Username" id="username" required> + <label for="password"> + <i class="fas fa-lock"></i> + </label> + <input type="password" name="password" placeholder="Password" id="password" required> + <input type="submit" value="Login"> + </form> + </div> + </body> +</html> + diff --git a/tests/code/menu.php b/tests/code/menu.php new file mode 100644 index 0000000..8236f91 --- /dev/null +++ b/tests/code/menu.php @@ -0,0 +1,42 @@ +<?php + +/* menus + * -------------------------------- + */ +$menu_json = '{ + "class" : "row", + "struct" : [ + { + "title" : "Σχετικά με το site", + "entity" : "page", + "list" : [2, 1, 3], + "template" : "list", + "width" : "col-md-4" + }, + { + "title" : "", + "template" : "null", + "width" : "col-md-3" + }, + { + "title" : "Eπικοινωνία", + "entity" : "page", + "content" : "Διεύθυνση: Κάποια Οδός 123 \nΤηλ. 6976.543.210", + "template" : "static", + "width" : "col-md-5" + } + ] +}'; + + + + +$menu = json_decode($menu_json); + +echo "<pre>"; + + print_r($menu); + +echo "</pre>"; + + diff --git a/tests/code/proxy.php b/tests/code/proxy.php new file mode 100755 index 0000000..c249c46 --- /dev/null +++ b/tests/code/proxy.php @@ -0,0 +1,38 @@ +<?php +/** + * @param class: needs to be a valid (full if namespaced) class + * @param method: method to call + * @param args (array): an array of passed arguments into method call + * @param ttl (int): will be used in some cache service + */ +function proxy($class, $method, $args, $ttl) +{ + // ksort($args); // is not recursive, won't sort category keys + $key = $class .':'. $method .':'. json_encode( + $args, + JSON_UNESCAPED_LINE_TERMINATORS|JSON_UNESCAPED_UNICODE + ); + $data = call_user_func_array([$class, $method], $args); + reply_json([ + 'key' => $key, + 'cache' => sha1($key), + 'data' => $data + ]); +} + +# proxy('app\models\market\ProductCategories_model','categoryProducts', +# [ +# [ 'id'=>10100, 'Hierarchy' => '.10.10100' ], // pass category (needs Hierarchy) +# 904 // pas store +# ], +# 100 // ttl +# ); + +proxy(app\models\market\ProductCategories_model::class,'categoryProducts', + [ + [ 'id'=>10100, 'Hierarchy' => '.10.10100' ], // pass category (needs Hierarchy) + 904 // pas store + ], + 100 // ttl +); + diff --git a/tests/code/session.php b/tests/code/session.php new file mode 100755 index 0000000..478160a --- /dev/null +++ b/tests/code/session.php @@ -0,0 +1,50 @@ +<?php +echo '<pre>'; +echo "\n(in) ". session_id(); + +echo "\nsesion path: ". session_save_path(); + +if (isset($_SESSION['c'])) { + echo "\nexist:". print_r($_SESSION['c'], true); + +} else { + $number = [ + rand(1,1000), + rand(1,1000), + rand(1,1000) + ]; + echo "\ncreated random:". print_r($number, true); + $_SESSION['c'] = $number; +} + +session_regenerate_id(); +echo "\n(out) ". session_id(); + +echo '</pre>'; +### class SomeSessionHandler extends SessionHandler +### { +### private $key; +### +### public function __construct() +### { +### // nothing +### } +### +### public function close() +### { +### return parent::close(); +### +### } +### +### } +### +### // we'll intercept the native 'files' handler, but will equally work +### // with other internal native handlers like 'sqlite', 'memcache' or 'memcached' +### // which are provided by PHP extensions. +### // ini_set('session.save_handler', 'files'); +### +### $handler = new SomeSessionHandler(); +### session_set_save_handler($handler, true); +### session_start(); +### +### echo 'hm!'; diff --git a/tests/code/str-replace.php b/tests/code/str-replace.php new file mode 100755 index 0000000..f02f25e --- /dev/null +++ b/tests/code/str-replace.php @@ -0,0 +1,5 @@ +<?php + +$arr = ['welcome', 'hello', 'goodbye']; + +print_r(str_replace('e', '@', $arr));
\ No newline at end of file diff --git a/tests/compare/compress.php b/tests/compare/compress.php new file mode 100755 index 0000000..74fdea1 --- /dev/null +++ b/tests/compare/compress.php @@ -0,0 +1,80 @@ +<?php + +echo "test started... "; +ob_flush(); + +Benchmark::add_spot('query-10000-products'); +$db = Registry::use('database'); +$products = $db->runQuery("SELECT * FROM products LIMIT 10000",[]); + + + +$originalLength = $compressLength = 0; +Benchmark::add_spot('gzcompress(1)-10000-products'); +foreach($products as $product) { + $original = serialize($product); + $compress = gzcompress($original, 1); + $originalLength = strlen($original); + $compressLength = strlen($compress); +} +echo "<pre>gzcompress(1) +compressed {$originalLength} to {$compressLength} or "; +echo ($originalLength-$compressLength)*100/$originalLength ."%\n</n>"; + + + +$originalLength = $compressLength = 0; +Benchmark::add_spot('gzcompress(4)-10000-products'); +foreach($products as $product) { + $original = serialize($product); + $compress = gzcompress($original, 4); + $originalLength = strlen($original); + $compressLength = strlen($compress); +} +echo "<pre>gzcompress(4) +compressed {$originalLength} to {$compressLength} or "; +echo ($originalLength-$compressLength)*100/$originalLength ."%\n</n>"; + + + +$originalLength = $compressLength = 0; +Benchmark::add_spot('gzcompress(6)-10000-products'); +foreach($products as $product) { + $original = serialize($product); + $compress = gzcompress($original, 6); + $originalLength = strlen($original); + $compressLength = strlen($compress); +} +echo "<pre>gzcompress(6) +compressed {$originalLength} to {$compressLength} or "; +echo ($originalLength-$compressLength)*100/$originalLength ."%\n</n>"; + + + +$cache = Registry::use('cache'); + +Benchmark::add_spot('Cache-save-10000-products'); +foreach($products as $product) { + $cache->set('cache.sav.'.$product['ID'], serialize($product), 3600); +} + + + +Benchmark::add_spot('gz(ser(),6)+Save-10000-products'); +foreach($products as $product) { + $cache->set('zx.ser.sav.'.$product['ID'], gzcompress(serialize($product), 6), 3600); +} + +$maxLen = 0; +Benchmark::add_spot('sha1(serialize())-10000-products'); +foreach($products as $product) { + $original = sha1(serialize($product)); + $maxlen = $maxLen > strlen($original) ? $maxLen : strlen($original); +} + + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die(); diff --git a/tests/compare/hashcost.php b/tests/compare/hashcost.php new file mode 100755 index 0000000..7a1401f --- /dev/null +++ b/tests/compare/hashcost.php @@ -0,0 +1,54 @@ +<?php +/** + * Password Hash Cost Calculator + * + * Set the ideal time that you want a password_hash() call to take and this + * script will keep testing until it finds the ideal cost value and let you + * know what to set it to when it has finished + * + * credit: https://gist.github.com/Antnee/a072b7a3c59334bf1872 + */ + +// Milliseconds that a hash should take (ideally) +$mSec = 100; + +$password = 'MyT3ST_P4$$w0rD'; + +echo '<pre>'; +echo "\nPassword Hash Cost Calculator\n\n"; +echo "Testing BCRYPT hashing the password '$password'\n\n"; +echo "We're going to run until the time to generate the hash takes longer than {$mSec}ms\n"; + +$cost = 3; +do { + $cost++; + echo "\nTesting cost value of $cost: "; + $time = benchmark($password, $cost); + echo "... took $time"; +} while ($time < ($mSec/1000)); + +echo "\n\nIdeal cost is $cost\n"; +echo "\nRunning 100 times to check the average:\n"; + +$start = microtime(true); +$times = []; +for ($i=1;$i<=100;$i++) { + echo "\r$i/100"; + $times[] = benchmark($password, $cost); +} + +echo "\n\ndone benchmarking in ".(microtime(true)-$start)."\n"; + +echo "\nSlowest time: ".max($times); +echo "\nFastest time: ".min($times); +echo "\nAverage time: ".(array_sum($times)/count($times)); + +echo "\n\nFinished\n"; +echo "</pre>"; + +function benchmark($password, $cost=4) +{ + $start = microtime(true); + password_hash($password, PASSWORD_BCRYPT, ['cost'=>$cost]); + return microtime(true) - $start; +} diff --git a/tests/compare/md5-v-sha1.php b/tests/compare/md5-v-sha1.php new file mode 100755 index 0000000..44b5148 --- /dev/null +++ b/tests/compare/md5-v-sha1.php @@ -0,0 +1,18 @@ +<?php + +echo "test started... "; +ob_flush(); + +Benchmark::add_spot('100.000 x md5'); +for($i = 0 ; $i<100000 ; $i++) $x = md5($i); + + +Benchmark::add_spot('100.000 x sha'); +for($i = 0 ; $i<100000 ; $i++) $x = sha1($i); + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die(); +
\ No newline at end of file diff --git a/tests/compare/memcached-v-filecache.php b/tests/compare/memcached-v-filecache.php new file mode 100755 index 0000000..539b0c5 --- /dev/null +++ b/tests/compare/memcached-v-filecache.php @@ -0,0 +1,35 @@ +<?php +echo "test started... "; +ob_flush(); + +Benchmark::add_spot('query-10000-products'); +$db = Registry::use('database'); +$products = $db->runQuery("SELECT * FROM products LIMIT 10000",[]); + +Benchmark::add_spot('memcached-set-start'); +foreach($products as $product) { + MemcachedCache::set('prod'.$product['ID'], $product, 600); +} + +Benchmark::add_spot('memcached-get-start'); +foreach($products as $product) { + $x = MemcachedCache::get('prod'.$product['ID']); +} + +Benchmark::add_spot('filecache-set-start'); +foreach($products as $product) { + FileCache::set('prod'.$product['ID'], $product, 600); +} + +Benchmark::add_spot('filecache-get-start'); +foreach($products as $product) { + $x = FileCache::get('prod'.$product['ID']); +} + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die(); + + diff --git a/tests/compare/redis-v-filecache.php b/tests/compare/redis-v-filecache.php new file mode 100755 index 0000000..e59c390 --- /dev/null +++ b/tests/compare/redis-v-filecache.php @@ -0,0 +1,35 @@ +<?php +echo "test started... "; +ob_flush(); + +Benchmark::add_spot('query-10000-products'); +$db = Registry::use('database'); +$products = $db->runQuery("SELECT * FROM products LIMIT 10000",[]); + +Benchmark::add_spot('redis-set-start'); +foreach($products as $product) { + RedisCache::set('prod'.$product['ID'], $product, 600); +} + +Benchmark::add_spot('redis-get-start'); +foreach($products as $product) { + $x = RedisCache::get('prod'.$product['ID']); +} + +Benchmark::add_spot('filecache-set-start'); +foreach($products as $product) { + FileCache::set('prod'.$product['ID'], $product, 600); +} + +Benchmark::add_spot('filecache-get-start'); +foreach($products as $product) { + $x = FileCache::get('prod'.$product['ID']); +} + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die(); + + diff --git a/tests/compare/serialize-v-jsonencode.php b/tests/compare/serialize-v-jsonencode.php new file mode 100755 index 0000000..ba9ccc9 --- /dev/null +++ b/tests/compare/serialize-v-jsonencode.php @@ -0,0 +1,35 @@ +<?php +echo "test started... "; +ob_flush(); + +Benchmark::add_spot('query-10000-products'); +$db = Registry::use('database'); +$products = $db->runQuery("SELECT * FROM products LIMIT 10000",[]); + +Benchmark::add_spot('serialize-start'); +foreach($products as $product) { + $ser = serialize($product); +} + +Benchmark::add_spot('serialize+unserialize-start'); +foreach($products as $product) { + $ser = serialize($product); + $ori = unserialize($ser); +} + +Benchmark::add_spot('jsonencode-start'); +foreach($products as $product) { + $json = json_encode($product); +} + +Benchmark::add_spot('jsonencode+decode-start'); +foreach($products as $product) { + $json = json_encode($product); + $ori = json_decode($json); +} + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die();
\ No newline at end of file diff --git a/tests/compare/sha1-v-sha256.php b/tests/compare/sha1-v-sha256.php new file mode 100755 index 0000000..4d10e7f --- /dev/null +++ b/tests/compare/sha1-v-sha256.php @@ -0,0 +1,22 @@ +<?php + +echo "test started... "; +echo '<pre>'; +echo "\nsha1: ". sha1('hello'); +echo "\nsha256: ". hash('sha256', 'hello'); +echo '</pre>'; +ob_flush(); + +Benchmark::add_spot('100.000 x sha1'); +for($i = 0 ; $i<100000 ; $i++) $x = sha1($i); + + +Benchmark::add_spot('100.000 x sha256'); +for($i = 0 ; $i<100000 ; $i++) $x = hash('sha256', $i); + +Benchmark::add_spot('end'); +Benchmark::render_report('code'); + +echo "test completed!"; +die(); +
\ No newline at end of file diff --git a/tests/dotnet-pass.php b/tests/dotnet-pass.php new file mode 100755 index 0000000..191a2d2 --- /dev/null +++ b/tests/dotnet-pass.php @@ -0,0 +1,503 @@ +<?php + +/** NOTE: + * ref, original AspNet Code: + * Github: aspnet/Identity + * (path) Identity/src/Microsoft.AspNetCore.Identity/PasswordHasher.cs + * (code) https://github.com/aspnet/Identity/blob/4ef80fabf66624b464e77ac9dd6e8c4461759e0c/src/Microsoft.AspNetCore.Identity/PasswordHasher.cs + * + * credits: + * https://stackoverflow.com/questions/46753050/reading-asp-hashed-password-in-php (answer by: ZerosAndOnes) + */ + + + +trait DotNetHasherChecker +{ + /** Verify_AspNet_HashedPassword() + * + * Check the given plain password against an already hashed one + * using DotNetHasher + * + * @param string $value + * @param string $hashedValue + * @param array $options + * @return bool + */ + public function Verify_AspNet_HashedPassword($value, $hashedValue, array $options = []) + { + echo "\nhash= ". $hashedValue; + + /** original code + * + byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword); + // read the format marker from the hashed password + if (decodedHashedPassword.Length == 0) + { + return PasswordVerificationResult.Failed; + } + switch (decodedHashedPassword[0]) + * + */ + + if (strlen($hashedValue) === 0) { + return false; + } + + $hash = base64_decode($hashedValue); + + $version = ord($hash[0]); // get first byte of first hash's char + // shall be 0 -or- 1; TODO: die if not + + // case 0x00: + // VerifyHashedPasswordV2() + if ($version === 0) { + + + /** version V2 + * + algo is sha1 + * + has fixed iterations, subKeyLength, salt size + * --- + * PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations. + * (See also: SDL crypto guidelines v5.1, Part III) + * Format: { 0x00, salt, subkey } + */ + + echo "\nhash is V2"; + + // no need to decode anything else ///////////////////////////////// + + // Format: { 0x00, salt, subkey } + $iterations = 1000; // default for Rfc2898DeriveBytes + $subKeyLength = 32; // 256 bits (/8 = 32bytes) + $saltSize = 16; // = 128 bits (/8 = 16bytes) + $salt = substr($hash, 1, $saltSize); + + echo "\nsalt= ". base64_encode($salt); + + echo "\nalgo= sha1"; + + $derived = hash_pbkdf2('sha1', $value, $salt, $iterations, $subKeyLength, true); + $newHash = chr(0x00) . $salt . $derived; + + /** oririnal AspNet code: + * + * + private static bool VerifyHashedPasswordV2(byte[] hashedPassword, string password) + { + const KeyDerivationPrf Pbkdf2Prf = KeyDerivationPrf.HMACSHA1; // default for Rfc2898DeriveBytes + const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes + const int Pbkdf2SubkeyLength = 256 / 8; // 256 bits + const int SaltSize = 128 / 8; // 128 bits + + // We know ahead of time the exact length of a valid hashed password payload. + if (hashedPassword.Length != 1 + SaltSize + Pbkdf2SubkeyLength) + { + return false; // bad size + } + + byte[] salt = new byte[SaltSize]; + Buffer.BlockCopy(hashedPassword, 1, salt, 0, salt.Length); + + byte[] expectedSubkey = new byte[Pbkdf2SubkeyLength]; + Buffer.BlockCopy(hashedPassword, 1 + salt.Length, expectedSubkey, 0, expectedSubkey.Length); + + // Hash the incoming password and verify it + byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, Pbkdf2Prf, Pbkdf2IterCount, Pbkdf2SubkeyLength); + return ByteArraysEqual(actualSubkey, expectedSubkey); + } + * + */ + + + + } else + + // case 0x01: + // VerifyHashedPasswordV3() + if ($version === 1) { + + /** version V3 + * + algo is any of sha1, sha256, sha512 + * + various options (iterations, subKeyLength, salt size); + * + options are pack(-ed) into final hash + * --- + * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations. + * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey } + * (All UInt32s are stored big-endian.) + */ + + echo "\nhash is V3"; + + // Read header information (decode options) + + // Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey } + $unp = unpack('N3', substr($hash, 1, 12)); + $prf = $unp[1]; + + echo "\nunp= "; print_r($unp); + + $algos = [ 'sha1', 'sha256', 'sha512' ]; // 0=sha1 1=sha256 2=sha512 + $algorithm = $algos[$prf]; // shall be [0-2]; TODO: die if not + $iterations = $unp[2]; + $saltLength = $unp[3]; // should be > 128 bits; TODO: die if not + $subKeyLength = 32; + + echo "\nalgo= ". $algorithm; + + $salt = substr($hash, 13, $saltLength); + // calculate derived + $derived = hash_pbkdf2($algorithm, $value, $salt, $iterations, $subKeyLength, true); + // pack all parts to construct the $newHash (to be compaired against $hash) + $newHash = chr(0x01) . pack('N3', $prf, $iterations, $saltLength) . $salt . $derived; + + + } // TODO: else { ERROR on version ; die() } + + + + echo "\nnewHash= ". base64_encode($newHash); + + return $hash === $newHash; + } + + +} + + +class SomeUserClass +{ + use DotNetHasherChecker; +} + + +?> +<html> + <head> + <style>pre{ font: 400 16px/24px 'JetBrains Mono NL', 'Ununtu Mono', Consolas, Monaco; }</style> + <body> + <pre> + + +<?php + $h = new SomeUserClass(); + + $result = $h->Verify_AspNet_HashedPassword( + '!$ola_04$', + 'AMHM+lMKiSdmucVv8KhQ9yyF/sVj8Pay16HJkBDORJxvHDm0WFP2vww9DBVo3JTEoA==' + ); + + echo "\nresult= ". json_encode([ 'match' => $result ]); +?> + + + </pre> + </body> +</html> + + +<?php + +/** RAW + * + * /src/Microsoft.AspNetCore.Identity/PasswordHasher.cs + * ... +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; +using Microsoft.AspNetCore.Cryptography.KeyDerivation; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Identity +{ + /// <summary> + /// Implements the standard Identity password hashing. + /// </summary> + /// <typeparam name="TUser">The type used to represent a user.</typeparam> + public class PasswordHasher<TUser> : IPasswordHasher<TUser> where TUser : class + { + // ======================= + // HASHED PASSWORD FORMATS + // ======================= + // + // Version 2: + // PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations. + // (See also: SDL crypto guidelines v5.1, Part III) + // Format: { 0x00, salt, subkey } + // + // Version 3: + // PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations. + // Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey } + // (All UInt32s are stored big-endian.) + /// + + private readonly PasswordHasherCompatibilityMode _compatibilityMode; + private readonly int _iterCount; + private readonly RandomNumberGenerator _rng; + + /// <summary> + /// Creates a new instance of <see cref="PasswordHasher{TUser}"/>. + /// </summary> + /// <param name="optionsAccessor">The options for this instance.</param> + public PasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null) + { + var options = optionsAccessor?.Value ?? new PasswordHasherOptions(); + + _compatibilityMode = options.CompatibilityMode; + switch (_compatibilityMode) + { + case PasswordHasherCompatibilityMode.IdentityV2: + // nothing else to do + break; + + case PasswordHasherCompatibilityMode.IdentityV3: + _iterCount = options.IterationCount; + if (_iterCount < 1) + { + throw new InvalidOperationException(Resources.InvalidPasswordHasherIterationCount); + } + break; + + default: + throw new InvalidOperationException(Resources.InvalidPasswordHasherCompatibilityMode); + } + + _rng = options.Rng; + } + + // Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized. + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + private static bool ByteArraysEqual(byte[] a, byte[] b) + { + if (a == null && b == null) + { + return true; + } + if (a == null || b == null || a.Length != b.Length) + { + return false; + } + var areSame = true; + for (var i = 0; i < a.Length; i++) + { + areSame &= (a[i] == b[i]); + } + return areSame; + } + + /// <summary> + /// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>. + /// </summary> + /// <param name="user">The user whose password is to be hashed.</param> + /// <param name="password">The password to hash.</param> + /// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns> + public virtual string HashPassword(TUser user, string password) + { + if (password == null) + { + throw new ArgumentNullException(nameof(password)); + } + + if (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV2) + { + return Convert.ToBase64String(HashPasswordV2(password, _rng)); + } + else + { + return Convert.ToBase64String(HashPasswordV3(password, _rng)); + } + } + + private static byte[] HashPasswordV2(string password, RandomNumberGenerator rng) + { + const KeyDerivationPrf Pbkdf2Prf = KeyDerivationPrf.HMACSHA1; // default for Rfc2898DeriveBytes + const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes + const int Pbkdf2SubkeyLength = 256 / 8; // 256 bits + const int SaltSize = 128 / 8; // 128 bits + + // Produce a version 2 (see comment above) text hash. + byte[] salt = new byte[SaltSize]; + rng.GetBytes(salt); + byte[] subkey = KeyDerivation.Pbkdf2(password, salt, Pbkdf2Prf, Pbkdf2IterCount, Pbkdf2SubkeyLength); + + var outputBytes = new byte[1 + SaltSize + Pbkdf2SubkeyLength]; + outputBytes[0] = 0x00; // format marker + Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize); + Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, Pbkdf2SubkeyLength); + return outputBytes; + } + + private byte[] HashPasswordV3(string password, RandomNumberGenerator rng) + { + return HashPasswordV3(password, rng, + prf: KeyDerivationPrf.HMACSHA256, + iterCount: _iterCount, + saltSize: 128 / 8, + numBytesRequested: 256 / 8); + } + + private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested) + { + // Produce a version 3 (see comment above) text hash. + byte[] salt = new byte[saltSize]; + rng.GetBytes(salt); + byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested); + + var outputBytes = new byte[13 + salt.Length + subkey.Length]; + outputBytes[0] = 0x01; // format marker + WriteNetworkByteOrder(outputBytes, 1, (uint)prf); + WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount); + WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize); + Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length); + Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length); + return outputBytes; + } + + private static uint ReadNetworkByteOrder(byte[] buffer, int offset) + { + return ((uint)(buffer[offset + 0]) << 24) + | ((uint)(buffer[offset + 1]) << 16) + | ((uint)(buffer[offset + 2]) << 8) + | ((uint)(buffer[offset + 3])); + } + + /// <summary> + /// Returns a <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison. + /// </summary> + /// <param name="user">The user whose password should be verified.</param> + /// <param name="hashedPassword">The hash value for a user's stored password.</param> + /// <param name="providedPassword">The password supplied for comparison.</param> + /// <returns>A <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.</returns> + /// <remarks>Implementations of this method should be time consistent.</remarks> + public virtual PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword) + { + if (hashedPassword == null) + { + throw new ArgumentNullException(nameof(hashedPassword)); + } + if (providedPassword == null) + { + throw new ArgumentNullException(nameof(providedPassword)); + } + + byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword); + + // read the format marker from the hashed password + if (decodedHashedPassword.Length == 0) + { + return PasswordVerificationResult.Failed; + } + switch (decodedHashedPassword[0]) + { + case 0x00: + if (VerifyHashedPasswordV2(decodedHashedPassword, providedPassword)) + { + // This is an old password hash format - the caller needs to rehash if we're not running in an older compat mode. + return (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV3) + ? PasswordVerificationResult.SuccessRehashNeeded + : PasswordVerificationResult.Success; + } + else + { + return PasswordVerificationResult.Failed; + } + + case 0x01: + int embeddedIterCount; + if (VerifyHashedPasswordV3(decodedHashedPassword, providedPassword, out embeddedIterCount)) + { + // If this hasher was configured with a higher iteration count, change the entry now. + return (embeddedIterCount < _iterCount) + ? PasswordVerificationResult.SuccessRehashNeeded + : PasswordVerificationResult.Success; + } + else + { + return PasswordVerificationResult.Failed; + } + + default: + return PasswordVerificationResult.Failed; // unknown format marker + } + } + + private static bool VerifyHashedPasswordV2(byte[] hashedPassword, string password) + { + const KeyDerivationPrf Pbkdf2Prf = KeyDerivationPrf.HMACSHA1; // default for Rfc2898DeriveBytes + const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes + const int Pbkdf2SubkeyLength = 256 / 8; // 256 bits + const int SaltSize = 128 / 8; // 128 bits + + // We know ahead of time the exact length of a valid hashed password payload. + if (hashedPassword.Length != 1 + SaltSize + Pbkdf2SubkeyLength) + { + return false; // bad size + } + + byte[] salt = new byte[SaltSize]; + Buffer.BlockCopy(hashedPassword, 1, salt, 0, salt.Length); + + byte[] expectedSubkey = new byte[Pbkdf2SubkeyLength]; + Buffer.BlockCopy(hashedPassword, 1 + salt.Length, expectedSubkey, 0, expectedSubkey.Length); + + // Hash the incoming password and verify it + byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, Pbkdf2Prf, Pbkdf2IterCount, Pbkdf2SubkeyLength); + return ByteArraysEqual(actualSubkey, expectedSubkey); + } + + private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount) + { + iterCount = default(int); + + try + { + // Read header information + KeyDerivationPrf prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1); + iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5); + int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9); + + // Read the salt: must be >= 128 bits + if (saltLength < 128 / 8) + { + return false; + } + byte[] salt = new byte[saltLength]; + Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length); + + // Read the subkey (the rest of the payload): must be >= 128 bits + int subkeyLength = hashedPassword.Length - 13 - salt.Length; + if (subkeyLength < 128 / 8) + { + return false; + } + byte[] expectedSubkey = new byte[subkeyLength]; + Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length); + + // Hash the incoming password and verify it + byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength); + return ByteArraysEqual(actualSubkey, expectedSubkey); + } + catch + { + // This should never occur except in the case of a malformed payload, where + // we might go off the end of the array. Regardless, a malformed payload + // implies verification failed. + return false; + } + } + + private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value) + { + buffer[offset + 0] = (byte)(value >> 24); + buffer[offset + 1] = (byte)(value >> 16); + buffer[offset + 2] = (byte)(value >> 8); + buffer[offset + 3] = (byte)(value >> 0); + } + } +} + +--- +*/ diff --git a/tests/mail.php b/tests/mail.php new file mode 100755 index 0000000..5c42b65 --- /dev/null +++ b/tests/mail.php @@ -0,0 +1,2 @@ +<?php +mail("gx23100@gmail.com", "test mail", "test message", "From: noreply@roptron.gr");
\ No newline at end of file diff --git a/tests/php.php b/tests/php.php new file mode 100755 index 0000000..58ef35c --- /dev/null +++ b/tests/php.php @@ -0,0 +1,2 @@ +<?php + phpinfo();
\ No newline at end of file diff --git a/tests/repository.php b/tests/repository.php new file mode 100755 index 0000000..5da4403 --- /dev/null +++ b/tests/repository.php @@ -0,0 +1,65 @@ +<?php + +use app\models\market\Market_repository as Market; + +// reply_json([ +// 'pool' => Market::echo(True) +// ]); die(); + +$shorts = Market::echo(True); +?><!DOCTYPE html> +<html> +<head> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script> + <!-- and it's easy to individually load additional languages --> + <!-- + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/go.min.js"></script> + --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/sql.min.js" integrity="sha512-efGcw9G3wD5/VEKACpydwQLvsYs8/QEWGLqnrMp+cEF5jFVdJmbmf3+D+y1LmoQR1IbtzO9XUCTeZhJ1riqX1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> + + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/atom-one-light.min.css" integrity="sha512-o5v54Kh5PH0dgnf9ei0L+vMRsbm5fvIvnR/XkrZZjN4mqdaeH7PW66tumBoQVIaKNVrLCZiBEfHzRY4JJSMK/Q==" crossorigin="anonymous" referrerpolicy="no-referrer" /> + <!-- + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/atom-one-dark.min.css" integrity="sha512-Jk4AqjWsdSzSWCSuQTfYRIF84Rq/eV0G2+tu07byYwHcbTGfdmLrHjUSwvzp5HvbiqK4ibmNwdcG49Y5RGYPTg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> + --> + <style> +body { font-size: .92em; } +h3, h4, pre, code { font-family: 'JetBrains Mono NL', 'Consolas','Monaco', 'monospace', monospace; } +h3 { padding: 2em 1.5em .5em; } +h4 { padding: .5em 2em; } + </style> +</head> +<body> + <?php foreach($shorts as $label => $sql) : ?> + <?php + $args = explode('_by:', $label)[1]; + $argsArray = explode('_', $args); + ?> + + + <h3><?=$label?></h3> + <pre><code class="language-sql"> + <?=$sql?></code></pre> + <h4>apply:</h4> + <pre><code class="language-php"> +use Registrty; +use app\models\market\Market_repository as Market; + +// ... + +Registry::use('database')->runQuery( + Market::pull('<?=$label?>'), + [ +<?php foreach($argsArray as $holder) : ?> + '<?=$holder?>' => ..., +<?php endforeach; ?> + ] +); + </code></pre> + + <?php endforeach; ?> + + <script>hljs.highlightAll();</script> +</body> +</html> + diff --git a/tests/service/entropy.php b/tests/service/entropy.php new file mode 100755 index 0000000..6401ffd --- /dev/null +++ b/tests/service/entropy.php @@ -0,0 +1,61 @@ +<html> + <head> + <title>Dev Tools</title> + </head> + <body> + <h1>Supported Crypt/Encrypt Methods</h1> + + <table width="100%"> + <tr> + <td width="50%" valign="top"> + + <h2>CIPHER Methods</h2> + <pre> +<?php +$ciphers = openssl_get_cipher_methods(); +$ciphers_and_aliases = openssl_get_cipher_methods(true); +$cipher_aliases = array_diff($ciphers_and_aliases, $ciphers); + +print_r($ciphers); + +print_r($cipher_aliases); + +?> + </pre> + </td> + + <td width="50%" valign="top"> + + <h2>DIGER Methods</h2> + <pre> +<?php +$digests = openssl_get_md_methods(); +$digests_and_aliases = openssl_get_md_methods(true); +$digests_aliases = array_diff($digests_and_aliases, $digests); + +print_r($digests); + +print_r($digests_aliases); +?> + + </pre> + + <h2>HASH Algorythms</h2> + <pre> + <?php print_r( hash_algos() ); ?> + </pre> + + <h2>Random</h2> + <pre> +random_bytes() +32Bytes: <?=bin2hex(random_bytes(32))?> + </pre> + + + </td> + + </tr> + </table> + + </body> +</html> diff --git a/tests/service/lorem-md.php b/tests/service/lorem-md.php new file mode 100755 index 0000000..c7b8d0f --- /dev/null +++ b/tests/service/lorem-md.php @@ -0,0 +1,71 @@ +<?php + +use Registry; + +define("LIMIT", 50); // number of random records to make + +function lorem_md() { + // create curl resource + $ch = curl_init(); + + // set url + curl_setopt($ch, CURLOPT_URL, "https://jaspervdj.be/lorem-markdownum/markdown.txt"); + + //return the transfer as a string + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + // $output contains the output string + $output = curl_exec($ch); + + + $title = substr($output, 2, strpos( $output, "\n" )-1); + $body = trim(substr($output, strpos( $output, "\n" )+1)); + $intro = str_replace("\n", " ", (substr($body, 3, strpos( $body, "\n" )-2) . $title)); + + + + // close curl resource to free up system resources + curl_close($ch); + + return [ + 'title' => $title, + 'intro' => $intro, + 'body' => $body + ]; + +} + +$rand_content = lorem_md(); + + +for ($i=0; $i < LIMIT ; $i++) { + + $rand_content = lorem_md(); + + $id = Registry::use('database')->query( + "INSERT INTO lesson (title, course_id, intro, `body`, `status`) + VALUES (:title, :courseid, :intro, :body, :status)", + [ + ':title' => $rand_content['title'], + ':courseid' => rand(3,11), + ':intro' => $rand_content['intro'], + ':body' => $rand_content['body'], + 'status' => rand(0,1) + ] + )->lastInsertID(); + + Registry::use('database')->runQuery( + "INSERT INTO lesson_privilege (lesson_id, privilege_id) + VALUES (:lesson_id, :privilege_id)", + [ + ':lesson_id' => $id, + ':privilege_id' => rand(1,2) + ] + ); + +} + + +?> + +done!
\ No newline at end of file diff --git a/tests/service/mailjet.php b/tests/service/mailjet.php new file mode 100644 index 0000000..8e97715 --- /dev/null +++ b/tests/service/mailjet.php @@ -0,0 +1,56 @@ +<?php + +$envelope = [ + 'email' => 'piipiis@gmail.com', + 'name' => 'Test User', + 'subject' => 'Some Subject', + 'body' => "Ευχαριστούμε,<br> + για την εγγραφή σας στο <b>Classroom</b>.<br> + <br> + <i>Καλή συνέχεια!</i>." +]; + + +$body = [ + 'Messages' => [ + [ + 'From' => [ + 'Email' => REPLY_TO_EMAIL, + 'Name' => MAIL_FROM_NAME + ], + 'To' => [ + [ + 'Email' => $envelope['email'], + 'Name' => $envelope['name'] + ] + ], + 'Subject' => $envelope['subject'], + 'HTMLPart' => $envelope['body'] + ] + ] +]; + +$ch = curl_init(); + +curl_setopt($ch, CURLOPT_URL, "https://api.mailjet.com/v3.1/send"); +curl_setopt($ch, CURLOPT_POST, 1); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json') +); +curl_setopt( + $ch, + CURLOPT_USERPWD, + MAIL_PASSWORD +); +$server_output = curl_exec($ch); +curl_close ($ch); + +$response = json_decode($server_output); + +echo '<pre>'; + print_r($response); + echo "\n\nstatus: ". $response->Messages[0]->Status; + if ($response->Messages[0]->Status == 'success') echo "\n\nSuccess = true"; +echo '</pre>';
\ No newline at end of file diff --git a/tests/service/memcached.php b/tests/service/memcached.php new file mode 100755 index 0000000..c925488 --- /dev/null +++ b/tests/service/memcached.php @@ -0,0 +1,12 @@ +<?php +$mc = new Memcached(); +$mc->addServer("mymemcached", 11211); +$mc->add("key1", "value1"); +$mc->add("key2", "value2"); +$mc->add("key3", "value3"); + +echo "key1 : " . $mc->get("key1") . "\n"; +echo "key2 : " . $mc->get("key2") . "\n"; +echo "key3 : " . $mc->get("key3") . "\n"; + +die();
\ No newline at end of file diff --git a/tests/service/redis.php b/tests/service/redis.php new file mode 100755 index 0000000..d9b7778 --- /dev/null +++ b/tests/service/redis.php @@ -0,0 +1,27 @@ +<?php + +$data = [ + 'test' => ['Redis', 'is', 'working'], + 'redis' => '!!' +]; + +try { + + $redis = new \Predis\Client([ + 'host' => 'redis' + ]); + + foreach($data as $key => $value) { + echo $key .' '; + $redis->set( $key, serialize($value), 'EX', 60 ); + } + echo "...\n\n"; + +} catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; +} + +$test = unserialize($redis->get('test')); +$redis = unserialize($redis->get('redis')); + +echo implode(' ', $test) . $redis;
\ No newline at end of file diff --git a/tests/userman.php b/tests/userman.php new file mode 100755 index 0000000..3474a39 --- /dev/null +++ b/tests/userman.php @@ -0,0 +1,27 @@ +<?php +namespace tests; + +//use UserManager; +use app\controllers\Classroom_user as CU; + + +//$a = new UserManager(); +// +$u = new CU(); + + + +/* +class ClassroomUserManager extends UserManager +{ + + private $user_identifier = 'email'; // identifing user field (username, email, etc ) + + public function __construct() + { + parent::__construct(); + } +} + +$u = new ClassroomUserManager(); +*/
\ No newline at end of file |
