2019-08-28 15:37:56 -05:00
|
|
|
from __future__ import unicode_literals
|
2014-07-30 15:16:58 -05:00
|
|
|
import zipfile
|
2017-12-29 13:22:49 -06:00
|
|
|
import os.path
|
2017-01-31 08:08:00 -06:00
|
|
|
import sys
|
2019-08-27 15:01:24 -05:00
|
|
|
from kodi_six import xbmc, xbmcvfs, xbmcgui
|
2019-08-27 14:55:22 -05:00
|
|
|
from . import dropbox
|
|
|
|
from . import utils as utils
|
|
|
|
from . dropbox.files import WriteMode,CommitInfo,UploadSessionCursor
|
2019-09-05 14:30:06 -05:00
|
|
|
from . authorizers import DropboxAuthorizer
|
2012-10-26 09:42:10 -05:00
|
|
|
|
|
|
|
class Vfs:
|
2012-11-04 14:39:17 -06:00
|
|
|
root_path = None
|
2012-10-26 09:42:10 -05:00
|
|
|
|
2013-01-28 15:44:22 -06:00
|
|
|
def __init__(self,rootString):
|
|
|
|
self.set_root(rootString)
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def set_root(self,rootString):
|
2012-11-05 11:13:48 -06:00
|
|
|
old_root = self.root_path
|
2012-11-04 14:39:17 -06:00
|
|
|
self.root_path = rootString
|
2014-07-31 17:29:59 -05:00
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
#fix slashes
|
|
|
|
self.root_path = self.root_path.replace("\\","/")
|
|
|
|
|
|
|
|
#check if trailing slash is included
|
|
|
|
if(self.root_path[-1:] != "/"):
|
|
|
|
self.root_path = self.root_path + "/"
|
2012-11-05 11:13:48 -06:00
|
|
|
|
|
|
|
#return the old root
|
|
|
|
return old_root
|
2012-11-04 14:39:17 -06:00
|
|
|
|
|
|
|
def listdir(self,directory):
|
2012-10-26 09:42:10 -05:00
|
|
|
return {}
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def mkdir(self,directory):
|
2012-10-26 09:42:10 -05:00
|
|
|
return True
|
|
|
|
|
2012-11-06 11:37:39 -06:00
|
|
|
def put(self,source,dest):
|
2012-10-26 09:42:10 -05:00
|
|
|
return True
|
2012-11-02 15:59:40 -05:00
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def rmdir(self,directory):
|
2012-11-02 15:59:40 -05:00
|
|
|
return True
|
|
|
|
|
2014-08-01 13:12:43 -05:00
|
|
|
def rmfile(self,aFile):
|
|
|
|
return True
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def exists(self,aFile):
|
2012-11-02 15:59:40 -05:00
|
|
|
return True
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def rename(self,aFile,newName):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def cleanup(self):
|
|
|
|
return True
|
2012-10-26 09:42:10 -05:00
|
|
|
|
2012-11-02 15:59:40 -05:00
|
|
|
class XBMCFileSystem(Vfs):
|
2013-01-28 15:44:22 -06:00
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def listdir(self,directory):
|
2012-11-02 15:59:40 -05:00
|
|
|
return xbmcvfs.listdir(directory)
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def mkdir(self,directory):
|
2014-08-08 10:37:16 -05:00
|
|
|
return xbmcvfs.mkdir(xbmc.translatePath(directory))
|
2012-11-02 15:59:40 -05:00
|
|
|
|
2012-11-06 11:37:39 -06:00
|
|
|
def put(self,source,dest):
|
2014-08-08 10:37:16 -05:00
|
|
|
return xbmcvfs.copy(xbmc.translatePath(source),xbmc.translatePath(dest))
|
2012-11-06 11:37:39 -06:00
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def rmdir(self,directory):
|
2012-11-02 15:59:40 -05:00
|
|
|
return xbmcvfs.rmdir(directory,True)
|
|
|
|
|
2014-08-01 13:12:43 -05:00
|
|
|
def rmfile(self,aFile):
|
|
|
|
return xbmcvfs.delete(aFile)
|
|
|
|
|
2014-07-30 15:16:58 -05:00
|
|
|
def rename(self,aFile,newName):
|
|
|
|
return xbmcvfs.rename(aFile, newName)
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
def exists(self,aFile):
|
2012-11-02 15:59:40 -05:00
|
|
|
return xbmcvfs.exists(aFile)
|
|
|
|
|
2014-07-30 15:16:58 -05:00
|
|
|
class ZipFileSystem(Vfs):
|
|
|
|
zip = None
|
|
|
|
|
|
|
|
def __init__(self,rootString,mode):
|
|
|
|
self.root_path = ""
|
2015-04-24 09:23:56 -05:00
|
|
|
self.zip = zipfile.ZipFile(rootString,mode=mode,compression=zipfile.ZIP_DEFLATED,allowZip64=True)
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def listdir(self,directory):
|
2014-08-01 12:57:55 -05:00
|
|
|
return [[],[]]
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def mkdir(self,directory):
|
|
|
|
#self.zip.write(directory[len(self.root_path):])
|
2014-08-01 12:57:55 -05:00
|
|
|
return False
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def put(self,source,dest):
|
2014-08-08 10:26:39 -05:00
|
|
|
|
|
|
|
aFile = xbmcvfs.File(xbmc.translatePath(source),'r')
|
|
|
|
|
2019-08-28 15:37:56 -05:00
|
|
|
self.zip.writestr(dest,aFile.readBytes())
|
2014-08-08 10:26:39 -05:00
|
|
|
|
2014-07-30 15:16:58 -05:00
|
|
|
return True
|
|
|
|
|
|
|
|
def rmdir(self,directory):
|
2014-08-01 12:57:55 -05:00
|
|
|
return False
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def exists(self,aFile):
|
2014-08-01 12:57:55 -05:00
|
|
|
return False
|
2014-07-30 15:16:58 -05:00
|
|
|
|
|
|
|
def cleanup(self):
|
|
|
|
self.zip.close()
|
2014-08-01 12:57:55 -05:00
|
|
|
|
2015-06-26 15:32:22 -05:00
|
|
|
def extract(self,aFile,path):
|
2014-08-01 12:57:55 -05:00
|
|
|
#extract zip file to path
|
2015-06-26 15:32:22 -05:00
|
|
|
self.zip.extract(aFile,path)
|
|
|
|
|
|
|
|
def listFiles(self):
|
|
|
|
return self.zip.infolist()
|
2014-07-30 15:16:58 -05:00
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
class DropboxFileSystem(Vfs):
|
2017-12-29 13:22:49 -06:00
|
|
|
MAX_CHUNK = 50 * 1000 * 1000 #dropbox uses 150, reduced to 50 for small mem systems
|
2012-11-05 12:25:25 -06:00
|
|
|
client = None
|
2014-10-09 14:30:39 -05:00
|
|
|
APP_KEY = ''
|
|
|
|
APP_SECRET = ''
|
2012-11-04 14:39:17 -06:00
|
|
|
|
2013-01-28 15:44:22 -06:00
|
|
|
def __init__(self,rootString):
|
2013-03-04 10:22:09 -06:00
|
|
|
self.set_root(rootString)
|
2013-01-28 15:44:22 -06:00
|
|
|
|
2017-01-31 08:08:00 -06:00
|
|
|
authorizer = DropboxAuthorizer()
|
2012-11-05 12:25:25 -06:00
|
|
|
|
2017-01-31 08:08:00 -06:00
|
|
|
if(authorizer.isAuthorized()):
|
|
|
|
self.client = authorizer.getClient()
|
2012-11-05 12:25:25 -06:00
|
|
|
else:
|
2017-01-31 08:08:00 -06:00
|
|
|
#tell the user to go back and run the authorizer
|
2017-01-31 08:16:54 -06:00
|
|
|
xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30105))
|
2017-01-31 08:08:00 -06:00
|
|
|
sys.exit()
|
2012-11-05 12:25:25 -06:00
|
|
|
|
2012-11-05 15:46:17 -06:00
|
|
|
def listdir(self,directory):
|
2017-12-03 17:32:21 -06:00
|
|
|
directory = self._fix_slashes(directory)
|
|
|
|
|
2012-11-05 15:46:17 -06:00
|
|
|
if(self.client != None and self.exists(directory)):
|
|
|
|
files = []
|
|
|
|
dirs = []
|
2017-12-03 17:32:21 -06:00
|
|
|
metadata = self.client.files_list_folder(directory)
|
2012-11-05 15:46:17 -06:00
|
|
|
|
2017-12-03 17:32:21 -06:00
|
|
|
for aFile in metadata.entries:
|
|
|
|
if(isinstance(aFile,dropbox.files.FolderMetadata)):
|
2019-08-28 15:37:56 -05:00
|
|
|
dirs.append(aFile.name)
|
2012-11-05 15:46:17 -06:00
|
|
|
else:
|
2019-08-28 15:37:56 -05:00
|
|
|
files.append(aFile.name)
|
2012-11-05 15:46:17 -06:00
|
|
|
|
|
|
|
return [dirs,files]
|
|
|
|
else:
|
|
|
|
return [[],[]]
|
|
|
|
|
|
|
|
|
2012-11-05 12:25:25 -06:00
|
|
|
def mkdir(self,directory):
|
2013-03-04 10:22:09 -06:00
|
|
|
directory = self._fix_slashes(directory)
|
2012-11-05 12:25:25 -06:00
|
|
|
if(self.client != None):
|
2017-12-03 17:32:21 -06:00
|
|
|
#sort of odd but always return true, folder create is implicit with file upload
|
2012-11-05 12:25:25 -06:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-11-05 15:46:17 -06:00
|
|
|
def rmdir(self,directory):
|
2013-03-04 10:22:09 -06:00
|
|
|
directory = self._fix_slashes(directory)
|
2012-11-05 15:46:17 -06:00
|
|
|
if(self.client != None and self.exists(directory)):
|
2014-07-29 08:43:34 -05:00
|
|
|
#dropbox is stupid and will refuse to do this sometimes, need to delete recursively
|
|
|
|
dirs,files = self.listdir(directory)
|
|
|
|
|
|
|
|
for aDir in dirs:
|
|
|
|
self.rmdir(aDir)
|
|
|
|
|
|
|
|
#finally remove the root directory
|
2017-12-03 17:32:21 -06:00
|
|
|
self.client.files_delete(directory)
|
2014-08-01 13:12:43 -05:00
|
|
|
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2014-11-21 13:30:22 -06:00
|
|
|
def rmfile(self,aFile):
|
2014-08-01 13:12:43 -05:00
|
|
|
aFile = self._fix_slashes(aFile)
|
2014-11-21 13:30:22 -06:00
|
|
|
|
2014-08-01 13:12:43 -05:00
|
|
|
if(self.client != None and self.exists(aFile)):
|
2017-12-03 17:32:21 -06:00
|
|
|
self.client.files_delete(aFile)
|
2014-08-01 13:12:43 -05:00
|
|
|
return True
|
2012-11-05 15:46:17 -06:00
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-11-05 12:25:25 -06:00
|
|
|
def exists(self,aFile):
|
2013-03-04 10:22:09 -06:00
|
|
|
aFile = self._fix_slashes(aFile)
|
2017-12-27 10:06:07 -06:00
|
|
|
|
2012-11-05 12:25:25 -06:00
|
|
|
if(self.client != None):
|
2017-12-03 17:32:21 -06:00
|
|
|
#can't list root metadata
|
|
|
|
if(aFile == ''):
|
|
|
|
return True
|
|
|
|
|
2012-11-04 14:39:17 -06:00
|
|
|
try:
|
2017-12-03 17:32:21 -06:00
|
|
|
meta_data = self.client.files_get_metadata(aFile)
|
2012-11-05 12:25:25 -06:00
|
|
|
#if we make it here the file does exist
|
|
|
|
return True
|
2012-11-04 14:39:17 -06:00
|
|
|
except:
|
2012-11-05 12:25:25 -06:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return False
|
2012-11-04 14:39:17 -06:00
|
|
|
|
2014-06-03 13:34:02 -05:00
|
|
|
def put(self,source,dest,retry=True):
|
2013-03-04 10:22:09 -06:00
|
|
|
dest = self._fix_slashes(dest)
|
|
|
|
|
2012-11-05 12:25:25 -06:00
|
|
|
if(self.client != None):
|
2017-12-29 13:22:49 -06:00
|
|
|
#open the file and get its size
|
2012-11-05 12:25:25 -06:00
|
|
|
f = open(source,'rb')
|
2017-12-29 13:22:49 -06:00
|
|
|
f_size = os.path.getsize(source)
|
|
|
|
|
2012-11-05 15:46:17 -06:00
|
|
|
try:
|
2017-12-29 13:22:49 -06:00
|
|
|
if(f_size < self.MAX_CHUNK):
|
|
|
|
#use the regular upload
|
|
|
|
response = self.client.files_upload(f.read(),dest,mode=WriteMode('overwrite'))
|
|
|
|
else:
|
|
|
|
#start the upload session
|
|
|
|
upload_session = self.client.files_upload_session_start(f.read(self.MAX_CHUNK))
|
|
|
|
upload_cursor = UploadSessionCursor(upload_session.session_id,f.tell())
|
|
|
|
|
|
|
|
while(f.tell() < f_size):
|
|
|
|
#check if we should finish the upload
|
|
|
|
if((f_size - f.tell()) <= self.MAX_CHUNK):
|
|
|
|
#upload and close
|
|
|
|
self.client.files_upload_session_finish(f.read(self.MAX_CHUNK),upload_cursor,CommitInfo(dest,mode=WriteMode('overwrite')))
|
|
|
|
else:
|
|
|
|
#upload a part and store the offset
|
|
|
|
self.client.files_upload_session_append_v2(f.read(self.MAX_CHUNK),upload_cursor)
|
|
|
|
upload_cursor.offset = f.tell()
|
|
|
|
|
2019-08-26 15:40:15 -05:00
|
|
|
#if no errors we're good!
|
2012-11-05 15:46:17 -06:00
|
|
|
return True
|
2017-12-29 13:22:49 -06:00
|
|
|
except Exception as anError:
|
|
|
|
utils.log(str(anError))
|
|
|
|
|
2012-11-05 15:46:17 -06:00
|
|
|
#if we have an exception retry
|
2014-06-03 13:34:02 -05:00
|
|
|
if(retry):
|
|
|
|
return self.put(source,dest,False)
|
|
|
|
else:
|
|
|
|
#tried once already, just quit
|
|
|
|
return False
|
2012-11-05 12:25:25 -06:00
|
|
|
else:
|
|
|
|
return False
|
2012-11-06 11:37:39 -06:00
|
|
|
|
|
|
|
def get_file(self,source,dest):
|
|
|
|
if(self.client != None):
|
|
|
|
#write the file locally
|
2017-12-03 17:32:21 -06:00
|
|
|
f = self.client.files_download_to_file(dest,source)
|
2013-03-04 10:27:25 -06:00
|
|
|
return True
|
2012-11-06 11:37:39 -06:00
|
|
|
else:
|
|
|
|
return False
|
2013-03-04 10:22:09 -06:00
|
|
|
|
|
|
|
def _fix_slashes(self,filename):
|
2017-12-03 17:32:21 -06:00
|
|
|
result = filename.replace('\\','/')
|
|
|
|
|
2017-12-08 08:46:12 -06:00
|
|
|
#root needs to be a blank string
|
2017-12-03 17:32:21 -06:00
|
|
|
if(result == '/'):
|
|
|
|
result = ""
|
|
|
|
|
2017-12-08 08:46:12 -06:00
|
|
|
#if dir ends in slash, remove it
|
|
|
|
if(result[-1:] == "/"):
|
|
|
|
result = result[:-1]
|
|
|
|
|
2017-12-03 17:32:21 -06:00
|
|
|
return result
|