import qt import urllib2 import ssl import cookielib import xml.etree.ElementTree as ET import re import StringIO import slicer import shutil import distutils import os class slicerNetwork: def __init__(self,parent): parent.title = "slicerNetwork" self.parent=parent class labkeyURIHandler(slicer.vtkURIHandler): def __init__(self): slicer.vtkURIHandler.__init__(self) self.className="labkeyURIHandler" slicer.mrmlScene.AddURIHandler(self) try: self.localCacheDirectory=os.path.join( os.environ["HOME"],"labkeyCache") except: #in windows, the variable is called HOMEPATH fhome=os.environ['HOMEDRIVE']+os.environ['HOMEPATH'] self.localCacheDirectory=os.path.join(fhome,"labkeyCache") def CanHandleURI(self,uri): print "labkeyURIHandler::CanHandleURI({0})".format(uri) if uri.find('labkey://')==0: return 1 return 0 def GetClassName(self): return self.className def GetHostName(self): return self.hostname def SetHostName(self,host): self.hostname=host def SetLocalCahceDirectory(self,dir): self.localCacheDirectory=dir def GetLocalCacheDirectory(self): return self.localCacheDirectory def GetLocalPath(self,source): relativePath=re.sub('labkey://','',source) sp=os.sep.encode('string-escape') print "Substituting / with {0} in {1}".format(sp,relativePath) relativePath=re.sub('/',sp,relativePath) return os.path.join(self.localCacheDirectory,relativePath) def GetFile(self,source): # check for file in cache. If available, use, if not, download localPath=self.GetLocalPath(source) if os.path.isfile(localPath): return localPath self.StageFileRead(source,localPath) return localPath def StageFileRead(self,source,dest): print "labkeyURIHandler::StageFileRead({0},{1})".format( source,dest) labkeyPath=re.sub('labkey://','',source) remote=self.readFile(self.hostname,labkeyPath) #make all necessary directories path=os.path.dirname(dest) try: os.makedirs(path) except: if not os.path.isdir(path): raise local=open(dest,'wb') #make sure we are at the begining of the file #check file size remote.seek(0,2) sz=remote.tell() print "Remote size: {0}".format(sz) remote.seek(0) shutil.copyfileobj(remote,local) print "Local size: {0}".format(local.tell()) local.close() def StageFileWrite(self,source,dest): print "labkeyURIHandler::StageFileWrite({0},{1}) not implemented yet".format( source,dest) def fileTypesAvailable(self): return ('VolumeFile','SegmentationFile','TransformFile') #mimic slicer.util.loadNodeFromFile def loadNodeFromFile(self, filename, filetype, properties={}, returnNode=False): #this is the only relevant part - file must be downloaded to cache localPath=self.GetFile(filename) slicer.util.loadNodeFromFile(localPath,filetype,properties,returnNode) #remove retrieved file try: if not(properties['keepCachedFile']) : os.remove(localPath) except: pass def loadVolume(self,filename, properties={}, returnNode=False): filetype = 'VolumeFile' #redirect to self.loadNodeFromFile first to get the cached file return self.loadNodeFromFile(filename,filetype, properties,returnNode) def loadSegmentation(self,filename,properties={},returnNode=False): filetype='SegmentationFile' #redirect to self.loadNodeFromFile first to get the cached file return self.loadNodeFromFile(filename,filetype, properties,returnNode) #add others if needed def configureSSL(self,cert,key,pwd,cacert): #do this first self.ctx=ssl.SSLContext(ssl.PROTOCOL_SSLv23) self.ctx.load_cert_chain(cert,key,pwd) self.ctx.verify_mode=ssl.CERT_REQUIRED self.ctx.load_verify_locations(cacert) def connectRemote(self,serverUrl,uname,pwd): https_handler=urllib2.HTTPSHandler(context=self.ctx) self.SetHostName(serverUrl) #cookie part cj=cookielib.CookieJar() cookie_handler=urllib2.HTTPCookieProcessor(cj) self.opener=urllib2.build_opener(https_handler,cookie_handler) loginUrl=serverUrl+"/labkey/login/login.post" r=urllib2.Request(str(loginUrl)) print "Connecting to {0}".format(loginUrl) r.add_header('ContentType','application/x-www-form-urlencoded') data="email="+uname+"&password="+pwd r.add_data(data) self.opener.open(r) #cj in opener contains the cookies def get(self,url): #r1=urllib2.Request('https://merlin.fmf.uni-lj.si/labkey/query/motionData/selectRows.api?schemaName=core&query.queryName=Users') r=urllib2.Request(url) return self.opener.open(r) #f contains json as a return value def post(self,url,data): r=urllib2.Request(url) #makes it a post r.add_data(data) r.add_header("content-type","application/json") f=self.opener.open(r) #f contains json as a return value def listDir(self,dir): print "Listing for {0}".format(dir) dirUrl=self.hostname+"/labkey/_webdav"+"/"+dir r=propfindRequest(dirUrl) PROPFIND=u"""\n \n \n \n \n """ r.add_header('content-type','text/xml; charset="utf-8"') r.add_header('content-length',str(len(PROPFIND))) r.add_header('Depth','1') r.add_data(PROPFIND) f=self.opener.open(r) tree=ET.XML(f.read()) rps=tree.findall('{DAV:}response') dirs=[] for r in rps: hr=r.find('{DAV:}href') dirent=hr.text dirent=re.sub('/labkey/_webdav/','',dirent) dirs.append(dirent) del dirs[0] return dirs def toRelativePath(self,dirs): flist1=[] for d in dirs: if d[-1]=='/': d=d[:-1] if d.rfind('/')>-1: d=d[d.rfind('/')+1:] flist1.append(d) return flist1 def readFile(self, serverUrl, path): dirUrl=serverUrl+"/labkey/_webdav"+"/"+path f=self.get(dirUrl) return StringIO.StringIO(f.read()) def loadDir(self, path): #dirURL=serverUrl+"/labkey/_webdav/"+path files=self.listDir(path) for f in files: #returns local path try: self.GetFile(f) except: #fails if there is a subdirectory; go recursively self.readDir(f) class propfindRequest(urllib2.Request): """ This request subclass allows explicit specification of the HTTP request method. Basic urllib2.Request class chooses GET or POST depending on self.has_data() """ def __init__(self, *args, **kwargs): #self.method = 'Propfind' urllib2.Request.__init__(self, *args, **kwargs) def get_method(self): return 'PROPFIND'