slicerNetwork.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import qt
  2. import urllib2
  3. import ssl
  4. import cookielib
  5. import xml.etree.ElementTree as ET
  6. import re
  7. import StringIO
  8. import slicer
  9. import shutil
  10. import distutils
  11. import os
  12. import base64
  13. class slicerNetwork:
  14. def __init__(self,parent):
  15. parent.title = "slicerNetwork"
  16. self.parent=parent
  17. class labkeyURIHandler(slicer.vtkURIHandler):
  18. def __init__(self):
  19. slicer.vtkURIHandler.__init__(self)
  20. self.className="labkeyURIHandler"
  21. slicer.mrmlScene.AddURIHandler(self)
  22. try:
  23. self.localCacheDirectory=os.path.join(os.environ["HOME"],"labkeyCache")
  24. except:
  25. #in windows, the variable is called HOMEPATH
  26. fhome=os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
  27. self.localCacheDirectory=os.path.join(fhome,"labkeyCache")
  28. def CanHandleURI(self,uri):
  29. print "labkeyURIHandler::CanHandleURI({0})".format(uri)
  30. if uri.find('labkey://')==0:
  31. return 1
  32. return 0
  33. def GetClassName(self):
  34. return self.className
  35. def GetHostName(self):
  36. return self.hostname
  37. def SetHostName(self,host):
  38. self.hostname=host
  39. def SetLocalCahceDirectory(self,dir):
  40. self.localCacheDirectory=dir
  41. def GetLocalCacheDirectory(self):
  42. return self.localCacheDirectory
  43. def GetLocalPath(self,source):
  44. relativePath=re.sub('labkey://','',source)
  45. sp=os.sep.encode('string-escape')
  46. print "Substituting / with {0} in {1}".format(sp,relativePath)
  47. relativePath=re.sub('/',sp,relativePath)
  48. return os.path.join(self.localCacheDirectory,relativePath)
  49. def GetFile(self,source):
  50. # check for file in cache. If available, use, if not, download
  51. localPath=self.GetLocalPath(source)
  52. if os.path.isfile(localPath):
  53. return localPath
  54. self.StageFileRead(source,localPath)
  55. return localPath
  56. def StageFileRead(self,source,dest):
  57. print "labkeyURIHandler::StageFileRead({0},{1})".format(source,dest)
  58. labkeyPath=re.sub('labkey://','',source)
  59. remote=self.readFile(self.hostname,labkeyPath)
  60. #make all necessary directories
  61. path=os.path.dirname(dest)
  62. try:
  63. os.makedirs(path)
  64. except:
  65. if not os.path.isdir(path):
  66. raise
  67. local=open(dest,'wb')
  68. #make sure we are at the begining of the file
  69. #check file size
  70. remote.seek(0,2)
  71. sz=remote.tell()
  72. print "Remote size: {0}".format(sz)
  73. remote.seek(0)
  74. shutil.copyfileobj(remote,local)
  75. print "Local size: {0}".format(local.tell())
  76. local.close()
  77. def StageFileWrite(self,source,dest):
  78. print "labkeyURIHandler::StageFileWrite({0},{1}) not implemented yet".format(
  79. source,dest)
  80. def fileTypesAvailable(self):
  81. return ('VolumeFile','SegmentationFile','TransformFile')
  82. #mimic slicer.util.loadNodeFromFile
  83. def loadNodeFromFile(self, filename, filetype, properties={}, returnNode=False):
  84. #this is the only relevant part - file must be downloaded to cache
  85. localPath=self.GetFile(filename)
  86. slicer.util.loadNodeFromFile(localPath,filetype,properties,returnNode)
  87. #remove retrieved file
  88. try:
  89. if not(properties['keepCachedFile']) :
  90. os.remove(localPath)
  91. except:
  92. pass
  93. def loadVolume(self,filename, properties={}, returnNode=False):
  94. filetype = 'VolumeFile'
  95. #redirect to self.loadNodeFromFile first to get the cached file
  96. return self.loadNodeFromFile(filename,filetype, properties,returnNode)
  97. def loadSegmentation(self,filename,properties={},returnNode=False):
  98. filetype='SegmentationFile'
  99. #redirect to self.loadNodeFromFile first to get the cached file
  100. return self.loadNodeFromFile(filename,filetype, properties,returnNode)
  101. #add others if needed
  102. def configureSSL(self,cert,key,pwd,cacert):
  103. #do this first
  104. try:
  105. self.ctx=ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  106. self.ctx.load_cert_chain(cert,key,pwd)
  107. self.ctx.verify_mode=ssl.CERT_REQUIRED
  108. self.ctx.load_verify_locations(cacert)
  109. except ssl.SSLError as err:
  110. print " Failed to configure SSL: {0}".format(str(err))
  111. def connectRemote(self,serverUrl,uname,pwd):
  112. https_handler=urllib2.HTTPSHandler(context=self.ctx)
  113. self.SetHostName(serverUrl)
  114. #cookie part
  115. cj=cookielib.CookieJar()
  116. cookie_handler=urllib2.HTTPCookieProcessor(cj)
  117. self.opener=urllib2.build_opener(https_handler,cookie_handler)
  118. loginUrl=serverUrl+"/labkey/login/login.post"
  119. r=urllib2.Request(str(loginUrl))
  120. print "Connecting to {0}".format(loginUrl)
  121. r.add_header('ContentType','application/x-www-form-urlencoded')
  122. data="email="+uname+"&password="+pwd
  123. #print "Data: '{0}".format(data)
  124. r.add_data(data)
  125. self.opener.open(r)
  126. def initRemote(self):
  127. https_handler=urllib2.HTTPSHandler(context=self.ctx)
  128. #cookie part
  129. cj=cookielib.CookieJar()
  130. cookie_handler=urllib2.HTTPCookieProcessor(cj)
  131. self.opener=urllib2.build_opener(https_handler,cookie_handler)
  132. #cj in opener contains the cookies
  133. def get(self,url):
  134. print "GET: {0}".format(url)
  135. r=urllib2.Request(url)
  136. base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
  137. r.add_header("Authorization", "Basic %s" % base64string)
  138. return self.opener.open(r)
  139. #f contains json as a return value
  140. def post(self,url,data):
  141. r=urllib2.Request(url)
  142. #makes it a post
  143. r.add_data(data)
  144. r.add_header("content-type","application/json")
  145. base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
  146. r.add_header("Authorization", "Basic %s" % base64string)
  147. f=self.opener.open(r)
  148. #f contains json as a return value
  149. def listDir(self,dir):
  150. print "Listing for {0}".format(dir)
  151. dirUrl=self.hostname+"/labkey/_webdav"+"/"+dir
  152. r=propfindRequest(dirUrl)
  153. PROPFIND=u"""<?xml version="1.0" encoding="utf-8"?>\n
  154. <propfind xmlns="DAV:">\n
  155. <prop>\n
  156. <getetag/>\n
  157. </prop>\n
  158. </propfind>"""
  159. r.add_header('content-type','text/xml; charset="utf-8"')
  160. r.add_header('content-length',str(len(PROPFIND)))
  161. r.add_header('Depth','1')
  162. r.add_data(PROPFIND)
  163. base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
  164. r.add_header("Authorization", "Basic %s" % base64string)
  165. print "PROPFIND: {0}".format(dirUrl)
  166. dirs=[]
  167. try:
  168. f=self.opener.open(r)
  169. except:
  170. print "No data"
  171. return dirs
  172. tree=ET.XML(f.read())
  173. rps=tree.findall('{DAV:}response')
  174. for r in rps:
  175. hr=r.find('{DAV:}href')
  176. dirent=hr.text
  177. dirent=re.sub('/labkey/_webdav/','',dirent)
  178. dirs.append(dirent)
  179. del dirs[0]
  180. return dirs
  181. def toRelativePath(self,dirs):
  182. flist1=[]
  183. for d in dirs:
  184. if d[-1]=='/':
  185. d=d[:-1]
  186. if d.rfind('/')>-1:
  187. d=d[d.rfind('/')+1:]
  188. flist1.append(d)
  189. return flist1
  190. def readFile(self, serverUrl, path):
  191. dirUrl=serverUrl+"/labkey/_webdav"+"/"+path
  192. f=self.get(dirUrl)
  193. return StringIO.StringIO(f.read())
  194. def loadDir(self, path):
  195. #dirURL=serverUrl+"/labkey/_webdav/"+path
  196. files=self.listDir(path)
  197. fdir="NONE"
  198. for f in files:
  199. #returns local path
  200. try:
  201. fdir=os.path.dirname(self.GetFile(f))
  202. except:
  203. #fails if there is a subdirectory; go recursively
  204. self.readDir(f)
  205. return fdir
  206. class propfindRequest(urllib2.Request):
  207. """
  208. This request subclass allows explicit specification of
  209. the HTTP request method. Basic urllib2.Request class
  210. chooses GET or POST depending on self.has_data()
  211. """
  212. def __init__(self, *args, **kwargs):
  213. #self.method = 'Propfind'
  214. urllib2.Request.__init__(self, *args, **kwargs)
  215. def get_method(self):
  216. return 'PROPFIND'