webservice.py :  » Network » Torrent-Swapper » swapper » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Torrent Swapper 
Torrent Swapper » swapper » webservice.py
import wx
import sys

from threading import Thread
from string import upper

from traceback import print_exc
from cStringIO import StringIO

from Utility.helpers import getSocket
from Utility.constants import *#IGNORE:W0611


################################################################
#
# Class: WebDialog
#
# Let the user specify settings for the webservice
#
################################################################
class WebDialog(wx.Dialog):
    def __init__(self, parent):
        self.utility = parent.utility
        
        title = self.utility.lang.get('webinterfaceservice')

        pre = wx.PreDialog()
        pre.Create(parent, -1, title)
        self.this = pre.this
        self.parent = parent
        self.window = self.utility.window
        
        self.utility.webserver.webdlg = self
        
        WebRead = self.utility.webconfig.Read
        
        self.warnlowport = [False, WebRead('webport')]

#        # Change old config value
#        oldval = WebRead('webIP')
#        if (oldval == "Automatics") or (oldval == "Automatic"):
#            self.utility.webconfig.Write('webIP', "")
#            self.utility.webconfig.Flush()
#            ip_choice = ""
#        elif (oldval == "Loop Back"):
#            self.utility.webconfig.Write('webIP', "127.0.0.1")
#            self.utility.webconfig.Flush()
#            
#        newval = WebRead('webIP')
        newval = self.utility.webserver.getIP()
        if newval == "":
            default_ip = self.utility.lang.get('automatic')
        elif newval == "127.0.0.1":
            default_ip = self.utility.lang.get('loopback')
        else:
            default_ip = newval
        
        outerbox = wx.BoxSizer(wx.VERTICAL)
        
        outerbox.Add(wx.StaticText(self, -1, self.utility.lang.get('webinterfacetitle')), 0, wx.ALIGN_CENTER|wx.ALL, 10)

        ip_choices = [self.utility.lang.get('automatic'), self.utility.lang.get('loopback')]

        ipandport_box = wx.BoxSizer(wx.HORIZONTAL)
        ipandport_box.Add(wx.StaticText(self, -1, self.utility.lang.get('webip')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        self.iptext = wx.ComboBox(self, -1, default_ip, wx.Point(-1, -1), wx.Size(120, -1), ip_choices, wx.CB_DROPDOWN|wx.CB_READONLY)
        ipandport_box.Add(self.iptext, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
       
        ipandport_box.Add(wx.StaticText(self, -1, self.utility.lang.get('webport')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        self.porttext = self.utility.makeNumCtrl(self, WebRead('webport'), max = 65536)
        ipandport_box.Add(self.porttext, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        outerbox.Add(ipandport_box, 0, wx.EXPAND|wx.ALL, 5)

        uniquekey_box = wx.BoxSizer(wx.HORIZONTAL)
        
        uniquekey_box.Add(wx.StaticText(self, -1, self.utility.lang.get('uniquekey')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        self.keytext = wx.TextCtrl(self, -1, WebRead('webID'), wx.Point(-1, -1), wx.Size(165, -1))
        uniquekey_box.Add(self.keytext, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        
        outerbox.Add(uniquekey_box, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)

        self.permissions = [ ['webquery', 'allow_query'], 
                             ['webadd', 'allow_add'], 
                             ['webdelete', 'allow_delete'], 
                             ['webqueue', 'allow_queue'], 
                             ['webstop', 'allow_stop'], 
                             ['webresume', 'allow_resume'], 
                             ['webpause', 'allow_pause'], 
                             ['webclearallcompleted', 'allow_clearcompleted'], 
                             ['priority', 'allow_setprio'], 
                             ['webgetparam', 'allow_getparam'], 
                             ['websetparam', 'allow_setparam' ] ]

        self.perm_checkbox = wx.CheckListBox(self, -1, size = wx.Size(100, 120), style = wx.LB_SINGLE)
        perm_text = [self.utility.lang.get(item[0]) for item in self.permissions]
        self.perm_checkbox.Set(perm_text)
         
        for i in range(0, len(self.permissions)):
            param = self.permissions[i][1]
            checked = WebRead(param, "boolean")
            if checked:
                self.perm_checkbox.Check(i)
        
        outerbox.Add(wx.StaticText(self, -1, self.utility.lang.get('commandpermission')), 0, wx.ALL, 5)
        outerbox.Add(self.perm_checkbox, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
  
        self.webautostart = wx.CheckBox(self, -1, self.utility.lang.get('webautostart'))
        
        outerbox.Add(self.webautostart, 0, wx.EXPAND|wx.ALL, 5)

        #CheckBox Set Value from Config
        #####################################
        self.webautostart.SetValue(WebRead('webautostart', "boolean"))

        self.actionbtn = wx.Button(self, -1, "")

        self.utility.webserver.updateLabels()

        applybtn  = wx.Button(self, wx.NewId(), self.utility.lang.get('apply'))
        self.Bind(wx.EVT_BUTTON, self.onApply, applybtn)

        okbtn  = wx.Button(self, wx.NewId(), self.utility.lang.get('ok'))
        self.Bind(wx.EVT_BUTTON, self.onOK, okbtn)

        cancelbtn = wx.Button(self, wx.ID_CANCEL, self.utility.lang.get('cancel'))
        self.Bind(wx.EVT_BUTTON, self.onClose, cancelbtn)
        
        self.Bind(wx.EVT_CLOSE, self.onClose)

        self.Bind(wx.EVT_BUTTON, self.OnAction, self.actionbtn)

        button_box = wx.BoxSizer(wx.HORIZONTAL)
        button_box.Add(applybtn, 0, wx.ALL, 5)
        button_box.Add(okbtn, 0, wx.ALL, 5)
        button_box.Add(cancelbtn, 0, wx.ALL, 5)

        outerbox.Add(self.actionbtn, 0, wx.ALIGN_CENTER|wx.ALL, 5)

        outerbox.Add(button_box, 0, wx.ALIGN_CENTER)

        self.SetAutoLayout(True)
        self.SetSizer(outerbox)
        self.Fit()

    def onOK(self, event = None):
        self.utility.webserver.webdlg = None
        if self.onApply():
            self.EndModal(wx.ID_OK)
            
    def onClose(self, event = None):
        self.utility.webserver.webdlg = None
        if event is not None:
            event.Skip()
        
    def onApply(self, event = None):
        self.saveParams()
        return True
        
    def saveParams(self):
        PORT = int(self.porttext.GetValue())

        if ((not self.warnlowport[0]
             or self.warnlowport[1] != str(PORT))
            and PORT < 1024):
            dlg = wx.MessageDialog(None, self.utility.lang.get('warningportunder1024') + "\n(" + str(PORT) + ")", self.utility.lang.get('warning'), wx.YES_NO|wx.ICON_INFORMATION)
            if dlg.ShowModal() == wx.ID_NO:
                dlg.Destroy()
                return False
            else:
                self.warnlowport[0] = True
            self.warnlowport[1] = str(PORT)
            dlg.Destroy()

        # Re-assign web parameters
        self.utility.webconfig.Write('webIP', self.iptext.GetStringSelection())
        self.utility.webconfig.Write('webport', str(self.porttext.GetValue()))
        self.utility.webconfig.Write('webID', self.keytext.GetValue())

        for i in range(0, self.perm_checkbox.GetCount()):
            param = self.permissions[i][1]
            checked = self.perm_checkbox.IsChecked(i)
            self.utility.webconfig.Write(param, checked, "boolean")
       
        if self.webautostart.GetValue():
            self.utility.webconfig.Write('webautostart', "1")
        else:
            self.utility.webconfig.Write('webautostart', "0")

        #######################################
        # Record New Config to webservice.conf
        #######################################
        self.utility.webconfig.Flush()
        
        return True
        
    def OnAction(self, event = None):
        if not self.utility.webserver.active:
            if self.saveParams():
                self.startWebService()
        else:
            self.stopWebService()

    def startWebService(self):
        ######################################
        # Start Web Interface Service
        ######################################
        self.utility.webserver.start()

    def stopWebService(self):
        # Stop Web Service
        self.utility.webserver.stop()
        
    def updateLabels(self):
        active = self.utility.webserver.active
        
        if active:
            label = self.utility.lang.get('stopservice')
        else:
            label = self.utility.lang.get('startservice')
        self.actionbtn.SetLabel(label)
        self.porttext.Enable(not active)
        self.keytext.Enable(not active)
        self.iptext.Enable(not active)


################################################################
#
# Class: WebListener
#
# Listens for webservice commands 
#
################################################################
class WebListener:
    def __init__(self, utility, webdlg = None):
        self.s = None
        self.utility = utility
        
        self.utility.webserver = self
        
        self.webdlg = webdlg
        
        self.active = False
        
        self.port = None
        self.ip = None
        
        self.client = WebClient(self.utility)

    def getIP(self):
        # Change old config value
        oldval = self.utility.webconfig.Read('webIP')
        if (oldval == "Automatics") or (oldval == "Automatic"):
            self.utility.webconfig.Write('webIP', "")
            self.utility.webconfig.Flush()
        elif (oldval == "Loop Back"):
            self.utility.webconfig.Write('webIP', "127.0.0.1")
            self.utility.webconfig.Flush()
#        if self.utility.webconfig.Read('webIP') == "Automatic":
#            IP = ""
#        else: #LoopBack
#            IP = "127.0.0.1"
#        return IP
        return self.utility.webconfig.Read('webIP')
    
    def getPort(self):
        try:
            PORT = self.utility.webconfig.Read('webport', "int")
        except:
            PORT = 56667
        return PORT
        
    def start(self):
        # Already running
        if self.active:
            return
        
        self.ip = self.getIP()   # Symbolic name meaning the local host
        self.port = self.getPort() # Arbitrary non-privileged port
        
        self.active = True
        self.updateLabels()
        
        webservice = Thread(target = self.startThread)
        webservice.setDaemon(False)
        webservice.start()
        
    def stop(self):
        # Not running, no need to stop
        if not self.active:
            return
        
        self.client.sendCmd("CLOSE|")
        
        self.port = None
        self.ip = None
        
        self.active = False
        self.updateLabels()
        
    def updateLabels(self):       
        self.utility.actions[ACTION_WEBSERVICE].updateButton()

        if self.webdlg is not None:
            self.webdlg.updateLabels()
        
    def startThread(self):
        self.s = getSocket(self.ip, self.port, "server")

        if self.s is None:
            #Display Dialog Can't open scoket
            dlg = wx.MessageDialog(None, self.utility.lang.get('cantopensocket') , self.utility.lang.get('socketerror'), wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

            self.active = False
            self.updateLabels()
            return
        WebServiceCmd(self).go()


################################################################
#
# Class: WebClient
#
# Used to sent brief commands to the webservice
# (i.e.: use to send the shutdown command)
#
################################################################
class WebClient:
    def __init__(self, utility):
        self.utility = utility
        self.webserver = self.utility.webserver

    def sendCmd(self, command):
        # Web service isn't even active -- don't bother sending a message
        if not self.webserver.active:
            return False
                
        HOST = self.webserver.ip          # The remote host
        PORT = self.webserver.port        # The same port as used by the server
        s = getSocket(HOST, PORT)
        if s is None:
            dlg = wx.MessageDialog(None, self.utility.lang.get('cantconnectabcwebinterface') , self.utility.lang.get('socketerror'), wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return False
            
        # if request is not close connection request
        # so it's torrent request copy .torrent
        # in backup torrent folder
        ##############################################
        mesg = "ID|" + self.utility.webconfig.Read('webID') + "\n" + command
        
        s.send(mesg)
        s.close()
        return True


################################################################
#
# Class: WebServiceCmd
#
# Processes the actual webservice commands
#
################################################################
class WebServiceCmd:
    def __init__(self, parent):
        self.parent = parent
        self.utility = self.parent.utility
        self.frame  = self.utility.frame
        
    def separate(self, info, splitchar = ","):
        try:
            separated = info.split(splitchar)
        except:
            self.conn.send("Feedback\nError=Bad Arguments")
            self.conn.close()
            separated = None
        return separated
        
    def getMappings(self, separated, splitchar = "="):
        mappings = {}
        
        for item in separated:
            try:
                pair = item.split(splitchar)
                mappings[pair[0]] = pair[1]
            except:
                self.conn.send("Feedback\nError=Bad Arguments")
                self.conn.close()
                mappings = None
                break
                
        return mappings

    def getTorrents(self, info = "", infohash_list = None):
        torrents = None
        
        if infohash_list is None:
            infohash_list = self.separate(info)
            if infohash_list is None:
                return torrents
        
        torrents = []
            
        for infohash in infohash_list:
            torrent = self.utility.queue.getABCTorrent(info_hash = infohash)
            
            if torrent is None:
                self.conn.send("Feedback\nError=No torrents match with this info hash: " + infohash + "\n")
                torrents = None
                break
            else:
                torrents.append(torrent)
                
        return torrents            

    def cmdSetParam(self, info):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_setparam', "boolean"):
            conn.send("Feedback\nError=SETPARAM,Permission denied")
            return

        separated = self.separate(info, "|")
        if separated is None:
            return
            
        mappings = self.getMappings(separated)
        if mappings is None:
            return
            
        for param in mappings:
            self.utility.config.Write(param, mappings[param])
        self.utility.config.Flush()
        conn.send("Feedback\nOK")

    def cmdGetParam(self, info):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_getparam', "boolean"):
            conn.send("Feedback\nError=GETPARAM,Permission denied")
            return

        separated = self.separate(info)
        if separated is None:
            return

        retmsg = ""
        Read = self.utility.config.Read
        for param in separated:
            value = Read(param)
            retmsg += value + "|"
        retmsg += "\n"
        conn.send("Feedback\n" + str(retmsg))
        
    def cmdClose(self):
        conn = self.conn
        
        self.utility.webserver.active = False
        self.utility.webserver.updateLabels()
        
        conn.close()
        self.parent.s.close()
        
#        sys.stderr.write("\nDone shutting down webservice")
               
    def cmdQuery(self, info = ""):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_query', "boolean"):
            conn.send("Feedback\nError=QUERY,Permission denied")
            conn.close()
            return

        if info == "":
            self.QueryFields()
        else:
            fields = self.separate(info, ",")
            if fields is None:
                return

            self.QueryFields(fields)

    def QueryFields(self, fieldlist = None):
        conn = self.conn
        
        maxid = self.utility.list.columns.maxid

        # Default to returning all fields
        if fieldlist is None:
            fieldlist = range(4, maxid)
            
        oldfields    = { "filename"        : COL_TITLE, 
                         "progress"        : COL_PROGRESS, 
                         "btstatus"        : COL_BTSTATUS, 
                         "eta"             : COL_ETA, 
                         "dlspeed"         : COL_DLSPEED, 
                         "ulspeed"         : COL_ULSPEED, 
                         "ratio"           : COL_RATIO, 
                         "peers"           : COL_PEERS, 
                         "seeds"           : COL_SEEDS, 
                         "copies"          : COL_COPIES, 
                         "dlsize"          : COL_DLSIZE, 
                         "ulsize"          : COL_ULSIZE, 
                         "peeravgprogress" : COL_PEERPROGRESS, 
                         "totalspeed"      : COL_TOTALSPEED, 
                         "totalsize"       : COL_SIZE, 
                         "priority"        : COL_PRIO }
        
        fieldids = []
        
        retmsg = ""
        for req_field in fieldlist:
            try:
                # A field number was specified
                fieldid = int(req_field)
                if fieldid >= 4 and fieldid < maxid:
                    fieldids.append(fieldid)
                else:
                    conn.send("Feedback\nError=Invalid field ID (must be between 4 and " + str(maxid) + ") = " + req_field)
                    conn.close()
                    return                    
            except:
                # Old format -- a field name was specified
                if req_field in oldfields:
                    fieldid = oldfields[req_field]
                    fieldids.append(fieldid)
                else:
                    # Can't identify the field
                    conn.send("Feedback\nError=Unknown field name = " + req_field)
                    conn.close()
                    return

            retmsg += self.utility.lang.get("column" + str(fieldid) + "_text") + "|"

        retmsg += "Info Hash\n"

        for ABCTorrentTemp in self.utility.torrents["all"]:
            retmsg += ABCTorrentTemp.getInfo(fieldlist = fieldids)
        
        conn.send(retmsg)
        conn.close()
                
    def cmdAdd(self, info):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_add', "boolean"):
            conn.send("Feedback\nError=ADD,Permission denied")
            return

        # What do we do if we don't have a default download location specified
        # and we call this from the webservice?
        ####################################################
        retmsg = self.utility.queue.addtorrents.AddTorrentURL(info, "web")
        conn.send("Feedback\n"+retmsg)
            
    def cmdDelete(self, info):
        conn = self.conn
        
        if upper(info) == "COMPLETED":
            if not self.utility.webconfig.Read('allow_clearcompleted', "boolean"):
                conn.send("Feedback\nError=CLEARCOMPLETED,Permission denied")
                return
                
            self.utility.actions[ACTION_CLEARCOMPLETED].action()
            conn.send("Feedback\nOK")
        else:
            if not self.utility.webconfig.Read('allow_delete', "boolean") != "1":
                conn.send("Feedback\nError=DELETE,Permission denied")
                return
            
            torrents = self.getTorrents(info)
            if torrents is None:
                return

            self.utility.actionhandler.procREMOVE(torrents)
            conn.send("Feedback\nOK")
                
    def cmdResume(self, info = "ALL"):
        conn = self.conn

        if not self.utility.webconfig.Read('allow_resume', "boolean"):
            conn.send("Feedback\nError=RESUME,Permission denied")
            return
        
        if upper(info) == "ALL":
            self.utility.actions[ACTION_UNSTOPALL].action()
            conn.send("Feedback\nOK")   
        else:
            torrents = self.getTorrents(info)
            if torrents is None:
                return

            self.utility.actionhandler.procRESUME(torrents)
            conn.send("Feedback\nOK")
                               
    def cmdStop(self, info = "ALL"):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_stop', "boolean"):
            conn.send("Feedback\nError=STOP,Permission denied")
            return
        
        if upper(info) == "ALL":
            self.utility.actions[ACTION_STOPALL].action()
            conn.send("Feedback\nOK")
        else:
            torrents = self.getTorrents(info)
            if torrents is None:
                return

            self.utility.actionhandler.procSTOP(torrents)
            conn.send("Feedback\nOK")

    def cmdPause(self, info, release = False):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_pause', "boolean"):
            conn.send("Feedback\nError=PAUSE,Permission denied")
            conn.close()
            return
            
        if upper(info) == "ALL":
            torrents = self.utility.torrents["active"].keys()
        else:
            torrents = self.getTorrents(info)
            if torrents is None:
                return
                       
        self.utility.actionhandler.procPAUSE(torrents, release = release)
        conn.send("Feedback\nOK")
                        
    def cmdQueue(self, info = "ALL"):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_queue', "boolean"):
            conn.send("Feedback\nError=QUEUE,Permission denied")
            return

        if upper(info) == "ALL":
            torrents = self.utility.torrents["all"]
        else:
            torrents = self.getTorrents(info)
            if torrents is None:
                return

        self.utility.actionhandler.procQUEUE(torrents)
        conn.send("Feedback\nOK")
        
    def cmdPriority(self, info):
        conn = self.conn
        
        if not self.utility.webconfig.Read('allow_setprio', "boolean"):
            conn.send("Feedback\nError=PRIORITY,Permission denied")
            return
            
        separated = self.separate(info, "|")
        if separated is None:
            return
            
        mappings = self.getMappings(separated, ",")
        if mappings is None:
            return
        
        for infohash in mappings:
            value = mappings[infohash]
            error = False
            try:
                prio = int(value)
                if (prio < 0) or (prio > 4):
                    error = True
            except:
                error = True
            if error:
                conn.send("Feedback\nError=Priority must be a number from 0-4")
                conn.close()
                return

        hashlist = [infohash for infohash in mappings]
        torrents = self.getTorrents(infohash_list = hashlist)
        if torrents is None:
            return
            
        for torrent in torrents:
            torrent.changePriority(prio)
            
        conn.send("Feedback\nOK")
        
    def go(self):
        while 1:
            conn, addr = self.parent.s.accept()
            self.conn = conn
            try:
                try:
                    data = conn.recv(5048)
                except:
                    try:
                        conn.close()
                    except:
                        pass
                    continue
                
                try:
                    idline, cmdline = data.split("\n")
                except:
                    conn.send("Feedback\nError=You need unique ID to command ABC!")
                    conn.close()
                    continue
    
                try:
                    idtag   = idline.split("|")
                    idkey   = idtag[0]
                    idvalue = idtag[1]
                except:
                    conn.send("Feedback\nError=You need unique ID to command ABC!")
                    conn.close()
                    continue

                if idkey != "ID":
                    conn.send("Feedback\nError=You need unique ID to command ABC!")
                    conn.close()
                    continue
                else:
                    if idvalue != self.utility.webconfig.Read('webID'):
                        conn.send("Feedback\nError=Incorrect unique ID")
                        conn.close()
                        continue
                
                try:                
                    cmd, info = cmdline.split("|")
                except:
                    #Bad Command
                    conn.send("Feedback\nError=Command should end with |")
                    conn.close()
                    continue
                
                sys.stdout.write('Web Request Recieved.\n' + data + '\n')
                
                # Convert the command to upper case
                cmd = upper(cmd)
                
                if cmd == "CLOSE" or self.utility.abcquitting:
                    self.cmdClose()
                    return
                
#                elif cmd == "KEEPALIVE":
#                    # Don't actually do anything
#                    pass
                
                elif cmd == "QUERY":
                    self.cmdQuery(info)
                                       
                elif cmd == "ADD":
                    self.cmdAdd(info)
                        
                elif cmd == "DELETE":
                    self.cmdDelete(info)
            
                elif cmd == "RESUME":
                    self.cmdResume(info)
    
                elif cmd == "PAUSE":
                    self.cmdPause(info)

                elif cmd == "UNPAUSE":
                    self.cmdPause(info, release = True)
    
                elif cmd == "STOP":
                    self.cmdStop(info)
    
                elif cmd == "QUEUE":
                    self.cmdQueue(info)
                    
                elif cmd == "PRIORITY":
                    self.cmdPriority(info)

                elif cmd == "SETPARAM":
                    self.cmdSetParam(info)
                    
                elif cmd == "GETPARAM":
                    self.cmdGetParam(info)
                    
                elif cmd == "GETSTRING":
                    conn.send("String\n" + self.utility.lang.get(info))

                elif cmd == "VERSION":
                    conn.send("Version\n" + self.utility.lang.get('version'))

                else: # Bad Command
                    conn.send("Feedback\nError=Command not found: " + cmd)
                    pass
            except:
                pass
            conn.close()
                
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.