Ashish Shah Ashish Shah - 1 month ago 14
PHP Question

Dropbox API Redirection Loop

I am using php sdk provided by Dropbox Core API. I have a minor bug... My file is being redirected all the time even I click on the allow button... Below is my index file:

index.php

<?php
session_start();

ini_set("display_errors",1);
require_once __DIR__.'/dropbox-sdk/Dropbox/strict.php';

$appInfoFile = __DIR__."/AppInfo.json";

// NOTE: You should be using Composer's global autoloader. But just so these examples
// work for people who don't have Composer, we'll use the library's "autoload.php".
require_once __DIR__.'/dropbox-sdk/Dropbox/autoload.php';

use \Dropbox as dbx;

$requestPath = init();
echo "Request path = ".$requestPath."<br>";
if ($requestPath === "/") {

$dbxClient = getClient();

if ($dbxClient === false) {
echo "Path: ".getPath("dropbox-auth-start")."<br>";die;
header("Location: ".getPath("dropbox-auth-start"));
exit;
}

$path = "/";//Debug completed

if (isset($_GET['path'])) $path = $_GET['path'];
$entry = $dbxClient->getMetadataWithChildren($path);

echo "Client<pre>";
print_r($dbxClient);
echo "</pre>";
echo "Entry".$entry;die;
if ($entry['is_dir']) {
echo renderFolder($entry);
}
else {
echo renderFile($entry);
}
}
else if ($requestPath == "/download") {
//die("Download");
$dbxClient = getClient();

if ($dbxClient === false) {
header("Location: ".getPath("dropbox-auth-start"));
exit;
}

if (!isset($_GET['path'])) {
header("Location: ".getPath(""));
exit;
}
$path = $_GET['path'];

$fd = tmpfile();
$metadata = $dbxClient->getFile($path, $fd);

header("Content-Type: $metadata[mime_type]");
fseek($fd, 0);
fpassthru($fd);
fclose($fd);
}
else if ($requestPath === "/upload") {
//die("Upload");
if (empty($_FILES['file']['name'])) {
echo renderHtmlPage("Error", "Please choose a file to upload");
exit;
}

if (!empty($_FILES['file']['error'])) {
echo renderHtmlPage("Error", "Error ".$_FILES['file']['error']." uploading file. See <a href='http://php.net/manual/en/features.file-upload.errors.php'>the docs</a> for details");
exit;
}

$dbxClient = getClient();

$remoteDir = "/";
if (isset($_POST['folder'])) $remoteDir = $_POST['folder'];

$remotePath = rtrim($remoteDir, "/")."/".$_FILES['file']['name'];

$fp = fopen($_FILES['file']['tmp_name'], "rb");
$result = $dbxClient->uploadFile($remotePath, dbx\WriteMode::add(), $fp);
fclose($fp);
$str = print_r($result, TRUE);
echo renderHtmlPage("Uploading File", "Result: <pre>$str</pre>");
}
else if ($requestPath === "/dropbox-auth-start") {
//die("dropbox-auth-start");
$authorizeUrl = getWebAuth()->start();
header("Location: $authorizeUrl");
}
else if ($requestPath === "/dropbox-auth-finish") {
//die("dropbox-auth-finish");
try {
list($accessToken, $userId, $urlState) = getWebAuth()->finish($_GET);
// We didn't pass in $urlState to finish, and we're assuming the session can't be
// tampered with, so this should be null.
assert($urlState === null);
}
catch (dbx\WebAuthException_BadRequest $ex) {
respondWithError(400, "Bad Request");
// Write full details to server error log.
// IMPORTANT: Never show the $ex->getMessage() string to the user -- it could contain
// sensitive information.
error_log("/dropbox-auth-finish: bad request: " . $ex->getMessage());
exit;
}
catch (dbx\WebAuthException_BadState $ex) {
// Auth session expired. Restart the auth process.
header("Location: ".getPath("dropbox-auth-start"));
exit;
}
catch (dbx\WebAuthException_Csrf $ex) {
respondWithError(403, "Unauthorized", "CSRF mismatch");
// Write full details to server error log.
// IMPORTANT: Never show the $ex->getMessage() string to the user -- it contains
// sensitive information that could be used to bypass the CSRF check.
error_log("/dropbox-auth-finish: CSRF mismatch: " . $ex->getMessage());
exit;
}
catch (dbx\WebAuthException_NotApproved $ex) {
echo renderHtmlPage("Not Authorized?", "Why not?");
exit;
}
catch (dbx\WebAuthException_Provider $ex) {
error_log("/dropbox-auth-finish: unknown error: " . $ex->getMessage());
respondWithError(500, "Internal Server Error");
exit;
}
catch (dbx\Exception $ex) {
error_log("/dropbox-auth-finish: error communicating with Dropbox API: " . $ex->getMessage());
respondWithError(500, "Internal Server Error");
exit;
}

// NOTE: A real web app would store the access token in a database.
$_SESSION['access-token'] = $accessToken;

echo renderHtmlPage("Authorized!",
"Auth complete, <a href='".htmlspecialchars(getPath(""))."'>click here</a> to browse.");
}
else if ($requestPath === "/dropbox-auth-unlink") {
//die("dropbox-auth-unlink");
// "Forget" the access token.
unset($_SESSION['access-token']);
echo renderHtmlPage("Unlinked.",
"Go back <a href='".htmlspecialchars(getPath(""))."'>home</a>.");
}
else {
//die("else part");
echo renderHtmlPage("Bad URL", "No handler for $requestPath");
exit;
}

function renderFolder($entry)
{
// TODO: Add a token to counter CSRF attacks.
$upload_path = htmlspecialchars(getPath('upload'));
$path = htmlspecialchars($entry['path']);
$form = <<<HTML
<form action='$upload_path' method='post' enctype='multipart/form-data'>
<label for='file'>Upload file:</label> <input name='file' type='file'/>
<input type='submit' value='Upload'/>
<input name='folder' type='hidden' value='$path'/>
</form>
HTML;

$listing = '';
foreach($entry['contents'] as $child) {
$cp = $child['path'];
$cn = basename($cp);
if ($child['is_dir']) $cn .= '/';

$cp = htmlspecialchars($cp);
$link = getPath("?path=".htmlspecialchars($cp));
$listing .= "<div><a style='text-decoration: none' href='$link'>$cn</a></div>";
}

return renderHtmlPage("Folder: $entry[path]", $form.$listing);
}

function getAppConfig()
{
global $appInfoFile;

try {
$appInfo = dbx\AppInfo::loadFromJsonFile($appInfoFile);
}
catch (dbx\AppInfoLoadException $ex) {
throw new Exception("Unable to load \"$appInfoFile\": " . $ex->getMessage());
}

$clientIdentifier = "examples-web-file-browser";
$userLocale = null;

return array($appInfo, $clientIdentifier, $userLocale);
}

function getClient()
{
if(!isset($_SESSION['access-token'])) {
return false;
}

list($appInfo, $clientIdentifier, $userLocale) = getAppConfig();
$accessToken = $_SESSION['access-token'];
return new dbx\Client($accessToken, $clientIdentifier, $userLocale, $appInfo->getHost());
}

function getWebAuth()
{
list($appInfo, $clientIdentifier, $userLocale) = getAppConfig();
$redirectUri = "http://localhost/MyApi/Dropbox/";//success.php";//getUrl("dropbox-auth-finish");
$csrfTokenStore = new dbx\ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token');
return new dbx\WebAuth($appInfo, $clientIdentifier, $redirectUri, $csrfTokenStore, $userLocale);
}

function renderFile($entry)
{
$metadataStr = htmlspecialchars(print_r($entry, true));
$downloadPath = getPath("download?path=".htmlspecialchars($entry['path']));
$body = <<<HTML
<pre>$metadataStr</pre>
<a href="$downloadPath">Download this file</a>
HTML;

return renderHtmlPage("File: ".$entry['path'], $body);
}

function renderHtmlPage($title, $body)
{
return <<<HTML
<html>
<head>
<title>$title</title>
</head>
<body>
<h1>$title</h1>
$body
</body>
</html>
HTML;
}

function respondWithError($code, $title, $body = "")
{
$proto = $_SERVER['SERVER_PROTOCOL'];
header("$proto $code $title", true, $code);
echo renderHtmlPage($title, $body);
}

function getUrl($relative_path)
{
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
$scheme = "https";
} else {
$scheme = "http";
}
$host = $_SERVER['HTTP_HOST'];
$path = getPath($relative_path);
return $scheme."://".$host.$path;
}

function getPath($relative_path)
{
if (PHP_SAPI === 'cli-server') {
return "/".$relative_path;
} else {
echo "Server values:<pre>";
print_r($_SERVER);
echo "</pre>";
return $_SERVER["SCRIPT_NAME"]."/".$relative_path;
}
}

function init()
{
global $argv;

// If we were run as a command-line script, launch the PHP built-in web server.
if (PHP_SAPI === 'cli') {
launchBuiltInWebServer($argv);
assert(false);
}

if (PHP_SAPI === 'cli-server') {
// For when we're running under PHP's built-in web server, do the routing here.
return $_SERVER['SCRIPT_NAME'];
}
else {
// For when we're running under CGI or mod_php.
if (isset($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
} else {
return "/";
}
}
}

function launchBuiltInWebServer($argv)
{
// The built-in web server is only available in PHP 5.4+.
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
fprintf(STDERR,
"Unable to run example. The version of PHP you used to run this script (".PHP_VERSION.")\n".
"doesn't have a built-in web server. You need PHP 5.4 or newer.\n".
"\n".
"You can still run this example if you have a web server that supports PHP 5.3.\n".
"Copy the Dropbox PHP SDK into your web server's document path and access it there.\n");
exit(2);
}

$php_file = $argv[0];
if (count($argv) === 1) {
$port = 5000;
} else if (count($argv) === 2) {
$port = intval($argv[1]);
} else {
fprintf(STDERR,
"Too many arguments.\n".
"Usage: php $argv[0] [server-port]\n");
exit(1);
}

$host = "localhost:$port";
$cmd = escapeshellarg(PHP_BINARY)." -S ".$host." ".escapeshellarg($php_file);
$descriptors = array(
0 => array("pipe", "r"), // Process' stdin. We'll just close this right away.
1 => STDOUT, // Relay process' stdout to ours.
2 => STDERR, // Relay process' stderr to ours.
);
$proc = proc_open($cmd, $descriptors, $pipes);
if ($proc === false) {
fprintf(STDERR,
"Unable to launch PHP's built-in web server. Used command:\n".
" $cmd\n");
exit(2);
}
fclose($pipes[0]); // Close the process' stdin.
$exitCode = proc_close($proc); // Wait for process to exit.
exit($exitCode);
}
?>


FYI: in my dropbox app I have set the redirect uri as : "localhost/MyApi/Dropbox/"... But it is going like loop... Can any one solve this? I thought to change the redirect uri to success.php but is there any other way to solve this?

Update:

I am also pasting my success.php file:

success.php

<?php
session_start();
ini_set("display_errors",1);

# Include the Dropbox SDK libraries
require_once "dropbox-sdk/Dropbox/autoload.php";
use \Dropbox as dbx;

$dbxClient = new dbx\Client($_SESSION['access-token'], "PHP-PicPixa/1.0");//This line is giving error
$accountInfo = $dbxClient->getAccountInfo();

echo "Account Info:<pre>";
print_r($accountInfo);
echo "</pre>";

$f = fopen("working-draft.txt", "a");
$result = $dbxClient->uploadFile("/working-draft.txt", dbx\WriteMode::add(), $f);
fclose($f);
print_r($result);

$folderMetadata = $dbxClient->getMetadataWithChildren("/");
print_r($folderMetadata);

$f = fopen("working-draft.txt", "w+b");
$fileMetadata = $dbxClient->getFile("/working-draft.txt", $f);
fclose($f);
echo "<br>File meta data:<br><pre>";
print_r($fileMetadata);
echo "</pre>";
?>


To access my full project please download it from: https://www.dropbox.com/sh/ps90blb2uujbxxh/AABdbU39upJSOeiLwxSnjufFa

Thank You,

Answer

It looks like you commented out code that would have redirected to dropbox-auth-finish. Since you're never going there, you're never finishing the auth process and never setting $_SESSION['access-token'] to anything.