public function makeTOTP($provider = null)
 {
     /***
      * Assign a user a multifactor authentication code
      *
      * @param string $provider The provider giving 2FA.
      * @return array with the status in the key "status", errors in "error" and "human_error",
      * username in "username", and provisioning data in "uri"
      ***/
     if (empty($this->username)) {
         $this->getUser();
         # We MUST have this properly assigned
         if (empty($this->username)) {
             return array('status' => false, 'error' => 'Unable to get user.');
         }
     }
     if ($this->getSecret() !== false) {
         return array('status' => false, 'error' => '2FA has already been enabled for this user.', 'human_error' => "You've already enabled 2-factor authentication.", 'username' => $this->username);
     }
     try {
         if (!class_exists('Stronghash')) {
             require_once dirname(__FILE__) . '/../core/stronghash/php-stronghash.php';
         }
         $salt = Stronghash::createSalt();
         require_once dirname(__FILE__) . '/../base32/src/Base32/Base32.php';
         $secret = Base32::encode($salt);
         ## The resulting provisioning URI should now be sent to the user
         ## Flag should be set server-side indicating the change id pending
         $l = $this->openDB();
         $query = 'UPDATE `' . $this->getTable() . '` SET `' . $this->tmpColumn . "`='{$secret}' WHERE `" . $this->userColumn . "`='" . $this->username . "'";
         $r = mysqli_query($l, $query);
         if ($r === false) {
             return array('status' => false, 'human_error' => 'Database error', 'error' => mysqli_error($l));
         }
         # The data was saved correctly
         # Let's create the provisioning stuff!
         self::doLoadOTP();
         $totp = new OTPHP\TOTP($secret);
         $totp->setDigest($this->getDigest());
         $totp->setLabel($this->username);
         $totp->setIssuer($provider);
         $uri = $totp->getProvisioningURI($label, $provider);
         # iPhones don't actually accept the full, valid URI
         $unsafe_uri = urldecode($uri);
         $uri_args = explode('?', $unsafe_uri);
         $iphone_uri = $uri_args[0] . '?';
         $iphone_args = array();
         $iphone_safe_args = array('secret', 'issuer');
         foreach (explode('&', $uri_args[1]) as $paramval) {
             $pv = explode('=', $paramval);
             $param = $pv[0];
             $val = $pv[1];
             if (in_array($param, $iphone_safe_args)) {
                 $iphone_args[] = $param . '=' . $val;
             }
         }
         $iphone_uri .= implode('&', $iphone_args);
         /* $iphone32 = str_replace("=","",$secret_part[1]); */
         /* $iphone_uri = $secret_part[0]."secret=".$iphone32; #still no good */
         $retarr = self::generateQR($iphone_uri);
         # Let's get a human-readable secret
         $human_secret0 = str_replace('=', '', $secret);
         $i = 0;
         $human_secret = '';
         foreach (str_split($human_secret0) as $char) {
             $human_secret .= $char;
             ++$i;
             if ($i == 4) {
                 $human_secret .= ' ';
                 $i = 0;
             }
         }
         $retarr['secret'] = $secret;
         $retarr['human_secret'] = $human_secret;
         $retarr['username'] = $this->username;
         return $retarr;
     } catch (Exception $e) {
         return array('status' => false, 'human_error' => 'Unexpected error in makeTOTP', 'error' => $e->getMessage(), 'username' => $this->username, 'provider' => $provider, 'label' => $totp->getLabel(), 'uri' => $uri, 'secret' => $secret);
     }
 }