示例#1
0
    def set_headers(self, stream):
        """Given an HTTP stream, parse and store the message headers.

        The HTTP stream must be positioned at the second line of a request.

        The message headers are read and a new Message instance is added to
        self. This instance will be updated in set_body once the body has been
        read. We have to do this in two stages because the length of the body is
        communicated to us via the headers.

        """

        # Read in everything until the next blank line, parsing as we go.
        # ===============================================================

        raw_headers = []
        parser_ = FeedParser()
        for line in stream:
            raw_headers.append(line)
            parser_.feed(line)
            if line == '\r\n':
                break

        # Now store on self.
        # ==================

        self.raw.extend(raw_headers)
        self.raw_headers = ''.join(raw_headers)
        self.message = parser_.close()
示例#2
0
 def lineReceived(self, line):
     log.debug("Line In: %s"%line)
     self.parser = FeedParser(Event)        
     self.parser.feed(line)
     self.message = self.parser.close()
     #if self.state is not READ_CONTENT (i.e Content-Type is already read) and the Content-Length is present
     #read rest of the message and set it as payload
     if self.message.has_key('Content-Length') and self.state!= 'READ_CONTENT':
         if self.enterRawMode():
             log.debug("Entering raw mode to read message payload")
             return 
     try:
         self.inspectMessage()   
     except:
         log.error("Exception in message processing ", exc_info=True)
示例#3
0
	def parse_headers(self):
		parser = FeedParser()
		while True:
			line = self.f.readline()
			self.hbuf.write(line)
			parser.feed(line)
			if not line.strip(): break
		self.m = parser.close()

		L = self.parse_addrs('from')
		self.h_from = L and L[0] or None
		self.h_to = self.parse_addrs('to')
		self.h_cc = self.parse_addrs('cc')
		self.h_rcpts = self.h_to + self.h_cc
		self.h_subject = decode_header(self.m.get('subject'))
		self.h_subject_len1 = len(self.h_subject)
		self.h_subject = self.h_subject.replace(' ', '')
		self.h_subject = self.h_subject.replace(u' ', '')
		self.h_subject_len2 = len(self.h_subject)
示例#4
0
    def parse_headers(self):
        parser = FeedParser()
        while True:
            line = self.f.readline()
            self.hbuf.write(line)
            parser.feed(line)
            if not line.strip(): break
        self.m = parser.close()

        L = self.parse_addrs('from')
        self.h_from = L and L[0] or None
        self.h_to = self.parse_addrs('to')
        self.h_cc = self.parse_addrs('cc')
        self.h_rcpts = self.h_to + self.h_cc
        self.h_subject = decode_header(self.m.get('subject'))
        self.h_subject_len1 = len(self.h_subject)
        self.h_subject = self.h_subject.replace(' ', '')
        self.h_subject = self.h_subject.replace(u' ', '')
        self.h_subject_len2 = len(self.h_subject)
示例#5
0
    def parse(self, fp, headersonly=False):
        feedparser = FeedParser(self._class)
        if headersonly:
            feedparser._set_headersonly()
        while True:
            data = fp.read(8192)
            if not data:
                break
            feedparser.feed(data)

        return feedparser.close()
示例#6
0
    def parse(self, fp, headersonly = False):
        feedparser = FeedParser(self._class)
        if headersonly:
            feedparser._set_headersonly()
        while True:
            data = fp.read(8192)
            if not data:
                break
            feedparser.feed(data)

        return feedparser.close()
示例#7
0
    def parse(self, fp, headersonly=False):
        """Create a message structure from the data in a file.

        Reads all the data from the file and returns the root of the message
        structure.  Optional headersonly is a flag specifying whether to stop
        parsing after reading the headers or not.  The default is False,
        meaning it parses the entire contents of the file.
        """
        feedparser = FeedParser(self._class)
        if headersonly:
            feedparser._set_headersonly()
        while True:
            data = fp.read(8192)
            if not data:
                break
            feedparser.feed(data)
        return feedparser.close()
示例#8
0
    def parse(self, fp, headersonly=False):
        """Create a message structure from the data in a file.

        Reads all the data from the file and returns the root of the message
        structure.  Optional headersonly is a flag specifying whether to stop
        parsing after reading the headers or not.  The default is False,
        meaning it parses the entire contents of the file.
        """
        feedparser = FeedParser(self._class)
        if headersonly:
            feedparser._set_headersonly()
        while True:
            data = fp.read(8192)
            if not data:
                break
            feedparser.feed(data)
        return feedparser.close()
示例#9
0
    def _handle_upload(self, headers, registry, parser):
        # file upload handling

        # mime parser
        from email.FeedParser import FeedParser
        fp = FeedParser()

        # need header
        content_type = headers['content-type']
        fp.feed('CONTENT-TYPE: %s\n' % content_type)

        # size limit
        size_limit = self.stdin_size_limit

        # read in chunks
        chunk_size = 8192

        # number of chunks
        n = size_limit / chunk_size

        # feed contents from stdin to parser
        import sys
        i = 0
        succeeded = False
        while i < n:
            data = sys.stdin.read(chunk_size)
            if not data:
                succeeded = True
                break
            fp.feed(data)
            continue
        if not succeeded:
            raise RuntimeError, "stdin too large"

        # parsed is a mime instance
        parsed = fp.close()

        #
        header = 'Content-Disposition'

        if self.inventory.debug:
            self._cgi_inputs['uploaded mime'] = parsed.as_string()

        args = []
        uploads = {}
        for part in parsed.walk():

            if part.get_content_maintype() == 'multipart':
                # this part is the parent message it self, skip
                continue

            filename = part.get_param('filename', header=header)
            if filename:
                # this means we are dealing with a real file
                # save them to a dictionary so that later actors can handle them
                content = part.get_payload(decode=True)
                uploads[filename] = content
            else:
                # just a key,value pair
                key = part.get_param('name', header=header)
                value = part.get_payload()
                args.append((key, value))

            # pass key,value pairs to pyre option registry
            arg = '&'.join(['%s=%s' % (k, v) for k, v in args])
            if arg: parser.parse(registry, arg, 'form')

        self._uploads = uploads
        return
示例#10
0
 def __init__(self,path):
     fp = FeedParser()
     charset = chardet.detect(open(path).read())
     fp.feed(codecs.open(path,encoding = charset["encoding"]).read())
     self.m = fp.close()
示例#11
0
class FSProtocol(basic.LineReceiver):
    """FreeSWITCH EventSocket protocol implementation.
    
    All the FreeSWITCH api and dptool commands are defined in this class
    """
    delimiter="\n\n"
    jobType = False
    state = "READ_CONTENT"
        
    def connectionMade(self):
        self.contentCallbacks = {"auth/request":self.auth, 
                        "api/response":self.onAPIReply, 
                        "command/reply":self.onCommandReply, 
                        "text/event-plain":self.onEvent, 
                        "text/disconnect-notice":self.disconnectNotice
                        }
        self.pendingJobs = []   
        self.pendingBackgroundJobs = {}        
        self.eventCallbacks = {}
        self.customEventCallbacks = {}
        self.subscribedEvents = []        
        log.info("Connected to FreeSWITCH")
        
    def connectionLost(self, reason):
        log.info("Cleaning up")
        self.disconnectedFromFreeSWITCH()
        
    def disconnectedFromFreeSWITCH(self):
        """Over-ride this to get notified of FreeSWITCH disconnection"""
        pass
    
    def registerEvent(self, event,subscribe, function, *args, **kwargs):
        """Register a callback for the event 
        event -- (str) Event name as sent by FreeSWITCH , Custom events should give subclass also 
                                eg : CUSTOM conference::maintenance
        subsribe -- (bool) if True subscribe to this event
        function -- callback function accepts a event dictionary as first argument
        args -- argumnet to be passed to callback function
        kwargs -- keyword arguments to be passed to callback function
        
        returns instance of  EventCallback , keep a reference of this around if you want to deregister it later
        """
        if subscribe:
            if self.needToSubscribe(event):
                self.subscribeEvents(event)
        ecb = EventCallback(event, function, *args, **kwargs)
        ecb_list = self.eventCallbacks.get(event, [])
        event_callbacks = self.eventCallbacks
        #handle CUSTOM events 
        if event.startswith("CUSTOM"):
            subclass = event.split(' ')            
            event = subclass[1]
            ecb.subclass = event
            ecb_list = self.customEventCallbacks.get(event, [])
            event_callbacks = self.customEventCallbacks
        ecb_list.append(ecb)
        event_callbacks[event] = ecb_list
        return ecb
        
    def needToSubscribe(self, event):
        """Decide if we need to subscribe to an event or not by comparing the event provided against already subscribeEvents
        
        event -- (str) event name 
        
        returns bool
        """
        if "all" in self.subscribedEvents:
            return False
        if event in self.subscribedEvents:
            return False
        if 'myevents' in self.subscribedEvents:
            return False
        else:
            return True
        
    def deregisterEvent(self,ecb):
        """Deregister a callback for the given event
        
        ecb -- (EventCallback) instance of EventCallback object
        """
        callbacks_list = self.eventCallbacks
        if ecb.eventname == 'CUSTOM':
            callbacks_list = self.customEventCallbacks
        ecbs = callbacks_list[ecb.eventname]
        try:
            ecbs.remove(ecb)
        except ValueError:
            log.error("%s already deregistered "%ecb)

    def dataReceived(self, data):
        """
        We override this twisted method to avoid being disconnected by default MAX_LENGTH for messages which cross
        that limit
        """
        if self._busyReceiving:
            self._buffer += data
            return

        try:
            self._busyReceiving = True
            self._buffer += data
            while self._buffer and not self.paused:
                if self.line_mode:
                    try:
                        line, self._buffer = self._buffer.split(
                            self.delimiter, 1)
                    except ValueError:
                        return
                    else:
                        why = self.lineReceived(line)
                        if (why or self.transport and
                            self.transport.disconnecting):
                            return why
                else:
                    data = self._buffer
                    self._buffer = b''
                    why = self.rawDataReceived(data)
                    if why:
                        return why
        finally:
            self._busyReceiving = False

    def lineReceived(self, line):
        log.debug("Line In: %s"%line)
        self.parser = FeedParser(Event)        
        self.parser.feed(line)
        self.message = self.parser.close()
        #if self.state is not READ_CONTENT (i.e Content-Type is already read) and the Content-Length is present
        #read rest of the message and set it as payload
        if self.message.has_key('Content-Length') and self.state!= 'READ_CONTENT':
            if self.enterRawMode():
                log.debug("Entering raw mode to read message payload")
                return 
        try:
            self.inspectMessage()   
        except:
            log.error("Exception in message processing ", exc_info=True)
        
    def rawDataReceived(self, data):
        """Read length of raw data specified by self.contentLength and set it as message payload """
        log.debug("Data In : %s"%data)
        self.rawdataCache = ''.join([self.rawdataCache, data])
        if len(self.rawdataCache) >= self.contentLength-1:
            self.clearLineBuffer()
            extra = self.rawdataCache[self.contentLength:]            
            currentResult = self.rawdataCache[:self.contentLength]
            self.message.set_payload(currentResult)
            try:
                self.inspectMessage()   
            except:
                log.error("Exception in message processing ", exc_info=True)        
            self.setLineMode(extra)

    def enterRawMode(self):
        """
        Change to raw mode from line mode if self.contentLength > 0
        """
        self.contentLength = int(self.message['Content-Length'].strip())
        if self.contentLength > 0:
            self.rawdataCache =''
            self.setRawMode()
            return True
        return False

    def inspectMessage(self):
        """Inspect message and dispatch based on self.state or Content-Type of message """
        if self.state == "READ_EVENT":
            return self.dispatchEvent()
        if self.state == "READ_CHANNELINFO":
            return self.onConnect()
        if self.state == 'READ_API':
            return self.fireAPIDeferred()
        if not self.message.has_key("Content-Type"):
            return
        ct = self.message['Content-Type']
        try:
            cb = self.contentCallbacks[ct]
            cb()
        except KeyError:
            log.error("Got unimplemented Content-Type : %s"%ct)
            
    def dispatchEvent(self):
        self.state = "READ_CONTENT"
        eventname = self.message['Event-Name']        
        #Handle background job event
        if eventname == "BACKGROUND_JOB":
            try:
                df = self.pendingBackgroundJobs.pop(self.message['Job-UUID'])
                df.callback(self.message)
            except KeyError:
                log.error("Stray BACKGROUND_JOB event received %s", self.message['Job-UUID'])
            except:
                log.error("Error in BACKGROUND_JOB event handler", exc_info=True)
        if eventname == 'CUSTOM':
            self.message.decode()
            ecbs = self.customEventCallbacks.get(self.message['Event-Subclass'], None)
        else:
            ecbs = self.eventCallbacks.get(eventname, None)
        if ecbs is None:
            return       
                
        for ecb in ecbs:
            try:
                ecb.func(self.message, *ecb.args, **ecb.kwargs)                
            except:                
                log.error("Message %s\nError in event handler %s on event %s:"%(self.message, ecb.func, eventname), exc_info=True)

    def onConnect(self):
        """Channel Information is ready to be read.
        """
        log.info("onconnect")
        
    def auth(self):
        """
        FreeSWITCH is requesting to authenticate         
        """
        pass
        
    def fireAPIDeferred(self):
        self.state = 'READ_CONTENT'
        df = self.pendingJobs.pop(0)
        df.callback(self.message)
        
    def onAPIReply(self):
        """
        Handle API reply 
        """
        if not self.message.has_key("Content-Length"):            
            self.currentDeferred = self.pendingJobs.pop(0)
            return self.currentDeferred.callback(self.message)
        if self.enterRawMode():
            self.state = "READ_API"
            log.debug("Entering raw mode to read API response")
            return
        else:
            self.currentDeferred.callback(self.message)
        
    def onCommandReply(self):
        """
        Handle CommandReply        
        """
        if self.message.has_key("Job-UUID"):
            return
        try:
            df = self.pendingJobs.pop(0)
        except IndexError:
            log.error("Command reply message received with out pending deferred %s"%self.message)
            return
        if self.message['Reply-Text'].startswith("+OK"):
            df.callback(self.message)        
        else:
            e = CommandError(self.message['Reply-Text'])
            df.errback(e)
        
    def onEvent(self):
        """
        Handle a new event
        """
        self.state = "READ_EVENT"
        
    def disconnectNotice(self):
        """
        Handle disconnect notice 
        """
        
        if not self.message.has_key("Content-Length"):
            return self.disconnectNoticeReceived(self.message)
        self.contentLength = int(self.message['Content-Length'])
        if self.contentLength>0:
            self.currentDeferred = defer.Deferred()
            log.info("Enter raw mode to read disconnect notice")
            self.rawdataCache = ''
            self.setRawMode()
        else:
            self.disconnectNoticeReceived(self.message)
       
    def disconnectNoticeReceived(self, msg):
        """Override this to receive disconnect notice from FreeSWITCH"""
        log.error("disconnectNoticeReceived not implemented")
        log.info(msg)
        
    def sendData(self, cmd, args=''):
        df = defer.Deferred()
        #self.pendingJobs.append((cmd, df))
        self.pendingJobs.append(df)
        if args:
            cmd = ' '.join([cmd, args])           
        self.sendLine(cmd)
        log.debug("Line Out: %r"%cmd)
        return df
        
    def sendMsg(self, msg):
        """Send message to FreeSWITCH
        
        msg -- (event) Event object 
        
        """
        df = defer.Deferred()        
        self.pendingJobs.append(df)
        msg = msg.as_string(True)
        self.transport.write(msg)
        log.debug("Line Out: %r"%msg)
        return df
        
    def sendCommand(self, cmd, args='', uuid='', lock=True):
        msg = Event()
        if uuid:
            msg.set_unixfrom("SendMsg %s"%uuid)
        else:
            msg.set_unixfrom("SendMsg")
        msg['call-command'] = "execute"
        msg['execute-app-name'] = cmd
        if args:            
            msg['execute-app-arg'] = args
        if lock:
            msg['event-lock'] = "true"        
        return self.sendMsg(msg)        
        
    def sendAPI(self, apicmd, background=jobType):
        if background:            
            return self.sendBGAPI(apicmd)
        else:
            return self.sendData("api", apicmd)
        
    def sendBGAPI(self, apicmd):
        jobid = str(uuid.uuid1())
        apicmd = ' '.join(['bgapi', apicmd])
        apicmd = '\n'.join([apicmd, "Job-UUID:%s"%jobid])                
        
        backgroundJobDeferred = defer.Deferred()
        self.pendingBackgroundJobs[jobid] = backgroundJobDeferred
        
        log.debug("Line Out: %r", apicmd)
        self.sendLine(apicmd)
        return backgroundJobDeferred
    
    def subscribeEvents(self, events):
        """Subscribe to FreeSWITCH events.
        
        events -(str) 'all'  subscribe to all events or event names separated by space
        this method can subscribe to multiple events but if the event is of CUSTOM type
        then only one CUSTOM event with subclass should be given
        """
        _events = []
        if not events.startswith("CUSTOM"):
            _events = events.split(' ')
        for event in _events:
            self.subscribedEvents.append(events)
        
        return self.sendData("event plain", events)
        
    def myevents(self, uuid=''):
        """Tie up the connection to particular channel events"""
        self.subscribedEvents.append("myevents")        
        if uuid:
            return self.sendData("myevents %s"%uuid)
        else:
            return self.sendData("myevents")
            
    def apiAvmd(self, uuid, start=True, background=jobType):
        """Execute avmd on provided channel. 
        uuid (str) -- uuid of the target channel
        start (bool)  -- If True avmd will start if false avmd will be stopped
        """
        if start:
            return self.sendAPI("avmd %s start"%uuid, background)
        else:
            return self.sendAPI("avmd %s stop"%uuid, background)
    
    def apiConferenceDial(self, name, url, background=jobType):
        """Dial the given url from conference 
        
        name -- (str) name of the conference 
        url -- (str) FreeSWITCH compatible call URL"""
        cmd = 'conference %s dial %s'%(name, url)
        return self.sendAPI(cmd, background)
        
    def apiConferenceKick(self,name, member, background=jobType):
        """Kick the given member from conference 
        
        name -- (str) name of the conference 
        member -- (str) member id or all or last 
        """
        cmd = "conference %s kick %s"%(name, member)
        return self.sendAPI(cmd, background)
        
    def apiConferenceList(self, name=None, delim=None, background=jobType):
        """List the conference 
        name - (str) name of the conference. if not given all the conferences will be listed 
        delim - (str) delimiter to use for separating values """
        
        cmd = "conference"
        if name is not None:
            cmd = ' '.join([cmd, name, 'list'])
        else:
            cmd = ' '.join([cmd,'list'])
            
        if delim is not None:
            cmd = ' '.join([cmd, 'delim',delim])
        return self.sendAPI(cmd, background)
        
    def apiConferenceListCount(self, name, background=True):
        """Return number of members in the conference
        
        name -- (str) name of the conference
        """
        cmd = 'conference %s list count'%name
        return self.sendAPI(cmd, background)
        
    def apiConferenceVolume(self, name, member, value=0, direction='out', background=jobType):
        """Set volume of conference 
        
        name -- (str) name of the conference 
        memeber -- (str) member id or all or last 
        value -- (int) 0 - 4
        direction -- (str) in or out"""
        
        cmd = "conference %s volume_%s %s %s"%(name, direction, member, value)
        return self.sendAPI(cmd, background)
        
    def apiConferenceMute(self, name, member, background=jobType):
        """Mute given member in a conference
        
        name -- (str) name of the conference
        member -- (str) member id or all or last
        """
        cmd = "conference %s mute %s"%(name, member)
        return self.sendAPI(cmd, background)
        
    def apiConferencePlay(self, name, filename, member=None, background=jobType):
        """Playback given file in conference
        
        name -- (str) name of the conference
        filename -- (str) name of the audio file to be played in conference
        member -- (str) member id in conference
        """
        if member:
            cmd = "conference %s play %s %s"%(name, filename, member)    
        else:
            cmd = "conference %s play %s"%(name, filename,)
        return self.sendAPI(cmd, background)
        
    def apiConferenceStop(self, name, fid=None, member=None, background=jobType):
        """Stop an ongoing/queued playback in conference
        
        name -- (str) name of the conference
        fid -- (str) file ID to stop takes all|async|current|last
        member -- (str) member id in conference
        """
        if member:
            cmd = "conference %s stop %s %s"%(name, fid, member)
        elif fid:
            cmd = "conference %s stop %s"%(name, fid)
        else:
            cmd = "conference %s stop"%(name, )
        return self.sendAPI(cmd, background)
        
    def apiConferenceUnMute(self, name, member, background=jobType):
        """UnMute given member in a conference
        
        name -- (str) name of the conference
        member -- (str) member id or all or last
        """
        cmd = "conference %s unmute %s"%(name, member)
        return self.sendAPI(cmd, background)
        
    def apiDomainExists(self, domain, background=jobType):
        cmd = "domain_exists %s"%domain
        return self.sendAPI(cmd, background)
        
    def apiGlobalGetVar(self,variable='', background=jobType):
        """Get the value of a global variable
        
        variable -- name of the variable
        
        returns the value of the provided global variable if argument variable is not present then all global variables are returned.
        """           
        apicmd = ' '.join(["global_getvar", variable])
        df = self.sendAPI(apicmd, background)
        if variable != '':
            return df      
        else:
            finalDF = defer.Deferred()
            df.addCallback(self._parseGlobalGetVar,finalDF)        
            return finalDF
            
    def _parseGlobalGetVar(self, result, df):
        result = result.get_payload()
        res = result.strip().split("\n")            
        finalResult = {}  
        try:
            for r in res:                
                k, v = r.split("=", 1)               
                finalResult[k] = v                
            else:
                df.callback(finalResult)                
        except Exception, err:            
            log.error(err)