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;
i'm trying to generate a unique id using this code:
$RCode = md5(uniqid(rand(), true));
then i want it to check in my database if the RCode is unique.
if it isnt i want it to use that part of the code again and check in my database again if it is unique,
if it is unique it should write to my database.
i have all the code i need for checking and writing into the database, i just have no idea how to make it loop back to the start.
Help is appreciated!
Thanks a lot in advance!
Don't bother checking at first. Instead put a unique constraint on the column, that way the insert will fail if the RCode isn't unique. Then you can handle that error/exception and try another hash. The probability of a collision is low so in this case you probably aren't going to be hammering the database.
Typical example for do-while loop.
Some PHP-pseudocode:
do {
$rcode = md5(uniqid(rand(), true));
$res = mysql_result(mysql_query("SELECT COUNT(*) FROM records WHERE rcode='$rcode'"));
} while ($res[0] > 0);
mysql_query("INSERT INTO records (rcode) VALUES ('$rcode')");
$found = false;
while (! $found) {
//try..
if (...unique...) {
$found = true;
}
}
Going to the start is as easy as implementing a while loop. Heck, you could even use goto (kidding!).
But I don't understand why you don't want to use auto_increment.
You can use the "loop forever then break out on success" method:
while (true) {
$RCode = ...;
if ($RCode does not exist in db) {
break;
}
}
write to the db
Edit: Or better, make sure the field has a unique constraint on it, then test for uniqueness by checking for failure of an insert:
while (true) {
$RCode = ...
try to insert RCode
if (no failure) {
break;
}
}
This will be more resilient to concurrent hits.
This answer is a little different to what you asked but it solves the problem of a unique ID in a different way that may be better to use depending on your application.
To be honest I like to use variables such as date and time combined with another variable such as an IP address for this type of thing, you can then be very certain that your ID will be unique because the date and time will not reoccur and in the event there are 2 requests in the same second the IP address of the user is completely unique at this time also. Plus no having to check with the database. An example would be
$idstring = date('Ymdhis');
$ipstring = $_SERVER['REMOTE_HOST'];
$hashme = $idstring.$ipstring;
$idhash = md5($hashme);
I hope this is helpful.
As you hash uniqid() returned value using md5() (the same goes for any other hashing algorithm), possibility of getting not unique string is extremely low.
In my opinion, its so low that checking for that string to be unique would be overkill.
All you need to do is insert value in the database. It will be unique!
Edit:
You should use uniqid(null, true) to get 23 chars long, unique string. If that is what you need - unique string.
you can just run MD5 on the timestamp...
$uniqueid = md5(time());
First, don't md5 uniqueid. uniqueid is good enough and it does not have the overhead of md5 if used by itself.
Second, you are far better off obscuring an automatically incrementing number than using a UUID or some equivalent.
But, if you must:
do {
$rcode = uniqid(rand(), true);
$res = mysql_query("SELECT COUNT(*) FROM records WHERE rcode='$rcode'");
} while ($res && mysql_num_rows($res));
mysql_query("INSERT INTO records (rcode) VALUES ('$rcode')");
// OR!
// assuming unique index on rcode
do {
$rcode = uniqid(rand(), true);
} while (mysql_query("INSERT INTO records (rcode) VALUES ('$rcode')"););
This is a follow-up question to a question I posted here.
I am using the following code to give users a unique id:
function NewGuid() {
$s = strtoupper(uniqid(rand(),true));
$guidText = substr($s,0,8) . '-' . substr($s,8,4) . '-' . substr($s,12,4). '-' . substr($s,16,4). '-' . substr($s,20); return $guidText;
}
$Guid = NewGuid();
echo $Guid;
$alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
function base_encode($num, $alphabet) {
$base_count = strlen($alphabet);
$encoded = '';
while ($num >= $base_count) {
$div = $num/$base_count;
$mod = ($num-($base_count*intval($div)));
$encoded = $alphabet[$mod] . $encoded;
$num = intval($div);
}
if ($num) $encoded = $alphabet[$num] . $encoded;
return $encoded;
}
function base_decode($num, $alphabet) {
$decoded = 0;
$multi = 1;
while (strlen($num) > 0) {
$digit = $num[strlen($num)-1];
$decoded += $multi * strpos($alphabet, $digit);
$multi = $multi * strlen($alphabet);
$num = substr($num, 0, -1);
}
return $decoded;
}
echo base_encode($Guid, $alphabet);
So, if a id that is generated is already in use, i want this code to be able to repeat until a completely new id is generated and entered into the database. IN addition i am new to programming, so please feel free to elaborate ;)
Any thoughts? Thanks.
Super easy.
You have 3 functions.
One - main generate guid function.
Two - Sub generate guid function.
Three - Sub insert guid function.
Sub generate function:
Does the actual generation, returns a guid.
Sub insert function:
Attempts to insert guid into the database. Returns false/null on failure. True/data on success.
Main function:
In a loop:
Call subfunction to get a guid.
Call subfunction to insert in the database where the guid is a unique or primary key.
On failure, restart the loop.
Success exits the loop and returns the guid.
Example:
function GetGuid()
{
do
{
$guid = GenerateGuid();
} while (!InsertGuid($guid));
return $guid;
}
function GenerateGuid()
{
// do your stuff here.
return $guid;
}
function InsertGuid($guid)
{
$sql = 'INSERT INTO `guid_table` (`guid`) VALUES ('$guid')';
$connection = //do sql connect here;
return // do sql execution here which will return false/null on failure;
}
function randr($j = 8){
$string = "";
for($i=0;$i < $j;$i++){
srand((double)microtime()*1234567);
$x = mt_rand(0,2);
switch($x){
case 0:$string.= chr(mt_rand(97,122));break;
case 1:$string.= chr(mt_rand(65,90));break;
case 2:$string.= chr(mt_rand(48,57));break;
}
}
return $string;
}
do{
$id = randr();
$check = mysql_query("SELECT uniq FROM users WHERE uniq = '$id'");
}while(mysql_num_rows($check) != 0);
Think about this.
I have to upgrade/fix a system that's written similarly to the way you code, and I gotta tell you, I've really grown to hate the original programmer.
Think about what you're doing for a sec, if another user creates an account between when you ask if the guid is valid (and get back yes) and when you actually insert the row, you can still have collisions. That's beyond horrible...
But the guys that made the database programs thought of this and offer you a painless alternative: identity columns. They provide 3 major advantages:
guaranteed to be unique (or the insertion fails)
they're automatically made into a primary key
the database generates them for you
To use them, make your ID column to be an identity column, and when you do your insert, write it like this:
insert into users (name, passwordhash, extrastuff)
values (#name, #passwordhash, #extrastuff);
select ##identity -- or ident_current() for mysql
And you get back the user id generated for you for further processing. This is all done simultaneously, no matter how many users are trying this at the same time.
I built similar code before, I typically start with a null variable, and I do while ($variable == null) { }
inside the while, I create the new code check it against the database and if it doesn't exist yet, I set $variable = $new_code (which will break the while) and then proceed accordingly.
Additionally, I log any collisions that may occur
hope this helps
May be , a slight different approach
i would move my generation logic inside a stored procedure and ask database to generate a unique sequence like in oracle.
This way , i would be able to avoid numerous trips to check the number is unique or not.