Advertisement
Guest User

owncloud-client-nemo

a guest
Dec 2nd, 2014
645
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.89 KB | None | 0 0
  1. #!/usr/bin/python3
  2. #
  3. # Copyright (C) by Klaas Freitag <[email protected]>
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. # for more details.
  14.  
  15. import os
  16. import urllib
  17. import socket
  18.  
  19. from gi.repository import GObject, Nemo
  20.  
  21.  
  22. def get_runtime_dir():
  23.     """Returns the value of $XDG_RUNTIME_DIR, a directory path.
  24.  
  25.    If the value is not set, returns the same default as in Qt5
  26.    """
  27.     try:
  28.         return os.environ['XDG_RUNTIME_DIR']
  29.     except KeyError:
  30.         fallback = '/tmp/runtime-' + os.environ['USER']
  31.         return fallback
  32.  
  33.  
  34. class syncStateExtension(GObject.GObject, Nemo.ColumnProvider, Nemo.InfoProvider):
  35.  
  36.     nemoVFSFile_table = {}
  37.     registered_paths = {}
  38.     remainder = ''
  39.     connected = False
  40.     watch_id = 0
  41.     appname = 'ownCloud'
  42.  
  43.     def __init__(self):
  44.         self.connectToSocketServer
  45.         if not self.connected:
  46.             # try again in 5 seconds - attention, logic inverted!
  47.             GObject.timeout_add(5000, self.connectToSocketServer)
  48.  
  49.     def connectToSocketServer(self):
  50.         do_reconnect = True
  51.         try:
  52.             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  53.             postfix = "/"+self.appname+"/socket"
  54.             sock_file = get_runtime_dir()+postfix
  55.             print ("XXXX " + sock_file + " <=> " + postfix)
  56.             if sock_file != postfix:
  57.                 try:
  58.                     print("Socket File: "+sock_file)
  59.                     self.sock.connect(sock_file)
  60.                     self.connected = True
  61.                     print("Setting connected to %r" % self.connected )
  62.                     self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
  63.                     do_reconnect = False
  64.                 except Exception as e:
  65.                     print("Could not connect to unix socket." + str(e))
  66.             else:
  67.                 print("Sock-File not valid: "+sock_file)
  68.         except Exception as e:
  69.             print("Connect could not be established, try again later " + str(e))
  70.             self.sock.close()
  71.         # print("Returning %r" % do_reconnect)
  72.         return do_reconnect
  73.  
  74.     def sendCommand(self, cmd):
  75.         if self.connected:
  76.             try:
  77.                 self.sock.send(cmd)
  78.             except:
  79.                 print("Sending failed.")
  80.                 GObject.source_remove(self.watch_id)
  81.                 self.connected = False
  82.                 GObject.timeout_add(5000, self.connectToSocketServer)
  83.  
  84.     def find_item_for_file(self, path):
  85.         if path in self.nemoVFSFile_table:
  86.             return self.nemoVFSFile_table[path]
  87.         else:
  88.             return None
  89.  
  90.     def askForOverlay(self, file):
  91.         # print("Asking for overlay for "+file)
  92.         if os.path.isdir(file):
  93.             folderStatus = self.sendCommand("RETRIEVE_FOLDER_STATUS:"+file+"\n");
  94.  
  95.         if os.path.isfile(file):
  96.             fileStatus = self.sendCommand("RETRIEVE_FILE_STATUS:"+file+"\n");
  97.  
  98.     def invalidate_items_underneath(self, path):
  99.         update_items = []
  100.         if not self.nemoVFSFile_table:
  101.             self.askForOverlay(path)
  102.         else:
  103.             for p in self.nemoVFSFile_table:
  104.                 if p == path or p.startswith(path):
  105.                     item = self.nemoVFSFile_table[p]['item']
  106.                     update_items.append(item)
  107.  
  108.             for item in update_items:
  109.                 item.invalidate_extension_info()
  110.  
  111.     # Handles a single line of server respoonse and sets the emblem
  112.     def handle_server_response(self, l):
  113.         Emblems = { 'OK'        : self.appname +'_ok',
  114.                     'SYNC'      : self.appname +'_sync',
  115.                     'NEW'       : self.appname +'_sync',
  116.                     'IGNORE'    : self.appname +'_warn',
  117.                     'ERROR'     : self.appname +'_error',
  118.                     'OK+SWM'    : self.appname +'_ok_shared',
  119.                     'SYNC+SWM'  : self.appname +'_sync_shared',
  120.                     'NEW+SWM'   : self.appname +'_sync_shared',
  121.                     'IGNORE+SWM': self.appname +'_warn_shared',
  122.                     'ERROR+SWM' : self.appname +'_error_shared',
  123.                     'NOP'       : self.appname +'_error'
  124.                   }
  125.  
  126.         print("Server response: "+l)
  127.         parts = l.split(':')
  128.         if len(parts) > 0:
  129.             action = parts[0]
  130.  
  131.             # file = parts[1]
  132.             # print "Action for " + file + ": "+parts[0]
  133.             if action == 'STATUS':
  134.                 newState = parts[1]
  135.                 emblem = Emblems[newState]
  136.                 if emblem:
  137.                     itemStore = self.find_item_for_file(parts[2])
  138.                     if itemStore:
  139.                         if( not itemStore['state'] or newState != itemStore['state'] ):
  140.                             item = itemStore['item']
  141.                             item.add_emblem(emblem)
  142.                             # print "Setting emblem on " + parts[2]+ "<>"+emblem+"<>"
  143.                             self.nemoVFSFile_table[parts[2]] = {'item': item, 'state':newState}
  144.  
  145.             elif action == 'UPDATE_VIEW':
  146.                 # Search all items underneath this path and invalidate them
  147.                 if parts[1] in self.registered_paths:
  148.                     self.invalidate_items_underneath(parts[1])
  149.  
  150.             elif action == 'REGISTER_PATH':
  151.                 self.registered_paths[parts[1]] = 1
  152.                 self.invalidate_items_underneath(parts[1])
  153.             elif action == 'UNREGISTER_PATH':
  154.                 del self.registered_paths[parts[1]]
  155.                 self.invalidate_items_underneath(parts[1])
  156.  
  157.                 # check if there are non pathes any more, if so, its usual
  158.                 # that mirall went away. Try reconnect.
  159.                 if not self.registered_paths:
  160.                     self.sock.close()
  161.                     self.connected = False
  162.                     GObject.source_remove(self.watch_id)
  163.                     GObject.timeout_add(5000, self.connectToSocketServer)
  164.  
  165.             else:
  166.                 # print "We got unknown action " + action
  167.                 1
  168.  
  169.     # notify is the raw answer from the socket
  170.     def handle_notify(self, source, condition):
  171.  
  172.         data = source.recv(1024)
  173.         # prepend the remaining data from last call
  174.         if len(self.remainder) > 0:
  175.             data = self.remainder+data
  176.             self.remainder = ''
  177.  
  178.         if len(data) > 0:
  179.             # remember the remainder for next round
  180.             lastNL = data.rfind('\n');
  181.             if lastNL > -1 and lastNL < len(data):
  182.                 self.remainder = data[lastNL+1:]
  183.                 data = data[:lastNL]
  184.  
  185.             for l in data.split('\n'):
  186.                 self.handle_server_response(l)
  187.         else:
  188.             return False
  189.  
  190.         return True # run again
  191.  
  192.     def get_local_path(self, path):
  193.         return path.replace("file://", "")
  194.  
  195.     def update_file_info(self, item):
  196.         if item.get_uri_scheme() != 'file':
  197.             return
  198.  
  199.         filename = urllib.unquote(item.get_uri()[7:])
  200.         if item.is_directory():
  201.             filename += '/'
  202.  
  203.         for reg_path in self.registered_paths:
  204.             if filename.startswith(reg_path):
  205.                 self.nemoVFSFile_table[filename] = {'item': item, 'state':''}
  206.  
  207.                 # item.add_string_attribute('share_state', "share state")
  208.                 self.askForOverlay(filename)
  209.                 break
  210.             else:
  211.                 # print("Not in scope:"+filename)
  212.                 pass
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement