#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
static const uint8_t Base64IndexTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define DECODE_MAP_SIZE 80
static char Base64DecodeTable[DECODE_MAP_SIZE];
static void generateDecodeTable()
{
static bool isDecodeMapGenerated = false;
if(!isDecodeMapGenerated)
{
const size_t base64_encode_map_size
= strlen(Base64IndexTable
); memset(Base64DecodeTable
, base64_encode_map_size
, DECODE_MAP_SIZE
);
for (size_t i = 0; i < base64_encode_map_size; ++i)
{
Base64DecodeTable[Base64IndexTable[i]] = i;
}
isDecodeMapGenerated = true;
}
}
char* decode(const char* encoded_str)
{
char buffer[4];
int p = 0;
const size_t base64_encode_map_size
= strlen(Base64IndexTable
);
generateDecodeTable();
for(int i = 0; encoded_str[i] != '\0'; i++)
{
buffer[i%4] = Base64DecodeTable[encoded_str[i]];
if((i+1)%4 == 0)
{
decoded_str[p++] = (buffer[0] << 2) + (buffer[1] >> 4);
if(buffer[2] != base64_encode_map_size)
{
decoded_str[p++] = (buffer[1] << 4) + (buffer[2] >> 2);
}
if(buffer[3] != base64_encode_map_size)
{
decoded_str[p++] = (buffer[2] << 6) + buffer[3];
}
}
}
decoded_str[p] = '\0';
printf("p = %d, size = %ld\n", p
, strlen(encoded_str
) * 3 / 4);
return decoded_str;
}
int main()
{
const char* encoded1 = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIakNDQWdhZ0F3SUJBZ0lSQUpBSUdqNUdCWmM0NzF0eUFiZnl3cVF3RFFZSktvWklodmNOQVFFTEJRQXcKSnpFbE1DTUdBMVVFQXhNY2NXRXRZMkVnUzJsMFkyaGxia052Ym01bFkzUWdVbTl2ZENCRFFUQWVGdzB5TkRFeQpNak14TWpNeE5UWmFGdzB5TlRFeU1qTXhNak14TlRaYU1DY3hKVEFqQmdOVkJBTVRISEZoTFdOaElFdHBkR05vClpXNURiMjV1WldOMElGSnZiM1FnUTBFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUIKQVFERzlMbGVFKzVRR0VZNTJGZVRmd3JqMlI0aFNBZHhPNkFyRERzLzM0QytkRDhmNGk2OTI5MFhNbUhBRWZnVQpiYkt6MTIvM2FHSDZhQ2EvZUVnQUt4SDE1YWxHZS9mTGdkOHRlcjJ4RWMvMjZZUDZGSExLZTBYN2FMZTFteCtuCmxlM3ZWZ3VMMWt0Qng0NEFUV0pucDVPNjl4aEtzZml1NlA0UzlSVkhnK3hxUGxsbi9ZdWFKdjBsKzd4MTlKM3EKWmlJT1owVVdoRGcwbjZrWGRjWTNuSSs5QVZCRUgzRjVzN0pod0Q2aFNqUGR5QmtPSGtkK2Vmc3FkVGlFOFAvcgpPTEkyVEFzOTFxUlNKc0FlMUtydUU1Y1ZrRTZUUzhTOHY5SUY1alFPUlJnUFBzckx5MGRJUjh0R09PSnRXeFVECjN4cWlrOUxIQ0FKMWJuZ09HYUdnZjk4ekFnTUJBQUdqUlRCRE1BNEdBMVVkRHdFQi93UUVBd0lCQmpBU0JnTlYKSFJNQkFmOEVDREFHQVFIL0FnRUJNQjBHQTFVZERnUVdCQlMwNWFCcC9FUDl1WVdjZ0c2b3FMM2w2QWdKdWpBTgpCZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFsOUhzcEZnZTZMUFduYmU5eXdtWXVYWGUxZHlTb2VLOEVLa2hyNUhIClMrenhCazNpU1g1Z2ZobFJlR25yZWg5allCOEVOWmVPa2dZOVg3cjFqMkZDUTlLZFlrbXduRTFnbGJMelc0Qm0KdGNpSWNPbmRqckV6QlBRTUN5Y0sxVTUrYzkvT0lNUWRsdGJDYXlOWVlUM01aSG9tQ01QMks1Z1pVTnI0cnpQNgp5ZU9uOHNzT0hkSUtQa3RyWHN3cWpmTVVwU01LdHpxbE5CS0laM3pGbWhpTWJUeEJnQ3I5SlBEQlZPK3Zjdzc0CjFuUC9VRlhVN0VoWVhaV05BZGczTTc1MkkxSXVYT0VOZktuOURteGM2YU5oMFJwL1J1bXRYQ3FWWFROSWxub1YKYWpWRVRMMmQ0cTJjYUtOYlpVSmJxNnZadUppNm1Dd3o5MExDamhHT2dxRU9VQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=";
const char* encoded2 = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0ekNDQXArZ0F3SUJBZ0lRZHJYRE1IWHZLenZzOE8xOVR4RnQwREFOQmdrcWhraUc5dzBCQVFzRkFEQXYKTVMwd0t3WURWUVFERXlSeFlTMWpZU0JMYVhSamFHVnVRMjl1Ym1WamRDQkpiblJsY20xbFpHbGhkR1VnUTBFdwpIaGNOTWpVd05ERTFNakF3TVRFMFdoY05Nall3TkRFMU1qQXdNakUwV2pBZk1SMHdHd1lEVlFRRERCUXlOVEEwCk1EQXdNREF4WDJaeWVXMWhjM1JsY2pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU1nRXZRT3kwSHp2WDF3NGY3RkJZdjlzaHgxNXhkZEhpR2hqMG1WZklBQjB3bDJRL0Q4blVPYUg0bDlaTTFWaQpwN05TbW8wUUhvWFFaUlY2U0lsMmR2a05uS0lwVnpIcVJBMExXRTl2MG45YUowMHk1cVhFa2lFV1k3VDlmbzNkCjNrN2ZWeVhBWU1IZXIrMk9qNFNNeG9MMzNPM1QwdlhmODBHM3N2OCtKdVVSWXgwTm5HQWpiRWQ3RW5wRndTNEEKcm4yNjlDOVE2bkliNGlOZjZ1eWpOVE1JZWE3Wm1LNThoQjI3QVJ6NWRPRHRVQWkvd3JUQ0NuOWVxMFpJWVN6awpXS2lCY2NCbDBlbjJwN1dReWpETURScERRL05OVGdvM210MkJ4R2VpUGxBZ3dnakc0Q1haNTB4U1R2dXlubWZjCkV1TU5nakt4UVFiMnVVUWozeS8wendNQ0F3RUFBYU9CM2pDQjJ6QU9CZ05WSFE4QkFmOEVCQU1DQmFBd0hRWUQKVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUIwR0ExVWREZ1FXQkJScVhTdTB5Tkh1ZXRIUgprTThqRkRYTEtKb3NpVEFmQmdOVkhTTUVHREFXZ0JUK0ZhaWpYdDJ4R2lzZkd4eDhHNVFNZWhCKzFEQWZCZ05WCkhSRUVHREFXZ2hReU5UQTBNREF3TURBeFgyWnllVzFoYzNSbGNqQkpCZ3dyQmdFRUFZS2taTVlvUUFFRU9UQTMKQWdFQkJBVmhaRzFwYmdRcldUTlFkRTVWVGpJNWFpMXBNR1l4ZEZReWNsOVpOa2gxWWkweVdXSjJhbWwyUTFJMApXRjlaYjA4dFl6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFqNTM2UHZZTmxaN3U0cHZBblNBc0dYL0MrODFiCndTRERJL3RrdGlUV1pid0xmbnMyR0FpY09lSWhSbHZKbHplYXRhYVdObWdkOUJ2TWJ3WStZazdvcUx1eUsrdzUKWGRGTEZtOGJDN09CbVAydVBiVEpJUE5mOFUrN3NFYW5ENFN3Qi9VOG01QzhsTmE4b1FGcnUveFVmQmNlbzZyQwpGTmNhZDJYL09ubWFRZC9sSzkzay9udFQ1cldyb3MvK3hmeHZ4UDIzU2JxNGhYYXFoS0JJbERvdkIyT1VqeFZpClJtQUJvTXRCV3V5SUNpaVNLbWhqR0xvY1BGVUNtYTF4SHF4Y2tQNnE3VUxZSWY4aEo0SHFDU0wwY3lOaHY1UnEKRVZyS1VxRXVvM0gwaGszMTFheHNCZ1BhcEhubWsxMnVhMGZGVGxPN1h3dHNRVnNGQ2FRZ1hseUEvdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURSakNDQWk2Z0F3SUJBZ0lRVmpYYnVmNVJTdmVabDN2amZVcDVCVEFOQmdrcWhraUc5dzBCQVFzRkFEQW4KTVNVd0l3WURWUVFERXh4eFlTMWpZU0JMYVhSamFHVnVRMjl1Ym1WamRDQlNiMjkwSUVOQk1CNFhEVEkwTVRJeQpNekV5TXpFMU4xb1hEVEkxTVRJeU16RXlNekUxTmxvd0x6RXRNQ3NHQTFVRUF4TWtjV0V0WTJFZ1MybDBZMmhsCmJrTnZibTVsWTNRZ1NXNTBaWEp0WldScFlYUmxJRU5CTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEEKTUlJQkNnS0NBUUVBblBZbmc5QXRPNFZwd1VnM3ZSNXoxRFlpS29xNWpMWFFuRnhEOUxOWEpHdFg1NUc2eHMxNAoraWI5WDczVlVUV3o1NjZMNjFITSt2ejkzRWd5algrdlB4c2RoSEVWcUZjb1NPdldHMlozSGJGRFYvOEdIRHR0CktHcUc2bHF6eU5mYU52ODFLUGZBMCtsa3lEVHdkT2UzSFI5MldjMGJDVzV0OEdOT1IvVWxza2VKc0YwWDlNVGoKa2NoSk1EQWZEeWRDYVBhSDN0R0FUc2hWZFdjUGlvSE53TW1xYW4yVzBvbUpxbmtkTnB6WFVFRWx0K1ZHRTdUZwpIRkVwUHJpL2NZbTFtM01jQXg0MDZmbVdySU5oMnd6bGZFaDUwc1BtcHZDYmhHMWZjbDdCOStWcWxkWFFFNU9QCkF6QlltQk84aDJpTjFkei9nSUovOHdRMllmK2xWeFBkbHdJREFRQUJvMll3WkRBT0JnTlZIUThCQWY4RUJBTUMKQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQWRCZ05WSFE0RUZnUVUvaFdvbzE3ZHNSb3JIeHNjZkJ1VQpESG9RZnRRd0h3WURWUjBqQkJnd0ZvQVV0T1dnYWZ4RC9ibUZuSUJ1cUtpOTVlZ0lDYm93RFFZSktvWklodmNOCkFRRUxCUUFEZ2dFQkFIR09lY1BMT3BIUWtYYk5JbitxNW5nSnRMSXQwNjkzSllQTlVWTGY0SjBzbHc2ZWJnaDcKWldmQ1JqQTFNWTB6SWRuY1JFRzIxNVd0elJkMmlyQXdOM21tbWlZY3JFYXhxTVNrOUhXajhOdC9FWmp5S3lVTgptaDY2SjVtNnZ1L2E1SHNDUXhCS3NWS2t2OE1hZ3I2M0RwNXdMZC93c3U0OWNpY3QyTzBUd0ZmeldXNnRsejJhCmpJT1JBNkRPWHkxYUl2Y1lvRzF6VnJOb3kxRzJPRFg4NHhPVWtrQXZtekNQNVpNNjM3ZEFXcnJabnZXSmJHNHMKa0VDUno5aXJJR3hqeVl1UzZvZE9zVXpPUVdnU1hMZnErUnJuTHZKWlE4anlzQWtNaUxjNnJncGJwWHh6aU1hMApFUjY4aUtkN3I5YU5QU05vUFFnL3RPaDlta0NMTjFxVUg3Zz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=";
const char* encoded3 = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeUFTOUE3TFFmTzlmWERoL3NVRmkvMnlISFhuRjEwZUlhR1BTWlY4Z0FIVENYWkQ4ClB5ZFE1b2ZpWDFrelZXS25zMUthalJBZWhkQmxGWHBJaVhaMitRMmNvaWxYTWVwRURRdFlUMi9TZjFvblRUTG0KcGNTU0lSWmp0UDEramQzZVR0OVhKY0Jnd2Q2djdZNlBoSXpHZ3ZmYzdkUFM5ZC96UWJleS96NG01UkZqSFEyYwpZQ05zUjNzU2VrWEJMZ0N1ZmJyMEwxRHFjaHZpSTEvcTdLTTFNd2g1cnRtWXJueUVIYnNCSFBsMDRPMVFDTC9DCnRNSUtmMTZyUmtoaExPUllxSUZ4d0dYUjZmYW50WkRLTU13TkdrTkQ4MDFPQ2plYTNZSEVaNkkrVUNEQ0NNYmcKSmRublRGSk8rN0tlWjl3UzR3MkNNckZCQnZhNVJDUGZML1RQQXdJREFRQUJBb0lCQUVtRS9GalVyQytQNk5SRAo3Q09pTGhwR3NPOVRxRFcyRkZ5U2ZHNUlaY0hsS09BdGY1cFRBRGlNTDlmdU9LRWs3eEZKeG9jZEtxcnk2NFRXCmVyMFVMeXppSlBXeURsdkppUlBtWEtKdUxzZ2l3aGx0SVR4RElaZEozSUpWUHVRMGJoYzlucEhBd1kvaEkzZEYKRkZtYlNRZ3d4U01oM2dRRU9peW9zZ0dCdmRncVFuVmJxMXliVUdtVStQTUZOR0sza2NuV2pwbzVGZ3B6ZTFlVgprMS9Pc0NHQ2xDWXY1RmdDQ1VHR2Y0dTdpRTI0NlZ6aUhjZE4zUWhWQyt2Z3lWcWVIUGNEdlFHVDV1WENNbFUrCmJkdFpBZnhNckZjQUhuek14YlFrUU9HQnZKN2ZpeXYrN04zQ0IyUWJUM2RkQ1JENzVIazFpZklqdFI0ckZxdCsKNk56eVZ1a0NnWUVBNnZFOHMxZDliL1hISlh4NFpvN3lyNTE0d3hsc3lWVGhWd2pYQXZDUkUva0syZDR2endWagpsdndIemFIWGRsS0tJL25SSFl6V3N4R3hqVjVVR1plVXhGRmdxeEFjektMUTl2WWp2STY0MUlYeU9mL2RnL3ptCmhVaTBMQS9DdE9SdWFIaXFpZG9PQnFqNzV1aDQrUmJKOC80TGRHUEsrMWhIeURqVlAvb2Q5czBDZ1lFQTJmSXMKSmZUNFczZFJ1V2dqQ1lsQ05tdWNNSFg1dUp4VE81R000WmYySGZPRGlyNWxBS0xyUEtaQm96RTRLWlZRWjBsRgpVR055UmJCLzVTaEdBdXFPeU1DcnBHeElTdnhYU1c5OWc0akY1TCtQLzZLa3RUUERiYUVHWUZSY0VNNHk4RzZ2CjJ3TThEcWNTSkQ2cUFORXhoUFVwVEhzRnNic2k1YldVM1VEMnZROENnWUVBbFFidXJRZ0xMbENsd1JhQ1BQUGgKNXhtcE40QlNMQ2RtUk5IN3FRYTEwQWlDSkk2Mm5zZlpVeldOTVplK1YzU2w0WW9lWm5NbTRUR1JBWTViSkZ5dApaaFlFanAzSzF0ZFVXOExvQ2p3eDY4VUhVRmtIeHloTmhUQUg4WWNSeDdLNmdoUkFnTzdMUk5nOTZVdC9LT21XCnN1bHJsS21VWVBpdmw4Yk5KaWJlaU9VQ2dZQjlNekZKWE1DUFNxd1g1a3E2WDY4NXMvZTFueEFsalNnRFFFbSsKRHAzRDl1L0o5RFh4ZDZYSzRYY3pXRUw3SUZ0ZitpZG5WcmwrYnpZSlhtbFpvNFVDcml2citJaFBDMGJaV01LeApuUkNScDdvQkVGMnQrbDU1eTlidDM0aEQzekJFRGxIWGJyUkJkcGhsV2RvdlBmMUVjOUdWcmRaSGswa296SGNICjR4bmE0UUtCZ1FDbWlzK2RJNGozUmtLQUVJSFEra3VYRlQrT05COE1NcnZaY05PbndMQjFJK2NYanJBZlJxZEgKV09GWjgySGhYeW95NXBKZ1pRSTNFNW1OYStVUmZ2aHRlYmxYdVliKytvaHdDaW9icDVOTm5OUy8vL2ZHV1YwcwpQTDlObkZFUnhWZGJ0Rm1OWGJHdHRXQjQ1QXZWcmF5d0I1bFR3OUE5bkdpNllKVFVZQ0hUMVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=";
char* decoded = decode(encoded2);
printf("Decoded:\n%s\n", decoded
);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRib29sLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8aW50dHlwZXMuaD4KCnN0YXRpYyBjb25zdCB1aW50OF90IEJhc2U2NEluZGV4VGFibGVbXT0iQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyI7CiNkZWZpbmUgREVDT0RFX01BUF9TSVpFIDgwCnN0YXRpYyBjaGFyIEJhc2U2NERlY29kZVRhYmxlW0RFQ09ERV9NQVBfU0laRV07CgpzdGF0aWMgdm9pZCBnZW5lcmF0ZURlY29kZVRhYmxlKCkKewogICAgc3RhdGljIGJvb2wgaXNEZWNvZGVNYXBHZW5lcmF0ZWQgPSBmYWxzZTsKCiAgICBpZighaXNEZWNvZGVNYXBHZW5lcmF0ZWQpCiAgICB7CiAgICAgICAgY29uc3Qgc2l6ZV90IGJhc2U2NF9lbmNvZGVfbWFwX3NpemUgPSBzdHJsZW4oQmFzZTY0SW5kZXhUYWJsZSk7CiAgICAgICAgbWVtc2V0KEJhc2U2NERlY29kZVRhYmxlLCBiYXNlNjRfZW5jb2RlX21hcF9zaXplLCBERUNPREVfTUFQX1NJWkUpOwogICAgCiAgICAgICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBiYXNlNjRfZW5jb2RlX21hcF9zaXplOyArK2kpCiAgICAgICAgewogICAgICAgICAgICBCYXNlNjREZWNvZGVUYWJsZVtCYXNlNjRJbmRleFRhYmxlW2ldXSA9IGk7CiAgICAgICAgfQogICAgICAgIGlzRGVjb2RlTWFwR2VuZXJhdGVkID0gdHJ1ZTsKICAgIH0KfQoKY2hhciogZGVjb2RlKGNvbnN0IGNoYXIqIGVuY29kZWRfc3RyKQp7CiAgICBjaGFyIGJ1ZmZlcls0XTsKICAgIGNoYXIqIGRlY29kZWRfc3RyID0gbWFsbG9jKHN0cmxlbihlbmNvZGVkX3N0cikgKiAzIC8gNCk7CiAgICBpbnQgcCA9IDA7CiAgICBjb25zdCBzaXplX3QgYmFzZTY0X2VuY29kZV9tYXBfc2l6ZSA9IHN0cmxlbihCYXNlNjRJbmRleFRhYmxlKTsKCiAgICBnZW5lcmF0ZURlY29kZVRhYmxlKCk7CiAgICAKICAgIGZvcihpbnQgaSA9IDA7IGVuY29kZWRfc3RyW2ldICE9ICdcMCc7IGkrKykKICAgIHsKICAgICAgICBidWZmZXJbaSU0XSA9IEJhc2U2NERlY29kZVRhYmxlW2VuY29kZWRfc3RyW2ldXTsKICAgICAgICBpZigoaSsxKSU0ID09IDApCiAgICAgICAgewogICAgICAgICAgICBkZWNvZGVkX3N0cltwKytdID0gKGJ1ZmZlclswXSA8PCAyKSArIChidWZmZXJbMV0gPj4gNCk7CiAgICAgICAgICAgIGlmKGJ1ZmZlclsyXSAhPSBiYXNlNjRfZW5jb2RlX21hcF9zaXplKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBkZWNvZGVkX3N0cltwKytdID0gKGJ1ZmZlclsxXSA8PCA0KSArIChidWZmZXJbMl0gPj4gMik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYoYnVmZmVyWzNdICE9IGJhc2U2NF9lbmNvZGVfbWFwX3NpemUpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGRlY29kZWRfc3RyW3ArK10gPSAoYnVmZmVyWzJdIDw8IDYpICsgYnVmZmVyWzNdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGRlY29kZWRfc3RyW3BdID0gJ1wwJzsKICAgIAogICAgcHJpbnRmKCJwID0gJWQsIHNpemUgPSAlbGRcbiIsIHAsIHN0cmxlbihlbmNvZGVkX3N0cikgKiAzIC8gNCk7CiAgICAKICAgIHJldHVybiBkZWNvZGVkX3N0cjsKfQoKaW50IG1haW4oKQp7CiAgICBjb25zdCBjaGFyKiBlbmNvZGVkMSA9ICJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VSSWFrTkRRV2RoWjBGM1NVSkJaMGxTUVVwQlNVZHFOVWRDV21NME56RjBlVUZpWm5sM2NWRjNSRkZaU2t0dldrbG9kbU5PUVZGRlRFSlJRWGNLU25wRmJFMURUVWRCTVZWRlFYaE5ZMk5YUlhSWk1rVm5VekpzTUZreWFHeGlhMDUyWW0wMWJGa3pVV2RWYlRsMlpFTkNSRkZVUVdWR2R6QjVUa1JGZVFwTmFrMTRUV3BOZUU1VVdtRkdkekI1VGxSRmVVMXFUWGhOYWsxNFRsUmFZVTFEWTNoS1ZFRnFRbWRPVmtKQlRWUklTRVpvVEZkT2FFbEZkSEJrUjA1dkNscFhOVVJpTWpWMVdsZE9NRWxHU25aaU0xRm5VVEJGZDJkblJXbE5RVEJIUTFOeFIxTkpZak5FVVVWQ1FWRlZRVUUwU1VKRWQwRjNaMmRGUzBGdlNVSUtRVkZFUnpsTWJHVkZLelZSUjBWWk5USkdaVlJtZDNKcU1sSTBhRk5CWkhoUE5rRnlSRVJ6THpNMFF5dGtSRGhtTkdrMk9USTVNRmhOYlVoQlJXWm5WUXBpWWt0Nk1USXZNMkZIU0RaaFEyRXZaVVZuUVV0NFNERTFZV3hIWlM5bVRHZGtPSFJsY2pKNFJXTXZNalpaVURaR1NFeExaVEJZTjJGTVpURnRlQ3R1Q214bE0zWldaM1ZNTVd0MFFuZzBORUZVVjBwdWNEVlBOamw0YUV0elptbDFObEEwVXpsU1ZraG5LM2h4VUd4c2JpOVpkV0ZLZGpCc0t6ZDRNVGxLTTNFS1dtbEpUMW93VlZkb1JHY3dialpyV0dSaldUTnVTU3M1UVZaQ1JVZ3pSalZ6TjBwb2QwUTJhRk5xVUdSNVFtdFBTR3RrSzJWbWMzRmtWR2xGT0ZBdmNncFBURWt5VkVGek9URnhVbE5LYzBGbE1VdHlkVVUxWTFaclJUWlVVemhUT0hZNVNVWTFhbEZQVWxKblVGQnpja3g1TUdSSlVqaDBSMDlQU25SWGVGVkVDak40Y1dsck9VeElRMEZLTVdKdVowOUhZVWRuWmprNGVrRm5UVUpCUVVkcVVsUkNSRTFCTkVkQk1WVmtSSGRGUWk5M1VVVkJkMGxDUW1wQlUwSm5UbFlLU0ZKTlFrRm1PRVZEUkVGSFFWRklMMEZuUlVKTlFqQkhRVEZWWkVSblVWZENRbE13TldGQ2NDOUZVRGwxV1ZkalowYzJiM0ZNTTJ3MlFXZEtkV3BCVGdwQ1oydHhhR3RwUnpsM01FSkJVWE5HUVVGUFEwRlJSVUZzT1VoemNFWm5aVFpNVUZkdVltVTVlWGR0V1hWWVdHVXhaSGxUYjJWTE9FVkxhMmh5TlVoSUNsTXJlbmhDYXpOcFUxZzFaMlpvYkZKbFIyNXlaV2c1YWxsQ09FVk9XbVZQYTJkWk9WZzNjakZxTWtaRFVUbExaRmxyYlhkdVJURm5iR0pNZWxjMFFtMEtkR05wU1dOUGJtUnFja1Y2UWxCUlRVTjVZMHN4VlRVcll6a3ZUMGxOVVdSc2RHSkRZWGxPV1ZsVU0wMWFTRzl0UTAxUU1rczFaMXBWVG5JMGNucFFOZ3A1WlU5dU9ITnpUMGhrU1V0UWEzUnlXSE4zY1dwbVRWVndVMDFMZEhweGJFNUNTMGxhTTNwR2JXaHBUV0pVZUVKblEzSTVTbEJFUWxaUEszWmpkemMwQ2pGdVVDOVZSbGhWTjBWb1dWaGFWMDVCWkdjelRUYzFNa2t4U1hWWVQwVk9aa3R1T1VSdGVHTTJZVTVvTUZKd0wxSjFiWFJZUTNGV1dGUk9TV3h1YjFZS1lXcFdSVlJNTW1RMGNUSmpZVXRPWWxwVlNtSnhOblphZFVwcE5tMURkM281TUV4RGFtaEhUMmR4UlU5VlFUMDlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMD0iOwogICAgY29uc3QgY2hhciogZW5jb2RlZDIgPSAiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUjBla05EUVhBclowRjNTVUpCWjBsUlpISllSRTFJV0haTGVuWnpPRTh4T1ZSNFJuUXdSRUZPUW1kcmNXaHJhVWM1ZHpCQ1FWRnpSa0ZFUVhZS1RWTXdkMHQzV1VSV1VWRkVSWGxTZUZsVE1XcFpVMEpNWVZoU2FtRkhWblZSTWpsMVltMVdhbVJEUWtwaWJsSnNZMjB4YkZwSGJHaGtSMVZuVVRCRmR3cElhR05PVFdwVmQwNUVSVEZOYWtGM1RWUkZNRmRvWTA1TmFsbDNUa1JGTVUxcVFYZE5ha1V3VjJwQlprMVNNSGRIZDFsRVZsRlJSRVJDVVhsT1ZFRXdDazFFUVhkTlJFRjRXREphZVdWWE1XaGpNMUpzWTJwRFEwRlRTWGRFVVZsS1MyOWFTV2gyWTA1QlVVVkNRbEZCUkdkblJWQkJSRU5EUVZGdlEyZG5SVUlLUVUxblJYWlJUM2t3U0hwMldERjNOR1kzUmtKWmRqbHphSGd4Tlhoa1pFaHBSMmhxTUcxV1prbEJRakIzYkRKUkwwUTRibFZQWVVnMGJEbGFUVEZXYVFwd04wNVRiVzh3VVVodldGRmFVbFkyVTBsc01tUjJhMDV1UzBsd1ZucEljVkpCTUV4WFJUbDJNRzQ1WVVvd01IazFjVmhGYTJsRlYxazNWRGxtYnpOa0NqTnJOMlpXZVZoQldVMUlaWElyTWs5cU5GTk5lRzlNTXpOUE0xUXdkbGhtT0RCSE0zTjJPQ3RLZFZWU1dYZ3dUbTVIUVdwaVJXUTNSVzV3Um5kVE5FRUtjbTR5TmpsRE9WRTJia2xpTkdsT1pqWjFlV3BPVkUxSlpXRTNXbTFMTlRob1FqSTNRVko2TldSUFJIUlZRV2t2ZDNKVVEwTnVPV1Z4TUZwSldWTjZhd3BYUzJsQ1kyTkNiREJsYmpKd04xZFJlV3BFVFVSU2NFUlJMMDVPVkdkdk0yMTBNa0o0UjJWcFVHeEJaM2RuYWtjMFExaGFOVEI0VTFSMmRYbHViV1pqQ2tWMVRVNW5ha3Q0VVZGaU1uVlZVV296ZVM4d2VuZE5RMEYzUlVGQllVOUNNMnBEUWpKNlFVOUNaMDVXU0ZFNFFrRm1PRVZDUVUxRFFtRkJkMGhSV1VRS1ZsSXdiRUpDV1hkR1FWbEpTM2RaUWtKUlZVaEJkMFZIUTBOelIwRlJWVVpDZDAxRFRVSXdSMEV4VldSRVoxRlhRa0pTY1ZoVGRUQjVUa2gxWlhSSVVncHJUVGhxUmtSWVRFdEtiM05wVkVGbVFtZE9Wa2hUVFVWSFJFRlhaMEpVSzBaaGFXcFlkREo0UjJselprZDRlRGhITlZGTlpXaENLekZFUVdaQ1owNVdDa2hTUlVWSFJFRlhaMmhSZVU1VVFUQk5SRUYzVFVSQmVGZ3lXbmxsVnpGb1l6TlNiR05xUWtwQ1ozZHlRbWRGUlVGWlMydGFUVmx2VVVGRlJVOVVRVE1LUVdkRlFrSkJWbWhhUnpGd1ltZFJjbGRVVGxGa1JUVldWR3BKTldGcE1YQk5SMWw0WkVaUmVXTnNPVnBPYTJneFdXa3dlVmRYU2pKaGJXd3lVVEZKTUFwWFJqbGFZakE0ZEZsNlFVNUNaMnR4YUd0cFJ6bDNNRUpCVVhOR1FVRlBRMEZSUlVGcU5UTTJVSFpaVG14YU4zVTBjSFpCYmxOQmMwZFlMME1yT0RGaUNuZFRSRVJKTDNScmRHbFVWMXBpZDB4bWJuTXlSMEZwWTA5bFNXaFNiSFpLYkhwbFlYUmhZVmRPYldka09VSjJUV0ozV1N0WmF6ZHZjVXgxZVVzcmR6VUtXR1JHVEVadE9HSkROMDlDYlZBeWRWQmlWRXBKVUU1bU9GVXJOM05GWVc1RU5GTjNRaTlWT0cwMVF6aHNUbUU0YjFGR2NuVXZlRlZtUW1ObGJ6WnlRd3BHVG1OaFpESllMMDl1YldGUlpDOXNTemt6YXk5dWRGUTFjbGR5YjNNdkszaG1lSFo0VURJelUySnhOR2hZWVhGb1MwSkpiRVJ2ZGtJeVQxVnFlRlpwQ2xKdFFVSnZUWFJDVjNWNVNVTnBhVk5MYldocVIweHZZMUJHVlVOdFlURjRTSEY0WTJ0UU5uRTNWVXhaU1dZNGFFbzBTSEZEVTB3d1kzbE9hSFkxVW5FS1JWWnlTMVZ4UlhWdk0wZ3dhR3N6TVRGaGVITkNaMUJoY0VodWJXc3hNblZoTUdaR1ZHeFBOMWgzZEhOUlZuTkdRMkZSWjFoc2VVRXZkejA5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUlNha05EUVdrMlowRjNTVUpCWjBsUlZtcFlZblZtTlZKVGRtVmFiRE4yYW1aVmNEVkNWRUZPUW1kcmNXaHJhVWM1ZHpCQ1FWRnpSa0ZFUVc0S1RWTlZkMGwzV1VSV1VWRkVSWGg0ZUZsVE1XcFpVMEpNWVZoU2FtRkhWblZSTWpsMVltMVdhbVJEUWxOaU1qa3dTVVZPUWsxQ05GaEVWRWt3VFZSSmVRcE5la1Y1VFhwRk1VNHhiMWhFVkVreFRWUkplVTE2UlhsTmVrVXhUbXh2ZDB4NlJYUk5RM05IUVRGVlJVRjRUV3RqVjBWMFdUSkZaMU15YkRCWk1taHNDbUpyVG5aaWJUVnNXVE5SWjFOWE5UQmFXRXAwV2xkU2NGbFlVbXhKUlU1Q1RVbEpRa2xxUVU1Q1oydHhhR3RwUnpsM01FSkJVVVZHUVVGUFEwRlJPRUVLVFVsSlFrTm5TME5CVVVWQmJsQlpibWM1UVhSUE5GWndkMVZuTTNaU05Yb3hSRmxwUzI5eE5XcE1XRkZ1Um5oRU9VeE9XRXBIZEZnMU5VYzJlSE14TkFvcmFXSTVXRGN6VmxWVVYzbzFOalpNTmpGSVRTdDJlamt6UldkNWFsZ3JkbEI0YzJSb1NFVldjVVpqYjFOUGRsZEhNbG96U0dKR1JGWXZPRWRJUkhSMENrdEhjVWMyYkhGNmVVNW1ZVTUyT0RGTFVHWkJNQ3RzYTNsRVZIZGtUMlV6U0ZJNU1sZGpNR0pEVnpWME9FZE9UMUl2Vld4emEyVktjMFl3V0RsTlZHb0thMk5vU2sxRVFXWkVlV1JEWVZCaFNETjBSMEZVYzJoV1pGZGpVR2x2U0U1M1RXMXhZVzR5VnpCdmJVcHhibXRrVG5CNldGVkZSV3gwSzFaSFJUZFVad3BJUmtWd1VISnBMMk5aYlRGdE0wMWpRWGcwTURabWJWZHlTVTVvTW5kNmJHWkZhRFV3YzFCdGNIWkRZbWhITVdaamJEZENPU3RXY1d4a1dGRkZOVTlRQ2tGNlFsbHRRazg0YURKcFRqRmtlaTluU1Vvdk9IZFJNbGxtSzJ4V2VGQmtiSGRKUkVGUlFVSnZNbGwzV2tSQlQwSm5UbFpJVVRoQ1FXWTRSVUpCVFVNS1FWRlpkMFZuV1VSV1VqQlVRVkZJTDBKQlozZENaMFZDTDNkSlFrRkVRV1JDWjA1V1NGRTBSVVpuVVZVdmFGZHZiekUzWkhOU2IzSkllSE5qWmtKMVZRcEVTRzlSWm5SUmQwaDNXVVJXVWpCcVFrSm5kMFp2UVZWMFQxZG5ZV1o0UkM5aWJVWnVTVUoxY1V0cE9UVmxaMGxEWW05M1JGRlpTa3R2V2tsb2RtTk9Da0ZSUlV4Q1VVRkVaMmRGUWtGSVIwOWxZMUJNVDNCSVVXdFlZazVKYml0eE5XNW5TblJNU1hRd05qa3pTbGxRVGxWV1RHWTBTakJ6YkhjMlpXSm5hRGNLV2xkbVExSnFRVEZOV1RCNlNXUnVZMUpGUnpJeE5WZDBlbEprTW1seVFYZE9NMjF0YldsWlkzSkZZWGh4VFZOck9VaFhhamhPZEM5RldtcDVTM2xWVGdwdGFEWTJTalZ0Tm5aMUwyRTFTSE5EVVhoQ1MzTldTMnQyT0UxaFozSTJNMFJ3TlhkTVpDOTNjM1UwT1dOcFkzUXlUekJVZDBabWVsZFhOblJzZWpKaENtcEpUMUpCTmtSUFdIa3hZVWwyWTFsdlJ6RjZWbkpPYjNreFJ6SlBSRmc0TkhoUFZXdHJRWFp0ZWtOUU5WcE5Oak0zWkVGWGNuSmFiblpYU21KSE5ITUthMFZEVW5vNWFYSkpSM2hxZVZsMVV6WnZaRTl6VlhwUFVWZG5VMWhNWm5FclVuSnVUSFpLV2xFNGFubHpRV3ROYVV4ak5uSm5jR0p3V0hoNmFVMWhNQXBGVWpZNGFVdGtOM0k1WVU1UVUwNXZVRkZuTDNSUGFEbHRhME5NVGpGeFZVZzNaejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89IjsKICAgIGNvbnN0IGNoYXIqIGVuY29kZWQzID0gIkxTMHRMUzFDUlVkSlRpQlNVMEVnVUZKSlZrRlVSU0JMUlZrdExTMHRMUXBOU1VsRmNFRkpRa0ZCUzBOQlVVVkJlVUZUT1VFM1RGRm1UemxtV0VSb0wzTlZSbWt2TW5sSVNGaHVSakV3WlVsaFIxQlRXbFk0WjBGSVZFTllXa1E0Q2xCNVpGRTFiMlpwV0RGcmVsWlhTMjV6TVV0aGFsSkJaV2hrUW14R1dIQkphVmhhTWl0Uk1tTnZhV3hZVFdWd1JVUlJkRmxVTWk5VFpqRnZibFJVVEcwS2NHTlRVMGxTV21wMFVERXJhbVF6WlZSME9WaEtZMEpuZDJRMmRqZFpObEJvU1hwSFozWm1ZemRrVUZNNVpDOTZVV0psZVM5Nk5HMDFVa1pxU0ZFeVl3cFpRMDV6VWpOelUyVnJXRUpNWjBOMVptSnlNRXd4UkhGamFIWnBTVEV2Y1RkTFRURk5kMmcxY25SdFdYSnVlVVZJWW5OQ1NGQnNNRFJQTVZGRFRDOURDblJOU1V0bU1UWnlVbXRvYUV4UFVsbHhTVVo0ZDBkWVVqWm1ZVzUwV2tSTFRVMTNUa2RyVGtRNE1ERlBRMnBsWVROWlNFVmFOa2tyVlVORVEwTk5ZbWNLU21SdWJsUkdTazhyTjB0bFdqbDNVelIzTWtOTmNrWkNRblpoTlZKRFVHWk1MMVJRUVhkSlJFRlJRVUpCYjBsQ1FVVnRSUzlHYWxWeVF5dFFOazVTUkFvM1EwOXBUR2h3UjNOUE9WUnhSRmN5UmtaNVUyWkhOVWxhWTBoc1MwOUJkR1kxY0ZSQlJHbE5URGxtZFU5TFJXczNlRVpLZUc5alpFdHhjbmsyTkZSWENtVnlNRlZNZVhwcFNsQlhlVVJzZGtwcFVsQnRXRXRLZFV4eloybDNhR3gwU1ZSNFJFbGFaRW96U1VwV1VIVlJNR0pvWXpsdWNFaEJkMWt2YUVrelpFWUtSa1p0WWxOUlozZDRVMDFvTTJkUlJVOXBlVzl6WjBkQ2RtUm5jVkZ1Vm1KeE1YbGlWVWR0VlN0UVRVWk9SMHN6YTJOdVYycHdielZHWjNCNlpURmxWZ3ByTVM5UGMwTkhRMnhEV1hZMVJtZERRMVZIUjJZMGRUZHBSVEkwTmxaNmFVaGpaRTR6VVdoV1F5dDJaM2xXY1dWSVVHTkVkbEZIVkRWMVdFTk5iRlVyQ21Ka2RGcEJabmhOY2taalFVaHVlazE0WWxGclVVOUhRblpLTjJacGVYWXJOMDR6UTBJeVVXSlVNMlJrUTFKRU56VklhekZwWmtscWRGSTBja1p4ZENzS05rNTZlVloxYTBObldVVkJOblpGT0hNeFpEbGlMMWhJU2xoNE5GcHZOM2x5TlRFMGQzaHNjM2xXVkdoV2QycFlRWFpEVWtVdmEwc3laRFIyZW5kV2FncHNkbmRJZW1GSVdHUnNTMHRKTDI1U1NGbDZWM040UjNocVZqVlZSMXBsVlhoR1JtZHhlRUZqZWt0TVVUbDJXV3AyU1RZME1VbFllVTltTDJSbkwzcHRDbWhWYVRCTVFTOURkRTlTZFdGSWFYRnBaRzlQUW5GcU56VjFhRFFyVW1KS09DODBUR1JIVUVzck1XaEllVVJxVmxBdmIyUTVjekJEWjFsRlFUSm1TWE1LU21aVU5GY3paRkoxVjJkcVExbHNRMDV0ZFdOTlNGZzFkVXA0VkU4MVIwMDBXbVl5U0daUFJHbHlOV3hCUzB4eVVFdGFRbTk2UlRSTFdsWlJXakJzUmdwVlIwNTVVbUpDTHpWVGFFZEJkWEZQZVUxRGNuQkhlRWxUZG5oWVUxYzVPV2MwYWtZMVRDdFFMelpMYTNSVVVFUmlZVVZIV1VaU1kwVk5OSGs0UnpaMkNqSjNUVGhFY1dOVFNrUTJjVUZPUlhob1VGVndWRWh6Um5OaWMyazFZbGRWTTFWRU1uWlJPRU5uV1VWQmJGRmlkWEpSWjB4TWJFTnNkMUpoUTFCUVVHZ0tOWGh0Y0U0MFFsTk1RMlJ0VWs1SU4zRlJZVEV3UVdsRFNrazJNbTV6WmxwVmVsZE9UVnBsSzFZelUydzBXVzlsV201TmJUUlVSMUpCV1RWaVNrWjVkQXBhYUZsRmFuQXpTekYwWkZWWE9FeHZRMnAzZURZNFZVaFZSbXRJZUhsb1RtaFVRVWc0V1dOU2VEZExObWRvVWtGblR6ZE1VazVuT1RaVmRDOUxUMjFYQ25OMWJISnNTMjFWV1ZCcGRtdzRZazVLYVdKbGFVOVZRMmRaUWpsTmVrWktXRTFEVUZOeGQxZzFhM0UyV0RZNE5YTXZaVEZ1ZUVGc2FsTm5SRkZGYlNzS1JIQXpSRGwxTDBvNVJGaDRaRFpZU3pSWVkzcFhSVXczU1VaMFppdHBaRzVXY213cllucFpTbGh0YkZwdk5GVkRjbWwyY2l0SmFGQkRNR0phVjAxTGVBcHVVa05TY0RkdlFrVkdNblFyYkRVMWVUbGlkRE0wYUVRemVrSkZSR3hJV0dKeVVrSmtjR2hzVjJSdmRsQm1NVVZqT1VkV2NtUmFTR3N3YTI5NlNHTklDalI0Ym1FMFVVdENaMUZEYldseksyUkpOR296VW10TFFVVkpTRkVyYTNWWVJsUXJUMDVDT0UxTmNuWmFZMDVQYm5kTVFqRkpLMk5ZYW5KQlpsSnhaRWdLVjA5R1dqZ3lTR2hZZVc5NU5YQktaMXBSU1RORk5XMU9ZU3RWVW1aMmFIUmxZbXhZZFZsaUt5dHZhSGREYVc5aWNEVk9UbTVPVXk4dkwyWkhWMVl3Y3dwUVREbE9ia1pGVW5oV1pHSjBSbTFPV0dKSGRIUlhRalExUVhaV2NtRjVkMEkxYkZSM09VRTVia2RwTmxsS1ZGVlpRMGhVTVZFOVBRb3RMUzB0TFVWT1JDQlNVMEVnVUZKSlZrRlVSU0JMUlZrdExTMHRMUW89IjsKICAgIAogICAgY2hhciogZGVjb2RlZCA9IGRlY29kZShlbmNvZGVkMik7CiAgICAKICAgIHByaW50ZigiRGVjb2RlZDpcbiVzXG4iLCBkZWNvZGVkKTsKICAgIGZyZWUoZGVjb2RlZCk7CgogICAgcmV0dXJuIDA7Cn0=