<?php

#
#   FILE:  SPT--ImportUsersExecute.php
#
#   FUNCTIONS PROVIDED:
#       None
#
#   FUNCTIONS EXPECTED:
#       None
#
#   Part of the Scout Portal Toolkit
#   Copyright 2004 Internet Scout Project
#   http://scout.cs.wisc.edu
#

# ----- EXPORTED FUNCTIONS ---------------------------------------------------

function PrintDuplicateUserList()
{
    global $DuplicateUsers;

    if (count($DuplicateUsers) > 0)
    {
        print "These users already exist and were not imported:<br>";
        foreach ($DuplicateUsers as $UserName)
            print "$UserName<br>";
    }
}

# ----- LOCAL FUNCTIONS ------------------------------------------------------

# init variables -- first time thru they will be null
function InitImportVars()
{
    global $ImportComplete, $FSeek, $UserCount, $DuplicateUsers;

    if (is_null($ImportComplete))
        $ImportComplete = 0;
    if (is_null($FSeek))
        $FSeek = 0;
    if (is_null($UserCount))
        $UserCount = 0;
    if (!is_array($DuplicateUsers))
        $DuplicateUsers = array();
}

# do/while loop, this is the main event
function DoWhileLoop()
{
    global $DB, $fp, $Session, $FSeek, $Title, $ImportComplete, $AF;
    global $_POST, $User, $UserCount, $LineCount;
    global $DuplicateUsers, $PrivDescriptions;

    $Schema = new MetadataSchema();
    $LineCount = 0;
    $LastUserName = NULL;

    while (!feof($fp) && $LineCount < 500 && $ImportComplete == 0)
    {
        # read in line from import file
        $fline = fgets($fp, 4096);

#        echo "fline=$fline<br>";
    
        # update variables 
        $LineCount++;
        $Session->PassVariable("LineCount", $LineCount);
        $FSeek += strlen($fline);
        $Session->PassVariable("FSeek", $FSeek);

        $Value = NULL;    
        # parse line from import file
        $Vars = explode("\t", $fline);

        $NumberOfVars = count($Vars);
        if ($NumberOfVars < 1 || feof($fp))
        {
            $ImportComplete = 1;
            break;
        }
        
        # should be 14 variables per line
        if (count($Vars) != 14)
        {
            $ErrorMessage = "Error: Wrong number of fields on Line ".$LineCount;
            $Session->PassVariable("ErrorMessage", $ErrorMessage);
            $AF->SetJumpToPage("ImportUsers");
            return;
        }

        # initial the vars
        $UserName = trim(addslashes($Vars[0]));
        $UserPassword = $Vars[1];
        $Email = addslashes($Vars[2]);
        $WebSite = addslashes($Vars[3]);
        $RealName = addslashes($Vars[4]);
        $AddressLineOne = addslashes($Vars[5]);
        $AddressLineTwo = addslashes($Vars[6]);
        $City = addslashes($Vars[7]);
        $State = addslashes($Vars[8]);
        $Country = addslashes($Vars[9]);
        $ZipCode = $Vars[10];
        $ActiveUI = $Vars[11];
        $BrowsingField = trim($Vars[12]);
        $PrivDescription = trim($Vars[13]);

        # should be 14 variables per line
        if (strlen($UserName) < 2 || strlen($UserName) > 24 ||
            strpos($UserName, " ") !== FALSE)
        {
            $ErrorMessage = "Error: Invalid User name \"".$UserName.
                "\" on Line ".
                $LineCount.". User names must be made up of one word ".
                "containing between 2 and 24 letters and/or numbers.";
            $Session->PassVariable("ErrorMessage", $ErrorMessage);
            $AF->SetJumpToPage("ImportUsers");
            return;
        }


        $Field = $Schema->GetFieldByName($BrowsingField);

        # force FieldId to reasonable value if not set
        if (is_object($Field))
            $FieldId = $Field->Id();
        else
            $FieldId = "NULL";

        # default UserPassword to UserName if blank
        if (empty($UserPassword))
            $UserPassword = $UserName;

        # encrypt the password
        if (isset($_POST["F_PasswordFlag"]) &&
            $_POST["F_PasswordFlag"] == 1)
            $UserPassword = crypt($UserPassword);

        # bail out if line was empty or end of file encountered
        if (is_null($UserName) || feof($fp))
        {
            break;
        }

        # just update privileges if this user is same as previous
        if ($LastUserName == $UserName && !empty($PrivDescription))
        {
            $Privilege = array_search($PrivDescription, $PrivDescriptions);
            $ThisUser = new User($DB, $UserName);
            $ThisUser->GivePriv($Privilege);
            continue;
        }

        # search for existing user and save it for later
        $query = "Select UserName from APUsers where UserName = \"$UserName\"";
        $DB->Query($query);
        if ($DB->NumRowsSelected() > 0)
        {
            if (array_search($UserName, $DuplicateUsers) === FALSE)
                $DuplicateUsers[] = $UserName;
            continue;
        }

        $query = "Insert into APUsers (".
                        "UserName, ".
                        "UserPassword, ".
                        "CreationDate, ".
                        "Email, ".
                        "WebSite, ".
                        "RealName, ".
                        "AddressLineOne, ".
                        "AddressLineTwo, ".
                        "City, ".
                        "State, ".
                        "Country, ".
                        "ZipCode, ".
                        "ActiveUI, ".
                        "BrowsingFieldId)".
                " Values (\"$UserName\", ".
                         "\"$UserPassword\", ".
                         "\"".strftime("%Y-%m-%d")."\", ".
                         "\"$Email\", ".
                         "\"$WebSite\", ".
                         "\"$RealName\", ".
                         "\"$AddressLineOne\", ".
                         "\"$AddressLineTwo\", ".
                         "\"$City\", ".
                         "\"$State\", ".
                         "\"$Country\", ".
                         "\"$ZipCode\", ".
                         "\"$ActiveUI\", ".
                         "$FieldId)";
    
#       echo "Query=".$query."<br>";

        $DB->Query($query);

        # add in privilege if set
        if (!empty($PrivDescription))
        {
            $Privilege = array_search($PrivDescription, $PrivDescriptions);
            $ThisUser = new User($DB, $UserName);
            $ThisUser->GivePriv($Privilege);
        }
        # cache user name for privileges
        $LastUserName = $UserName;
        
        # keep track of number of users added
        $UserCount++;
        $Session->PassVariable("UserCount", $UserCount);
    }
}

# ----- MAIN -----------------------------------------------------------------

# non-standard global variables
global $DuplicateUsers;
global $FSeek;
global $ImportComplete;
global $LineCount;
global $PrivDescriptions;
global $Title;
global $UserCount;
global $_POST;
global $fp;

# check if current user is authorized
if (!CheckAuthorization(PRIV_SYSADMIN, PRIV_USERADMIN)) {  return;  }

$DB = new SPTDatabase();
$ClassDB = new SPTDatabase();

$FSeek = $Session->Get("FSeek");
$TempFile = $Session->Get("TempFile");
$UserCount = $Session->Get("UserCount");
$DuplicateUsers = $Session->Get("DuplicateUsers");

InitImportVars();

# check for Cancel button
if (isset($_POST["Submit"]) && $_POST["Submit"] == "Cancel")
{
    $ImportComplete = 1;
    $AF->SetJumpToPage("SysAdmin");
    return;
}

# register some key variables for other html code
$Session->PassVariable("ImportComplete", $ImportComplete);

if (isset($_FILES['F_FileName']['tmp_name']) &&
    is_uploaded_file($_FILES['F_FileName']['tmp_name']))
{
    # zero length or tiny file
    if ($_FILES['F_FileName']['size'] == 0)
    {
        $ErrorMessage = "Error: File doesn't exist or is empty.";
        $Session->PassVariable("ErrorMessage", $ErrorMessage);
        $AF->SetJumpToPage("ImportUsers");
        return;
    }
    # files with illegal extensions
    elseif (preg_match('/\.php/i', $_FILES['F_FileName']['name'])
            || preg_match('/\.js/i', $_FILES['F_FileName']['name'])
            || preg_match('/\.html/i', $_FILES['F_FileName']['name']))
    {
        $ErrorMessage = "Error: File type is not allowed.";
        $Session->PassVariable("ErrorMessage", $ErrorMessage);
        $AF->SetJumpToPage("ImportUsers");
        return;
    }

    $ScriptFileName = GetFullScriptFileName();

    $TempFile = dirname($ScriptFileName).
        "/tmp/".
        $_FILES['F_FileName']['name'];

    copy($_FILES['F_FileName']['tmp_name'], $TempFile);

    $fp = fopen($TempFile, 'r');
    unlink($_FILES['F_FileName']['tmp_name']);
}
else if ($FSeek > 0)
{
    $fp = fopen($TempFile, 'r');
}
else
{
    switch($_FILES['F_FileName']['error'])
    {
        # no error; possible file attack!
        case 0:
            $ErrorMessage = "There was a problem with your upload.";
            break;

        # uploaded file exceeds the upload_max_filesize directive in php.ini
        case 1:
            $ErrorMessage = "The file you are trying to upload is too big.";
            break;

        # uploaded file exceeds the MAX_FILE_SIZE directive that
        # was specified in the html form
        case 2:
            $ErrorMessage = "The file you are trying to upload is too big.";
            break;
            
        # uploaded file was only partially uploaded
        case 3:
            $ErrorMessage = 
                "The file you are trying upload was only partially uploaded.";
            break;

        # no file was uploaded
        case 4:
            $ErrorMessage = "You must select a file for upload.";
            break;

        # a default error, just in case!
        default:
            echo "There was a problem with your upload.";
            break;
    }
    $Session->PassVariable("ErrorMessage", $ErrorMessage);
    $AF->SetJumpToPage("ImportUsers");
    return;
}

# seek to the next line
if ($FSeek > 0)
{
    fseek($fp, $FSeek);
}

# the main work happenes here
DoWhileLoop();

# end of file reached?
if (feof($fp))
{
    $ImportComplete = 1;
}
$Session->PassVariable("ImportComplete", $ImportComplete);
$Session->PassVariable("UserCount", $UserCount);
$Session->PassVariable("FSeek", $FSeek);
$Session->PassVariable("TempFile", $TempFile);
$Session->PassVariable("DuplicateUsers", $DuplicateUsers);

#  Time to auto-refresh?
if ($ImportComplete == 0)
{
    $AutoRefreshToPage = "index.php?P=ImportUsersExecute";
}

PageTitle("Import Users");

# register post-processing function with the application framework
$AF->AddPostProcessingCall("PostProcessingFn", $TempFile, $fp, $ImportComplete);

# post-processing call
function PostProcessingFn($TempFile, $fp, $ImportComplete)
{
    if ($ImportComplete == 1)
    {
        fclose($fp);
        # remove temporary uploaded file
        unlink($TempFile);
    }
}

?>
