#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Blobstore support classes.

Classes:

  DownloadRewriter:
    Rewriter responsible for transforming an application response to one
    that serves a blob to the user.

  CreateUploadDispatcher:
    Creates a dispatcher that is added to dispatcher chain.  Handles uploads
    by storing blobs rewriting requests and returning a redirect.
"""




import cgi
import cStringIO
import logging
import mimetools
import re

from google.appengine.api import apiproxy_stub_map
from google.appengine.api import blobstore
from google.appengine.api import datastore
from google.appengine.api import datastore_errors
from google.appengine.api.files import file_service_stub
from google.appengine.tools import dev_appserver_upload



UPLOAD_URL_PATH = '_ah/upload/'


UPLOAD_URL_PATTERN = '/%s(.*)' % UPLOAD_URL_PATH


AUTO_MIME_TYPE = 'application/vnd.google.appengine.auto'


ERROR_RESPONSE_TEMPLATE = """
<html>
  <head>
    <title>%(response_code)d %(response_string)s</title>
  </head>
  <body text=#000000 bgcolor=#ffffff>
    <h1>Error: %(response_string)s</h1>
    <h2>%(response_text)s</h2>
  </body>
</html>
"""


def GetBlobStorage():
  """Get blob-storage from api-proxy stub map.

  Returns:
    BlobStorage instance as registered with blobstore API in stub map.
  """
  return apiproxy_stub_map.apiproxy.GetStub('blobstore').storage


def ParseRangeHeader(range_header):
  """Parse HTTP Range header.

  Args:
    range_header: A str representing the value of a range header as retrived
      from Range or X-AppEngine-BlobRange.

  Returns:
    Tuple (start, end):
      start: Start index of blob to retrieve.  May be negative index.
      end: None or end index.  End index is exclusive.
    (None, None) if there is a parse error.
  """
  if not range_header:
    return None, None
  try:

    range_type, ranges = range_header.split('=', 1)
    if range_type != 'bytes':
      return None, None
    ranges = ranges.lstrip()
    if ',' in ranges:
      return None, None
    end = None
    if ranges.startswith('-'):
      start = int(ranges)
      if start == 0:
        return None, None
    else:
      split_range = ranges.split('-', 1)
      start = int(split_range[0])
      if len(split_range) == 2 and split_range[1].strip():
        end = int(split_range[1]) + 1
        if start > end:
          return None, None
    return start, end
  except ValueError:
    return None, None


def _GetGoogleStorageFileMetadata(blob_key):
  """Retreive metadata about a GS blob from the blob_key.

  Args:
    blob_key: The BlobKey of the blob.

  Returns:
    Tuple (size, content_type, open_key):
      size: The size of the blob.
      content_type: The content type of the blob.
      open_key: The key used as an argument to BlobStorage to open the blob
        for reading.
    (None, None, None) if the blob metadata was not found.
  """
  try:
    gs_info = datastore.Get(
        datastore.Key.from_path(file_service_stub.GS_INFO_KIND,
                                blob_key,
                                namespace=''))
    return gs_info['size'], gs_info['content_type'], gs_info['storage_key']
  except datastore_errors.EntityNotFoundError:
    return None, None, None


def _GetBlobstoreMetadata(blob_key):
  """Retreive metadata about a blobstore blob from the blob_key.

  Args:
    blob_key: The BlobKey of the blob.

  Returns:
    Tuple (size, content_type, open_key):
      size: The size of the blob.
      content_type: The content type of the blob.
      open_key: The key used as an argument to BlobStorage to open the blob
        for reading.
    (None, None, None) if the blob metadata was not found.
  """
  try:
    blob_info = datastore.Get(
        datastore.Key.from_path(blobstore.BLOB_INFO_KIND,
                                blob_key,
                                namespace=''))
    return blob_info['size'], blob_info['content_type'], blob_key
  except datastore_errors.EntityNotFoundError:
    return None, None, None


def _GetBlobMetadata(blob_key):
  """Retrieve the metadata about a blob from the blob_key.

  Args:
    blob_key: The BlobKey of the blob.

  Returns:
    Tuple (size, content_type, open_key):
      size: The size of the blob.
      content_type: The content type of the blob.
      open_key: The key used as an argument to BlobStorage to open the blob
        for reading.
    (None, None, None) if the blob metadata was not found.
  """
  size, content_type, open_key = _GetGoogleStorageFileMetadata(blob_key)
  if size is None:
    size, content_type, open_key = _GetBlobstoreMetadata(blob_key)
  return size, content_type, open_key


def _SetRangeRequestNotSatisfiable(response, blob_size):
  """Short circuit response and return 416 error.

  Args:
    response: Response object to be rewritten.
    blob_size: The size of the blob.
  """
  response.status_code = 416
  response.status_message = 'Requested Range Not Satisfiable'
  response.body = cStringIO.StringIO('')
  response.headers['Content-Length'] = '0'
  response.headers['Content-Range'] = '*/%d' % blob_size
  del response.headers['Content-Type']


def DownloadRewriter(response, request_headers):
  """Intercepts blob download key and rewrites response with large download.

  Checks for the X-AppEngine-BlobKey header in the response.  If found, it will
  discard the body of the request and replace it with the blob content
  indicated.

  If a valid blob is not found, it will send a 404 to the client.

  If the application itself provides a content-type header, it will override
  the content-type stored in the action blob.

  If blobstore.BLOB_RANGE_HEADER header is provided, blob will be partially
  served.  If Range is present, and not blobstore.BLOB_RANGE_HEADER, will use
  Range instead.

  Args:
    response: Response object to be rewritten.
    request_headers: Original request headers.  Looks for 'Range' header to copy
      to response.
  """
  blob_key = response.headers.getheader(blobstore.BLOB_KEY_HEADER)
  if blob_key:
    del response.headers[blobstore.BLOB_KEY_HEADER]

    blob_size, blob_content_type, blob_open_key = _GetBlobMetadata(blob_key)

    range_header = response.headers.getheader(blobstore.BLOB_RANGE_HEADER)
    if range_header is not None:
      del response.headers[blobstore.BLOB_RANGE_HEADER]
    else:
      range_header = request_headers.getheader('Range')



    if (blob_size is not None and blob_content_type is not None and
        response.status_code == 200):
      content_length = blob_size
      start = 0
      end = content_length

      if range_header:
        start, end = ParseRangeHeader(range_header)
        if start is None:
          _SetRangeRequestNotSatisfiable(response, blob_size)
          return
        else:
          if start < 0:
            start = max(blob_size + start, 0)
          elif start >= blob_size:
            _SetRangeRequestNotSatisfiable(response, blob_size)
            return
          if end is not None:
            end = min(end, blob_size)
          else:
            end = blob_size
          content_length = min(end, blob_size) - start
          end = start + content_length
          response.status_code = 206
          response.status_message = 'Partial Content'
          response.headers['Content-Range'] = 'bytes %d-%d/%d' % (
              start, end - 1, blob_size)

      blob_stream = GetBlobStorage().OpenBlob(blob_open_key)
      blob_stream.seek(start)
      response.body = cStringIO.StringIO(blob_stream.read(content_length))
      response.headers['Content-Length'] = str(content_length)

      content_type = response.headers.getheader('Content-Type')
      if not content_type or content_type == AUTO_MIME_TYPE:
        response.headers['Content-Type'] = blob_content_type
      response.large_response = True

    else:

      if response.status_code != 200:
        logging.error('Blob-serving response with status %d, expected 200.',
                      response.status_code)
      else:
        logging.error('Could not find blob with key %s.', blob_key)

      response.status_code = 500
      response.status_message = 'Internal Error'
      response.body = cStringIO.StringIO()

      if response.headers.getheader('content-type'):
        del response.headers['content-type']
      response.headers['Content-Length'] = '0'


def CreateUploadDispatcher(get_blob_storage=GetBlobStorage):
  """Function to create upload dispatcher.

  Returns:
    New dispatcher capable of handling large blob uploads.
  """


  from google.appengine.tools import old_dev_appserver

  class UploadDispatcher(old_dev_appserver.URLDispatcher):
    """Dispatcher that handles uploads."""

    def __init__(self):
      """Constructor.

      Args:
        blob_storage: A BlobStorage instance.
      """
      self.__cgi_handler = dev_appserver_upload.UploadCGIHandler(
          get_blob_storage())



    def Dispatch(self,
                 request,
                 outfile,
                 base_env_dict=None):
      """Handle post dispatch.

      This dispatcher will handle all uploaded files in the POST request, store
      the results in the blob-storage, close the upload session and transform
      the original request in to one where the uploaded files have external
      bodies.

      Returns:
        New AppServerRequest indicating request forward to upload success
        handler.
      """

      if base_env_dict['REQUEST_METHOD'] != 'POST':
        outfile.write('Status: 400\n\n')
        return


      upload_key = re.match(UPLOAD_URL_PATTERN, request.relative_url).group(1)
      try:
        upload_session = datastore.Get(upload_key)
      except datastore_errors.EntityNotFoundError:
        upload_session = None

      if upload_session:
        success_path = upload_session['success_path']
        max_bytes_per_blob = upload_session['max_bytes_per_blob']
        max_bytes_total = upload_session['max_bytes_total']
        bucket_name = upload_session.get('gs_bucket_name', None)

        upload_form = cgi.FieldStorage(fp=request.infile,
                                       headers=request.headers,
                                       environ=base_env_dict)

        try:


          mime_message_string = self.__cgi_handler.GenerateMIMEMessageString(
              upload_form,
              max_bytes_per_blob=max_bytes_per_blob,
              max_bytes_total=max_bytes_total,
              bucket_name=bucket_name)

          datastore.Delete(upload_session)
          self.current_session = upload_session


          header_end = mime_message_string.find('\n\n') + 1
          content_start = header_end + 1
          header_text = mime_message_string[:header_end].replace('\n', '\r\n')
          content_text = mime_message_string[content_start:].replace('\n',
                                                                     '\r\n')


          complete_headers = ('%s'
                              'Content-Length: %d\r\n'
                              '\r\n') % (header_text, len(content_text))

          return old_dev_appserver.AppServerRequest(
              success_path,
              None,
              mimetools.Message(cStringIO.StringIO(complete_headers)),
              cStringIO.StringIO(content_text),
              force_admin=True)
        except dev_appserver_upload.InvalidMIMETypeFormatError:
          outfile.write('Status: 400\n\n')
        except dev_appserver_upload.UploadEntityTooLargeError:
          outfile.write('Status: 413\n\n')
          response = ERROR_RESPONSE_TEMPLATE % {
              'response_code': 413,
              'response_string': 'Request Entity Too Large',
              'response_text': 'Your client issued a request that was too '
              'large.'}
          outfile.write(response)
        except dev_appserver_upload.FilenameOrContentTypeTooLargeError, ex:
          outfile.write('Status: 400\n\n')
          response = ERROR_RESPONSE_TEMPLATE % {
              'response_code': 400,
              'response_string': 'Bad Request',
              'response_text': str(ex)}
          outfile.write(response)
      else:
        logging.error('Could not find session for %s', upload_key)
        outfile.write('Status: 404\n\n')


    def EndRedirect(self, dispatched_output, original_output):
      """Handle the end of upload complete notification.

      Makes sure the application upload handler returned an appropriate status
      code.
      """
      response = old_dev_appserver.RewriteResponse(dispatched_output)
      logging.info('Upload handler returned %d', response.status_code)
      outfile = cStringIO.StringIO()
      outfile.write('Status: %s\n' % response.status_code)

      if response.body and len(response.body.read()) > 0:
        response.body.seek(0)
        outfile.write(response.body.read())
      else:
        outfile.write(''.join(response.headers.headers))

      outfile.seek(0)
      old_dev_appserver.URLDispatcher.EndRedirect(self,
                                                  outfile,
                                                  original_output)

  return UploadDispatcher()
