File Transfer User Interface Tutorial in PHP

Overview

A scenario server providers might experience is how to give a client access to transfer files between servers, without actually having to give FTP or SSH access. This tutorial will provide the code to create a simple web portal that will use the SCP command in the background of a Linux server to transfer specific types of files between to remote server locations.

Directory Structure

\---LinuxFileTransfer
    |   func.php
    |   index.php
    |   login.php
    |   logout.php
    |
    \---inc
        |   .htaccess
        |   openid.php

 

 

 

 

 

 

 

 

 

 

 

Description of Each File

  • func.php – Contains functions used to convert the 64-Bit format of a steamid to the standard format.
  • index.php – The primary landing page, which displays an image used to log in. If a valid matching steamid is received, the interface for the server transfer page will be displayed here.
  • login.php – Logic for the login page, which is used by index.php.
  • logout.php – Functionality for signing out.
  • inc/.htaccess – Used to prevent access to the inc folder.
  • inc/openid.php – Contains a library for OpenID authentication, based on OAuth2. For this example we will be using a steam login as the authentication method.

Execution of our application will begin in index.php

session_start();
include 'func.php';
$validID = array("STEAM_0:1:20076328");
$validUser = 0;
$success = 0;
$filename = "";
  1. We will begin a PHP session using session_start(), this will allow us to have a persistent login as the user changes pages.
  2. Include the func.php file which contains two functions, one for converting the steamid format and the other to set the stream blocking mode to blocking, which will cause the program to wait until sufficient data is received.
  3. $validID – For instructional purposes there is only one steamid inside of the array of valid ID’s.
  4. $validUser – Checks if the user is allowed to access our interface.
  5. $success – The return status of whether or not our user successfully logged in.

Check for user id

if(!isset($_SESSION["steam_id"])){
	require "login.php";
}

if(isset($_SESSION["steam_id"])) {
	foreach($validID as $ID) {
		if($_SESSION["steam_id"] == $ID) {
			$validUser = 1;
		}
	}
}
  • Inside of our PHP $_SESSION, we will have a key/value pair for the steamid$_SESSION[“steam_id”] will be checked to see if there is any value for the index key steam_id. If no value is found then we will take our user to the login page.
  • Line 5 – If the user makes it through the login page, once again check if the a steamid exists for the user in this session. If the steamid does exist, then we will compare it against the array of steamids that can access our interface. If there is an ID match, then set our $validUser flag to 1, indicating the user have access to the page.

login.php

<?php
require 'inc/openid.php';
include 'func.php';
$_STEAMAPI = "3252EDEACE318BB2FF4209F6387DC1";
 
try 
{
    $openid = new LightOpenID('http://yoursite.com/test');
    if(!$openid->mode) 
    {
        if(isset($_GET['login'])) 
        {
            $openid->identity = 'http://steamcommunity.com/openid/?l=english';    // This is forcing english because it has a weird habit of selecting a random language otherwise
            header('Location: ' . $openid->authUrl());
			echo $openid->authUrl();
        }
?>

<form action="?login" method="post">
    <input type="image" src="http://cdn.steamcommunity.com/public/images/signinthroughsteam/sits_small.png">
</form>

<?php
    } 
    elseif($openid->mode == 'cancel') 
    {
        echo 'User has canceled authentication!';
    } 
    else 
    {
        if($openid->validate()) 
        {
                $id = $openid->identity;
                // identity is something like: http://steamcommunity.com/openid/id/76561197960435530
                // we only care about the unique account ID at the end of the URL.
                $ptn = "/^https:\/\/steamcommunity\.com\/openid\/id\/(7[0-9]{15,25}+)$/";
                preg_match($ptn, $id, $matches);

                $url = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=$_STEAMAPI&steamids=$matches[1]";
                $_SESSION["$json_object"] = file_get_contents($url);
                $json_decoded = json_decode($_SESSION["$json_object"]);

                foreach ($json_decoded->response->players as $player)
                {
					$_SESSION["steam_id"] = toSteamID($player->steamid);
                    echo 'User is logged in (SteamID: ' . $_SESSION["steam_id"] . ')
';
                }
        } 
        else 
        {
                echo "User is not logged in.\n";
        }
    }
} 
catch(ErrorException $e) 
{
    echo $e->getMessage();
}
?>
  • Include the openid light library and set our steam api key.
  • Initialize a new LightOpenID object with our URL as the only parameter.
  • If there is no mode set for LightOpenID, check if the user is logged in and set the authorization URL.
  • Create a login form that allows the user to post to the current login page.
  • Match the steam community ID and then get user information from the steam API.
  • Convert the response to from a JSON object to a PHP variable and then save the current user’s steamid into $_SESSION[“steam_id”].

Invalidate unauthenticated user

   
if (!$validUser &amp;&amp; isset($_SESSION["steam_id"])) {
        session_destroy();
	echo "You do not have permission to use this page!";
	exit();
}

Display our file transfer form

 

  • If $validUser is set to a positive value, then display our submission for file transfer.
  • This must be echoed because of the fact that we are combing PHP and HTML.
  • Each form will take a file with the extension as input.  This application will allow HTML and PHP files to be transferred between servers.
  • The file must already exist on our server that is sending the file. It will send the file to a remote server (or servers) that has the same file structure.

Transfer our file to multiple servers

if (!function_exists("shell_exec")) 
    die("Cannot find shell execution function!");
    
if(isset($_POST["transferHTML"])){
    if(!extensionExists($_POST['fileName'])) {
        $filename = $_POST['fileName'] . ".html";
    } else {
        $filename = $_POST['fileName'];
    }

    transferFile($filename);
}

if(isset($_POST["transferPHP"])){
    if(!extensionExists($_POST['fileName'])) {
        $filename = $_POST['fileName'] . ".php";
    } else {
        $filename = $_POST['fileName'];
    }

    transferFile($filename);
}
  • Check if the shell_exec function exists.
  • Check if either the transferHTML or transferPHP post variables have been set to anything.
  • Check if the user entered an extension to the file.
  • Call our transferFile function to complete the transaction.

Add a logout form for the user

Functions inside func.php

function extensionExists($filename) {
    $file_parts = pathinfo($filename);

    switch($file_parts['extension']){
        case "html":
        return 1;
        break;
        
        case "php":
        return 1;
        break;
        
        case NULL: // Handle no file extension
        return 0;
        break;
        
        default:
        echo "Filename must end in HTML, PHP, or no extension!";
        exit();
    }
    return 0;
}
  • extensionExists() – This function will check the input from our server to see if they have added an html or php extension.
  • If there is no extension, zero is returned and the needed file extension is added.
  • If an extension besides php or html is used, the program will exit.

Primary transfer function

function transferFile($filename)
{
    $success = 0;
    if (!function_exists("shell_exec")) {
        die("Cannot find shell execution function!");
    }

    $result = shell_exec("sudo -u testuser ls /home/testuser/ | grep " . $filename);

    if($result){
        if(!($return = shell_exec("sudo -u testuser sshpass -f /home/testuser/resources/passwordServer1 scp -r /home/testuser/" . $filename . " remoteUser@34.182.233.135:/var/www/website 2>&1"))){
            echo "$result transferred to the server1 successfully! 
";
            $success++;
        } else {
            echo $return . "
";
        }
        
        if(!($return = shell_exec("sudo -u testuser sshpass -f /home/testuser/resources/passwordServer2 scp -r /home/testuser/" . $filename . " remoteUser@102.63.138.32:/var/www/website 2>&1"))){
            echo "$result transferred to the server2 successfully! 
";
            $success++;
        } else {
            echo $return . "
";
        }
    }
    else{
        echo "$filename not found!";
    }

    if($success == 2){
        echo "$result has been transferred to all servers successfully! 
";
    }
}
  • transferFile() – This function will verify that the filename exists and then execute the transfer process.
  • The command shell_exec(sudo -u testuser ls /home/testuser/ | grep ” . $filename); will login as our testuser, list the contents of its home directory and then search that directory for the name of the file. It will then return the result.
  • shell_exec(“sudo -u testuser sshpass -f /home/testuser/resources/passwordServer1 scp -r /home/testuser/” . $filename . ” remoteUser@34.182.233.135:/var/www/website 2>&1″) – This function does the actual transfer process. Make sure testuser’s home folder contains the password needed to log into your external server.
  • The scp -r command transfers a file from the current host to a remote host, which in our case is remoteUser@34.182.233.135
  • The directory to transfer the .html or .php file is located in /var/www in order for changes to be made to this website, without actually having to give your user ssh access!

logout.php

<?php
	session_start();
	unset($_SESSION);
	session_destroy();
	header("Location: index.php");
	echo "You have successfully logged out!";
?>
  • Unset any $_SESSION variables.
  • Destroy the session.
  • Redirect the user to index.php.
  • Echo to the user that they have logged out.

 

Feel free to down the solution for this example provided below!

Posted in Programming, Webdev.

Leave a Reply