Exemplo n.º 1
0
	def __init__(self, book, bytes_range = None):
		status = 200 if bytes_range is None else 206 # 'OK' or 'Partial Content'
		DummyResponse.__init__(self, status, self._HEADERS)
		self.book = book
		self.length = book.file_size

		if bytes_range is None:
			self.range_begin = 0
			self.range_end = self.length - 1
			self.range_length = self.length
			self.headers['Content-Length'] = self.length
		else:
			self.range_begin = bytes_range[0]
			self.range_end = bytes_range[1]
			self.range_length = bytes_range[2]
			self.headers['Content-Range'] = 'bytes=%d-%d/%d' % ( self.range_begin, self.range_end, self.length )
			self.headers['Content-Length'] = self.range_length

		self.headers['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(book.file_path)
		self.headers['Content-Type'] = book.content_type

		if book.cde_content_type == 'EBOK':
			# Kindles do not support annotations for PDOCs
			if annotations.has(book.asin):
				self.headers['Hint-Sidecar-Download'] = 1
			if annotations.apnx_path(book):
				self.headers['Hint-APNX-Available'] = 1
Exemplo n.º 2
0
    def call(self, request, device):
        if request.headers['X-ADP-Reason'] == 'Poll':
            return DummyResponse(headers=_POLL_HEADERS, data=_POLL_BODY)
        q = request.get_query_params()
        reason = q.get('reason')
        if reason == 'Poll':
            return DummyResponse(headers=_POLL_HEADERS, data=_POLL_BODY)

        if device.is_provisional():
            # tell the device to do a full snapshot upload, so that we can get the device serial and identify it
            return DummyResponse(headers=_POLL_HEADERS,
                                 data=_first_contact(request, device))

        if reason == 'ServiceRefresh':
            return DummyResponse(headers=_POLL_HEADERS,
                                 data=_service_refresh(request, device))

        lto = q.get('device_lto', -1)
        if lto != -1:
            try:
                device.lto = int(lto)
            except:
                pass

        response = self.call_upstream(request, device)
        if response.status == 200:
            # use default UTF-8 encoding
            with minidom.parseString(response.body_text()) as doc:
                if _process_xml(request, doc, device):
                    xml = doc.toxml('UTF-8')
                    response.update_body(xml)

        return response
Exemplo n.º 3
0
	def __init__(self, book, bytes_range = None):
		status = 200 if bytes_range is None else 206 # 'OK' or 'Partial Content'
		DummyResponse.__init__(self, status, _HEADERS)
		self.book = book
		self.length = book.file_size

		if bytes_range is None:
			self.range_begin = 0
			self.range_end = self.length - 1
			self.range_length = self.length
			self.headers['Content-Length'] = self.length
		else:
			self.range_begin = bytes_range[0]
			self.range_end = bytes_range[1]
			self.range_length = bytes_range[2]
			self.headers['Content-Range'] = 'bytes=%d-%d/%d' % ( self.range_begin, self.range_end, self.length )
			self.headers['Content-Length'] = self.range_length

		self.headers['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(book.file_path)
		self.headers['Content-Type'] = book.content_type

		if book.cde_content_type == 'EBOK':
			# annotations are only supported for MOBI books
			if annotations.has(book.asin):
				self.headers['Hint-Sidecar-Download'] = 1
			if annotations.apnx_path(book):
				self.headers['Hint-APNX-Available'] = 1
Exemplo n.º 4
0
    def call(self, request, device):
        if device.is_provisional():
            return DummyResponse(data=_DUMMY_BODY)

        if not request.body:
            q = request.get_query_params()
            q['cde_type'] = q.get('type')
            if _process_item(device, **q):
                return DummyResponse(data=_DUMMY_BODY)
        else:
            with minidom.parseString(request.body_text()) as doc:
                if _process_xml_response(doc, device):
                    xml = doc.toxml('UTF-8')
                    request.update_body(xml)

        return self.call_upstream(request, device)
Exemplo n.º 5
0
 def calibre_collections(self):
     lines = ['<?xml version="1.0" encoding="utf-8"?><collections>']
     for series_name, books_list in collections.series().items():
         if books_list:
             lines += _collection_node(series_name, books_list)
     for tag_name, books_list in collections.tags().items():
         if books_list:
             lines += _collection_node("{" + tag_name + "}", books_list)
     lines.append('</collections>')
     return DummyResponse(data=bytes(''.join(lines), 'utf-8'))
Exemplo n.º 6
0
    def call(self, request, device):
        if request.path.startswith('/images/P/'):
            asin = request.path[10:]
            asin = asin[:asin.find('.', 11)]
            if is_uuid(asin):
                book = calibre.book(asin)
                # logging.debug("looking for cover of %s %s", asin, book)
                if book and book.file_path:
                    image_path = os.path.join(os.path.dirname(book.file_path),
                                              "cover.jpg")
                    image_data = None
                    if os.path.isfile(image_path):
                        try:
                            with open(image_path, 'rb') as fi:
                                image_data = fi.read()
                        except:
                            logging.exception("failed to read cover for %s",
                                              book)
                    if image_data:
                        return DummyResponse(headers=_HEADERS, data=image_data)
                return 404  # forces Kindle 4 PC to use the cover from the .mobi file, if any

        return DummyResponse(
            303, headers={'Location: http://' + _ECX + request.path})
Exemplo n.º 7
0
 def call(self, request, device):
     q = request.get_query_params()
     asin = q.get('key')
     if q.get('type') == 'EBOK' and is_uuid(asin, 'EBOK'):
         book = calibre.book(asin)
         apnx_path = annotations.apnx_path(book)
         # logging.debug("looking for apnx of %s, found %s", book, apnx_path)
         if apnx_path:
             # APNX files are usually small (a few Ks at most),
             # so there's no need to do stream copying
             apnx_data = None
             with open(apnx_path, 'rb') as apnx:
                 apnx_data = apnx.read()
             if apnx_data:
                 return DummyResponse(headers=_HEADERS, data=apnx_data)
Exemplo n.º 8
0
def _last_read(book, exclude_device=None):
    lr_list = []
    for lr in annotations.list_last_read(book.asin):
        if lr.device == exclude_device:
            continue
        device = devices.get(lr.device)
        alias = device.alias if device else lr.device
        alias = lr.device if alias is None \
           else alias.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace('\'', '&apos;')
        lr_list.append(
            _LAST_READ %
            (lr.timestamp * 1000, device_lto(device), lr.pos, alias))
    if lr_list:
        xml = '<?xml version="1.0" encoding="UTF-8"?><book>' + ''.join(
            lr_list) + '</book>'
    else:
        xml = '<?xml version="1.0" encoding="UTF-8"?><book/>'
    return DummyResponse(headers={'Content-Type': 'text/xml;charset=UTF-8'},
                         data=bytes(xml, 'UTF-8'))
Exemplo n.º 9
0
	def call(self, request, device):
		q = request.get_query_params()
		cde_type = q.get('type')
		if 'key' in q and cde_type in ('EBOK', 'PDOC'):
			key = q['key']
			if is_uuid(key, cde_type): # very likely comes from our library
				return self.book_response(key, device, request.headers['Range'])

		if device.is_provisional():
			return None

		if request.is_secure():
			if request.is_signed():
				redirect_header = { 'Location': 'https://cde-ta-g7g.amazon.com' + request.path }
			else:
				redirect_header = { 'Location': 'https://cde-g7g.amazon.com' + request.path }
			return DummyResponse(302, redirect_header)

		# the request was made over http, we'll have to download the file ourselves
		return self.call_upstream(request, device)