When a user signs up to my website, for example, I create a unique string of length 40 and insert it into the database. We then send an email to the newly signed up user containing this unique string in the form of an URL, and this all works fine.
But how do you create and insert this signup entity ensuring that the field with the unique property is actually unique?
My current approach is as follows:
$key = '';
$repeat = true;
while ($repeat) {
$key = generate_hash(40);
$is_unique = (count($model->get_by_key($key)) === 0) ? true : false;
$repeat = ($is_unique) ? false : true;
}
// At this point I know the key is unique and can insert it...
I am not happy with this code, as I try to avoid while loops in general. Is there a better way to achieve what I am doing here?
The bottom line is that the MySQL field containing these keys has the unique property and I need to know that no unique-violations will occur when inserting these keys.
Ok, basically you have two approaches.
Let the DB handle this and use UUID() to create a unique identifier that you can use in the emails.
According to your MySQL version you have some options:
A. With MySQL 4.1 and above you can use the function directly with INSERT INTO:
INSERT INTO table_name
(unique_id, field1, field2)
VALUES
(UUID(), "smth", "smth")
B. With MySQL 5.0 you can create a TRIGGER and have the unique field automatically filled upon insertion:
CREATE TRIGGER
unique_id
BEFORE INSERT ON
table_name
FOR EACH ROW
SET NEW.unique_id = UUID()
You can check programatically if the the generated id is really unique. The same you are doing now but you can refactor the code a little bit like so:
$key = generate_hash(40);
while ( count($model->get_by_key($key)) ) {
$key = generate_hash(40);
}
//here you have an unique id in $key
There are built in unique id functions in almost every language for that.In php,
echo uniqid();
You can generate 256^40 different 40-characters strings.
Sun will explode before you generate 2 identical strings.
You can use md5(time()) as your unique value instead. md5 of time wouldn't be same for each user submitting.
$time = time();
$md5 = md5($time);
As long as md5() just containing 32 string length, you can add an unique word after the md5().
$unique = $md5."uniq1234";
Now you have 40 unique string length. At last you can add $unique as your unique value in database
You can use this function to generate uniqueID ,
function keygen($length=10)
{
$key = '';
list($usec, $sec) = explode(' ', microtime());
mt_srand((float) $sec + ((float) $usec * 100000));
$inputs = array_merge(range('z','a'),range(0,9),range('A','Z'));
for($i=0; $i<$length; $i++)
{
$key .= $inputs{mt_rand(0,61)};
}
return $key;
}
echo keygen(10);
Basically I need to insert a random key along with the users ip address and web browser into a MySQL table; This is for authentication etc and this key must be unique.
However, I seem to of found that the use of "goto" in php is hugely discouraged, I need to make a random key, check if it already exists and if it does create and check another key else just insert the key.
I tried to to use on duplicate update but it didn't seem to work at all:
INSERT INTO fkey (fkey,ip,browser) VALUES ('$subhash', '$ip', '$browser')
ON DUPLICATE KEY UPDATE fkey='substr($sessionID,$rand,$rand+29)';
I am unsure of how make this process as efficient as possible, I tried having an continuous while loop of which is only skipped if the key if unique but it turns out while(true) is also discouraged.. Admittedly I could use now() etc to assure uniqueness but I am also simply just curious on how I could solve this without the use of such.
So I could solve it through current using time and dates in the hash but I am just curious of how this is done without that.
function fkey($sessionID, $mysqli){
$hashed = hash('sha256',$sessionID);
$rand = rand(2, 34);
$subhash = substr($sessionID,$rand,$rand+30);
//$subhash = 'b4';
$ip = $_SERVER['REMOTE_ADDR'];
$browser = $_SERVER['HTTP_USER_AGENT'];
recheck:
if($stmt = $mysqli->prepare("SELECT id FROM fkey WHERE fkey = ? LIMIT 1")){
$stmt->bind_param('s', $subhash);
$stmt->execute();
if($stmt->num_rows > 0){
$rand = rand(2, 34);
$subhash = substr($sessionID,$rand,$rand+29);
goto recheck;
}else{
if($ins = $mysqli->prepare("INSERT INTO fkey (fkey,ip,browser) VALUES (?,?,?)")){
$ins->bind_param('sss', $subhash, $ip, $browser);
$ins->execute();
return $subhash;
}else{ return "fail1"; }
}
}return "fail2";
}
you can pre-populate a table with random unique keys. in the example below i sucked in 100 from a previous create to determine the speed in doing selects. note that on my dorky mysql box creating a row of varchar(128) or 110 can do about 20 per second. but a select can do about 12000/sec. if you secure your mysql appropriately, can say have an index on id plus the random key plus a column specifying if it has been used yet, and load up say 10k, you can just use them, and mark them as used. there are a 100 ways to do it. if used you can always delete them.
<?php
$authids=array(
"0N9nFd8mIkyWYh0Nw7ZW5LGrGLEy93saQBxwOFSx0rtYJuMgCMcHxT9dEOMORfYIQveFb7dbyHaicXyOJLvhFEvkti8kx73oCh4Ooh0XZbgb8P",
"odgKwd1SXazjyevKMRFcNIhJXUOtUn8iBp37C40AfzTNOpxBgcN4V4NTZBmUZvdAVgHxlH8Ah1o6rVIH8wL4AzXAbkvaPILKYsikarUssiyUeh",
"4e9pc9oGFvMMJBRbyQr2xSneVVlzE6xJkH9xQxdw30iMC9Xb0pdxhBLcw7MbekVy246TCkpFkHsXRp8RPlp6Xbjti5FwqB5tGcmiwLYQtrOlRX",
"Y1WtAdCpF0JmDxBRxi4c3XaKRuj6H1bF388ElL30LMmokYgShl4kif4aKohrqs6tAf7W1bXNXjbiisazNeT6uYhemyFM0MgA1ow3ztQxN2P6u0",
"qURs5KjQNiLzW3YYTFYEBOmaiMUomXjMRafWUyMIRyiNChLwWJaxywIQjCfFAysrJHoDgam8JEVmVHSRr2pZz7QSK5ykE1MnIa0Zlm7513rWLj",
"7sNG0Sh9wpX6td6eqkAanNzZ2hgLawShYFYZyf94F6b8jimKCXUZKuYMLexVLqdK5bKErUJ60UekcB4PyZOitM4f1CaN2ny8yjM0dv6dqlyDXD",
"YxOtazf0TtwkGezi5R30DVBVpXkP7xL64zAe9Pe2jLnZ0Xi5Om6shHnHFHwNfiTjRty0jN3DyrDyoWEdiKFAs3h7LOV06PjYjSZDF3geuUNTQr",
"st6JfSN9r1qCc0yRGp8izo12XggkZkWrN3b3VYcn0DZcDx4kXcCwAEzyUQSTaPlYSw1OvebvRaIvIMPGYrdz5M7ZD0TNPeMILOxh2INUTvpCif",
"jOhaI6eJa8C648rqcogyMjhe2LudixUClcM4i1Ns9pzey0EKpVibfAqhmVvFsqhOC3SV5Fnf5XtDY8nn3GzihZADU6inwAb9E34JIsYOpsrnAP",
"atPdkwKXseCFzL0j4qa5dhCEBJ0cjJ7ucWIxtsuWH7BgTCAX2K3g1GVDqWPJFWdSSWplpUh61TmUwWSzHVPIBLl1HaLm7ZeZVElkyDrzxNu3Km",
"8GVpFlt6KOBCFvH2EeTzGXroO0CHxSjGyf5eAyllnWY2sF56TYGAV7YK7AsFtMl21rgC0BXnyWp1Bv7vtN5pV4a2FCI8o4apvr2v30TCWjDxOK",
"s50W5ccqzkkpHpd63Y6bvzgd53qy1EntJoqOADfaXzzFYMM1KSdgrttxxU6zyu2iSt7t6mD4WcJVZwXJoa0QEuocouLXYNfRhnknKYsHbcCaIA",
"kk8icwACb3j2Z2OM3lHJOXMJrSdJg8LAtTSFqsiBwBEwEtiIPZrDXemo6z7nITYbNRRdk9PRKtopWH8MGApEPM2Vmaj53ihQ984uhTl2mJrjqA",
"PKXIenpXnSHcb759PwpfhcsiiaOSo4xdPuW3Sm1geItpQyzG4YVmboEtyslWxSamn7pftrwI9Z70xGGCFCYQ0Cky5FvCyGYVNobhPHZYG7YeOF",
"LxjdBBup57A3O72a9AS2fZ2ck8Wx0moMUIZvjuVpBvtqCwAM6sPlsSyM0uk1QJNLrNgLhcaTHEjkaU7gnWCQOaDPEXQvHEg8rxUJJ5CrJWLURS",
"cM55TkqyiAeQcIBlPiy2JAFSWZkAHz2Tl8YftoNLZ1CbKdwzw4BfFg8BgsbX1eRnnPCQeqCdseocrVLXZndFElhUOtSQHJe5zRVNhx0JMoVejH",
"LBzYGkuWRw69WjnuBtIoledEB5YJiYK4Aj2gDxdv3jE0D1vfvdEQrSu3YtMgrxl2RoiuVwZZPEZtGuJbHn29fxce0ZusxPvoeNS9jS99w8DcDm",
"qPKAWimz39YF3D4ERIwy2sxlTdY7LsqcibMft9OwjNcmrg1iZxR10omTCl1nNsz6Dml7waEQXQdo7eH6Mz7NYuHAPIYDaxJOU5VqfzhdquCxJk",
"bihI6mrkSuYChEoWbDkIJpnOYqDERdk2wBKCXcWQHVsZzRWLvgtfFR3EhGj8UDbrfW3d903QVwPvoLhT2K8HBcmTTF2Nidey9iLijO9ekYKIK1",
"SoarFLmefQrI4UuQGcUsDQDYTHLaxFnp4yRJkeYz4ph9jLZZYUsCK6BDNmOl2cL6KCQ4QODVdV4xG4xFZZhJ5SnTfcehoZo8Cedt3RohMtOtxl",
"ITouzjkXHnRoelxMwR3pdh6hyg0RKOTtHiYgBiejG6IVrfHX7Lnk2tBAKBsvqlZ7EXofgDyWJhSbwz8DkwXmZzXKbpfBLfJpc7FsLepuvhF1RO",
"2mOoHz4XnfFre7qcQvNd4z8rEA5OjQ7lcVJUvORS4xjiEKuvghIkQRLvrQjKHr6TmQNREFKId40RPvn5N5pEXb9o2t9JUfDh6r9K7TtkYucNZz",
"EquImfHavYc7dGT6Mjdo8xXbSZ72CnehOIZaXHltGxATeu01NepWLn8EmfHZDVgrEgCCXX5DvGxJbyKZMaWyx4dUkUTXQaovr17pYd3tUBd69Y",
"WReLfasvrh5B88shBqp22zTImE47Zv3VmiHCs98TreuAnXSYni0qST9exdlxJot6HaI9kR3L5xmsverTxrkpltDTHZqqnTw43feo7h9cPwFlL6",
"huA2kum0baUvNg2se6Ui0MswlIYezvgQZRTklfkwqf2dw4FKaz2amvHIdGWNbdDb4xvpMQWc6YqC26mcFpn2U5K8LHVXUz9Z6FoTwk5CiwelCB",
"cttEp6bR9jTz5Q6yc1vGYISECws0fqusTX6j3ibdC4MHUTg7VMOTuGx7c08srCUlz1FDjQQWUDDPxUXsGLmbrUiEUq6l20HC1mglc7h7LVXiPU",
"GP2q9Ga6DF9X2xKc5VKX0UmTYejmh3UXTXo2Ez9ieifgP0sUVdSW7eP6t8tKcnI5l67ZFhiUzxaoyDjuQbqYqg4TpxEBVnGhuOh95z3E7e3FRm",
"iSSchAs9ZP6GqUAC2pv7q9Dp2Fv9sRrKKkX1UpbUfhBFbcieBOm1XZr0EWa7OBSyVPAQfLLu2maeystahPbeODftApAo1tXXixNyjy2mVdBtG4",
"zODIdKbMCGbVK3tkJAxli94546Cy0UNAJqiWauINbUIVXcfGMN24W690dMzeGnOqN7nYB6LM0uIXGYEsLGxINHJ0tjfaG3BuaYsM5ez5Ih3pgH",
"GU2Qs5dbmTncpSI7mDIJKteP5dfp6n0Ni2DK8RWuKkGacphz30jNuxDzKSYRgZFy2ijaafEUzl5MLnlOoEBScerX7qPnpuWsNfCXvhS5CXSold",
"q766yMq6TV58WK70sArvZKIkFmqqSAGiHNpfzPltLqCHbJIDk98kTREzd505FHonuNC4DYxop95BTOedXnxRecrrisxY9VlDIXImWfKlpQWiFb",
"nVWyU0YqWuygwZjL7vPppXTqP4dDFpu3lqBgrAGn4fEBeYmmtcMT9GkYKxCpX7six3zZDfnIv1kJ0G6uTSn2yH1ieEHbL9ujd3iRiGzNHTxHAE",
"hFSt1bfzMxusEMRng2w3wBUQaSFe2COkiGNkS2TEAo6eaYBr07uwJpnTh38kGWEYCsiuuc94BgjLeUde2ILM78FpcOJSKoQmQ8Rll1pWhJIvDV",
"Tw7lU5cAefnywt9tFWAeki8QJKvhYa6RGdcBjpbyEz7a2gEIdeWyw5pgPUyN5EFMSSnchzKW8R6a8LSmZPVwUkMKfkykZe6R6u4n3OjbGqmPbf",
"2dW5Qq9RkWpXQwZl2LGeOEA7woMkh1cje9p5zzXUwmRmSQIUCo8r2Jzz8lTqn6JCf9HPIFJe1ABUrjP4IYvLH5lQqegOl0qB98qSO96PKIKb2z",
"mycn55dTfLHIz8N7pNwRV585lNH5od9LLm8RrmLH7spHAdO00lSWr01MNJScW2XIo6zQskxANXhna5nbrf7Sf9E3SxfPAdxZk6QMrnnelEBwKZ",
"Vy07268pzr0XdxSds8zfLNNO947SWXERvFYyL7XlzYiMvaZYjzd5m0Uw51o1Z3TvIS3uZ0PyZ8lujlsDUGIhHCNMEcODgH8Yzbszci8bqtFJO8",
"pUYpffU5tksQ5Ai3xChkfdSH87IUE0m3UlsaBng4HIVNjdQRQ8b6l3NubvpPwMSr7lCIJSNqBJeUW5LNdXTz0G4cct1IfUangM6ZETqgDEaAKW",
"GmRyQwiAhUDlJlQQrIF0wjwnlFCBsGF82xHT30tlU6GDsxuTg9UMtq9P6Mqys6HuDpoHpR2jYJXqgrkwBei5EsUKekjGq0b4pzLOrO8px5QOxa",
"jsSWAdSCUd2DtMZez84fG7C5epU21Gvk8ohIC9kwmn9Pa94Ji8ZYfB4u1Yx3E3oMrFv4PPAbdJ1nS57ae69uIdYKbvNPycC0R75GXFSapTxhZF",
"Z0PB4nV3QgFjGUOjzSxSHyKQDxZ9U84T8Tuchqg8HVrnQfGq7eiPN2FqAFAuNEnWyS9QipY0lpnbF4CNjUC6XixxY72MLpIkiRaAh8BDyZOd3r",
"XzGH8PX6AUK9gEF8LgyqBNHcsyGxJkwGTcn21l9CgUMxysFkIeKj2swu1d1LxysrKQuMbDpsxbZ6DFqlTbFVDbqForqW0SoKISwUwVn47maL2B",
"VgtOicMMkzONnCQmJezC02JmsoWSRQYN7sBpEocZX1MlECHoQh0RjKdL9aD01CO95pyJOLJLNv7r8OQZ5QQpB4bKfOLhrzrwZZgNLZyzvF0DuR",
"hmew39W3lvjmrYP4aTEusVJQFDHNr9YIwcezmbCHGW48UTc4NQzgMj6rWOfnXd5tqk2MvFucBykvsxAfo9vasCCpqRMn4SQudTgIyLVajgGMNg",
"qETGm4HI5YdsvRC74ytdjQgObMLchjqIXkojp51v3fYz6AHa8ans1Egcr2pImQqjbPDAVF5YU4y1EgbNqzfsdwEEz4nVVNf6DTGyzMxuQ6vvmG",
"YCptaRL4cGizLZDUD5pDZjYvSAsOIrBH41afSVj5CCEoBiifnHTn1RSUrkIaMkRRl16eXpjz2XXEfgTCXMZZDST5dBfZV7Rh8Xv5nOFpMD31TW",
"KsM5f3iqqnGBmW6bKnfVeeNd3N7vsoKdRxj6ABx1YdDlaJwU7LQl0Ez3rGzT4k6WRp3r1As0O5lYPSTXEJjEnSIOyhIDBPzseCUgdng1sCZivS",
"BqKCKeFgfvoGG7hPuYmJFCHD1E5VaoVMOGpzU5QaAeQgm86Q6tAL5hp7Wu27SYTHFigzo6KYlBfHJlxQO7BUp11lv4so2m6HFmh3t22PDhwnC3",
"Fq16e19wyk0SGBiJT15ZSfufb8Hv9ElO5mVko4QXpQP5s7Pm9Ul1aQhlYYQ8DcWJyS3XWUUlKJrcQhzZbU1mLiHKgySUKPDjHGgEAaZlUryLI7",
"tiqE3JZUXeTnrLTr9lXPztDlhvk8o5ZSnpxr8wl6Keuc0nDaJA0i4DEl9Yty4tqrTYT2uf8fuCru04EJFE2JiG5sFy0J2rbVp4YUk69OJAiKFW",
"l6IzJkUTsUhfGupzFoh9S6YiU7iKOxi9D1JmlEgOyy4f3uOIS6SLcQ36XmQLU9VxaFUwkblSJq8MUXvN3nygdCmaYdWSnSqxxl4RwqKfQS2KQx",
"gFZM1YcX89sRuJnJBFzVoO1rrfIJ1zIhfI4hGgePqHGVq3E1JdW72YyuehdfRWx6FCnlTCajjReKUTMD7JK9IjEWBScsPJzulXQfz0yTSNEMHq",
"T9ndbkiCjsLYc5e2CTswLuEe74PtmyXgIktUFLwZeiYqncsZ5VvRpa6weV0BuYRcjl6Y7DYlVWLi8eieaO5zYb6d67OB5FNo1Un8xltsifLqt4",
"IhfRwL3hZCXyAGgHhZxSGLidh2nn5U8NbnEI9I08lYHVEYDWXaPEV7SdafBgaJ3l6I4gr5pM36II4lE2vtHrBzEMPf2ZY6l5OpmfuL2ySKgX5V",
"ubp25oyvBzdAPuXfdzFPWPBHnKPCV4zpgYsln1RZA4AqyxFL7lB3acKyXzaSEKhUIJg6K75lbGLKerwlM7oXj9vgJF8npqi8ayeVFkhR02Beu7",
"CGYZyYgumosn5RFHyi3eJAYEu7lIMJspqqoYoFtK3V88NOPl6TzQtxvXFQFrA8Q0yfZWUsHYoQ6cEWxLP7BiF6fkXVMx3CxCSxyN0gLp6RBKO9",
"DUkxkYp7hsLTdZoVHFcYkPwqroX4Bdae8vLstbzLElESk3N2J013PxthWrlxFwLN1xfuIPgmaUevY2xH3zKS6ea3FvAk1l72SnxBdNYnIdTGfr",
"eNWdhPqwdZXOaJF6ata2CQ0zgKzhBxoPkk3B9t8nt5bDORKZlU2XL2w1N6ioDGeY1hAaKIxeOJRCABCVwETiHqjuxCTaj89kpJvas3ogMgSnSv",
"bWUlH46vDHt9S3Mq9nypDfaeV2si6W1iTWDB0K6ErANjEAKOYidBxnPsqhLxeMP7JsJJcPoEqcY4MISL06mxub0VtMsHyhPiKy1XopBOBAToiM",
"fBQXJSpThFBGhWqqKE1VvJzavLu6xf6NRWLBPbu6R5M82dyMSzHnjhyO22VAi1o9YaLNlfUclGlnUT9MtQaM8IBbLwL3yadwkZkFeeSzVdXP66",
"qjVf5QkfQ35PqjjiASIO543M0WWR4XXugTKmJ5Bz8Gpy0IQABypHCstDoqvtnsYElJ05OCFWi4ujNkUoTj5vMy9bZEFn7D1tn2ybEe8XiDg5Xa",
"6B4HMtvdSC1wkwSyknp8K7wUSumEmASsbXaYqGbjidPCJIb45AcPIIKAd7eAH73T4dSvU4OchEP1m05sBhij03Tea8OSfSLj6DO0HDcZh10D25",
"K830rbGVtSK7juL9r1z7BuHuEi0SbjDVsGVUSCPmuAtN4fWwhwDT1lnGEoyPIbKaSG4LiT7NtBByRy484I154pMINkxvwiFoZJaiCh55TGDKeI",
"cvu0CGhQ6WtOBQr3QyHVhHQY6wBfRwt32X4FEmvKiYzTP0XGzEBRmsQsYrIQXbU08YFNkaxC96wZ7tFG7hyuKoWJPFzNQtNZrsMLDkoNrUMyns",
"kigZu2NNulOIMVaISMhPCncHrEwkKHr50I4uKShfe6X028IUU0JxnWePBL9msBrtjwX3pfiDlgDnomijn1QLY5AzQKVjlnMETKHj0ZWmfAJEX1",
"Ia8V0TKTQqjfwgDhViO9yS7mklsDCXfk8ng9h127rlnXC0fxj3HSWPegaHUNE98MxoVPpXWRjjPVk4tE8bw50LlbsfY6p6TXvOMVMJM53B1oGu",
"BkbMxpytzfJC2GkJdEQPswRfspfIcLLN6XzDm77VnQxqwR9Kw0AYxrd0RtI3fuQlrqYNx6JVWhlt8vdEwOD4fQ46kNazh0VJrUxZ0gUWxgqGME",
"CEr30TZQjsoDIioxU2HItVrLKKXMqev3TW6UQ6L9y9NgsbOmew5HrwtbhqXIFsLypSsfYeoxncOPnCbB8hjANNL4eJNTcysBrVRq9gXwsMmQpy",
"ZcDrYZgAwPfFuL7NEDaplCh1owXOGRnF41730nDxdSdHElviYFHkiZmGvjucbSSfT0jUoWsBPGjt1PM0utlNtHuZ0ZbcR4sL5LGtI94xPo0RdM",
"FgbbzPxV3TAO9vntafzJPrxkXtYfyk7dBjpa8W5cPG0ZcosmE25ttDOr6MGF7NTI7iSgeYs3Et2RRvdvyiZ2VNt2AaHHYAp5Til7hObWheN9K0",
"G2iksg0BqF666j6ehDYrOmmLeOgbC3Yj6gEyxE9Xkf4qzaERNDiBZEnesEq5HppOF3mcHwa1Leslo7ccKuOK9cYCQpIxO7mubIHTeSV06nlvux",
"lx2uuHAB8Dv3gBv44nVEbvC7HVsCXjMiRONlwnWE1sHi4dm8BiNMNqUvmn8jGUCyJpTfNQTOjB6nOtwqLjczJ655udpb81JRrC7ft14MCbarEG",
"ndTuvo5rf9z8fKN257Xzxv4hx0qtHxS5KMzfbEHqOgz31m66u4G1zKj7LKAthsy2f8iqNZQBgqEhMKngO3hnOBuAl53DyCFNKXdxX48duNuhxS",
"IZjZpi8QGYJuzm2MWIF71kdF8QKRDCOmB7l1puR6tBB2XDPTmu1nPf2X6MPJpE50Mr2cVUipvTssxhmTMohBDjzJ6osv3xwPYz1UtjkYcMrK4O",
"uL2HZzCLbXwuXjzKZNz3I0UfY6ofqrwVcyCc8fXjcuOaNnUNbuQTvL8uRxJiYfebNQoV6lfjP4tDsoqDThwo2ESTbCcaRqlFhKBn5RGVVaynzZ",
"ertQ2OgnJhhU0oTYcBZ2rRqqH6X1gNAve4lhSCFCTXxTlqSx2SzuJ0Ur7SsnF3TT7fbZSRCLO9F9AyHCqh69h0BoT3My7GseWDeOvQAj0gtBOa",
"axhzfC01R9pPcQTmSurHoBtTg1bgwVGHtXgJzhKrq9gD09ZTErA224Vj57AB2gjwdzfMQZdh9uU9DU2ilDkoIfHNmippyJVLiay9aMrkgmtUhw",
"yW2ZjPJufQH20BNFUhh4bKjf3iUGH4vf0xejmYNCOvEP7ru1JM5UwpaAH4go8LE8jTsGRgiGLWvSo0U8M02jpdT7h9vpVaye30UVgdB297Vy8P",
"3EPE0AOATEvLmmMKFgnqlKrYmyEuweWATMfUm4ufIZ14mOO24csqWUpjs3NZhKzbxP5TTz9CzbGVZvX4HpvEjUXMXLLfwkq3avX357FEimziRx",
"lIFXKnaTNVpKogH4loOzwORMW7hdyR6TzMQk91dXXDIlUpqfNfOk4F70NodmfkgP66ag8nd61WsVlTa98YtcEBdsZrOfL45Sbf8kCmqDiSyELI",
"RxQYzRmeXaH2z4DYn4vne3g3Gv3aOy5F5VDFM0TJbBLKFoJ3tfqHiHLZcOa0mfGsak8Xk2GvDsgjRZmkeN2xuNwHBGIYWor6Iz33BKzfdPz5PW",
"m2XDtyGA7OaTlPrd83duMlsMtzjsQ17d45QxDw8LliEG85Ug98LVtdIWN1pE2xR7CIEgfM1B5FidLduUlfQOtyLhzbVCINKlwoBLbCnhiFu3SY",
"vx2GgVws5IjA0dLh95HlANlIeZWWZI4ug6bw2IY7qiIrvtIFyq19emRslOolwtPMA0jCIhJ9zsA5VjKuJLDX7vqtjPOQiEDSEWvnefwOH6TDqD",
"Vow5UBOk67xApFGo5FV76SRkEK1rEVJAjfGdRuxXC5y2KfrPUmX1fOlTznlei5OCluPcZnaCtIEdX63St1TIPfCpDYDW3sypWnBWLLyeudssjv",
"L1bOIuHK47U9ZA0mXftuqDeOMbctx5Jj6U7PpPztXtDW4Dj1TMwjqL7cWkFupoOwjWlILUcIoPFstYumL1FcNMoK74ewt22NYowKjItHy9a18F",
"N4z2567XL5VftWgCF9Blcl0vl87u86lWaUYg06dMb91F6iiLrT7De89Agh4onqlykkOlq28Bcagisz4UscyHlHiBYn0mNlU8FJt5MCHYMYgfxl",
"ufGydCn9U7gPXthq2tWDmOrOPaMsxvV2LBAYeY895oZ3ShtVKqy6e0V4bHwIdrKY3lWhj4rptqsmHWhsmQzAQuE2cbKpCvoFRlXbpoATO3fwZx",
"DqRtFnN99tvNaHfbQ7vsSb5rCHFAyvwbVoFALsKVWgI7YYiP5OhXZnpC45cDAJPv7u6TXRPT7x05wjUC7cA7AZJF5ViFF7bNCiGz9vtg3tmANh",
"rs1tlZoMZMAINnM7tPUCBDxOgbCupqeRTgkefJ1fwBYjYKrrAm4c0B0gMCLc3Z3Wgobv8cLEOJYMuqe5MihMUi2HUNTYNXV3m6zujk8746Uyw8",
"Ts4f9XBjDiVbcvmk5toQ75QIIqxT77l0AqgJnS21aYcmuzHA35qabgTUHrOOzaO9A5TYXVZ7UcupMbZPhp0tGUnolccUm14X6XV3TVbO8FdURd",
"SxFyVnxRiYfOq7DzVFZmO7K8BArT9dl2L0AGn8xG6NvwU86QN6dCdXKOxcIHp3Ja4jRssp8ycD56LbXzhabv7WkF83ny76JbqADS0MrcpwjbIg",
"tWt4iG0oLa0sDVKFR6CTWRgnUoJE7MNAIgF1XFqIQrbunV9e1L8XDolxM4cURZvAgaBdP2WGt7aQ3k545d2JBngostjjsOUIYwWOySu20FT3ZY",
"KcoCIpyGHuAZgIUbiSwETvvbhdNsEXGo951SuAyc49ckR6w9Y3OSzj4QxRibOZAY5CQAcoMhxZCp58z4cnWLH0CfSUrGU1F0DvAQUn7smJSsSr",
"hy4fkKzFgkZ3mnKWALnBz7DgE4U0mQsEpxTJhtpyOpBaNl7n6uZGCCXhGRi2HKH7hARy4h6SGI3t3aQaFQQhsNy9EQcmBTuSulryDyqjguMjED",
"e3UF9UrIZeq0lQwJyfZW4X41bjLGuHwJLroUlPDl43lqTR9r69ob6tchMXYgFvZqWnkhdYCh1YHUPRmW0L77ejp1hohWTgnPEI7RGK9IIQCxIZ",
"3G8GRWiEJrZ8sWZN1KefnJPamjwIxmnB3wiUtAyd2yluuliw5xMsgBDCUaksxH4AemvHX4UZCfu7ANEGkq9A2NdWXypugu5uQBbNF5NiliqW54",
"BROaRc01Bi5Nm8YROG48qzv6qVyMMlTodIy4Uz6vSbjejh58XagoJMu9I3WvpPTCysGt1MYTYi8hAdpxnGW6sqgbucGT2zwA2c33Z2XXl5fVjE",
"1ZKUZExDSkm8vhMPyauwvaCKiKflxVDyVnsU20yUkV3QdQFL09hwkUgCFvXcrALnYdi1dQWyMZoZP4KQd2mxXDaC97PBIAYGNgI17EATDZSt3D",
"lRQ5ICYaUts23qtvnciSvO07afGRql1LcSRUvP5pjxrmXVSl7bdCZeJ9uq1UL2GYUxSqnXPHvg4tbWPj83V7hFhM5iGRknPfVIFiGvZbM4FY0u",
"MfYv6zz44riLbZypKMIuMP2pCvC3b06Yg5tnE2rJuKvFJ34uQNYDC13fwFiIGpGWuaj9cLSHvnmfrrJieIWRJZ7gFqYlPEhkOAt1mmIRK56cwP",
"vb7HdgT2gzCSqpYBlUgUqCAMFaTapd3VoaCCqwFH5hAwHy73snXT0yFGIzQ7MT3b3FNucsbiKLOskVvMjsGk0m0JVRRIKUUOAHjMav5VgTnBPT",
"VHcDudoFJlOK2zQkG9TrD4MTvGBDKu3GbfjGtHmc3bW5LNqrWjTAoFuUm5x6zBMLR6skOPxR0uXMhndeG6P5MjZ8pwfY72KY8djX2QO3lMPC93",
"IDVsOUowXyOgdQdqleazNyXKxrA1EXmnAhPpceWaMKq0AErWSBvF9tpGV0HzY4XzlMYx0UHNE8OfMfcFQIk0cKH7LpHJtEjPrhnsc4fRd470jj",
"PuxrC4isrB0yKCKdAKzGB1mekuy2A43pyBRbG9D7LEGvgqJRbixNkU1EozHZEKpcmgn2q19bFPHWgqNsJlf3ggIEQpEva3Hxk5zK6JWMyDIP3w",
"1KMBUUsLZ5glS9iaCmRo1Jdgynh2dUQfECQzxjkwpBShKarnwjLy2YPBm7DA1tPG6GgDZAapc2GWc8kJr6hu475reJ1fcRWjxcXxN7WZaDWnLg",
"ui1RgxCE4NYhX60iHIxcH4Xu1UzO5KrA3srk03Y4QXmO3m7L5EXMIVhKPQzUA0vEtWYuZXyQUVFXhMJmqH99CqUrgtmRtRvXOurNr0ElVjjc53",
"nXgaGfGrSd5Pzi4wIU0RyEpqqhHxZjdmhuwXKcoCpurZMwvvrvn09NrA4973slpJQWHA86dyAFxnc3TDzgEJ35j7eqaHLArCx8cFfqeP5MdiP6",
"xTwWVuZg8VQ6g8oVaZQ3k1LWKKDwww24qy1l31BcXsidAH8KHZO11zXLkBhR7kVxSXTWZv9WXs9x9iiQi6SjFP40qmRyGN5zKZwKuFGr7PZh8h",
"RPS2v1aKYXTKasS4p9vKfSpkMczJRlxJapMFqWppTj94L28acEUrxkMjxm3pHB8S0UxrRXQKg0P13YcfD7GartuZPyox9xparWBiUs3atTcwSo",
"Z3qxUzfB6ociXot7NpyVwImkOj8aUk6Unxsh6HSd65v4tZbgoJcVsyggSorMJyH659nbRgpXmU2PUd6iXieqRuHJT8wCGdIMm6XdnnbJidycrF",
"AL18jRC7zMw5Xv43901876dEOZGUVNqvzsDSjf0S2wY0133b35jbbwPZvwUqjlWTNzM7PMZRiYSk1Vv50Ogbk6bQC6hWrdPfNCmDomvHkn1mix",
"3uLky94sCXjRluK4QcrBNkNjEiyABFtFafZJp4b11uTnYDrPQSqDddXRwvr8aVNlaM4ARfBSKufJ8HyYzYCNczEI56Qg1DBcqFMhVoaGTpp17X",
"2ldCazbeUaY3B5Id9fGPPkD0KTfrZWS2i5FsFRHz1GCDLlQUAwKpRoqChG3hDVjV1ZoGQ6fRNSvydltOSdeKBFmTlpbYlvUmuj2kqhcdaHMo3f",
"ANzCDN6LNykDW84BLhly50LWPFl83DJEqjg46mPTVaxRiCt4UOCZPoVF3gN6UxLlQ1pXofRjqobJ1FNVupUjNQYQ6MX1kInaKM892ZssoEbqjY",
"KzDCXnZ2va3e7LrqgUZkwbIbi1ucapKVYoxWMwZhH2wPOYf4Seppp8BI96UjvFeu3LrPiq70tEPhD4mvjLVJUxr3Dmm92BE6m5WFw4FZIuhlzD",
"OEbUmNo4tzACFHAlYGb17y9K2zFJK1oyFAt2nS7RrHu7o4snLEoTcyDf7jYRkmqZXU2kM9bdQGlfLNCws1qEz3UGmSyHfZGcTIwGSIUIpfYa3B",
"DxHeToVQEYeqqAM1WGUYHW4OJN6PNq1rXJFR7BHMzWd0wZ2tGXrnTwcDjjt7KuyHedymPg8pclpJlsc1pDpj9CXtVqAFV8n9mWvbcEBpZ08ktk",
"ZoPnaqlyC2Cy2E20dUIVyId9LAN3NAVNZLa9bwHNzkmBZpCdjl8S3m1OWOSKpNxozIyKfgyOBUpAj1NCmWvqjwegl61LUy9thIewYMkAGKa0LY",
"CcbaFD7nDfcPd0xFu8Pw5DUiRkiMqd02pcd5PksszFhNFPtaYiG3WAlNVEAlRBohNBmCWP5wumjacMka50d1BzPwdqS51hmOSJrPzwl3TFe5ry",
"5joXMrlyXsEC0oVHlyjzYThp4UWJ0k76Dw4qYpYVSCxS1tAm1TWZNdpR8lA9GIfkfjKdJJ8BlFun84KaYGaLTAD2WebCWqWcKHptqx5MdA9mFT",
"Ki7j43Q4ooW4fiLGK2uKbr0ueNo0WRFGaN0eRRigfelux6ai8F2j73OmRdmN42ufPutHmLXB0i6xohPxWSR4VFqMTNAYP4dFzGmVrjwsCCZ0TP",
"tpJu4mYtgqjQZQ7h23ieTc54OIJGL6HevqJANI348nU8d1pf5ItYVz3JhNq3T8ioz1ZmK2qTql2DnrTsanq5WuPdhghaozzXByklBLf16hFtJy",
"PPCZK9s1R96wCNYWRgbNxUsAgXILb5t0V50FfsG7BNEdBCatSlgqgJ1wHJhSOKSJQSp6l5dWTRavulYmGfNWYOtFxKymvq6mjvsEBGBvyL026Z",
"qxOQGfihHtyEXRasRB3xHodFwVMNRbMiJB9pRrHyVfdT7nlYYowGNJlkE87wkTO3vXsmpaUkp8exvzvuY1aMKw6pFdWZ7K2DIvZ7FUs52GCxg8",
"vUJdsLgbhckW5lLlySEt1z6jXdE0cSOHNyVfjbqAoLxt6jOFbt9c3fw0ta0F2PnQoi5HuwiShQlo9a3kDcwHs2HVdIBgyY6WgbDKHWDZMYnV9q",
"UnT2d1N250lNj4w1RKQUiYlA78PaeIR86KbkLYmRYHFiLbjDVaxd8TOf2Eqgnhpt2ANOy9GxRlQDwagslOGuHuKK9a1wsqZv1MjAWZ8NkZrR9H",
"bBa30xEJExW7zpeXK1GZ2ID6xLBwF3ERFPUFmzp17m8GLnDwokvq38xAT87zbLqQBlwXUWY1i7I3umATG5jJdQk7YsHae80PtxMntLpMT7Qotq",
"SDUGOvP0mFBLtXvSIGaKv0EZYdCTk3xdGrTvWJvjp74S4ALNhWyMWcLVpoOKrlX7NRDKB830g8TkIE80AGMxSysiWh2oD0wqS9buifuynnT621",
"9ek36gK1PsRYt87xDxukV4mGwiWoIiFRw0UCgFE57v4BEb9hJECEIYlfgiDYAiP7iKJzpoFxTJ9xViPFWrjEqFUHXxGxQvF9gpIGNndH7nf2F4",
"Yz3PwmQeLESssSxvcS2s9kgzEFHE0QTZpWOWiEa4j3wMV3h8WjA6EQGiwoWwePvEMkA5ZL9iOF4KJmSGFtMjktCQRzn6pTKbdlgc7pvV5AGOWy",
"1HZVyENCsbcmiVoVERZT0rrXfBkzgwGieFeMj1oLdB7wwwrbnq5nSxl78GGocmHq1WdlYC7bdfHKL9V8A1wsyRAGyg5KDNbFJo1I08TdoBYaLT",
"OIJE3h1FFyXv5MnvoiQVSixMSS5FYUDMCmrGEtlk1jP75dCtwtpoLXaEPgjOaXANk2tYvPjx88EelhISK8gw5raVHuJSrkGLmaKSZ3p8c4mym5",
"N84mZd53XtTkFDOGPCz37xhTfahB3phRyldyzjBxMuRr8G8YiI1qfijvtA7w0oozJB7jVIQHdI9mpikI0l8fDsL72SE3g2C0EKkztbgHTq3jIn",
"awWxIB2NT7Vck38gTEu9sh5iGHPiY018xXGfzI3sQYFa2NqVsV5UcadTS3bQ3dZBaFQKoTceSRoUFPQ7KV2X6gQZj2PnfPYqvPaTJn8BexwTmm",
"sYCfUw6dWoyIp3FqKS0qlqWA0ZpGuMyXKacFHjTDHrm6v2xfUxFfXCQYBfF62d3Nogs5zlIgN4ni6Uy1sdgpP6oqm3xohAbFREKr0tINx56E0E",
"aIY9XPJ14MImaUL2PaR2CH61nTLJO8hYQf8N4RO9DxvNrhPhrGk4oq5LkQv8YM6O2eC75qhJYNwq4mHw32ArsFdMwJUvw1kygWGmnX5lLCLPYt",
"3d46eNJ5eS4f1U7XvEwM3pBw6f6hkPHo3LuhzenO6s47nb4SQAFU0hr6xxoRm5gpRKHrZ5g5xkcUwhNnSshSKJZhgn9Dtp3laLM9Q2fonrjUJ6",
"5e1ZTyh408dZQnMqtsbToo20szjxKUsP9uP22772gk16HOxbgJ4E77FzGZ7qTzg23656ec8ux9BfY9qeSvSZDyyjyGKrg1uk8AqmMyRjItyGCZ",
"lTEux3ECKtrTDFUs973xRQlO8NgeYrojl3OS6suRWVKzBE1LM5iEVEs4rJipaHIvKwoQZSIWOsvq7xbTDuxy80DzJVZUDHqoeOeeHXawpGWxe8",
"g8TxqvW732RCBgIDRGeQiCdwLUNzhvaxD444z1bC43fFjYjaFx0YaeuV8iupNFXrJ2vj4GW8KbN3a6ePEfNOtiKCAf2nV0OE3jY70UfL62Ph93",
"uymiLAA91UfNgc0qkDBe7xPUPALjgnwKVT2HtDQuy6iOijfCXRQ5oGZehKxx83h4WkLqYCVxIem1yCEvtvARbA5slC0tGiyDCk4BW08FevHM7l",
"x9wursUtNAaop0SdSifahlHTewFLUXmr7SVzkQ28qcwQdp35IjgZFXTUuyFow1QETMeeCgm2tTSGjWM1g21V0UPutuS0wIFquTE7919DU2jdZ5",
"suKdEITgYGKHKAAYJpM21Kf9BAtBOhZgLKuqsnGr3q9N1KMLayNbj3lVDOws6wISgciJAZbDqkrs4edeN1q74L2IAyaG4Syl5R4FRfjhALKFZX",
"vl4L8u3GP85KGYN86WWta1KsDgOd3NPz9TkhnoYdx3Xd2Ll9HiCSknkXD8aHW0h5UCmi1lwyotMrf8AXrcPLAaJdjTVfUdlOPI7R3Dqs7cTmlu",
"YnFTIvsQ0DalYojSBq0BD2nFgn8XrApqY5jGBMwCpHXn6ggHHhjkjG0A38yvJXVH3eoE0UgqCdOIu4qblJwFqxftGNZpLU7P9vtaqKA2XpLstb",
"sBwvO0zxh3hGNdqMg01xCLUMg8uxC4y4F5Au691ndj40xvNNvPl7AfURnoo0sX583FD9OFw2ZA2w5PkAFFIgVD7i1wjutoCx3gGSVcUUNXrSNL",
"1TB96SZMDl5XguCiUDR5Bb0gUzUaZji0cUaiMa4pvanLEZ4zCVEe7Fu2fpceIvfUppdcAiC5tZR7YVHARmOY1i0hHdvqILl8bykLRWQkVHrTD9",
"aGVBrVnJlKnvaHpTWmcqqmHg1mdhN0AXHvy8qVSMGghRXGKU3Wktj2JkoXCcYcaFHIO8EGUkWcbUTVOWS9pcb9xA69M5lWK3Fybjf6EciQ6bMV",
"pEg8gLqkrlgV5CG9EGRmaVgULjTSWC2mhivx4VSvh8rnK7wpNoMYk2S5mMXio0EFj9dn55TmekJYrfoeEacYd53zR1Rg1wVkG9ILeB7tWQrn6Q",
"iVX0zXc7yh3KvvNMPUXHjSwBafY3Nh95c76L4iTCAXn6sbSh5QZpIw0TLZWzg6FtdMfh49UF6hLzsERyuQXdnY79X3Ie9oHnaXEf6zUdQGMjkD",
"FntRDfx0TGi8yAAHWE4Dy1CFMAU2tGA9430HiyIce1lNCWvzAzc9AOPnoKpSr01v32dmBWzQXUEzQ98rIlBjaqGzb6rC6t7awlx7h6Xf1BPSLX",
"ck1n6Me3xZLL2Up5MYDa0ay7fEaPAucMOdaVZoZxoKiqFHvrG9CHjaOzOYootAbiNleNKdk8XDzDk441eHIxRx6Fwv4Z5fiSBwGlJ0uHD3kY8o",
"wdGvSVxDRaohDr2RpKo8b6wZBvwEkGIQTomMjTpb3OsGguyGfWOq2lqDQXibD02xpojIhITlxm2NRAt6wiwyDXcuUvFxvI5V6oDo6xKDUMrLmU",
"1soYOKlbDUtmISnrn9izlM1fnw78dBYe3mdR7z3Ltx8cpwENFWn0Jpg7Wng9Zeo2BBUJbYvFvERVavIPs6Qbv6iruyBtNZwpBq8MoErUijPsOx",
"OKypJ6Pp5ejQklvDmxj0STCoqVZggLP5vouevjDAyXqTiVxFsQFlJiJ9eIqutgAZE4d9oRKXPaQ76nNzdtUWMD60mxvPN5Osa2BzUmwJxnRDKE",
"0BzlNDbTSHqH2bc20eNXer5bl2CLyoPz0pUO26HVN8CQjOTj2Ghh8mstp4eXt4wutqivx0qk83bsR4LUL3bTqEmPJBMdFjH8K0Eh15C98NB0Sn",
"BQxCWYm2XsrC1pGB1PerYEOeRL0X1n2CezfbyBdw4F864PH5EWxCBlRs6Sq7gsKu20FABT6GyfMD5uJJqgm1BeuI6VQnoBRqCx1dr8T0nGDsan",
"1RxR2HK3vHQOOnOFqF7XuknIzswuyv8zmGrpoctTTkHIHwo7bv5GQsoqVVVtr43OKve9HH2B1KjIhHQtdV93oyujtpMVtQJelYn2FqDGaXpsFf",
"41Kh52liId51w1iAtkrBYUkZRWVM3qU7sEpyGLQpYWqvXI5r3x22rm1iiX5mo0tQFTomEfLCcb7aUdBYKD0b02uj0AFoB9eg2DCHTnk5zrfuEQ",
"iZ8CjVT6FVUtXS9Xc5Hq9e9hOi2LicpBcxdwt7C92xC0pMXCSF31TcjHumtNyToLqChUJT4MqHNQtKtmpwojIH0d4u0DnooO1FJLzNxZukQY5j",
"mP0qHsb12K13p6C5ISg2tAwAST7t6gut5vUMX5OZPP3fVFkEyAG1bdC36Kxc11G6wATuFHtvxxKtc47KFOMQ1pU7arkbt0i0BbugTYLqvwUIB1",
"CBcMwWNx2Y4vFk0DiNx1w6fSKZLAi9lVLxHhtvPwuU19e2NwQkymrNfcN0N6a81VGJdae3GIXISbLFIB0gYs4dESerYoAZkgIyqXB7FyPyKAes",
"NqzHzbZPXN6twCSTvMjYt4o95KLcoxmbXWTx7Sm5Gsyd5r6BdpzHuYQAICM7a9i75bEd40jKtRXzj4awuKeYI5yrIlySuQZA2EN7F7R9YPIhTS",
"ah9I1bpDHKyaN6B9G0dD2VvAncfbssTDJ2lLeLpVvY6i4HrKIFoKBUlY7A9z22dM5yyjkXfPVm8Z3AJMf8xQ2SPatZJw1Wj7vRrPOHFK3OJ7ot",
"lxFSvfZW6p01hvATKyDCWH3B67NKrUxNscGXsFTy4UzmqafbJTNFARhHY4sqZ0drcTpEzidDdM0DXfOG9BmKtDrrIURIU497YzMxRZb4MbIKrw",
"ft3C2sAMNaGlWhBD5XNXBfgVP038OdK3HNGJghv4rcpnt01zXOwz3MuTNx1BLMFszmcPDIT4UisojtXhiuQmglf4ShGE3l7CIjsl2mqWFTkYmi",
"CGivjFoYDRlBmdgB6lBtU30KtUslpPh1wzxPfVOSM9u8nKKt5mWZpXJTSceh1vjx5QmkLadykHHIssbyO8xe6h7YulgvRz3WqqhcBuLVcsDEVP",
"pm0v8p2MmUAIC9fVyCCGcR2J8fvWHJL65LCdbE0xzBgcKw8j8KZlC14KhAHYjs5peIDqmEYWff90LhjT2jfElkpCV6BfzHEOpieMWdJcsScdaw",
"qcgmWXlonOxrl4SOxm8xAn8NLYI0zz7ZLnmHlH6JwEaRI3FfqOM0bUOXTxXs65rRtNzOvGy1kIT2Myicn4dyZ2wSztlFyNx1A6Q6No7870aTzs",
"QO2stD1jd6csvW7ueTeTwP7FELrxNzgDni6RV8a8enBKjJfxCtq9iyPXkgu7QKLd3R5ZZf8eDKYWtdu6HVfZu4XOlrVccGpgyvfxLoLo8KkCYP",
"XtX7DtuH0HQlVecEu1o0YzbCypNwfiVcMTjpnO7owYKrcW5HYuHX3SzBim8xE4KqY4QlSYJoXtQ9qWRoqymtrV5JidhWh1ng6eBYdlnaOdkf9b",
"pOgJSpRnpLedr6QVV4Uc8M7Loez7bngAcwk4WcslXHzoNpkJufVC23oqhYytmO4ykoDgA5CyMbWABhj5wfIyj7YA5w4rl80FxDW7JzGwLC7mTq",
"ND0Y2aYgc2wlQ3yi5aW4ZSs80uw4jpN63O56Y3mb5TxWX5e3fb8f4An44T8ojWvnLAtJDQVJJsFHyUKO5S39sqexjnVDkq051tPFkKo4d3LLXv",
"hxWH8kIzKB0jomex4OgkuNwSBnsac2rtzoaIIShtuiNTE1qJPH4kuAc5YFfaHHDh5OZOHhibz54e7uXWb2hGCuLB91LRJp8Pd8DVpV6Y1bd8Gb",
"Ft2VRbavlJqg4iqtJzE7jEnW5LpmIRpolsjdDtIYd8fhrFKaepiy3Fv8rUvaMVy7nSl0l4ZzdeQEUBO916H5Mcde7JoTFW12Om3aq2JEgAiac7",
"JvcqyGGDRm1i3zphjhRETotJi64Sxj2hPfHnVn1NK36NCv4VNVAGk3qD9vwHOzYDOG0K41yO4EBH9GDWCdDWg4Aqz67nF60uM1fR3NF8rhPAYt",
"9Sk8iONT26wmJLnKFkyqDDhimRlcWsT6leeE31x574sQPQBvaaWNOd6a5sn2Ug8fvnUyprEwv6nlWZR7aNVY1187uv9oMhEhEyQ30uAwBYSyYJ",
"0xl6cmbMoSEE2OpXiL26VEFm9PCGPcJQJ5WWs7IQ0mv3aU1tG3ABHfYR5BxUNhKxnHtPPbGPybTI6UcMYNoG2nx8Y52MnNjKuMAjYg9wr2fxXs",
"8pncTqgpwdxeM9Q1zIbGZB3dKptGJeKRD84xykW5xukkDamdTyTS9W5UmzB5OmWru1Z3lW8Trte5EAix8bpi8vcu4NzT9wlExkHTgQMHj0MXB4",
"YphSzYYb5lALzqwfXMv92ZEUO8LPvB9u0rmApkLvGlggLNwJA1SC1wxPFjFaUPEVg1vGmgb2CsjogP7QQZtRw0Hbjnmec1at2F9oWlrzOKX4A4",
"yEGbuGhngySjN0L7efnkZro6tDMVPU1oyIz3pQqGoi0ciMjx1GS08h6CUTyKNA8liIoIyPoX7oaqbtYcaQdj8jV2cuM04VlnDK5czt9HSk83O6",
"gxJ84TMIQxjvA0fG4QkMDq9gToPEP075yReCL0lCxF77GnNKe7wRyG7r4X6TYeZw5d8RdutL9BSPYGAcO63mMbOR8UK78KDeXM6bgzXqaPg9wQ",
"pmHdFhKBmpe6y3OiFdTCiiZlLbQcPnUfJBsoSd0fCembhatXomzGEz1qLSDBfxQY9in2woh8DDjVOMSc9sTO1UfNMTo2qe1AxoC3MTcqxwlljd",
"91hERc7xmVu9ADbh4LACL7SXvpOMTPD3QVII8PfuKKDkoPBsAb4miXjOn8AgXdkO92whRMLCxpXVeyoOKtb3ruRODr5AFpoOsV6kHRWegTausy",
"e1SfTMPf2vYtZG8CPKF3ZrASA4LcIZPX1IcVv2axy91xQa9GUPJUhkMRox37xT4zBhu7jFFRPHpFRzlMp5GGptxO1AVzt085hDdBiSt7zSNrs8",
"fC7QsYHQK5kE7YxqZ01SPivIhhiAq1RFDZw5YeWIkhnrfUReVS7KbDtsUL2kNU0qTxwRLtA6KXxZSpeNilyuY1XTNZeAUf1OMyFy1gELdcK6CY",
"tgw0q3hbq6kEtb0YHqFjG8CG2HSx7aFAqbARfS3GYnlrymqfN5ztecahU3O1dtBEFcwV4zC2XXuvjVL61kAfxKwrNls1O4GugdplM1oJZSfiO0",
"k930lDiLl1JxWLpUQzjMB3x405N5nrdHAhHWU0Hg2rOYcdS3NcQofosftglQHyyiQgeLgW1inPhA39ERmugBSIRmZccGLKZB1dmiaoAydS8h2M",
"T5jWoWBVEqhwIg7GPd9806046wfX026T7qPwmrr0RJxAZFhOSqWSxXWDubBudHol7eStGjuy2181GqQzQNrnLo1fACKOk8arn2V3lqBosKp9ag",
"KrEpeu7uB8fGbRperilZO0rVhLopz9nkB1JPwRk7ZzObrdpSwLRkLig34EsEOPYqRIfnzAuz9jKBxat3WloHEFKIjdn83lyU3OiDoMcy6XaD7E",
"zVuaB7nxZSFY4jucNX3qoIzoLve2IHpiCUse1PL1Ir0MKuYyr2ZPKyev3syMaX4MSw0UmMV4eWRZqPySSxID5W89pGVzEZmwwnrSanXojOoJEW",
"TrzBrFWhaiUCn2A66IOufc4tzea9a9v4B5F2LCkVUfyih8onRdR6pWAZaK8lTEquK6xvISrC70Uo8iM0vD6VzHUKr26lHwQrCoWkgoXooRMxay",
"1fXajFfoEPwG2Jv3Oq9o59c6fQamHdHItETMk8aYYGE0qa4fBdDGnQNCHXZobG7El0qG9BE8hj8IudX5qBLNsyq9wpyI6FmsGN8QoMYG67pAkm",
"CXjENwG2BDU0EmmORCKb3e1Kbr6Sc52P2ltPS9RtMLuq8Rf0t0bxechqEoiRtlGwH9lzjd35Zxw8oL8SLjp0wHqb5J3z4J5LTrlcFoiEWPNlBV",
"N918EyaHZNfVZ99Vo62SU94za2R2CzTqJVyntI5swkovuxrTEtLzDP8NS0QvAJVjFuH9cMCJ60eBxGuc9fLN5UAXUrtuboNQSu05gCOnC3YaJt",
"XBSgip6faPWBwmVDTOCn7K2xo0VjKQfIs7YKx50HUWjrjf4c4HzbsCJQCEanvp5Xw4H39HL4E4vXjzanhJzJlizXXKks9qpFu7JEPuIuydrSNB",
"b6LLimNDYdUnmnLuMbIBKjAcLJeQQUY20KOi7BW6PRubefG0qpCaJdnuXBlNwjQx4EQcgNi5ENhT2XUtmwE5K1AHDVv9flHk0xwglPlZCCTFAN",
"XWQcPiVAGK61xoMZjrc3fAlDs15vUzqSwg4mz0WfL3gir3iLuuOJ4anxbt262tZzK4Vj4SyQVP9mSr8nVW6Z6uxiYzo02nAMrw6woEnjuwGmXO",
"QAQWsDymaHcGBOHqH4ojTH7wC1tCqvVh5MdyqMUBt7h4VYuD3TWWB4sd5WQwrLOxy16YO1zh8Rm4PRHSKEPmIhAOeqkGc8dKakIYligt9DxZuf",
"nVlidzlgp9UQMfwVDv2AnklRphuFPWfcRAu4aQlz0fpNvWI8rLJP54Gvlbba7qnZ1S4bJpKJFaxa6gjy12o674CsgNDnd1nfTrqCQbmwmTHta1",
"uown1KPMzPZr24PBYQfTYk0rMbjfejPIHm5I7VvHKu9MzYoxPDrNXrfKDyZRSPzzbFhjAM0lha8R9wpYaRL8j0SWzSOrHo1T3jcE6dZon7fwEF",
"izD5eDdMnxNyq4reEoisZFo36sV7Ks532I8gll3JTQhjVJyz7Q17vqaCS5JDyOGAxORTaUC3LTnGDVgKLhShH3TA9DeHsUiZJaTU4vYQplw2hM",
"CMVF5LznrvbW0uSoK8wWEgaky7NZFq5id1XiNxGe2Rb3m3r6cY3QfdaNkYN0oTiCUfVINBWQt8TPbkWojZeydpmyn9yM3QoX6kFTVCJpKCeWXa",
"cEUPsQV8eq3knQvSI90YL9OhsLKaPlX10RQtIMBWdFgAvMteWtdID106MKhC6eD66uzOhbLuQ24lOyAL2NtFPtLCd2ejhRqnmZcDaY700cmPKX",
"jwzlvApoOyslkf2BsJj79Qax64RVpLXJiw4N7tbV2EhmTjYm2huc7EJeJB98m6SFDWsKqEGsjXPcgNzi43vcIeqrPAAcGsSjpk4PZKhiH6uYU3",
"syFBPjNoCZwf1aSA328mlmssAltIxSnZq3BgmpEZobfqm71p9aMvweX6zrO7jc7KfJ1B8FBxRQXdYZD79pDFEAMd2BlmNt72c8ElOfSF6QT4Pw",
"09OhQx7j4M4qBOcRklwlwuDymVZiFHUGRIXHg40kQ5LrTXjejPzQkdoG9oYP6SvYBsFSwGdnMYPGW8UfXu5hHuYQSWFZPaXrDDjakxx7vnNrvI",
"WxyY6IVCmXFb9wSnjOx4pAyMP0FPjyAg68ecQaPd7uog1hDl5bpvLYiBYYqiw0yC8NPZXFc49BlbSZxYbXuWVNyTLYchZLU8yK8wpkByWWKPVh",
"RvSNH2tsVDSDTrZyMcFa43sWluzb7EUZaMNSPhkKUdoNEnmrA2CE55BrzbCHPwGZjuR8LcTFqht4FPwfR8UXewoNH0uxxbxRFpZqBT62bz7QpD",
"GKmxnXyK2hFU8SAjjzWIJ46OqbjN8OdPzAmWxUGAcmvkf5EyFAhoFod6AwTJl6yUHVRfPyP1Vkmaq0J5B1tgpGmZcgJymhs4ckj2S84NtrXTrH",
"39avrM0zV4IO8c18s0AexlREC7R0vMDyWO3oA4Xv9GkhTlqll1ATnrxZzo04bDC7rGv2KsxU8Rc2dCnzEXs1p01Yp12AFEH7ld95GH0OzcRMPe"
);
// Create connection
$con=mysqli_connect("localhost","root","password","test");
// Check connection
if (mysqli_connect_errno($con))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{ echo "connected fine.<br>";
}
function generateRandomString($length = 110) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
function create100() {
global $con;
$query = "INSERT INTO authid (authid) VALUES ('";
echo "begin generate random inserts<br>";
for ($i=1; $i<=100; $i++)
{ /*echo $query.$RandomString."')";*/
$RandomString=generateRandomString();
/*echo $RandomString."<br>";*/
/*echo $query.$RandomString."')"."<br>";*/
$result=$con->query($query.$RandomString."')");
if (!$result) {
printf("%s\n", $mysqli->error);
}
}
echo "end generate random inserts<br>";
}
$command=$_GET['action'];
if ($command=="create100")
{ create100();
}
if ($command=="findme")
{ echo "begin find me<br>";
$iCounts=0;
$beginTime = microtime(true);
for ($i=1;$i<=1;$i++)
{ for ($j=0;$j<211;$j++)
{
$query = "select authid from authid where authid='".$authids[$j]."'";
/*echo $query."<br>";*/
$result=$con->query($query);
/*printf("Select returned %d rows.<br>", mysqli_num_rows($result));*/
if (!$result) {
printf("%s\n", $mysqli->error);
}
/*echo $result."<br>";*/
$iCounts++;
}
}
$endTime = microtime(true);
printf("findme found %d ids in %01.3f seconds, %01.3f rows/sec<br>",$iCounts,$endTime-$beginTime,$iCounts/($endTime-$beginTime));
}
?>
Do you want to implement a password-reset function, or something similar with a one-time token?
If this token will grant access to a user account, then you should consider this: The token should not be stored plaintext in the database, instead it should be handled like a password. That means that only a hash of the token ist stored in the database, an this implicates, that you cannot search for this token in the database table anyway.
One way to solve this problem is, that the row-id will become part of the token. The tokens are not required to be unique then (no check), the row-id makes them unique. I wrote a PHP class, that helps generating one-time tokens for password-resets, and allows to validate them. It can be used likewise for other purposes.
I'm trying to create a function that, when run, creates numerical ID, checks to see if that ID exists in the DB and if it does exists then create another ID and check again until it has a unique ID. I'm stuck on how to loop in the functions withing a function
function createUniqueID() {
function buildUnique() {
$uniqueID = rand(100000000000,999999999999);
return $uniqueID;
}
function compareWithDB($uniqueID) {
$s = "SELECT id FROM table WHERE id='{$uniqueID}'";
$r = mysql_query($s);
return $r;
}
function countDBRows($r) {
if(mysql_num_rows($r) >0){
$f = false; // found
} else{
$f = true;
}
}
$uniqueID = buildUnique();
$r = compareWithDB($uniqueID);
$f = countDBRows($r);
if (!$f) {
$uniqueID = 'nope';
}
return $uniqueID;
}
You're much better off to call MySQL's UUID() function, and store & return the value of that, unless the value absolutely must be numeric.
SELECT UUID();
If you want a unique number, then just use AUTO_INCREMENT
If you want a unique random number (why?) create a unique index on the ID column and keep trying until you get no errors. This is better for concurrency: multiple concurrent calls can have the same number and pass the test. Better still, let the DB engine do it with RAND...
Theres another way too,
You can use the sha1() function in conjuction with an static variable as shown:
function GetUniqueID() {
static $salt=1;
$id = sha1("somestring".(string)$salt);
$salt++;
return $id;
}
Here $salt being an static one retains its value between all calls incrementing ensuring unique ID's (hash of SHA1).for more security "somestring" can be made randomized also .
Might I suggest the much easier and more efficient uniqid function which will do this for you. It generates guaranteed unique IDs based on the timestamp in milliseconds. The generated Id is 13 digits long unless you decide to add a prefix or use extra 'entropy' (more uniqueness).
Edit: Note that this is both numbers and letters returned by the function.
http://php.net/manual/en/function.uniqid.php
Edit 2:
Using your method here is how to nest the loops...
while (true) {
$uniqueID = buildUnique();
$r = compareWithDB($uniqueID)
if (countDBRows($r)) { break; }
}
Your unique ID is then stored in $uniqueID. I do however discourage this because it's bulky and inefficient... but there you go! :)
I'm answering my own question because I have found a solution of creating a big number that (likely) will never duplicate. I use three random 2-digit variables and three different date syntax.
Putting them together makes it clear that they will never duplicate unless someone happens to post during the same year, week and with the same number of seconds in the minute an also have 3 different random number all be the same.
I think the chances of this happening would be in the millions and if there are millions of posts happening then i'm sure I will have more resources to solve this issue.
$rand1 = rand(10,99);
$rand2 = rand(10,99);
$rand3 = rand(10,99);
$date1 = date("s"); // seconds
$date2 = date("y"); // 2 digit year
$date3 = date("W"); // week number (out of 52)
$uniqueID = $date1.$rand1.$date2.$rand2.$date3.$rand3;
return $uniqueID;
What’s the best way of generating a unique key, that can’t be guessed easily?
I would like to create a unique key for both account activation and referral purposes, that includes a checksum to help prevent users from easily guessing other users activation or referral keys.
Also, in PHP is it possible to create you own session key?
If so, how would you make this unique?
Any help is greatly appreciated.
Don't over-complicate it:
$key = md5(microtime().rand());
You can use uniqid to generate unique IDs. Look at the comments for PHP implementations of UUID (universally unique identifier) generation as well.
This is what I use for uniq key in php:
$activation = md5(uniqid(rand(), true));
Just use PHP's build-in function uniqid(). See PHP manual.
Other answers have already covered the topic about creating a (pseudo) unique ID, so I only cover how to set your own session id:
The session id in PHP gets automatically generated, but you can set your own. See session_id() how to do it.
Exemplary it works like this:
$mySessionId = generate_my_session_id();
$oldId = session_id($mySessionId);
session_start(); // session must start _after_ setting the id.
I use this script to randomly generate passwords, you change a couple things around and it will work quite well for what you want.
function generatePassword ($length) {
$possible = "0123456789abcdfghjkmnpqrstvwxyzABCDEFGHIJKLMNOPQRESTUVWXYZ_"; // allowed chars in the password
if ($length == "" OR !is_numeric($lengh)){
$length = 8;
}
srand(make_seed());
$i = 0;
$password = "";
while ($i < $length) {
$char = substr($possible, rand(0, strlen($possible)-1), 1);
if (!strstr($password, $char)) {
$password .= $char;
$i++;
}
}
return $password;
}
and for your own session key its pretty simple
start_session();
$_SESSION['NewSessionVariable']=$VariableToSet;
You can use this function i wrote sometimes ago..
function generateToken($type = null) {
if($type) {
return '<input type="hidden" name="token_id" value="'.$_SESSION['token_id'].'">';
} else {
if(!isset($_SESSION['token_id'])) {
$token_id = md5(substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10));
$_SESSION['token_id'] = $token_id;
return $_SESSION['token_id'];
}
return $_SESSION['token_id'];
}
}
there have been hundreds if not thousands of posts concerning the use of PHP's eval(); to run code from a database. Through all my searching I have not found an answer to my question (explained shortly).
Firstly I'll introduce you to my application.
I have three records of valid code stored in a database:
eg:
['code1']
$num1 = 1;
$num2 = 3;
$num3 = $num1+$num2; //4
['code2']
$num4 = $num3; //4
$num5 = 5;
$num6 = $num4+$num5; //9
['code3']
$num7 = $num4; //4
$num8 = $num6; //9
$num9 = $num7+$num8; //13
echo $num9; //13
Next I have a function to call and run a record:
eg:
function runCode($codeName) {
// assume db connection is established
$result = mysql_query("SELECT `code` FROM CodeStore WHERE `name` = '".$codeName."'");
if ($result) {
// Fetch one row
$row = mysql_fetch_assoc($result);
if (!$row) {
die('No rows returned.');
} else {
return eval($row['code']);
}
} else {
die('Invalid query: '.mysql_error());
}
}
Now, what needs to happen is to call the three above snippets, one after each other, and have the variables inside ($numX) available for use between each other.
eg:
runCode('code1');
runCode('code2');
runCode('code3');
The above call of the three snippets from the db should echo '13', it does not. And there is my question:
How can I make these variables available outside the eval'd code?
You're not fetching the results from the db. mysql_query() does not return all the SELECTed rows.
function runCode($codeName) {
// assume db connection is established
$result = mysql_query("SELECT `code` FROM CodeStore WHERE `name` = '".$codeName."'");
if ($result) {
// Fetch one row
$row = mysql_fetch_assoc($result);
if (!$row)
die('No rows returned.');
$valid = eval($row['code']);
if($valid) {
return $valid;
} else {
die('Error executing: '.$codeName);
}
} else {
die('Invalid query: '.mysql_error());
}
}
See the manual for mysql_fetch_assoc.
How can I make these variables
available outside the eval'd code?
That's a bit difficult, there's no simple way to do this.
The eval'd pieces of code don't run in the same scope, so you'll have to somehow save the current symbol table and restore it afterwards.
If keeping the variables is enough for you, you might try get_defined_vars (and probably a combo of compact and extract or a roll your own replacement for those functions). However this functions returns the name of all defined vars (include superglobals like $_GET etc.).
If you build a clever diff algorithm, you could probably compare the variables which were defined before and after the eval'd code and find out which variables are new. Good luck with that :).
In addition to svens's answer, I think you're not checking the return value from eval() correctly. From the PHP manual:
eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned. If there is a parse error in the evaluated code, eval() returns FALSE and execution of the following code continues normally.
You should only treat it as a failure if FALSE === eval($code). Even then, you could get in trouble if your code returns FALSE.
Variables from DB are local in function. Make them global.
So you may use global keyword to change variables scope:
<?php
error_reporting (E_ALL);
$txt = array(
'$num1 = 1;
$num2 = 3;
global $num3; // make it global, will be used later
$num3 = $num1+$num2;
echo "num3=" . $num3 . "<br>"; //4',
'global $num3; // need to use value from this var
global $num4; // make it global, will be used later
$num4 = $num3; //4
$num5 = 5;
global $num6; // make it global, will be used later
$num6 = $num3+$num5;
echo "num6=" . $num6 . "<br>"; //9',
'global $num4; // need to use value from this var
global $num6; // need to use value from this var
$num7 = $num4; //4
$num8 = $num6; //9
global $num9; // make it global, will be used later (maybe)
$num9 = $num7+$num8; //13
echo "num9=" . $num9 . "<br>"; //13'
);
function runCode($codeName) { // just for example
eval($codeName);
}
runCode($txt[0]);
runCode($txt[1]);
runCode($txt[2]);
?>
This solution demands changing existing code in a DB. It may be difficult.
So, here is a different algorithm. At first, join all code chunks together. Then run eval function and pass joined code to it. For example:
function composeCode($codeName) {
// assume db connection is established
$result = mysql_query("SELECT `code` FROM CodeStore WHERE `name` = '".$codeName."'");
if ($result) {
// Fetch one row
$row = mysql_fetch_assoc($result);
if (!$row) {
die('No rows returned.');
} else {
return $row['code']; // CHANGED ORIGINAL CODE
}
} else {
die('Invalid query: '.mysql_error());
}
}
$code = '';
$code .= composeCode('code1');
$code .= composeCode('code2');
$code .= composeCode('code3');
eval($code);
I would definitely go with the "pass an array of code names to runCode()" way.
The benefits you get:
You can get all the snippets with a single SELECT ... WHERE name IN ('code1', 'code2', ...) query
You share the variables between the snippets while keeping them in the scope of the runCode() function call (so that they get destroyed when the function execution terminates)
Then, you can operate in two ways:
eval() them one-by-one while fetching rows from the database result
implode() them with newline character to get a single code snippet to eval() at once.