lwl5219
1/23/2018 - 9:09 AM

dropbox.lua

-- Project: Dropbox Module
-- Description: A module for accessing Dropbox from Lua/CoronaSDK using the Dropbox REST API. Module written
-- 		by F. E. Torkel, based off code by Michael Weingarden.


local lfs = require( "lfs" )
local json = require( "json" )

local M = {}


local consumer_key = ""			-- key string goes here
local consumer_secret = ""		-- secret string goes here
local root						-- "dropbox" or "sandbox"

local webURL = "http://www.google.com"
local authString

myFile = "smallButton.png"

local mySigMethod = "PLAINTEXT"
local access_token = ""
local access_token_secret = ""
local request_token = ""
local request_token_secret = ""
M.response = ""


-- Loads a token from file.
local function loadToken( type )
	local saveData = ""
	local path = system.pathForFile( type, system.DocumentsDirectory )
	local file = io.open( path, "r" )
	if file then
		saveData = file:read( "*a" )
		io.close( file )
	end
	file = nil
	return saveData
end


-- Saves a token to file.
local function storeToken( type, data )
	local path = system.pathForFile( type, system.DocumentsDirectory )
	local file = io.open( path, "w" )
	file:write( data )
	io.close( file )
	file = nil
end


-- Generic network listener.
local function dropboxListener( event )
	if ( event.isError ) then
		print( "Network error!")
	else
		print ( "RESPONSE: " .. event.response )
	end
end


-- Returns the raw request from Dropbox based on the arguments.
local function rawGetRequest( url, rawdata ) 

	-- Callback function
	local function rawGetListener( event )		
		if event.isError then
			print( "Network error!", event.status, event.response )
		else
			--print ( "rawGetListener RESPONSE: ", event.status, event.response )
		end

		-- the event.response is the requested data from Dropbox
		-- you can either process the response here or use a global variable or pass it to
		-- another function
		-- using accountInfo to either store account info or incoming text file
		accountInfo = event.response
	end

	url = url .. "?" .. rawdata
	local result = network.request( url, "GET", rawGetListener )
	return result
end


local function rawPostRequest( url, rawdata, callback )

	-- callback function
	local function rawPostListener( event )		
		if event.isError then
			print( "Network error!", event.status, event.response)
		else
			print ( "Dropbox RESPONSE: ", event.status,  event.response )	-- **debug
		end
		if callback then
			print( "calling back from rawPostRequest" )	
			callback( event.isError, event.response )		-- return with response
		end
	end

	local params = {}
	local headers = {}
	headers["Content-Type"] = "text/plain"
	headers["Authorization"] = "OAuth "..rawdata
	params.headers = headers
	local result = network.request( url, "POST", rawPostListener, params )
	return result
end


local function getRequestToken( consumer_key, token_ready_url, request_token_url, consumer_secret, callback )
	--Your HTTP request should have the following header:
	--Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="<app-key>", oauth_signature="<app-secret>&"
   local post_data = "oauth_version=\"1.0\", oauth_signature_method=\"" .. mySigMethod .. "\", oauth_consumer_key=\"" .. consumer_key .. "\", oauth_signature=\"" .. consumer_secret .. "&\""
   return rawPostRequest( request_token_url, post_data, callback )
end


local function getAccessToken( token, token_secret, consumer_key, consumer_secret, access_token_url, callback )
    --Authorization: OAuth oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="<app-key>", oauth_token="<request-token>", oauth_signature="<app-secret>&<request-token-secret>"
    local post_data =  "oauth_version=\"1.0\", oauth_signature_method=\"" .. mySigMethod .. "\", oauth_consumer_key=\"" .. consumer_key .. "\", oauth_token=\"" .. token .. "\", oauth_signature=\"" .. consumer_secret .. "&" .. token_secret .. "\""
    return rawPostRequest(access_token_url, post_data, callback)
end


local function responseToTable( str, delimiters )

	local obj = {}

	while str:find(delimiters[1]) ~= nil do
		if #delimiters > 1 then
			local key_index = 1
			local val_index = str:find(delimiters[1])
			local key = str:sub(key_index, val_index - 1)
	
			str = str:sub((val_index + delimiters[1]:len()))
	
			local end_index
			local value
	
			if str:find(delimiters[2]) == nil then
				end_index = str:len()
				value = str
			else
				end_index = str:find(delimiters[2])
				value = str:sub(1, (end_index - 1))
				str = str:sub((end_index + delimiters[2]:len()), str:len())
			end
			obj[key] = value
			--print(key .. ":" .. value)		-- **debug
		else
	
			local val_index = str:find(delimiters[1])
			str = str:sub((val_index + delimiters[1]:len()))
	
			local end_index
			local value
	
			if str:find(delimiters[1]) == nil then
				end_index = str:len()
				value = str
			else
				end_index = str:find(delimiters[1])
				value = str:sub(1, (end_index - 1))
				str = str:sub(end_index, str:len())
			end
			
			obj[#obj + 1] = value

		end
	end
	
	return obj
end


-- Authorizes Dropbox
local function authorizeDropbox(event)

	local remain_open = true

	print("event.url: "..event.url)
	print("webURL: "..webURL)
	print("authorizeDropbox: ", event.url)
	local callbackURL = true
	local url = event.url

	if url:find("callback") then
		callbackURL = true
	else
		callbackURL = false
	end

	if url:find("oauth_token") and not callbackURL then
		remain_open = false

		function getAccess_ret( status, access_response )
			print("getAccess_ret")
			print("access_response: "..access_response)
					
			access_response = responseToTable( access_response, {"=", "&"} )
			access_token = access_response.oauth_token
			access_token_secret = access_response.oauth_token_secret
			user_id = access_response.user_id
			screen_name = access_response.screen_name
			storeToken( "access_token", access_token )
			storeToken( "access_token_secret", access_token_secret )
		end

		print("getAccess")
		getAccessToken(request_token, request_token_secret, consumer_key, 
			 consumer_secret, "https://api.dropbox.com/1/oauth/access_token", getAccess_ret )

	end

	return remain_open
end


local function requestToken_ret( status, result )

	print("result: "..result)
        
	request_token = result:match('oauth_token=([^&]+)')
	request_token_secret = result:match('oauth_token_secret=([^&]+)')

	print("request_token_secret: "..request_token_secret)

	-- Displays a webpopup to access the Twitter site so user can sign in
	-- urlRequest dictates whether the WebPopup will remain open or not
	native.showWebPopup(0, 0, display.contentWidth, display.contentHeight, "https://www.dropbox.com/1/oauth/authorize?oauth_token="
		.. request_token.."&oauth_callback="..webURL, {urlRequest = authorizeDropbox})
end


-- Sets needed variables to connect. Tries to load access tokens. If it fails, get them.
function M.connect( key, secret, r )
	consumer_key = key
	consumer_secret = secret

	if r == "dropbox" or r == "sandbox" then
		root = r
	else
		print( "Invalid 'root' value: must be 'dropbox' or 'sandbox'." )
	end

	access_token = loadToken( "access_token" )
	access_token_secret = loadToken( "access_token_secret")

	if access_token == "" then
		getRequestToken( consumer_key, webURL, "https://api.dropbox.com/1/oauth/request_token", consumer_secret, requestToken_ret )
	end

	authString = "oauth_version=1.0&oauth_signature_method=" .. mySigMethod .. "&oauth_consumer_key=" .. consumer_key .. "&oauth_token=" .. access_token .. "&oauth_signature=" .. consumer_secret .. "%26" .. access_token_secret
end


-- Obtains info. on the Dropbox account.
function M.getAccount()
    local url = "https://api.dropbox.com/1/account/info" .. "?" .. authString
	network.request( url, "GET", dropboxListener )
end


-- Gets a file.
function M.getFile( path, listener )
    local url = "https://api-content.dropbox.com/1/files/sandbox/" .. path .. "?" .. authString
    network.request( url, "GET", listener )
end


-- Gets metadata for the account.
function M.getMeta( path, listener )
	local url = "https://api.dropbox.com/1/metadata/sandbox/" .. path .. "?" .. authString
	network.request( url, "GET", listener )
end


function M.displayInfo()
	print( "accountInfo: " .. accountInfo )
	local path = system.pathForFile( myFile, system.DocumentsDirectory )
	local file = io.open( path, "w" )
	file:write( accountInfo )
	io.close( file )
	file = nil
end


-- Sends a file to Dropbox.
function M.putFile( path, listener, params )
    local url = "https://api-content.dropbox.com/1/files_put/sandbox/" .. path .. "?" .. authString
	network.request( url, "PUT", listener, params )
end


return M