diff --git a/gui/irodsCreateTicket.py b/gui/irodsCreateTicket.py
index 88755be06c13c81f2dbf84a72536f9c4f9f890c4..225624f98c3dcc0d44ac067d781f0596531aac4d 100644
--- a/gui/irodsCreateTicket.py
+++ b/gui/irodsCreateTicket.py
@@ -34,8 +34,8 @@ class irodsCreateTicket():
 
         #gather info
         idx, path = self.irodsmodel.get_checked()
-        if path == None:
-            self.widget.infoLabel.setText("ERROR: No data selected.")
+        if path == None or self.ic.session.data_objects.exists(path):
+            self.widget.infoLabel.setText("ERROR: Please select a collection.")
             self.widget.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
             self.widget.createTicketButton.setEnabled(True)
             return
diff --git a/gui/irodsTicketLogin.py b/gui/irodsTicketLogin.py
index e1a84f2f2892d3d07c4d20fc898e68337347355a..29233f866ef3505eab600baccef98c06f2e1f838 100644
--- a/gui/irodsTicketLogin.py
+++ b/gui/irodsTicketLogin.py
@@ -1,7 +1,72 @@
 from PyQt5 import QtWidgets
 from PyQt5.uic import loadUi
+from utils.irodsConnectorAnonymous import irodsConnectorAnonymous
+import os
 
 class irodsTicketLogin():
-    def __init__(self):
+    def __init__(self, widget):
+        self.ic = None
+        self.coll = None
+        self.widget = widget
+        self.widget.connectButton.clicked.connect(self.irodsSession)
+        self.widget.homeButton.clicked.connect(self.loadTable)
+        self.widget.collTable.doubleClicked.connect(self.browse)
+        
 
-        print("TODO")
+    def irodsSession(self):
+        self.widget.infoLabel.clear()
+        host = self.widget.serverEdit.text()
+        token = self.widget.ticketEdit.text()
+        path = self.widget.pathEdit.text()
+
+        try:
+            self.ic = irodsConnectorAnonymous(host, token, path)
+            self.coll = self.ic.getData()
+            self.loadTable()
+        except Exception as e:
+            self.widget.infoLabel.setText("LOGIN ERROR: Check ticket and iRODS path.\n"+repr(e))
+
+    
+    def loadTable(self, update = None):
+        self.widget.infoLabel.clear()
+        if self.coll == None:
+            self.widget.infoLabel.setText("No data avalaible. Check ticket and iRODS path.")
+            return
+        if update == None or update == False:
+            update = self.coll
+
+        self.widget.collTable.setRowCount(0)
+        self.widget.collTable.setRowCount(len(update.subcollections)+len(update.data_objects))
+        row = 0
+        for subcoll in update.subcollections:
+            self.widget.collTable.setItem(row, 0, 
+                    QtWidgets.QTableWidgetItem(os.path.dirname(subcoll.path)))
+            self.widget.collTable.setItem(row, 1, 
+                    QtWidgets.QTableWidgetItem(subcoll.name+"/"))
+            self.widget.collTable.setItem(1, 2, QtWidgets.QTableWidgetItem(""))
+            self.widget.collTable.setItem(1, 3, QtWidgets.QTableWidgetItem(""))
+            row = row + 1
+        for obj in update.data_objects:
+            self.widget.collTable.setItem(row, 0,
+                    QtWidgets.QTableWidgetItem(os.path.dirname(obj.path)))
+            self.widget.collTable.setItem(row, 1, QtWidgets.QTableWidgetItem(obj.name))
+            self.widget.collTable.setItem(row, 2, QtWidgets.QTableWidgetItem(str(obj.size)))
+            self.widget.collTable.setItem(row, 3, QtWidgets.QTableWidgetItem(str(obj.checksum)))
+            self.widget.collTable.setItem(row, 4, 
+                    QtWidgets.QTableWidgetItem(str(obj.modify_time)))
+            row = row+1
+        self.widget.collTable.resizeColumnsToContents()
+
+
+    def browse(self, index):
+        self.widget.infoLabel.clear()
+        col = index.column()
+        row = index.row()
+        if self.widget.collTable.item(row, 0).text() != '':
+            path = self.widget.collTable.item(row, 0).text()
+            item = self.widget.collTable.item(row, 1).text()
+            if item.endswith('/'):
+                item = item[:-1]
+            if self.ic.session.collections.exists(path+'/'+item):
+                coll = self.ic.session.collections.get(path+'/'+item)
+                self.loadTable(update = coll)
diff --git a/gui/mainmenu.py b/gui/mainmenu.py
index 67ee8ad7d5783401bf3501d67de3afe28d318016..40ee7d01e9be79db779a27d6f73ec0e64e653f2e 100644
--- a/gui/mainmenu.py
+++ b/gui/mainmenu.py
@@ -29,7 +29,7 @@ class mainmenu(QMainWindow):
         if ic == None and ienv == None:
             ticketAccessWidget = loadUi("gui/ui-files/tabTicketAccess.ui")
             self.tabWidget.addTab(ticketAccessWidget, "Ticket Access")
-            self.ticketAccessTab = irodsTicketLogin()
+            self.ticketAccessTab = irodsTicketLogin(ticketAccessWidget)
         else:
             self.ic = ic
             self.ienv = ienv
diff --git a/gui/ui-files/tabTicketAccess.ui b/gui/ui-files/tabTicketAccess.ui
index acd3bc5babf1fb9f1b08cb5ce7539b3cd001ee84..8e981bc6eebd4844b7ff20a4a1104e8415bd8be5 100644
--- a/gui/ui-files/tabTicketAccess.ui
+++ b/gui/ui-files/tabTicketAccess.ui
@@ -36,34 +36,80 @@ QLineEdit
 background-color: rgb(85, 87, 83);
 }
 
+QLabel#infoLabel
+{
+	color: rgb(217, 174, 23);
+}
+
 
 </string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <layout class="QFormLayout" name="formLayout">
-     <item row="0" column="0">
+     <item row="1" column="0">
       <widget class="QLabel" name="label">
        <property name="text">
         <string>Ticket:</string>
        </property>
       </widget>
      </item>
-     <item row="1" column="0">
+     <item row="2" column="0">
       <widget class="QLabel" name="label_2">
        <property name="text">
-        <string>Path</string>
+        <string>iRODS path: </string>
        </property>
       </widget>
      </item>
-     <item row="0" column="1">
+     <item row="1" column="1">
       <widget class="QLineEdit" name="ticketEdit"/>
      </item>
-     <item row="1" column="1">
+     <item row="2" column="1">
       <widget class="QLineEdit" name="pathEdit"/>
      </item>
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>iRODS server: </string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="serverEdit"/>
+     </item>
+     <item row="3" column="1">
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <spacer name="horizontalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="connectButton">
+         <property name="text">
+          <string>Connect</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
     </layout>
    </item>
+   <item>
+    <widget class="QLabel" name="infoLabel">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
    <item>
     <spacer name="verticalSpacer">
      <property name="orientation">
@@ -81,7 +127,10 @@ background-color: rgb(85, 87, 83);
     </spacer>
    </item>
    <item>
-    <widget class="QTableWidget" name="tableWidget">
+    <widget class="QTableWidget" name="collTable">
+     <property name="sizeAdjustPolicy">
+      <enum>QAbstractScrollArea::AdjustToContents</enum>
+     </property>
      <property name="editTriggers">
       <set>QAbstractItemView::NoEditTriggers</set>
      </property>
@@ -101,6 +150,11 @@ background-color: rgb(85, 87, 83);
        <string>Name</string>
       </property>
      </column>
+     <column>
+      <property name="text">
+       <string>Size</string>
+      </property>
+     </column>
      <column>
       <property name="text">
        <string>Checksum</string>
@@ -115,6 +169,17 @@ background-color: rgb(85, 87, 83);
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QPushButton" name="homeButton">
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset>
+         <normaloff>../icons/home.png</normaloff>../icons/home.png</iconset>
+       </property>
+      </widget>
+     </item>
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
@@ -129,7 +194,14 @@ background-color: rgb(85, 87, 83);
       </spacer>
      </item>
      <item>
-      <widget class="QPushButton" name="pushButton">
+      <widget class="QPushButton" name="downloadButton">
+       <property name="text">
+        <string>Download all</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="downloadSelectionButton">
        <property name="text">
         <string>Download selected</string>
        </property>
diff --git a/utils/irodsConnectorAnonymous.py b/utils/irodsConnectorAnonymous.py
new file mode 100644
index 0000000000000000000000000000000000000000..eea67d55c13feb34d366505cf39a2cb9e59e52a2
--- /dev/null
+++ b/utils/irodsConnectorAnonymous.py
@@ -0,0 +1,202 @@
+from irods.session import iRODSSession
+from irods.ticket import Ticket
+from irods.exception import CollectionDoesNotExist
+
+import os
+from base64 import b64decode
+from shutil import disk_usage
+import hashlib
+import logging
+
+RED = '\x1b[1;31m'
+DEFAULT = '\x1b[0m'
+YEL = '\x1b[1;33m'
+BLUE = '\x1b[1;34m'
+
+class irodsConnectorAnonymous():
+    def __init__(self, host, ticket, path):
+        """
+        iRODS anonymous login.
+        Input:
+            server: iRODS server
+            ticket: string
+            path: iRODS path the ticket grants access to
+
+        """
+        self.__name__="irodsConnectorAnonymous"
+        if path.endswith('/'):
+            path = path[:-1]
+        if not path.startswith("/"):
+            raise Exception("Not a valid iRODS path.")
+        zone = path.split('/')[1]
+        self.session = iRODSSession(user='anonymous',
+                                    password='',
+                                    zone=zone,
+                                    port=1247,
+                                    host=host)
+        self.token = ticket
+        self.path = path
+
+    def getData(self):
+        ticket = Ticket(self.session, self.token)
+        ticket.supply()
+        try:
+            item = self.session.collections.get(self.path)
+            return item
+        except:
+            raise
+
+    def getUserInfo(self):
+        pass
+
+    def getPermissions(self, iPath):
+        pass
+
+    def setPermissions(self, rights, user, path, zone, recursive = False):
+        pass
+
+    def ensureColl(self, collPath):
+        pass
+
+    def search(self, keyVals = None):
+        pass
+
+    def listResources(self):
+        pass
+
+    def getResource(self, resource):
+        '''
+        Raises:
+            irods.exception.ResourceDoesNotExist
+        '''
+        return self.session.resources.get(resource)
+
+    def resourceSize(self, resource):
+        """
+        Returns the available space left on a resource in bytes
+        resource: Name of the resource
+        Throws: ResourceDoesNotExist if resource not known
+                AttributeError if 'free_space' not set
+        """
+        try:
+            size = self.session.resources.get(resource).free_space
+            return size
+        except Exception as error:
+            logging.info('RESOURCE ERROR: Either resource does not exist or size not set.',
+                            exc_info=True)
+            raise error("RESOURCE ERROR: Either resource does not exist or size not set.")
+        
+
+    def uploadData(self, source, destination, resource, size, buff = 1024**3, 
+                         force = False, diffs = []):
+        pass 
+
+    def downloadData(self, source, destination, size, buff = 1024**3, force = False, diffs=[]):
+        '''
+        Download object or collection.
+        source: iRODS collection or data object
+        destination: absolute path to download folder
+        size: size of data to be downloaded in bytes
+        buff: buffer on resource that should be left over
+        force: If true, do not calculate storage capacity on destination
+        diffs: output of diff functions
+        '''
+        logging.info('iRODS DOWNLOAD: '+str(source)+'-->'+destination) 
+        options = {kw.FORCE_FLAG_KW: '', kw.REG_CHKSUM_KW: ''}
+
+        if destination.endswith(os.sep):
+            destination = destination[:len(destination)-1]
+        if not os.path.isdir(destination):
+            logging.info('DOWNLOAD ERROR: destination path does not exist or is not directory', 
+                    exc_info=True)
+            raise FileNotFoundError(
+                "ERROR iRODS download: destination path does not exist or is not directory")
+        if not os.access(destination, os.W_OK):
+            logging.info('DOWNLOAD ERROR: No rights to write to destination.', 
+                exc_info=True)
+            raise PermissionError("ERROR iRODS download: No rights to write to destination.")
+
+        if diffs == []:#Only download if not present or difference in files
+            if self.session.data_objects.exists(source.path):
+                (diff, onlyFS, onlyIrods, same) = self.diffObjFile(source.path,
+                                                    os.path.join(
+                                                    destination, os.path.basename(source.path)),
+                                                    scope="checksum")
+            elif self.session.collections.exists(source.path):
+                subdir = os.path.join(destination, source.name)
+                if not os.path.isdir(os.path.join(destination, source.name)):
+                    os.mkdir(os.path.join(destination, source.name))
+
+                (diff, onlyFS, onlyIrods, same) = self.diffIrodsLocalfs(
+                                                    source, subdir, scope="checksum")
+            else:
+                raise FileNotFoundError("ERROR iRODS upload: not a valid source path")
+        else:
+            (diff, onlyFS, onlyIrods, same) = diffs
+
+        if not force:#Check space on destination
+            try:
+                space = disk_usage(destination).free
+                if int(size) > (int(space)-buff):
+                    logging.info('DOWNLOAD ERROR: Not enough space on disk.', 
+                            exc_info=True)
+                    raise ValueError('ERROR iRODS download: Not enough space on disk.')
+                if buff < 0:
+                    logging.info('DOWNLOAD ERROR: Negative disk buffer.', exc_info=True)
+                    raise BufferError('ERROR iRODS download: Negative disk buffer.')
+            except Exception as error:
+                logging.info('DOWNLOAD ERROR', exc_info=True)
+                raise error()
+
+        if self.session.data_objects.exists(source.path) and len(diff+onlyIrods) > 0:
+            try:
+                logging.info("IRODS DOWNLOADING object:"+ source.path+
+                                "to "+ destination)
+                self.session.data_objects.get(source.path, 
+                            local_path=os.path.join(destination, source.name), **options)
+                return
+            except:
+                logging.info('DOWNLOAD ERROR: '+source.path+"-->"+destination, 
+                        exc_info=True)
+                raise
+
+        try: #collections/folders
+            subdir = os.path.join(destination, source.name)
+            logging.info("IRODS DOWNLOAD started:")
+            for d in diff:
+                #upload files to distinct data objects
+                logging.info("REPLACE: "+d[1]+" with "+d[0])
+                self.session.data_objects.get(d[0], local_path=d[1], **options)
+
+            for IO in onlyIrods: #can contain files and folders
+                #Create subcollections and upload
+                sourcePath = source.path + "/" + IO
+                locO = IO.replace("/", os.sep)
+                destPath = os.path.join(subdir, locO)
+                if not os.path.isdir(os.path.dirname(destPath)):
+                    os.makedirs(os.path.dirname(destPath))
+                logging.info('INFO: Downloading '+sourcePath+" to "+destPath)
+                self.session.data_objects.get(sourcePath, local_path=destPath, **options)
+        except:
+            logging.info('DOWNLOAD ERROR', exc_info=True)
+            raise
+
+
+    def addMetadata(self, items, key, value, units = None):
+        pass
+            
+    def updateMetadata(self, items, key, value, units = None):
+        pass
+
+    def deleteMetadata(self, items, key, value, units):
+        pass
+
+    def deleteData(self, item):
+        pass
+
+    def executeRule(self, ruleFile, params, output='ruleExecOut'):
+        pass
+
+
+    def createTicket(self, path, expiryString=""):
+        pass