Created
November 16, 2012 23:22
-
-
Save AntonioCiolino/4091848 to your computer and use it in GitHub Desktop.
Codea - Dropbox integration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--DropBox features | |
--This code allows an application to register with DropBox and perform file functions. | |
--There are 3 steps to getting a NEW app registed to a DropBox folder: | |
--1: get a request token. this says, "I'm going to request access" | |
--2. have the USER authorize. This proves that a human is choosing to do the request | |
--3. get a "real" token and secret (password) to access DropBox. This is what we want | |
-- to save, so we can access DropBox in the future without re-registering. | |
DropBox = class() | |
--We allow the developer to set these. These are the app Key and app Secret, | |
-- generally these should be read from storage, but that's inflexible for my needs. | |
function DropBox:init(key, secret) | |
self.appKey = key | |
self.appSecret = secret | |
--this is a cache of the querystring with all of the params. This should not ever | |
--be directly assigned. I did this for speed. | |
self.params = nil | |
end | |
--Unused Utility: wer'e only clearing the in-memory params. | |
--consider a clearing of the localdata later. | |
function DropBox:ClearMemoryParams() | |
self.params = nil | |
--clearLocalData() --would have to re-authenticate! | |
end | |
--Used to build a base parameter string for any OAuth/Dropbox authenticated call. | |
-- if these 4 strings don't already exist / are populated, we never really authenticated. | |
function DropBox:BuildParams() | |
--if we've already cached our params, just return them. | |
if self.params ~= nil then return self.params end | |
--read these from storage. | |
local accessToken = readLocalData("oauth_token") | |
local accessSecret= readLocalData("oauth_token_secret") | |
if (accessToken == nil) then | |
--read these from storage. | |
accessToken = readGlobalData("oauth_token") | |
accessSecret= readGlobalData("oauth_token_secret") | |
print("-- Using global key from ModelExchange --") | |
end | |
assert(accessToken ~= nil, | |
"You must create a new request and authorize before accessng DropBox information.") | |
assert(accessSecret ~= nil, | |
"You must create a new request and authorize before accessng DropBox information.") | |
assert(appKey ~= nil, "You must assign a DropBox application before accessng DropBox.") | |
assert(appSecret ~= nil, "You must assign a DropBox application before accessng DropBox.") | |
self.params = | |
"?oauth_consumer_key=".. self.appKey .. | |
"&oauth_token=" .. accessToken .. | |
"&oauth_version=1.0" .. | |
"&oauth_signature_method=PLAINTEXT" .. | |
"&oauth_signature=" .. self.appSecret .."%26" .. accessSecret | |
return self.params | |
end | |
--Begins the association of an app with DropBox. This gets a request token, | |
--which is a request to connect to a DropBox app | |
function DropBox:GetRequestToken() | |
local params = | |
"?oauth_consumer_key=".. self.appKey .. | |
"&oauth_version=1.0" .. | |
"&oauth_signature_method=PLAINTEXT" .. | |
"&oauth_signature=" .. self.appSecret .."%26" .."" | |
http.get("https://api.dropbox.com/1/oauth/request_token"..params, | |
function(data,status,headers) | |
--split data into two | |
token = string.gsub(data, "([^&=]+)=([^&=]*)&?", | |
function (k,v) | |
saveLocalData("req_"..k,v) | |
end) | |
print("Ready to authorize") | |
end, | |
httpError) | |
end | |
--Opens browser so user can authorize this request. User must hit OK for the temporary request | |
--token to be accepted in the next step. | |
--The user should take a few seconds after the browser approval before returning and hitting the | |
--GetAccessToken portion of the code, otherwise DropBox will refuse the request. Trying | |
--to authenticate again after a few seconds does work, though. | |
function DropBox:DoAuthorize() | |
local token = readLocalData("req_oauth_token") or "" | |
local params = "?oauth_token=" .. token | |
local url = "https://www.dropbox.com/1/oauth/authorize"..params | |
openURL(url) | |
print("Ready to GetAccessToken") | |
end | |
--This is where we get the "real token". This is the token we store in the appliatio so that | |
--we can call DropBox with our functions. Once through here, we have access to the /sandbox. | |
function DropBox:GetAccessToken() | |
local token = readLocalData("req_oauth_token") or "" | |
local token_secret = readLocalData("req_oauth_token_secret") or "" | |
local params = | |
"?oauth_consumer_key=".. self.appKey .. | |
"&oauth_token=" ..token .. | |
"&oauth_version=1.0" .. | |
"&oauth_signature_method=PLAINTEXT" .. | |
"&oauth_signature=" .. self.appSecret .."%26" .. token_secret | |
local url = "https://api.dropbox.com/1/oauth/access_token"..params | |
http.get(url, | |
function(data,status,headers) | |
--split data into two | |
token = string.gsub(data, "([^&=]+)=([^&=]*)&?", | |
function (k,v) | |
saveLocalData(k,v) | |
saveGlobalData(k,v) --so other lua apps can use it! | |
end) | |
print("Ready for Query Info") | |
end | |
, httpError) | |
end | |
--Helper function. | |
--Used to call various Dropbox endpoints. Will parse the resulting JSON into a LUA table. | |
function DropBox:_GetJSONResult(url, callback) | |
local cb = callback or nil | |
http.get(url, | |
function(data,status,headers) | |
--AC: JSON class isn't namespaced... | |
result = {} | |
result= JSON:decode(data) | |
if cb ~= nil then cb(result) end | |
end, | |
httpError) | |
end | |
---once we have the proper keys, we can actually read data and get meaadata from DropBox. | |
function DropBox:GetInfo(callback) | |
local params = self:BuildParams() | |
local url = "https://api.dropbox.com/1/account/info"..params | |
print("Get Info") | |
DropBox:_GetJSONResult(url, callback) | |
end | |
--save a file to DropBox. If the file already exists, we will get an error. | |
--Filename is rooted to /sandbox; we are not doing any /dropbox (global) saves. | |
--We didn't call JSON here becuase we have to pass a bucket of data and we want to stay | |
--as clean as possible here. | |
function DropBox:Write(filename, data, callback) | |
local cb = callback or nil | |
params = self:BuildParams() | |
local tbl = {["method"]="POST", ["data"]=data} | |
--save the contents | |
http.get("https://api-content.dropbox.com/1/files_put/sandbox/".. filename .. params, | |
function(data,status,headers) | |
--AC: my JSON class isn't namespaced. boo... | |
result = {} | |
result= JSON:decode(data) | |
if cb ~= nil then cb(result) end | |
end, | |
httpError, tbl) | |
end | |
--Reads a file, if a callback routine is supplied, calls it after the read is complete. | |
--NOTE that this SHOULDN'T call the JSON routine as that would attempt to DECODE the file. | |
--We want the raw (sorta, see below) file from DropBox. | |
function DropBox:Read(filename, callback) | |
local cb = callback or nil | |
local params = self:BuildParams() | |
http.get("https://api-content.dropbox.com/1/files/sandbox/".. filename .. params, | |
function(data,status,headers) | |
--return raw data - no post processing. | |
--NOTE THAT CODEA INTERJECTS ITSELF AND WILL PARSE AN IMAGE | |
--INTO THE IMAGE CLASS. | |
if cb ~= nil then cb(data) end | |
end, | |
httpError) | |
end | |
--searches the DropBox for a file name. At least 3 chars are needed, we don't assert it though. | |
function DropBox:Search(query, callback) | |
local params = self:BuildParams() | |
local searchparams = params .. "&query=" .. query | |
local url = "https://api.dropbox.com/1/search/sandbox".. searchparams | |
DropBox:_GetJSONResult(url, callback) | |
end | |
--Copies a file from one DropBox Sandbox place to another - NOT USING FILEREF. | |
function DropBox:Copy(src, dest, callback) | |
local params = self:BuildParams() | |
local copyparams = params .. "&root=sandbox&from_path=" .. src .. "&to_path=" ..dest | |
local url = "https://api.dropbox.com/1/fileops/copy" .. copyparams | |
DropBox:_GetJSONResult(url, callback) | |
end | |
--Moves a file from one DropBox Sandbox place to another - NOT USING FILEREF. | |
function DropBox:Move(src, dest, callback) | |
local params = self:BuildParams() | |
local moveparams = params .. "&root=sandbox&from_path=" .. src .. "&to_path=" ..dest | |
local url = "https://api.dropbox.com/1/fileops/move" .. moveparams | |
DropBox:_GetJSONResult(url, callback) | |
end | |
--Deletes a Dropbox Sandbox file. DOES NOT ASK FOR APPROVAL. | |
function DropBox:Delete(filename, callback) | |
local params = self:BuildParams() | |
local deleteparams = params .. "&root=sandbox&path=" ..filename | |
local url = "https://api.dropbox.com/1/fileops/delete" .. deleteparams | |
DropBox:_GetJSONResult(url, callback) | |
end | |
function DropBox:CreateFolder(foldername, callback) | |
local params = self:BuildParams() | |
local folderparams = params .. "&root=sandbox&path=" ..foldername | |
local url = "https://api.dropbox.com/1/fileops/create_folder" .. folderparams | |
DropBox:_GetJSONResult(url, callback) | |
end | |
--users can remove this function when integrating - it's proof of operation. | |
--Note that since we are doing callbacks, things to not generate output in sequence; | |
--some operations take longer and shorter than others. | |
function DropBox:TestHarness(callback) | |
--report my "info" | |
self:GetInfo(callback) | |
--write an arbtrary byte file, and test the "zeroes" issue we get with Codea. | |
output = string.char(65,0,0,126) | |
fname = "test.bin" | |
self:Write(fname, output, | |
function(data) print("File Written") end) | |
--read the file | |
self:Read(fname, function(data) print("File Read") end) | |
--delete and create folders. Cascade. we really should check the JSON for an error node! | |
--we are intentionally forcing one thing to wait for another this way. | |
self:Delete("/testfolderfromcodea2", | |
function(data) | |
print("Directory deleted") | |
--after the delete is complete, call the create! | |
self:CreateFolder("/testfolderfromcodea2", | |
function(data) | |
print("Directory added") | |
end) | |
end) | |
--we really shoud nest this into the above function, but that would be hard to | |
--read and understand. | |
--copy the earlier created "test.bin" file into the new folder we just created. | |
self:Copy("/test.bin", "/testfolderfromcodea2/test.bin", | |
function(data) print ("File Copied") | |
--once copied, move the file from the subfolder to the top level dir, and rename it | |
self:Move("/testfolderfromcodea2/test.bin", "/moved.bin", | |
function(data) print ("File Moved") | |
end) | |
end) | |
--last call, searches the sandbox for the file we just moved. | |
print("Search Results for moved") | |
self:Search("moved", callback) | |
end | |
function httpError(error) | |
print("DropBox HTTP Error:"..error) | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- JSON encode / decode functionality | |
-- ret = encode(object) | |
-- tbl = decode(ret) | |
-- or -- | |
-- ret = JSON:encode(object) | |
-- tbl = JSON:decode(ret) | |
JSON = class() | |
----------------------------------------------------------------------------- | |
-- JSON4Lua: JSON encoding / decoding support for the Lua language. | |
-- json Module. | |
-- Author: Craig Mason-Jones | |
-- Homepage: http://json.luaforge.net/ | |
-- Version: 0.9.40 | |
-- This module is released under the MIT License (MIT). | |
-- Please see LICENCE.txt for details. | |
-- | |
-- USAGE: | |
-- This module exposes two functions: | |
-- encode(o) | |
-- Returns the table / string / boolean / number / nil / json.null | |
-- value as a JSON-encoded string. | |
-- decode(json_string) | |
-- Returns a Lua object populated with the data encoded in the JSON string json_string. | |
-- | |
-- REQUIREMENTS: | |
-- compat-5.1 if using Lua 5.0 | |
-- | |
-- CHANGELOG | |
-- 0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix). | |
-- Fixed Lua 5.1 compatibility issues. | |
-- Introduced json.null to have null values in associative arrays. | |
-- encode() performance improvement (more than 50%) through table.concat rather than .. | |
-- Introduced decode ability to ignore /**/ comments in the JSON string. | |
-- 0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays. | |
-- 0.9.10.ac.1 Codea: added gloabal JSON: class wrappers as coding style helpers. | |
----------------------------------------------------------------------------- | |
----------------------------------------------------------------------------- | |
-- Imports and dependencies | |
----------------------------------------------------------------------------- | |
--local math = require('math') | |
--local string = require("string") | |
--local table = require("table") | |
local base = _G | |
----------------------------------------------------------------------------- | |
-- Module declaration | |
----------------------------------------------------------------------------- | |
--module("json") | |
-- Private functions | |
local decode_scanArray | |
local decode_scanComment | |
local decode_scanConstant | |
local decode_scanNumber | |
local decode_scanObject | |
local decode_scanString | |
local decode_scanWhitespace | |
local encodeString | |
local isArray | |
local isEncodable | |
----------------------------------------------------------------------------- | |
-- CLASS WRAPPERS : can use as statics. | |
-- note that this class is not clean, the functions are globally defined, we should | |
-- consider making them locals at least, and namespacing them at best. | |
----------------------------------------------------------------------------- | |
function JSON:encode(v) | |
return encode(v) | |
end | |
function JSON:decode(s, startPos) | |
return decode(s, startPos) | |
end | |
----------------------------------------------------------------------------- | |
-- PUBLIC FUNCTIONS | |
----------------------------------------------------------------------------- | |
--- Encodes an arbitrary Lua object / variable. | |
-- @param v The Lua object / variable to be JSON encoded. | |
-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode) | |
function encode (v) | |
-- Handle nil values | |
if v==nil then | |
return "null" | |
end | |
local vtype = base.type(v) | |
-- Handle strings | |
if vtype=='string' then | |
return '"' .. encodeString(v) .. '"' -- Need to handle encoding in string | |
end | |
-- Handle booleans | |
if vtype=='number' or vtype=='boolean' then | |
return base.tostring(v) | |
end | |
-- Handle tables | |
if vtype=='table' then | |
local rval = {} | |
-- Consider arrays separately | |
local bArray, maxCount = isArray(v) | |
if bArray then | |
for i = 1,maxCount do | |
table.insert(rval, encode(v[i])) | |
end | |
else -- An object, not an array | |
for i,j in base.pairs(v) do | |
if isEncodable(i) and isEncodable(j) then | |
table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j)) | |
end | |
end | |
end | |
if bArray then | |
return '[' .. table.concat(rval,',') ..']' | |
else | |
return '{' .. table.concat(rval,',') .. '}' | |
end | |
end | |
-- Handle null values | |
if vtype=='function' and v==null then | |
return 'null' | |
end | |
base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v)) | |
end | |
--- Decodes a JSON string and returns the decoded value as a Lua data structure / value. | |
-- @param s The string to scan. | |
-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1. | |
-- @param Lua object, number The object that was scanned, as a | |
-- Lua table / string / number / boolean or nil, | |
-- and the position of the first character after | |
-- the scanned JSON object. | |
function decode(s, startPos) | |
startPos = startPos and startPos or 1 | |
startPos = decode_scanWhitespace(s,startPos) | |
base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']') | |
local curChar = string.sub(s,startPos,startPos) | |
-- Object | |
if curChar=='{' then | |
return decode_scanObject(s,startPos) | |
end | |
-- Array | |
if curChar=='[' then | |
return decode_scanArray(s,startPos) | |
end | |
-- Number | |
if string.find("+-0123456789.e", curChar, 1, true) then | |
return decode_scanNumber(s,startPos) | |
end | |
-- String | |
if curChar==[["]] or curChar==[[']] then | |
return decode_scanString(s,startPos) | |
end | |
if string.sub(s,startPos,startPos+1)=='/*' then | |
return decode(s, decode_scanComment(s,startPos)) | |
end | |
-- Otherwise, it must be a constant | |
return decode_scanConstant(s,startPos) | |
end | |
--- The null function allows one to specify a null value in an associative array (which is otherwise | |
-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null } | |
function null() | |
return null -- so json.null() will also return null ;-) | |
end | |
----------------------------------------------------------------------------- | |
-- Internal, PRIVATE functions. | |
-- Following a Python-like convention, I have prefixed all these 'PRIVATE' | |
-- functions with an underscore. | |
----------------------------------------------------------------------------- | |
--- Scans an array from JSON into a Lua object | |
-- startPos begins at the start of the array. | |
-- Returns the array and the next starting position | |
-- @param s The string being scanned. | |
-- @param startPos The starting position for the scan. | |
-- @return table, int The scanned array as a table, and the position of the next character to scan. | |
function decode_scanArray(s,startPos) | |
local array = {} -- The return value | |
local stringLen = string.len(s) | |
base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s ) | |
startPos = startPos + 1 | |
-- Infinite loop for array elements | |
repeat | |
startPos = decode_scanWhitespace(s,startPos) | |
base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.') | |
local curChar = string.sub(s,startPos,startPos) | |
if (curChar==']') then | |
return array, startPos+1 | |
end | |
if (curChar==',') then | |
startPos = decode_scanWhitespace(s,startPos+1) | |
end | |
base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.') | |
object, startPos = decode(s,startPos) | |
table.insert(array,object) | |
until false | |
end | |
--- Scans a comment and discards the comment. | |
-- Returns the position of the next character following the comment. | |
-- @param string s The JSON string to scan. | |
-- @param int startPos The starting position of the comment | |
function decode_scanComment(s, startPos) | |
base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos) | |
local endPos = string.find(s,'*/',startPos+2) | |
base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos) | |
return endPos+2 | |
end | |
--- Scans for given constants: true, false or null | |
-- Returns the appropriate Lua type, and the position of the next character to read. | |
-- @param s The string being scanned. | |
-- @param startPos The position in the string at which to start scanning. | |
-- @return object, int The object (true, false or nil) and the position at which the next character should be | |
-- scanned. | |
function decode_scanConstant(s, startPos) | |
local consts = { ["true"] = true, ["false"] = false, ["null"] = nil } | |
local constNames = {"true","false","null"} | |
for i,k in base.pairs(constNames) do | |
--print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k) | |
if string.sub(s,startPos, startPos + string.len(k) -1 )==k then | |
return consts[k], startPos + string.len(k) | |
end | |
end | |
base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos) | |
end | |
--- Scans a number from the JSON encoded string. | |
-- (in fact, also is able to scan numeric +- eqns, which is not | |
-- in the JSON spec.) | |
-- Returns the number, and the position of the next character | |
-- after the number. | |
-- @param s The string being scanned. | |
-- @param startPos The position at which to start scanning. | |
-- @return number, int The extracted number and the position of the next character to scan. | |
function decode_scanNumber(s,startPos) | |
local endPos = startPos+1 | |
local stringLen = string.len(s) | |
local acceptableChars = "+-0123456789.e" | |
while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true) | |
and endPos<=stringLen | |
) do | |
endPos = endPos + 1 | |
end | |
local stringValue = 'return ' .. string.sub(s,startPos, endPos-1) | |
local stringEval = base.loadstring(stringValue) | |
base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos) | |
return stringEval(), endPos | |
end | |
--- Scans a JSON object into a Lua object. | |
-- startPos begins at the start of the object. | |
-- Returns the object and the next starting position. | |
-- @param s The string being scanned. | |
-- @param startPos The starting position of the scan. | |
-- @return table, int The scanned object as a table and the position of the next character to scan. | |
function decode_scanObject(s,startPos) | |
local object = {} | |
local stringLen = string.len(s) | |
local key, value | |
base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s) | |
startPos = startPos + 1 | |
repeat | |
startPos = decode_scanWhitespace(s,startPos) | |
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.') | |
local curChar = string.sub(s,startPos,startPos) | |
if (curChar=='}') then | |
return object,startPos+1 | |
end | |
if (curChar==',') then | |
startPos = decode_scanWhitespace(s,startPos+1) | |
end | |
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.') | |
-- Scan the key | |
key, startPos = decode(s,startPos) | |
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) | |
startPos = decode_scanWhitespace(s,startPos) | |
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) | |
base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos) | |
startPos = decode_scanWhitespace(s,startPos+1) | |
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) | |
value, startPos = decode(s,startPos) | |
object[key]=value | |
until false -- infinite loop while key-value pairs are found | |
end | |
--- Scans a JSON string from the opening inverted comma or single quote to the | |
-- end of the string. | |
-- Returns the string extracted as a Lua string, | |
-- and the position of the next non-string character | |
-- (after the closing inverted comma or single quote). | |
-- @param s The string being scanned. | |
-- @param startPos The starting position of the scan. | |
-- @return string, int The extracted string as a Lua string, and the next character to parse. | |
function decode_scanString(s,startPos) | |
base.assert(startPos, 'decode_scanString(..) called without start position') | |
local startChar = string.sub(s,startPos,startPos) | |
base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string') | |
local escaped = false | |
local endPos = startPos + 1 | |
local bEnded = false | |
local stringLen = string.len(s) | |
repeat | |
local curChar = string.sub(s,endPos,endPos) | |
-- Character escaping is only used to escape the string delimiters | |
if not escaped then | |
if curChar==[[\]] then | |
escaped = true | |
else | |
bEnded = curChar==startChar | |
end | |
else | |
-- If we're escaped, we accept the current character come what may | |
escaped = false | |
end | |
endPos = endPos + 1 | |
base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos) | |
until bEnded | |
local stringValue = 'return ' .. string.sub(s, startPos, endPos-1) | |
local stringEval = base.loadstring(stringValue) | |
base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos) | |
return stringEval(), endPos | |
end | |
--- Scans a JSON string skipping all whitespace from the current start position. | |
-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached. | |
-- @param s The string being scanned | |
-- @param startPos The starting position where we should begin removing whitespace. | |
-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string | |
-- was reached. | |
function decode_scanWhitespace(s,startPos) | |
local whitespace=" \n\r\t" | |
local stringLen = string.len(s) | |
while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do | |
startPos = startPos + 1 | |
end | |
return startPos | |
end | |
--- Encodes a string to be JSON-compatible. | |
-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-) | |
-- @param s The string to return as a JSON encoded (i.e. backquoted string) | |
-- @return The string appropriately escaped. | |
function encodeString(s) | |
s = string.gsub(s,'\\','\\\\') | |
s = string.gsub(s,'"','\\"') | |
s = string.gsub(s,"'","\\'") | |
s = string.gsub(s,'\n','\\n') | |
s = string.gsub(s,'\t','\\t') | |
return s | |
end | |
-- Determines whether the given Lua type is an array or a table / dictionary. | |
-- We consider any table an array if it has indexes 1..n for its n items, and no | |
-- other data in the table. | |
-- I think this method is currently a little 'flaky', but can't think of a good way around it yet... | |
-- @param t The table to evaluate as an array | |
-- @return boolean, number True if the table can be represented as an array, false otherwise. If true, | |
-- the second returned value is the maximum | |
-- number of indexed elements in the array. | |
function isArray(t) | |
-- Next we count all the elements, ensuring that any non-indexed elements are not-encodable | |
-- (with the possible exception of 'n') | |
local maxIndex = 0 | |
for k,v in base.pairs(t) do | |
if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair | |
if (not isEncodable(v)) then return false end -- All array elements must be encodable | |
maxIndex = math.max(maxIndex,k) | |
else | |
if (k=='n') then | |
if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements | |
else -- Else of (k=='n') | |
if isEncodable(v) then return false end | |
end -- End of (k~='n') | |
end -- End of k,v not an indexed pair | |
end -- End of loop across all pairs | |
return true, maxIndex | |
end | |
--- Determines whether the given Lua object / table / variable can be JSON encoded. The only | |
-- types that are JSON encodable are: string, boolean, number, nil, table and json.null. | |
-- In this implementation, all other types are ignored. | |
-- @param o The object to examine. | |
-- @return boolean True if the object should be JSON encoded, false if it should be ignored. | |
function isEncodable(o) | |
local t = base.type(o) | |
return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or | |
(t=='function' and o==null) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Dropbox Support | |
function setup() | |
--displayMode(FULLSCREEN) | |
--the app info to connect to. These come from your DropBox app developer page. | |
--I am not giving my key out in an open forum! | |
appKey = "YOURAPPKEY" --app key | |
appSecret = "YOURAPPSECRET" --app secret | |
db = DropBox(appKey, appSecret) | |
-- =================== | |
-- Simple UI | |
-- =================== | |
button1000 = TextButton('Initial Request', 20, 700, 150, 730) | |
button1001 = TextButton('Authorize (external)', 20, 640, 210, 670) | |
button1002 = TextButton('Get Access Token', 20, 580, 170, 610) | |
button1003 = TextButton('Run Test Harness', 300, 600, 450, 630) | |
end | |
function draw() | |
button1000:draw() | |
button1001:draw() | |
button1002:draw() | |
button1003:draw() | |
end | |
function touched(touch) | |
button1000:touched(touch) | |
button1001:touched(touch) | |
button1002:touched(touch) | |
button1003:touched(touch) | |
if (button1000.pressed) then | |
db:GetRequestToken() | |
end | |
if (button1001.pressed) then | |
db:DoAuthorize() | |
end | |
if (button1002.pressed) then | |
db:GetAccessToken() | |
end | |
if (button1003.pressed) then | |
db:TestHarness(GotInfo) | |
end | |
end | |
function keyboard(key) | |
if CCActiveTextBox then | |
CCActiveTextBox:acceptKey(key) | |
end | |
end | |
function GotInfo(result) | |
print (dump(result)) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment