<?PHP
#
#   FILE:  CreateUser.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2011 Edward Almasy and Internet Scout
#   http://scout.wisc.edu
#

# When someone first logs in via OpenID and doesn't yet have a CWIS account,
# it is created for them here.

/**
* Generate a unique username by adding sequence numbers if necessary.
* @param BaseName The desired username
* @return A unique username
*/
function GenerateUsername($BaseName)
{
    global $DB;

    $DB->Query("SELECT UserName FROM APUsers");

    $Names = array();
    while ($Row = $DB->FetchRow())
    {
        $Names []= $Row["UserName"];
    }

    $Str="";
    while (in_array($BaseName.$Str, $Names) )
    {
        $Str = ($Str==="")? 1 : $Str+1;
    }

    return $BaseName.$Str;
}

global $DB, $AF, $SysConfig;
global $SPT_DBUserName, $SPT_DBPassword, $SPT_DBHost;

# Check that we got here via the OpenId machinery and not some drive-by linking
#  We should have parameters D (giving data in a base64'd, gzipped, serialized array),
#  And C giving a checksum of D based on our DB information, which should be secret.
if (isset($_GET["D"]) && isset($_GET["C"]) &&
    md5($_GET["D"].$SPT_DBUserName.$SPT_DBPassword.$SPT_DBHost) == $_GET["C"])
{
    # If the checksum is legit, extract the data we were given,
    # which will contain an OpenID reply.
    $Response = unserialize( gzinflate( base64_decode( $_GET["D"] )));

    # Check that the OID request was actually successful:
    if ($Response["Status"] == "success" && time() - $Response["Timestamp"] < 600 )
    {
        $UserName = $DB->Query(
            "SELECT UserName FROM OpenId_UserMap "
            ."WHERE DisplayId='".addslashes($Response["DisplayId"])."'",
            "UserName");
        $ExtInfo = $Response["ExtendedInfo"];

        # If there's not a username stored for this OpenID, and if the
        # OID provider was kind enough to tell us about their email
        # address (they don't always), generate a username for it:

        if ($UserName === NULL && isset($ExtInfo["email"]) )
        {
            $UserFactory = new CWUserFactory();

            # If the user gave us a nickname, try to use that plus an
            # optional sequence number
            if (isset($ExtInfo["nickname"]))
            {
                $UserName = GenerateUsername($ExtInfo["nickname"]);
            }

            # If we have no nickname, but we have a full name, smash all the
            # alphabetic characters in it together, and try to use that plus
            # an optional sequence number.
            elseif (isset($ExtInfo["fullname"]))
            {
                $FnMunge = preg_replace("/[^A-Za-z]/", "", $ExtInfo["fullname"]);
                $UserName = GenerateUsername($FnMunge);
            }
            # If all that fails, use the local part on someone's email
            else
            {
                $EmailParts = explode('@', $ExtInfo["email"]);
                $TmpName = array_shift($EmailParts);

                $UserName = GenerateUsername($TmpName);
            }

            # Stuff in a dummy password:
            $UserPassword = md5(time());

            # And create the user, skipping validation that would already have been
            #  provided by the OID provider (e.g., valid email)
            $TmpUser = $UserFactory->CreateNewUser(
                $UserName,
                $UserPassword, $UserPassword,
                $ExtInfo["email"], $ExtInfo["email"],
                array(U_ILLEGALPASSWORD, U_ILLEGALPASSWORDAGAIN,
                      U_ILLEGALEMAIL, U_ILLEGALEMAILAGAIN,
                      U_ILLEGALUSERNAME));

            # Check to make sure that user creation worked,
            # complaining if it did not.
            if (!is_object($TmpUser) )
            {
                global $G_ErrorMessages;

                if (in_array(U_DUPLICATEEMAIL, $TmpUser)){
                    $G_ErrorMessages []= "The email address associated with your OpenId "
                        ."is already associated with an account. "
                        ."If you have forgotten the account user name or"
                        ." password you can click"
                        ." <a href=\"index.php?P=ForgottenPasswordComplete&UN="
                        .$ExtInfo["email"]
                        ."\">here</a>"
                        ." to send a reminder via e-mail.";
                } else {
                    # Shouldn't ever happen, but add a general error message just in case:
                    $G_ErrorMessages []= "Could not create user.";
                }
            }
            else
            {
                # No other errors should be possible, so proceed with
                # setting up the user:

                $TmpUser->Set("ActiveUI", $SysConfig->DefaultActiveUI());
                foreach ($SysConfig->DefaultUserPrivs() as $Privilege)
                {
                    $TmpUser->GivePriv($Privilege);
                }

                # Mark the user as active:
                $TmpUser->IsActivated(TRUE);

                # signal that user has been added and verified
                $AF->SignalEvent("EVENT_USER_ADDED", array(
                                     "UserId" => $TmpUser->Id(),
                                     "Password" => $UserPassword));
                $AF->SignalEvent("EVENT_USER_VERIFIED",
                                 array("UserId" => $TmpUser->Id()));

                $DB->Query(
                    "INSERT INTO OpenId_UserMap (DisplayId, UserName) "
                    ."VALUES ('".addslashes($Response["DisplayId"])."',"
                    ."'".addslashes($TmpUser->Name())."')");

                $AF->SetJumpToPage("P_OpenId_FinishAuth&D=".urlencode($_GET["D"])."&C=".$_GET["C"]);
            }
        }
    }
}
