Beispiel #1
0
    def do_POST(self):
        """Called when a new event has been received"""

        # make sure this is what we expect
        if self.path != '/event':
            raise RuntimeError(
                'Unexpected path when parsing event: {0}'.format(self.path))

        # validate our content type
        content_type = self.headers.get('content-type', None)
        if content_type != 'text/x-apple-plist+xml':
            raise RuntimeError(
                'Unexpected Content-Type when parsing event: {0}'.format(
                    content_type))

        # and the body length
        content_length = int(self.headers.get('content-length', 0))
        if content_length == 0:
            raise RuntimeError('Received an event with a zero length body.')

        # parse XML plist
        xml = self.rfile.read(content_length)
        if len(xml) < content_length:
            # sometimes the content is not complete...
            self.event = plist_loads(xml + "</dict></plist>")
        else:
            self.event = plist_loads(xml)
Beispiel #2
0
    def decoded_content(self):
        if self._next is not None:
            return self._next.decoded_content()

        self.check_content_type()
        if self.content_type is None or self.content_type in ('text/plain', 'text/html'):
            if self.charset is not None:
                return self._buffer.decode(self.charset)
            return self._buffer.decode()

        try:
            if self.content_type in ['text/x-apple-plist+xml', 'application/x-apple-binary-plist']:
                return plist_loads(self._buffer)
            elif self.content_type == 'text/parameters':
                dd = {}
                for line in self._buffer.split(b'\n'):
                    if line == b'':
                        continue
                    k, v = line.split(b':', 1)
                    dd[k] = v.strip()
                return dd
            elif self.content_type == 'application/json':
                return json.loads(self._buffer.decode())
            elif self.content_type == 'multipart/byteranges':
                boundary = self.charset.split('=', 1)[1]
                start = self._buffer.find(b'--')
                if start == -1:
                    return []
                parts = self._buffer[start:].strip().split("--{}".format(boundary).encode())
                return [self.parse_range_multipart(p) for p in parts if len(p) > 2]
        except:
            return self._buffer
Beispiel #3
0
    def decoded_content(self):
        if self._next is not None:
            return self._next.decoded_content()

        self.check_content_type()
        if self.content_type is None or self.content_type in ('text/plain', 'text/html'):
            if self.charset is not None:
                return self._buffer.decode(self.charset)
            return self._buffer.decode()

        try:
            if self.content_type in ['text/x-apple-plist+xml', 'application/x-apple-binary-plist']:
                return plist_loads(self._buffer)
            elif self.content_type == 'text/parameters':
                dd = {}
                for line in self._buffer.split(b'\n'):
                    if line == b'':
                        continue
                    k, v = line.split(b':', 1)
                    dd[k] = v.strip()
                return dd
            elif self.content_type == 'application/json':
                return json.loads(self._buffer.decode())
            elif self.content_type == 'application/xml':
                return etree.fromstring(self._buffer.decode())
            elif self.content_type == 'multipart/byteranges':
                boundary = self.charset.split('=', 1)[1]
                start = self._buffer.find(b'--')
                if start == -1:
                    return []
                parts = self._buffer[start:].strip().split("--{}".format(boundary).encode())
                return [self.parse_range_multipart(p) for p in parts if len(p) > 2]
        except:
            return self._buffer
Beispiel #4
0
    def do_POST(self):
        """Called when a new event has been received"""

        # make sure this is what we expect
        if self.path != '/event':
            raise RuntimeError('Unexpected path when parsing event: {0}'.format(self.path))

        # validate our content type
        content_type = self.headers.get('content-type', None)
        if content_type != 'text/x-apple-plist+xml':
            raise RuntimeError('Unexpected Content-Type when parsing event: {0}'.format(content_type))

        # and the body length
        content_length = int(self.headers.get('content-length', 0))
        if content_length == 0:
            raise RuntimeError('Received an event with a zero length body.')

        # parse XML plist
        self.event = plist_loads(self.rfile.read(content_length))
Beispiel #5
0
def sample_airportscan():

    proc = Popen(['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-xs'], stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()

    if proc.returncode:
        return
    if not out:
        return
    
    networks = []
    
    for data in plist_loads(out):
        networks.append({
            'ssid': data['SSID_STR'],
            'bssid': data['BSSID'],
            'rssi': data['RSSI'],
        })

    return {'networks': networks}
Beispiel #6
0
    def _command(self, uri, method='GET', body='', **kwargs):
        """Makes an HTTP request through to an AirPlay server

        Args:
            uri(string):    The URI to request
            method(string): The HTTP verb to use when requesting `uri`, defaults to GET
            body(string):   If provided, will be sent witout alteration as the request body.
                            Content-Length header will be set to len(`body`)
            **kwargs:       If provided, Will be converted to a query string and appended to `uri`

        Returns:
            True: Request returned 200 OK, with no response body
            False: Request returned something other than 200 OK, with no response body

            Mixed: The body of the HTTP response
        """

        # generate the request
        if len(kwargs):
            uri = uri + '?' + urlencode(kwargs)

        request = method + " " + uri + " HTTP/1.1\r\nContent-Length: " + str(
            len(body)) + "\r\n\r\n" + body

        try:
            request = bytes(request, 'UTF-8')
        except TypeError:
            pass

        # send it
        self.control_socket.send(request)

        # parse our response
        result = self.control_socket.recv(self.RECV_SIZE)
        resp = HTTPResponse(FakeSocket(result))
        resp.begin()

        # if our content length is zero, then return bool based on result code
        if int(resp.getheader('content-length', 0)) == 0:
            if resp.status == 200:
                return True
            else:
                return False

        # else, parse based on provided content-type
        # and return the response body
        content_type = resp.getheader('content-type')

        if content_type is None:
            raise RuntimeError('Response returned without a content type!')

        if content_type == 'text/parameters':
            body = resp.read()
            try:
                body = str(body, 'UTF-8')
            except TypeError:
                pass

            return email.message_from_string(body)

        if content_type == 'text/x-apple-plist+xml':
            return plist_loads(resp.read())

        raise RuntimeError(
            'Response received with unknown content-type: {0}'.format(
                content_type))
Beispiel #7
0
    def _command(self, uri, method='GET', body='', **kwargs):
        """Makes an HTTP request through to an AirPlay server

        Args:
            uri(string):    The URI to request
            method(string): The HTTP verb to use when requesting `uri`, defaults to GET
            body(string):   If provided, will be sent witout alteration as the request body.
                            Content-Length header will be set to len(`body`)
            **kwargs:       If provided, Will be converted to a query string and appended to `uri`

        Returns:
            True: Request returned 200 OK, with no response body
            False: Request returned something other than 200 OK, with no response body

            Mixed: The body of the HTTP response
        """

        # generate the request
        if len(kwargs):
            uri = uri + '?' + urlencode(kwargs)

        request = method + " " + uri + " HTTP/1.1\r\nContent-Length: " + str(len(body)) + "\r\n\r\n" + body

        try:
            request = bytes(request, 'UTF-8')
        except TypeError:
            pass

        # send it
        self.control_socket.send(request)

        # parse our response
        result = self.control_socket.recv(self.RECV_SIZE)
        resp = HTTPResponse(FakeSocket(result))
        resp.begin()

        # if our content length is zero, then return bool based on result code
        if int(resp.getheader('content-length', 0)) == 0:
            if resp.status == 200:
                return True
            else:
                return False

        # else, parse based on provided content-type
        # and return the response body
        content_type = resp.getheader('content-type')

        if content_type is None:
            raise RuntimeError('Response returned without a content type!')

        if content_type == 'text/parameters':
            body = resp.read()
            try:
                body = str(body, 'UTF-8')
            except TypeError:
                pass

            return email.message_from_string(body)

        if content_type == 'text/x-apple-plist+xml':
            return plist_loads(resp.read())

        raise RuntimeError('Response received with unknown content-type: {0}'.format(content_type))
Beispiel #8
0
def parse_output(out):
    if not out:
        return
    data = plist_loads(out)[0]
    return dict((k, data[k]) for k in KEYS)