Example #1
0
    def _update_response_headers(self, request, response, headers):
        """
        Combine all headers that were set by the different content types
        We are interested in Cache-Control, Last-Modified, Expires
        """
        from django.utils.http import http_date

        # Ideally, for the Cache-Control header, we'd want to do some intelligent
        # combining, but that's hard. Let's just collect and unique them and let
        # the client worry about that.
        cc_headers = set()
        for x in (cc.split(",") for cc in headers.get('Cache-Control', ())):
            cc_headers |= set((s.strip() for s in x))

        if len(cc_headers):
            response['Cache-Control'] = ", ".join(cc_headers)
        else:   # Default value
            response['Cache-Control'] = 'no-cache, must-revalidate'

        # Check all Last-Modified headers, choose the latest one
        lm_list = [parsedate(x) for x in headers.get('Last-Modified', ())]
        if len(lm_list) > 0:
            response['Last-Modified'] = http_date(mktime(max(lm_list)))

        # Check all Expires headers, choose the earliest one
        lm_list = [parsedate(x) for x in headers.get('Expires', ())]
        if len(lm_list) > 0:
            response['Expires'] = http_date(mktime(min(lm_list)))
Example #2
0
def put_object_headers(response, meta, restricted=False, token=None):
    response['ETag'] = meta['checksum']
    response['Content-Length'] = meta['bytes']
    response.override_serialization = True
    response['Content-Type'] = meta.get('type', 'application/octet-stream')
    response['Last-Modified'] = http_date(int(meta['modified']))
    if not restricted:
        response['X-Object-Hash'] = meta['hash']
        response['X-Object-UUID'] = meta['uuid']
        if TRANSLATE_UUIDS:
            meta['modified_by'] = \
                retrieve_displayname(token, meta['modified_by'])
        response['X-Object-Modified-By'] = smart_str(
            meta['modified_by'], strings_only=True)
        response['X-Object-Version'] = meta['version']
        response['X-Object-Version-Timestamp'] = http_date(
            int(meta['version_timestamp']))
        for k in [x for x in meta.keys() if x.startswith('X-Object-Meta-')]:
            response[smart_str(
                k, strings_only=True)] = smart_str(meta[k], strings_only=True)
        for k in (
            'Content-Encoding', 'Content-Disposition', 'X-Object-Manifest',
            'X-Object-Sharing', 'X-Object-Shared-By', 'X-Object-Allowed-To',
                'X-Object-Public'):
            if k in meta:
                response[k] = smart_str(meta[k], strings_only=True)
    else:
        for k in ('Content-Encoding', 'Content-Disposition'):
            if k in meta:
                response[k] = smart_str(meta[k], strings_only=True)
Example #3
0
def send_file(request, filepath, last_modified=None, filename=None):
    fullpath = filepath
    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    if filename:
        mimetype, encoding = mimetypes.guess_type(filename)
    else:
        mimetype, encoding = mimetypes.guess_type(fullpath)
        
    mimetype = mimetype or 'application/octet-stream'
    response = HttpResponse(open(fullpath, 'rb').read(), mimetype=mimetype)
    
    if not last_modified:
        response["Last-Modified"] = http_date(statobj.st_mtime)
    else:
        if isinstance(last_modified, datetime):
            last_modified = float(dateformat.format(last_modified, 'U'))
        response["Last-Modified"] = http_date(epoch_seconds=last_modified)
    
    response["Content-Length"] = statobj.st_size
    
    if encoding:
        response["Content-Encoding"] = encoding
    
    # TODO: Escape filename
    if filename:
        response["Content-Disposition"] = "attachment; filename=%s" % filename.encode('utf-8')
    
    return response
Example #4
0
def serve(request, path, **kwargs):
    if not settings.DEBUG and not kwargs.get("insecure"):
        raise ImproperlyConfigured(
            "The gears view can only be used in debug mode or if the " "--insecure option of 'runserver' is used."
        )

    # It is only required check because we generate
    # version arg for each file
    if "HTTP_IF_MODIFIED_SINCE" in request.META:
        response = HttpResponse()
        response["Expires"] = http_date(time.time() + MAX_AGE)
        response.status_code = 304
        return response

    normalized_path = posixpath.normpath(parse.unquote(path)).lstrip("/")
    try:
        asset = build_asset(environment, normalized_path)
    except FileNotFound:
        return staticfiles_serve(request, path, **kwargs)

    last_modified = asset.mtime
    if request.GET.get("body"):
        asset = asset.processed_source
    mimetype, encoding = mimetypes.guess_type(normalized_path)
    mimetype = mimetype or "application/octet-stream"
    response = HttpResponse(asset, mimetype=mimetype)
    if encoding:
        response["Content-Encoding"] = encoding
    response["Last-Modified"] = http_date(last_modified)
    return response
Example #5
0
    def test_cache_conditional_get_last_modified_expired(self, mock_requests):
        """
        Tests that the cache performs a conditional GET request when asked to
        update the response for a URL with a Last-Modified header, which has
        since expired.
        """
        last_modified = http_date(time.time() - 3600)
        self.set_mock_response(mock_requests, headers={
            'Last-Modified': last_modified
        })
        cache = HttpCache(self.cache_directory)
        url = 'http://example.com'
        cache.update(url)
        # Set a new Last-Modified and content value
        new_last_modified = http_date(time.time())
        self.response_content = b'Response'
        self.set_mock_response(mock_requests, headers={
            'Last-Modified': new_last_modified
        })

        # Run the update again
        response, updated = cache.update(url)

        self.assertTrue(updated)
        self.assertEqual(200, response.status_code)
        # The new content is found in the cache
        self.assertEqual(self.response_content, cache.get_content(url))
        # The new Last-Modified is found in the headers cache
        self.assertEqual(
            new_last_modified,
            cache.get_headers(url)['Last-Modified']
        )
Example #6
0
def qrcode(req, width):
    import qr

    url = req.GET.get('url')
    if url is None:
        raise Http404

    try:
        data = url.encode('ascii')
    except UnicodeError:
        # only supports URLs properly urlencoded
        raise Http404

    if width == "480":
        magnify = 8
    else:
        magnify = 4

    buf = StringIO()
    try:
        qr.qrcode(data, buf, format=qr.GIF, magnify=magnify)
    except ValueError:
        # qr module wasn't be compiled with GD library
        raise Http404

    content = buf.getvalue()

    CACHE_TIMEOUT = 86400
    res = HttpResponse(content, content_type='image/gif')
    res['Content-Length'] = str(len(content))
    res['ETag']           = '"%s"' % md5(content).hexdigest()
    res['Last-Modified']  = http_date()
    res['Expires'] = http_date(time.time() + CACHE_TIMEOUT)
    patch_cache_control(res, max_age=CACHE_TIMEOUT)
    return res
Example #7
0
def border(req, style, rgb):
    import gd
    rgb = tuple(map(lambda x: int(x, 16), (rgb[0:2], rgb[2:4], rgb[4:6])))

    try:
        width = int(req.GET.get('w', 228))
    except (ValueError, TypeError):
        width = 228

    try:
        height = int(req.GET.get('h', 1))
    except (ValueError, TypeError):
        height = 1

    if width < 1 or height < 1:
        raise Http404

    if rgb != (0, 0, 0):
        # if line is black, then use white(#FFFFF) as background color
        backcolor = (255, 255, 255)
    else:
        backcolor = (0, 0, 0)

    # TODO
    # check display width
    img = gd.image((width, height))

    back = img.colorAllocate(backcolor)
    img.colorTransparent(back)

    color = img.colorAllocate(rgb)

    if style == 'dotted':
        pattern = (color, color, back, back)
    elif style == 'dashed':
        pattern = (color, color, color, back, back, back)
    else:
        # solid
        pattern = (color,)

    img.setStyle(pattern)
    for y in xrange(height):
        img.line((0, y), (width, y), gd.gdStyled)

    fp = StringIO()
    img.writeGif(fp)
    content = fp.getvalue()
    fp.close()

    content_type = 'image/gif'
    res = HttpResponse(content, content_type=content_type)
    res['Content-Type']   = content_type
    res['Content-Length'] = str(len(content))
    res['ETag']           = '"%s"' % md5(content).hexdigest()
    res['Last-Modified']  = http_date()
    res['Expires'] = http_date(time.time() + CACHE_TIMEOUT)
    patch_cache_control(res, max_age=CACHE_TIMEOUT)

    return res
 def test_should_regenerate(self, mocktime):
     now = 1319128343
     mocktime.time.return_value = now
     cm = CachingMixin()
     response = HttpResponse()
     response['Last-Modified'] = http_date(now)
     self.assertFalse(cm.should_regenerate(response))
     response['Last-Modified'] = http_date(now - (100 + settings.BETTERCACHE_LOCAL_POSTCHECK))
     self.assertTrue(cm.should_regenerate(response))
Example #9
0
def _image_response(image):
    response = HttpResponse(
        image.render(),
        image.mimetype
    )
    response['Last-Modified'] = http_date(image.modified)
    expire_time = getattr(settings, 'IMAGEFIT_EXPIRE_HEADER', 3600*24*30)
    response['Expires'] = http_date(time.time() + expire_time)
    return response
Example #10
0
def media(request, path):
    fullpath = os.path.join(settings.STATIC_MEDIA_ROOT, path)
    mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'

    # Rendering directory listing
    if os.path.isdir(fullpath):
        return directory_index(path, fullpath)

    # Render single file
    if not os.path.isdir('%s.d' % fullpath):
        try:
            modified = os.stat(fullpath)[stat.ST_MTIME]
        except OSError:
            raise Http404()

        if not was_modified_since(
            request.META.get('HTTP_IF_MODIFIED_SINCE'),
            modified,
        ):
            return HttpResponseNotModified(content_type=mimetype)

        contents = render_file(fullpath)
        response = HttpResponse(contents, content_type=mimetype)
        response['Last-Modified'] = http_date(modified)
        response['Content-Length'] = len(contents)

        return response

    # Render .d directory

    latest = -1
    filenames = []

    for root, _, files in os.walk('%s.d' % fullpath, followlinks=True):
        for filename in [os.path.join(root, x) for x in files]:
            if filename.endswith('~'):
                continue
            filenames.append(filename)
            latest = max(latest, os.stat(filename)[stat.ST_MTIME])

    if not was_modified_since(
        request.META.get('HTTP_IF_MODIFIED_SINCE'),
        latest,
    ):
        return HttpResponseNotModified(content_type=mimetype)

    contents = ""
    for filename in sorted(filenames):
        contents += render_file(filename)

    response = HttpResponse(contents, content_type=mimetype)
    response['Last-Modified'] = http_date(latest)
    response['Content-Length'] = len(contents)

    return response
            def wrapper(*args, **kwargs):
                response = another_view_func(*args, **kwargs)
                if isinstance(response, http.HttpResponse) \
                    and not settings.DEBUG:
                    expiry = time.time() + cache_duration
                    response['Expires']         = http_date(expiry)
                    response['X-Cache-Expires'] = http_date(expiry)
                    response['X-Cache-Time']    = http_date()
                    response['X-Cache']         = 'Miss'

                    patch_cache_control(response, max_age=cache_duration)
                return response
Example #12
0
def cache_headers(response, request, exercise, flag=False):
    if (
        not flag
        and request.method == 'GET'
        and not exercise.get('personalized', False)
        and exercise.get('cacheable', True)
    ):
        response['Last-Modified'] = http_date(exercise['mtime'])
        expiry = exercise.get('expiry_minutes', settings.DEFAULT_EXPIRY_MINUTES)
        if expiry > 0:
            response['Expires'] = http_date(time.time() + expiry * 60)
    return response
    def _process_request(self, request):
        
        #  We won't to refresh dev names for static requests.
        #  So once static content generated it becomes cached
        #  on the browser until changed
        if request.path.startswith(DEV_MEDIA_URL) and 'HTTP_IF_MODIFIED_SINCE' in request.META:
            response = HttpResponse()
            response['Expires'] = http_date(time.time() + self.MAX_AGE)
            response.status_code = 304
            return response

        # We refresh the dev names only once for the whole request, so all
        # media_url() calls are cached.
        # _refresh_dev_names()

        if not self.names_generated:
            _refresh_dev_names()
            self.names_generated = True
        
        if not request.path.startswith(DEV_MEDIA_URL):
            return

        filename = request.path[len(DEV_MEDIA_URL):]

        try:
            backend = _backend_mapping[filename]
        except KeyError:
            raise Http404('The mediagenerator could not find the media file "%s"'
                          % filename)

        content, mimetype = backend.get_dev_output(filename)
        print "MIME", mimetype, filename
        if not mimetype:
            if filename.endswith('.woff'):
                mimetype = 'application/x-font-woff'
            else:
                mimetype = 'application/octet-stream'
        if isinstance(content, unicode):
            content = content.encode('utf-8')
        if mimetype.startswith('text/') or mimetype in TEXT_MIME_TYPES:
            mimetype += '; charset=utf-8'
        response = HttpResponse(content, content_type=mimetype)
        response['Content-Length'] = len(content)

        # Cache manifest files MUST NEVER be cached or you'll be unable to update
        # your cached app!!!
        if response['Content-Type'] != 'text/cache-manifest' and \
                response.status_code == 200:
            patch_cache_control(response, public=True, max_age=self.MAX_AGE)
            response['Expires'] = http_date(time.time() + self.MAX_AGE)

        response['Last-Modified'] = http_date(time.time())
        return response
Example #14
0
def http_date(timestamp):
    """
    A wrapper around Django's http_date that accepts DateFields and
    datetime objects directly.
    """
    from django.utils.http import http_date

    if isinstance(timestamp, (DateField, datetime)):
        return http_date(time.mktime(timestamp.timetuple()))
    elif isinstance(timestamp, basestring):
        return timestamp
    else:
        return http_date(timestamp)
Example #15
0
    def serialize_items(self, request, language, queryset):
        default_host = settings.XMPP_HOSTS[settings.DEFAULT_XMPP_HOST]
        base_url = default_host['CANONICAL_BASE_URL']
        title = self.get_feed_title(request)
        feed_url = request.build_absolute_uri(reverse('blog:home'))

        # see: http://www.feedvalidator.org/docs/warning/MissingAtomSelfLink.html
        href = request.build_absolute_uri(request.get_full_path())

        root = etree.Element("rss", version="2.0", nsmap={
            'atom': self.atom_ns,
        })
        channel = self.sub(root, 'channel')

        self.sub(channel, 'title', title)
        self.sub(channel, 'link', feed_url)
        self.sub(channel, 'description', _('Follow recent updates for %s') % request.site['BRAND'])
        self.sub(channel, 'language', language)
        self.sub(channel, 'lastBuildDate', http_date())

        skipHours = self.sub(channel, 'skipHours')
        for i in range(0, 7):
            self.sub(skipHours, 'hour', text=str(i))

        # add image
        image = self.sub(channel, 'image')
        self.sub(image, 'title', title)
        self.sub(image, 'link', feed_url)
        self.sub(image, 'url', request.build_absolute_uri(static('feed/rss.png')))
        self.sub(image, 'width', '120')
        self.sub(image, 'height', '120')

        # add url (NOTE: This does not have anything to do with the Atom standard)
        self.sub(channel, '{%s}link' % self.atom_ns, rel='self', type='application/rss+xml',
                 href=href)

        for post in queryset:
            canonical_url = post.get_canonical_url()
            content = absolutify_html(post.get_html_summary(request), base_url)

            item = self.sub(channel, 'item')
            self.sub(item, 'title', post.title.current)
            self.sub(item, 'description', content)
            self.sub(item, 'link', canonical_url)
            self.sub(item, 'guid', canonical_url, isPermaLink='true')
            self.sub(item, 'pubDate', http_date(post.created.timestamp()))

            # We do not add an author element, because this *requires* an email address.
            #self.sub(item, 'author', post.author.node)

        return root
Example #16
0
    def test_precondition_failed_last_modified(self):
        "Test precondition using last-modified dates."
        from datetime import datetime, timedelta
        from django.utils.http import http_date

        last_modified_date = datetime.now()

        class PreconditionResource(Resource):
            use_etags = False
            use_last_modified = True

            def put(self, request):
                pass

            def get(self, request):
                return {}

            def get_last_modified(self, request, *args, **kwargs):
                return last_modified_date

        resource = PreconditionResource()

        # Send non-safe request with a old last-modified date.. fail
        if_modified_since = http_date(timegm((last_modified_date - timedelta(seconds=10)).utctimetuple()))
        request = self.factory.put(
            "/",
            data='{"message": "hello world"}',
            content_type="application/json",
            HTTP_IF_UNMODIFIED_SINCE=if_modified_since,
        )
        response = resource(request)
        self.assertEqual(response.status_code, codes.precondition_failed)
        self.assertEqual(response["Content-Type"], "application/json")
        self.assertTrue("no-cache" in response["Cache-Control"])
        self.assertTrue("must-revalidate" in response["Cache-Control"])
        self.assertTrue("max-age=0" in response["Cache-Control"])

        # Old last-modified on GET, updated content is returned
        if_modified_since = http_date(timegm((last_modified_date - timedelta(seconds=10)).utctimetuple()))
        request = self.factory.get("/", HTTP_IF_MODIFIED_SINCE=if_modified_since)
        response = resource(request)
        self.assertEqual(response.status_code, codes.ok)
        self.assertEqual(response["Content-Type"], "application/json")

        # Mimic future request on GET, resource not modified
        if_modified_since = http_date(timegm((last_modified_date + timedelta(seconds=20)).utctimetuple()))
        request = self.factory.get("/", HTTP_IF_MODIFIED_SINCE=if_modified_since)
        response = resource(request)
        self.assertEqual(response.status_code, codes.not_modified)
        self.assertEqual(response["Content-Type"], "application/json")
Example #17
0
def patch_cache_headers(response, timestamp=None, cache_timeout=None):

    if timestamp is None:
        timestamp = time.time() * 1000

    timestamp = int(timestamp)
    response['Last-Modified'] = http_date(timestamp / 1000)
    response['ETag'] = '"' + str(timestamp) + '"'

    if cache_timeout != None and cache_timeout > 0:
        timeout_str = str(cache_timeout)
        response['Cache-Control'] = 'private, max-age=' + timeout_str
        response['Expires'] = http_date(time.time() + cache_timeout)
    else:
        response['Cache-Control'] = 'private, max-age=0, post-check=0, pre-check=0, must-revalidate'
Example #18
0
        def inner(request, *args, **kwargs):
            # Compute values (if any) for the requested resource.
            def get_last_modified():
                if last_modified_func:
                    dt = last_modified_func(request, *args, **kwargs)
                    if dt:
                        return timegm(dt.utctimetuple())

            res_etag = etag_func(request, *args, **kwargs) if etag_func else None
            res_last_modified = get_last_modified()

            response = get_conditional_response(
                request,
                etag=res_etag,
                last_modified=res_last_modified,
            )

            if response is None:
                response = func(request, *args, **kwargs)

            # Set relevant headers on the response if they don't already exist.
            if res_last_modified and not response.has_header('Last-Modified'):
                response['Last-Modified'] = http_date(res_last_modified)
            if res_etag and not response.has_header('ETag'):
                response['ETag'] = quote_etag(res_etag)

            return response
Example #19
0
File: views.py Project: atupal/hue
def download(request, path):
    """
    Downloads a file.

    This is inspired by django.views.static.serve.
    ?disposition={attachment, inline}
    """
    if not request.fs.exists(path):
        raise Http404(_("File not found: %(path)s.") % {'path': escape(path)})
    if not request.fs.isfile(path):
        raise PopupException(_("'%(path)s' is not a file.") % {'path': path})

    mimetype = mimetypes.guess_type(path)[0] or 'application/octet-stream'
    stats = request.fs.stats(path)
    mtime = stats['mtime']
    size = stats['size']
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), mtime, size):
        return HttpResponseNotModified()
        # TODO(philip): Ideally a with statement would protect from leaks,
    # but tricky to do here.
    fh = request.fs.open(path)

    response = HttpResponse(_file_reader(fh), mimetype=mimetype)
    response["Last-Modified"] = http_date(stats['mtime'])
    response["Content-Length"] = stats['size']
    response['Content-Disposition'] = request.GET.get('disposition', 'attachment')
    return response
Example #20
0
def patch_response_headers(response, cache_timeout=None):
    """
    Add HTTP caching headers to the given HttpResponse: Expires and
    Cache-Control.

    Each header is only added if it isn't already set.

    cache_timeout is in seconds. The CACHE_MIDDLEWARE_SECONDS setting is used
    by default.
    """
    if cache_timeout is None:
        cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
    if cache_timeout < 0:
        cache_timeout = 0  # Can't have max-age negative
    if settings.USE_ETAGS and not response.has_header('ETag'):
        warnings.warn(
            "The USE_ETAGS setting is deprecated in favor of "
            "ConditionalGetMiddleware which sets the ETag regardless of the "
            "setting. patch_response_headers() won't do ETag processing in "
            "Django 2.1.",
            RemovedInDjango21Warning
        )
        if hasattr(response, 'render') and callable(response.render):
            response.add_post_render_callback(set_response_etag)
        else:
            response = set_response_etag(response)
    if not response.has_header('Expires'):
        response['Expires'] = http_date(time.time() + cache_timeout)
    patch_cache_control(response, max_age=cache_timeout)
Example #21
0
    def process_request(self, request):
        if not MEDIA_DEV_MODE:
            return

        # We refresh the dev names only once for the whole request, so all
        # media_url() calls are cached.
        _refresh_dev_names()

        if not request.path.startswith(DEV_MEDIA_URL):
            return

        filename = request.path[len(DEV_MEDIA_URL):]

        try:
            backend = _backend_mapping[filename]
        except KeyError:
            raise Http404('No such media file "%s"' % filename)
        content, mimetype = backend.get_dev_output(filename)
        response = HttpResponse(content, content_type=mimetype)
        response['Content-Length'] = len(content)

        # Cache manifest files MUST NEVER be cached or you'll be unable to update
        # your cached app!!!
        if response['Content-Type'] != 'text/cache-manifest' and \
                response.status_code == 200:
            patch_cache_control(response, public=True, max_age=self.MAX_AGE)
            response['Expires'] = http_date(time.time() + self.MAX_AGE)
        return response
Example #22
0
def _image_response(image):
    response = HttpResponse(
        image.render(),
        image.mimetype
    )
    response['Last-Modified'] = http_date(image.modified)
    return response
Example #23
0
def sitemap(request, sitemaps, section=None,
            template_name='sitemap.xml', content_type='application/xml'):

    req_protocol = request.scheme
    req_site = get_current_site(request)

    if section is not None:
        if section not in sitemaps:
            raise Http404("No sitemap available for section: %r" % section)
        maps = [sitemaps[section]]
    else:
        maps = list(six.itervalues(sitemaps))
    page = request.GET.get("p", 1)

    urls = []
    for site in maps:
        try:
            if callable(site):
                site = site()
            urls.extend(site.get_urls(page=page, site=req_site,
                                      protocol=req_protocol))
        except EmptyPage:
            raise Http404("Page %s empty" % page)
        except PageNotAnInteger:
            raise Http404("No page '%s'" % page)
    response = TemplateResponse(request, template_name, {'urlset': urls},
                                content_type=content_type)
    if hasattr(site, 'latest_lastmod'):
        # if latest_lastmod is defined for site, set header so as
        # ConditionalGetMiddleware is able to send 304 NOT MODIFIED
        response['Last-Modified'] = http_date(
            timegm(site.latest_lastmod.utctimetuple()))
    return response
Example #24
0
    def list(self, request, **kwargs):
        if_modified_since = request.headers.get('If-Modified-Since')
        if if_modified_since:
            if_modified_since = parse_http_date_safe(if_modified_since)
        if_unmodified_since = request.headers.get('If-Unmodified-Since')
        if if_unmodified_since:
            if_unmodified_since = parse_http_date_safe(if_unmodified_since)
        if not hasattr(request, 'event'):
            return super().list(request, **kwargs)

        lmd = request.event.logentry_set.filter(
            content_type__model=self.queryset.model._meta.model_name,
            content_type__app_label=self.queryset.model._meta.app_label,
        ).aggregate(
            m=Max('datetime')
        )['m']
        if lmd:
            lmd_ts = timegm(lmd.utctimetuple())

        if if_unmodified_since and lmd and lmd_ts > if_unmodified_since:
            return HttpResponse(status=412)

        if if_modified_since and lmd and lmd_ts <= if_modified_since:
            return HttpResponse(status=304)

        resp = super().list(request, **kwargs)
        if lmd:
            resp['Last-Modified'] = http_date(lmd_ts)
        return resp
Example #25
0
    def patch_headers(self, response):
        """Set the headers we want for caching."""

        # Remove Vary:Cookie if we want to cache non-anonymous
        if not getattr(settings, 'BETTERCACHE_ANONYMOUS_ONLY', False):
            vdict = get_header_dict(response, 'Vary')
            try:
                vdict.pop('cookie')
            except KeyError:
                pass 
            else:
                set_header_dict(response, 'Vary', vdict)

        #  Set max-age, post-check and pre-check
        cc_headers = get_header_dict(response, 'Cache-Control')
        try:
            timeout = cc_headers['max-age']
        except KeyError:
            timeout = settings.BETTERCACHE_CACHE_MAXAGE
            cc_headers['max-age'] = timeout
        # This should never happen but let's be safe
        if timeout is 0:
            return response
        if not 'pre-check' in cc_headers:
           cc_headers['pre-check'] = timeout
        if not 'post-check' in cc_headers:
           cc_headers['post-check'] = int(timeout * settings.BETTERCACHE_EDGE_POSTCHECK_RATIO)
        set_header_dict(response, 'Cache-Control', cc_headers)
        # this should be the main/first place we're setting edge control so we can just set what we want
        ec_dict = {'cache-maxage' : settings.BETTERCACHE_EDGE_MAXAGE}
        set_header_dict(response, 'Edge-Control', ec_dict)
        response['Last-Modified'] = http_date()
        return response
Example #26
0
    def process_response(self, request, response):
        response['Date'] = http_date()
        if not response.has_header('Content-Length'):
            response['Content-Length'] = str(len(response.content))

        if response.has_header('ETag'):
            if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
            if if_none_match == response['ETag']:
                # Setting the status is enough here. The response handling path
                # automatically removes content for this status code (in
                # http.conditional_content_removal()).
                response.status_code = 304

        if response.has_header('Last-Modified'):
            if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
            if if_modified_since is not None:
                try:
                    # IE adds a length attribute to the If-Modified-Since header
                    separator = if_modified_since.index(';')
                    if_modified_since = if_modified_since[0:separator]
                except:
                    pass
                if_modified_since = parse_http_date_safe(if_modified_since)
            if if_modified_since is not None:
                last_modified = parse_http_date_safe(response['Last-Modified'])
                if last_modified is not None and last_modified <= if_modified_since:
                    # Setting the status code is enough here (same reasons as
                    # above).
                    response.status_code = 304

        return response
Example #27
0
    def GET(self, request, spot_id, image_id, thumb_width, thumb_height):
        try:
            img = SpotImage.objects.get(pk=image_id)
            spot = img.spot

            if int(spot.pk) != int(spot_id):
                raise Exception("Image Spot ID doesn't match spot id in url")

            thumb_width = int(thumb_width)
            thumb_height = int(thumb_height)

        except Exception as e:
            response = HttpResponse('{"error":"Bad Image URL"}')
            response.status_code = 404
            return response

        if thumb_height <= 0 or thumb_width <= 0:
            response = HttpResponse('{"error":"Bad Image URL"}')
            response.status_code = 404
            return response

        image = img.image
        im = Image.open(image.path)

        thumb = im.resize((thumb_width, thumb_height), Image.ANTIALIAS)

        tmp = StringIO()
        thumb.save(tmp, im.format)
        tmp.seek(0)

        response = HttpResponse(tmp.getvalue())
        # 7 day timeout?
        response['Expires'] = http_date(time.time() + 60 * 60 * 24 * 7)
        response["Content-type"] = img.content_type
        return response
Example #28
0
 def test_was_modified_since_fp(self):
     """
     A floating point mtime does not disturb was_modified_since (#18675).
     """
     mtime = 1343416141.107817
     header = http_date(mtime)
     self.assertFalse(was_modified_since(header, mtime))
Example #29
0
File: files.py Project: nirgal/ngw
    def get(self, request, fid, cid):
        cf = get_object_or_404(ContactField, pk=fid)
        if not perms.c_can_view_fields_cg(request.user.id,
                                          cf.contact_group_id):
            raise PermissionDenied
        fullpath = os.path.join(settings.MEDIA_ROOT, 'fields', fid, cid)
        if not os.path.exists(fullpath):
            raise Http404(_('"{path}" does not exist').format(path=fullpath))
        # Respect the If-Modified-Since header.
        statobj = os.stat(fullpath)
        if not static.was_modified_since(
           request.META.get('HTTP_IF_MODIFIED_SINCE'),
           statobj.st_mtime, statobj.st_size):
            return HttpResponseNotModified()

        # START OF content_type detection
        cfv = get_object_or_404(ContactFieldValue,
                                contact_id=cid, contact_field_id=fid)
        fileinfo = json.loads(cfv.value)
        content_type = fileinfo['content_type']
        # END OF content_type detection

        response = FileResponse(open(fullpath, 'rb'),
                                content_type=content_type)
        response["Last-Modified"] = http_date(statobj.st_mtime)
        if stat.S_ISREG(statobj.st_mode):
            response["Content-Length"] = statobj.st_size

        response['Content-Disposition'] = 'inline; filename="{0}"'.format(
            header_encode(fileinfo['filename'].encode('utf-8'), 'utf-8'))
        return response
Example #30
0
    def process_response(self, request, response):
        response['Date'] = http_date()
        if not response.streaming and not response.has_header('Content-Length'):
            response['Content-Length'] = str(len(response.content))

        if response.has_header('ETag'):
            if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
            if if_none_match == response['ETag']:
                # Setting the status is enough here. The response handling path
                # automatically removes content for this status code (in
                # http.conditional_content_removal()).
                response.status_code = 304

        # Last-Modified 用于指示最后修改的时间
        if response.has_header('Last-Modified'):
            if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
            if if_modified_since is not None:
                if_modified_since = parse_http_date_safe(if_modified_since)
            if if_modified_since is not None:
                last_modified = parse_http_date_safe(response['Last-Modified'])
                if last_modified is not None and last_modified <= if_modified_since:
                    # Setting the status code is enough here (same reasons as
                    # above).
                    response.status_code = 304

        return response
Example #31
0
    def __call__( self, environ, start_response ):

        def done( status, headers, output ):
            # a good place for debug loging 
            # e.g. logger.debug('done from self.static_file_root: %s' %self.static_file_root, status, headers)
            start_response( status, headers.items() )
            return output

        path_info = environ['PATH_INFO']
        if path_info[0] == '/':
            path_info = path_info[1:]
        file_path = os.path.normpath( os.path.join( self.static_file_root, path_info ) )

        # prevent escaping out of paths below media root (e.g. via "..")
        if not file_path.startswith( self.static_file_root ):
            status = '401 UNAUTHORIZED'
            headers = {'Content-type': 'text/plain'}
            output = ['Permission denied. illegal path'] 
            return done( status, headers, output )

        # only allow GET or HEAD requests e.g. not PUT, DELETE, POST, etc.
        if not (environ['REQUEST_METHOD'] == 'GET' or environ['REQUEST_METHOD'] == 'HEAD'):
            status = '405 METHOD NOT ALLOWED'
            headers = {'Content-type': 'text/plain'}
            output = SimpleResponse(['405 method not allowed'])
            output.status_code = 405
            return done(status, headers, output)
        
        if not os.path.exists( file_path ):
            status = '404 NOT FOUND'
            headers = {'Content-type': 'text/plain'}
            output = SimpleResponse(['Page not found: %s' % file_path])
            output.status_code = 404
            return done( status, headers, output )

        try:
            fp = open( file_path, 'rb' )
        except IOError:
            status = '401 UNAUTHORIZED'
            headers = {'Content-type': 'text/plain'}
            output = SimpleResponse(['Permission denied: %s' % file_path])
            output.status_code = 401
            return done( status, headers, output )

        # This is a very simple implementation of conditional GET with
        # the Last-Modified header. It makes media files a bit speedier
        # because the files are only read off disk for the first request
        # (assuming the browser/client supports conditional GET).

        # mtime needs to be ascii not unicode as django is all unicode need to do conversion
        mtime = http_date( os.stat(file_path)[stat.ST_MTIME] ).encode('ascii', 'ignore') 
        headers = {'Last-Modified': mtime}
        if environ.get('HTTP_IF_MODIFIED_SINCE', None) == mtime:
            status = '304 NOT MODIFIED'
            output = SimpleResponse() 
            output.status_code = 304
        else:
            status = '200 OK'
            mime_type = mimetypes.guess_type(file_path)[0]
            if mime_type:
                headers['Content-Type'] = mime_type

            # naive version with whole file read as a string place in a list
            # output = [fp.read()]
            # fp.close()
            # use BlockIteratorResponse for larger file/network efficiency
            output = BlockIteratorResponse(fp)
            
        return done( status, headers, output )
Example #32
0
def list_actions(request):
    can_add = request.user.has_perm('actions.add_action')
    if request.method == 'POST' and can_add:
        form = ActionForm(request.POST)
        if form.is_valid():
            action = form.save()
            return redirect(action.get_absolute_url())
        else:
            print(form.errors)

    qset, ctx = _get_actions(request, include_future=False)
    if not ctx.get('is_cal'):
        actions = Action.objects.for_user(request.user).filter(when__gte=now())
        ctx['upcoming'] = actions[:6]
    else:
        actions = None
    current_date = ctx['current_date']
    ctx['next_month'] = current_date + timedelta(days=31)
    ctx['last_month'] = current_date + timedelta(days=-1)

    cal_days = list(
        calendar.Calendar(firstweekday=6).itermonthdates(
            current_date.year, current_date.month))
    this_month = []
    this_week = []
    month_actions = defaultdict(list)

    for action in qset:
        # Convert day to local day so actions land in the right day for current view.
        day = action.when.astimezone(tz.tzlocal()).date()
        month_actions[day].append(action)

    event_colors = {
        'talk': 'xr-bg-pink',
        'action': 'xr-bg-green',
        'ally': 'xr-bg-light-green',
        'meeting': 'xr-bg-lemon',
        'orientation': 'xr-bg-purple',
        'art': 'xr-bg-warm-yellow',
        'nvda': 'xr-bg-light-blue',
        'regen': 'xr-warm-yellow xr-bg-dark-blue',
    }
    for daynum, mdate in enumerate(cal_days, 1):
        todays_actions = month_actions[mdate]
        obj = {
            'day': mdate,
            'events': todays_actions,
            'bg': '',
        }
        if mdate.month == current_date.month:
            for a in todays_actions:
                tagnames = a.tags.names()
                for t in a.tags.names():
                    color = event_colors.get(t, None)
                    if color:
                        obj['bg'] = color
                        break
        else:
            # previous month
            obj['bg'] = 'bg-light'
        if mdate == ctx['today']:
            obj['today'] = True
        this_week.append(obj)
        if daynum % 7 == 0:
            this_month.append(this_week)
            this_week = []
    if this_week:
        this_month.append(this_week)
    ctx['month'] = this_month
    ctx['can_add'] = can_add
    if ctx['can_add']:
        ctx['form'] = ActionForm()
    calendar_link = 'webcal://{}/action/ical/XR%20Mass%20Events'.format(
        request.get_host())
    link_pars = {}
    if request.user.is_authenticated:
        link_pars['token'] = signing.Signer().sign(request.user.id)
    if ctx.get('current_tag'):
        link_pars['tag'] = ctx.get('current_tag')
    ctx['calendar_link'] = calendar_link + '?' + urlencode(link_pars)
    resp = render(request, 'list_actions.html', ctx)
    resp['Vary'] = 'Cookie'

    if request.user.is_authenticated:
        resp['Cache-Control'] = 'private'
    if actions:
        resp['Last-Modified'] = http_date(actions.last().when.timestamp())
    return resp
Example #33
0
 def test_correct_signature(self):
     now = http_date()
     signature = make_signature(self.mouse, self.rat.inbox, now)
     return self.send_follow(self.mouse, signature, now).status_code == 200
Example #34
0
def render_file(request, path):
    """
    Returns a resized version of the given photo.
    """
    path = clean_path(path)

    # check input
    form = PhotoForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest()

    # check permissions
    if not has_permission(posixpath.dirname(path), 'can_read', request.user):
        return HttpResponseForbidden()

    # check file exists
    filepath = os.path.join(settings.COCONUTS_DATA_ROOT, url2path(path))
    if not os.path.exists(filepath):
        raise Http404

    def create_cache_dir(cachefile):
        cachedir = os.path.dirname(cachefile)
        if not os.path.exists(cachedir):
            try:
                os.makedirs(cachedir)
            except OSError:
                # FIXME: checking then creating creates a race condition,
                # the directory can be created between these two steps
                pass

    mimetype = mimetypes.guess_type(filepath)[0]
    ratio = 0.75
    size = form.cleaned_data['size']
    cachesize = size, int(size * ratio)

    if mimetype in IMAGE_TYPES:
        # check thumbnail
        cachefile = os.path.join(settings.COCONUTS_CACHE_ROOT, str(size),
                                 url2path(path))
        if not os.path.exists(cachefile):
            create_cache_dir(cachefile)
            img = Image.open(filepath)

            # rotate if needed
            orientation = get_image_exif(img).get(EXIF_ORIENTATION)
            if orientation:
                img = img.rotate(ORIENTATIONS[orientation][2], Image.NEAREST,
                                 True)

            img.thumbnail(cachesize, Image.ANTIALIAS)
            img.save(cachefile, quality=90)
    elif mimetype in VIDEO_TYPES:
        mimetype = 'image/jpeg'
        path += '.jpg'
        cachefile = os.path.join(settings.COCONUTS_CACHE_ROOT, str(size),
                                 url2path(path))
        if not os.path.exists(cachefile):
            create_cache_dir(cachefile)
            info = get_video_info(filepath)
            pic_ratio = float(info['height']) / float(info['width'])
            if pic_ratio > ratio:
                width = int(cachesize[1] / pic_ratio)
                height = cachesize[1]
            else:
                width = cachesize[0]
                height = int(cachesize[0] * pic_ratio)
            subprocess.check_call([
                'avconv', '-loglevel', 'quiet', '-i', filepath, '-s',
                '%sx%s' % (width, height), '-vframes', '1', cachefile
            ])
    else:
        # unhandled file type
        return HttpResponseBadRequest()

    # serve the photo
    if hasattr(settings, 'COCONUTS_CACHE_ACCEL'):
        response = HttpResponse()
        response['X-Accel-Redirect'] = posixpath.join(
            settings.COCONUTS_CACHE_ACCEL, str(size), path)
    else:
        response = django.views.static.serve(
            request,
            posixpath.join(str(size), path),
            document_root=settings.COCONUTS_CACHE_ROOT)
    response['Content-Type'] = mimetype
    response['Expires'] = http_date(time.time() + 3600 * 24 * 365)
    return response
Example #35
0
def plugin_static_serve(request, plugin, path, show_indexes=False):
    """
    Serve static files below a given point in the directory structure.

    To use, put a URL pattern such as::

        (r'^(?P<path>.*)$', 'django.views.static.serve', {'document_root' : '/path/to/my/files/'})

    in your URLconf. You must provide the ``document_root`` param. You may
    also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
    of the directory.  This index view will use the template hardcoded below,
    but if you'd like to override it, you can create a template called
    ``static/directory_index.html``.
    """

    import mimetypes
    import os
    import posixpath
    import stat
    import urllib
    from email.Utils import parsedate_tz, mktime_tz

    from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
    from django.utils.http import http_date
    from django.views.static import was_modified_since, directory_index

    from django.conf import settings

    document_root = os.path.join(settings.PROJECT_ROOT, 'plugins', plugin,
                                 'media')

    # Clean up given path to only allow serving files below document_root.
    path = posixpath.normpath(urllib.unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')

    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)

    if os.path.isdir(fullpath):
        if show_indexes:
            return directory_index(newpath, fullpath)
        raise Http404("Directory indexes are not allowed here.")
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)

    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(mimetype=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, mimetype=mimetype)
    response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
    response["Content-Length"] = len(contents)
    return response
Example #36
0
 def dispatch(self, request, *args, **kwargs):
     response = super().dispatch(request, *args, **kwargs)
     if not self.is_modified(request):
         return HttpResponseNotModified()
     response['Last-Modified'] = http_date(self.last_timestamp)
     return response
Example #37
0
 def wrapper(request, *args, **kwargs):
     response = func(request, *args, **kwargs)
     response['Last-Modified'] = http_date()
     return response
Example #38
0
def static_media(request, module, path, root=None):
    """
    Serve static files below a given point in the directory structure.
    """
    from django.utils.http import http_date
    from django.views.static import was_modified_since
    import mimetypes
    import os.path
    import posixpath
    import stat
    import urllib

    if root:
        document_root = root
    elif module == 'sentry':
        document_root = os.path.join(settings.MODULE_ROOT, 'static', module)
    elif module == dj_settings.COMPRESS_OUTPUT_DIR:
        document_root = os.path.join(dj_settings.STATIC_ROOT, module)
    elif module not in dj_settings.INSTALLED_APPS:
        raise Http404('Invalid module provided.')
    else:
        if module not in STATIC_PATH_CACHE:
            try:
                mod = __import__(module)
            except ImportError:
                raise Http404('Import error raised while fetching module')

            STATIC_PATH_CACHE[module] = os.path.normpath(
                os.path.join(
                    os.path.dirname(mod.__file__),
                    'static',
                    module,
                ))

        document_root = STATIC_PATH_CACHE[module]

    path = posixpath.normpath(urllib.unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')
    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)
    if os.path.isdir(fullpath):
        raise Http404('Directory indexes are not allowed here.')
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)
    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(mimetype=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, mimetype=mimetype)
    response['Last-Modified'] = http_date(statobj[stat.ST_MTIME])
    response['Content-Length'] = len(contents)
    return response
Example #39
0
def view_summary(request, period='month', year=None, month=None):
    reference = datetime.now()
    year = reference.year if year is None else int(year)
    month = reference.month if month is None else int(month)
    reference = datetime(int(year), int(month), 1)

    if period == 'month':
        start_time = get_start_of_period(reference, request.user)
        end_time = get_end_of_period(start_time, request.user)
    elif period == 'year':
        if 'start_time' in request.GET and 'end_time' in request.GET:  # allow start/end time to be overwritten by URL
            start_time = datetime_from_string(request.GET['start_time'])
            end_time = datetime_from_string(request.GET['end_time'])
        else:
            start_time = get_start_of_period(datetime(int(year), 1, 1),
                                             request.user)
            end_time = datetime(start_time.year + 1, start_time.month,
                                start_time.day)

            start_time, end_time = adjust_start_end_times(
                request, start_time, end_time)
    else:
        raise Exception('Invalid period')

    last_period_start_time = get_start_of_period(
        reference - timedelta(days=15), request.user)
    last_period_end_time = get_end_of_period(last_period_start_time,
                                             request.user)

    summary, transactions, total = create_summary(request, start_time,
                                                  end_time, request.user)

    projected_transactions = []
    last_month = False
    # calculate projections for the current unfinished month only
    if period == 'month' and year == datetime.now(
    ).year and month == datetime.now().month:
        last_month = True
        last_period_transactions = transactions_for_period(
            request, last_period_start_time, last_period_end_time)
        transaction_descriptions = set([x.description for x in transactions])
        for last_period_transaction in last_period_transactions:
            if last_period_transaction.category and last_period_transaction.category.period == 1 and last_period_transaction.description not in transaction_descriptions:
                projected_transactions.append(last_period_transaction)

    if period == 'month':
        prev = first_of_previous_month(end_time)
        previous_year, previous_month = prev.year, prev.month
        next_url = first_of_next_month(end_time)
        next_year, next_month = next_url.year, first_of_next_month(
            end_time).month if not last_month else None,
        next_period = next_month
    elif period == 'year':
        previous_year, previous_month = year - 1, None
        next_year, next_month = year + 1, None
        next_period = year < datetime.now().year
    else:
        assert False

    resp = render_to_response(
        'money/view_period.html',
        RequestContext(
            request, {
                'lossgain': 'loss' if total < 0 else 'gain',
                'summary': summary,
                'total': total,
                'year': year,
                'month': month,
                'period': period,
                'monthly_average_divisor': (end_time - start_time).days / 30,
                'projected_transactions': projected_transactions,
                'projected_sum': sum(
                    [x.amount for x in projected_transactions]),
                'previous_year': previous_year,
                'previous_month': previous_month,
                'next_year': next_year,
                'next_month': next_month,
                'start_time': start_time,
                'end_time': end_time,
                'next_period': next_period,
                'transactions': transactions,
                'categories': Category.objects.filter(user=request.user),
            }))
    import time
    resp['Expires'] = http_date(time.time() + 1000)
    return resp
Example #40
0
 def get_modified_date(self):
     return http_date(mktime(self.modified.timetuple()))
Example #41
0
 def get_uploaded_date(self):
     return http_date(mktime(self.uploaded.timetuple()))
Example #42
0
    def process_response(self, request: HttpRequest,
                         response: HttpResponse) -> HttpResponse:
        if getattr(response, "asynchronous", False):
            # This special Tornado "asynchronous" response is
            # discarded after going through this code path as Tornado
            # intends to block, so we stop here to avoid unnecessary work.
            return response

        try:
            request.get_host()
        except DisallowedHost:
            # If we get a DisallowedHost exception trying to access
            # the host, (1) the request is failed anyway and so the
            # below code will do nothing, and (2) the below will
            # trigger a recursive exception, breaking things, so we
            # just return here.
            return response

        if (not request.path.startswith("/static/")
                and not request.path.startswith("/api/")
                and not request.path.startswith("/json/")):
            subdomain = get_subdomain(request)
            if subdomain != Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
                try:
                    get_realm(subdomain)
                except Realm.DoesNotExist:
                    return render(request,
                                  "zerver/invalid_realm.html",
                                  status=404)
        """
        If request.session was modified, or if the configuration is to save the
        session every time, save the changes and set a session cookie or delete
        the session cookie if the session has been emptied.
        """
        try:
            accessed = request.session.accessed
            modified = request.session.modified
            empty = request.session.is_empty()
        except AttributeError:
            pass
        else:
            # First check if we need to delete this cookie.
            # The session should be deleted only if the session is entirely empty
            if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
                response.delete_cookie(
                    settings.SESSION_COOKIE_NAME,
                    path=settings.SESSION_COOKIE_PATH,
                    domain=settings.SESSION_COOKIE_DOMAIN,
                )
            else:
                if accessed:
                    patch_vary_headers(response, ('Cookie', ))
                if (modified
                        or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
                    if request.session.get_expire_at_browser_close():
                        max_age = None
                        expires = None
                    else:
                        max_age = request.session.get_expiry_age()
                        expires_time = time.time() + max_age
                        expires = http_date(expires_time)
                    # Save the session data and refresh the client cookie.
                    # Skip session save for 500 responses, refs #3881.
                    if response.status_code != 500:
                        try:
                            request.session.save()
                        except UpdateError:
                            raise SuspiciousOperation(
                                "The request's session was deleted before the "
                                "request completed. The user may have logged "
                                "out in a concurrent request, for example.")
                        host = request.get_host().split(':')[0]

                        # The subdomains feature overrides the
                        # SESSION_COOKIE_DOMAIN setting, since the setting
                        # is a fixed value and with subdomains enabled,
                        # the session cookie domain has to vary with the
                        # subdomain.
                        session_cookie_domain = host
                        response.set_cookie(
                            settings.SESSION_COOKIE_NAME,
                            request.session.session_key,
                            max_age=max_age,
                            expires=expires,
                            domain=session_cookie_domain,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None,
                            samesite=settings.SESSION_COOKIE_SAMESITE,
                        )
        return response
Example #43
0
        def inner(request, *args, **kwargs):
            # Get HTTP request headers
            if_modified_since = request.META.get("HTTP_IF_MODIFIED_SINCE")
            if if_modified_since:
                if_modified_since = parse_http_date_safe(if_modified_since)
            if_none_match = request.META.get("HTTP_IF_NONE_MATCH")
            if_match = request.META.get("HTTP_IF_MATCH")
            if if_none_match or if_match:
                # There can be more than one ETag in the request, so we
                # consider the list of values.
                try:
                    etags = parse_etags(if_none_match or if_match)
                except ValueError:
                    # In case of invalid etag ignore all ETag headers.
                    # Apparently Opera sends invalidly quoted headers at times
                    # (we should be returning a 400 response, but that's a
                    # little extreme) -- this is Django bug #10681.
                    if_none_match = None
                    if_match = None

            # Compute values (if any) for the requested resource.
            res_last_modified, res_etag = get_last_modified_and_etag_func(last_modified_and_etag_func, request, *args,
                                                                          **kwargs)

            response = None
            if not ((if_match and (if_modified_since or if_none_match)) or
                        (if_match and if_none_match)):
                # We only get here if no undefined combinations of headers are
                # specified.
                if ((if_none_match and (res_etag in etags or
                                                    "*" in etags and res_etag)) and
                        (not if_modified_since or
                             (res_last_modified and if_modified_since and
                                      res_last_modified <= if_modified_since))):
                    if request.method in ("GET", "HEAD"):
                        response = HttpResponseNotModified()
                    else:
                        logger.warning('Precondition Failed: %s', request.path,
                                       extra={'status_code': 412, 'request': request}
                                       )
                        response = HttpResponse(status=412)
                elif if_match and ((not res_etag and "*" in etags) or
                                       (res_etag and res_etag not in etags)):
                    logger.warning('Precondition Failed: %s', request.path,
                                   extra={'status_code': 412, 'request': request}
                                   )
                    response = HttpResponse(status=412)
                elif (not if_none_match and request.method == "GET" and
                          res_last_modified and if_modified_since and
                              res_last_modified <= if_modified_since):
                    response = HttpResponseNotModified()

            if response is None:
                response = func(request, *args, **kwargs)

            # refresh last_modified and res_etag if needed
            if (request.method in ("PUT", "POST", "PATCH")) and (
                        (res_last_modified and not response.has_header('Last-Modified')) or
                        (res_etag and not response.has_header('ETag'))):  # refresh last_modified and res_etag!
                res_last_modified, res_etag = get_last_modified_and_etag_func(last_modified_and_etag_func, request,
                                                                              *args, **kwargs)

            # Set relevant headers on the response if they don't already exist.
            if res_last_modified and not response.has_header('Last-Modified'):
                response['Last-Modified'] = http_date(res_last_modified)
            if res_etag and not response.has_header('ETag'):
                response['ETag'] = quote_etag(res_etag)

            return response
Example #44
0
def staticfiles_handler_serve(self, request):
    import time
    resp = serve(request, self.file_path(request.path), insecure=True)
    if resp.status_code == 200:
        resp["Expires"] = http_date(time.time() + 24 * 3600)
    return resp
Example #45
0
def prop_dav_creationdate(dav, request, resource):
    return http_date(int(resource.created_at.strftime('%s')))
Example #46
0
def convert_date_for_last_modified(date):
    return http_date(timegm(date.utctimetuple()))
Example #47
0
def prop_dav_getlastmodified(dav, request, resource):
    return http_date(int(resource.updated_at.strftime('%s')))
Example #48
0
def getFormatLastModified(lastmodified):
    return http_date(time.mktime(lastmodified.timetuple()))
Example #49
0
 def test_http_date(self):
     t = 1167616461.0
     self.assertEqual(http_date(t), 'Mon, 01 Jan 2007 01:54:21 GMT')
Example #50
0
def gzip_compressor(request):
    plugins = split_commas(request.GET.get("plugins", ""))
    languages = split_commas(request.GET.get("languages", ""))
    themes = split_commas(request.GET.get("themes", ""))
    files = split_commas(request.GET.get("files", ""))
    source = request.GET.get("src", "") == "true"
    isJS = request.GET.get("js", "") == "true"
    compress = request.GET.get("compress", "true") == "true"
    content = []

    response = HttpResponse()
    response["Content-Type"] = "text/javascript"

    if not isJS:
        response.write(
            render_to_string(
                "tinymce/tiny_mce_gzip.js", {"base_url": tinymce.settings.JS_BASE_URL}
            )
        )
        return response

    patch_vary_headers(response, ["Accept-Encoding"])

    now = datetime.utcnow()
    response["Date"] = now.strftime("%a, %d %b %Y %H:%M:%S GMT")

    cacheKey = "|".join(plugins + languages + themes)
    cacheData = cache.get(cacheKey)

    if cacheData is not None:
        if "ETag" in cacheData:
            if_none_match = request.META.get("HTTP_IF_NONE_MATCH")
            if if_none_match == cacheData["ETag"]:
                response.status_code = 304
                response.content = ""
                response["Content-Length"] = "0"
                return response

        if "Last-Modified" in cacheData:
            if_modified_since = request.META.get("HTTP_IF_MODIFIED_SINCE")
            if if_modified_since == cacheData["Last-Modified"]:
                response.status_code = 304
                response.content = ""
                response["Content-Length"] = "0"
                return response

    tinyMCEPreInit = {
        "base": tinymce.settings.JS_BASE_URL,
        "suffix": "",
    }
    content.append(f"var tinyMCEPreInit={json.dumps(tinyMCEPreInit)};")

    # Add core
    files = ["tinymce"]

    # Add core languages
    for lang in languages:
        files.append(f"langs/{lang}")

    # Add plugins
    for plugin in plugins:
        files.append(f"plugins/{plugin}/plugin")

        for lang in languages:
            files.append(f"plugins/{plugin}/langs/{lang}")

    # Add themes
    for theme in themes:
        files.append(f"themes/{theme}/theme")

        for lang in languages:
            files.append(f"themes/{theme}/langs/{lang}")

    for f in files:
        # Check for unsafe characters
        if not safe_filename_re.match(f):
            continue
        content.append(get_file_contents(f, source=source))

    # Restore loading functions
    content.append(
        'tinymce.each("{}".split(",")'.format(",".join(files))
        + ', function(f){tinymce.ScriptLoader.markDone(tinyMCE.baseURL+"/"+f+".js");});'
    )

    # Compress
    if compress:
        content = compress_string(b"".join([c.encode("utf-8") for c in content]))
        response["Content-Encoding"] = "gzip"
        response["Content-Length"] = str(len(content))

    response.write(content)
    timeout = 3600 * 24 * 10
    patch_response_headers(response, timeout)
    if not response.has_header("Last-Modified"):
        response["Last-Modified"] = http_date()
    cache.set(
        cacheKey,
        {"Last-Modified": response["Last-Modified"], "ETag": response.get("ETag", "")},
    )
    return response
Example #51
0
def gzip_compressor(request):
    plugins = split_commas(request.GET.get('plugins', ''))
    languages = split_commas(request.GET.get('languages', ''))
    themes = split_commas(request.GET.get('themes', ''))
    isJS = request.GET.get('js', '') == 'true'
    compress = request.GET.get('compress', 'true') == 'true'
    suffix = request.GET.get('suffix', '') == '_src' and '_src' or ''
    content = []

    response = HttpResponse()
    response['Content-Type'] = 'text/javascript'

    if not isJS:
        response.write(render_to_string('tinymce/tiny_mce_gzip.js', {
            'base_url': tinymce.settings.JS_BASE_URL,
        }))
        return response

    patch_vary_headers(response, ['Accept-Encoding'])

    now = datetime.utcnow()
    response['Date'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')

    cacheKey = '|'.join(plugins + languages + themes)
    cacheData = cache.get(cacheKey)

    if cacheData is not None:
        if 'ETag' in cacheData:
            if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
            if if_none_match == cacheData['ETag']:
                response.status_code = 304
                response.content = ''
                response['Content-Length'] = '0'
                return response

        if 'Last-Modified' in cacheData:
            if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
            if if_modified_since == cacheData['Last-Modified']:
                response.status_code = 304
                response.content = ''
                response['Content-Length'] = '0'
                return response

    tinyMCEPreInit = {
        'base': tinymce.settings.JS_BASE_URL,
        'suffix': '',
    }
    content.append('var tinyMCEPreInit={!s};'.format(
        json.dumps(tinyMCEPreInit)
    ))

    # Add core
    files = ['tiny_mce']

    # Add core languages
    for lang in languages:
        files.append('langs/{!s}'.format(lang))

    # Add plugins
    for plugin in plugins:
        files.append('plugins/{!s}/editor_plugin{!s}'.format(plugin, suffix))

        for lang in languages:
            files.append('plugins/{!s}/langs/{!s}'.format(plugin, lang))

    # Add themes
    for theme in themes:
        files.append('themes/{!s}/editor_template{!s}'.format(theme, suffix))

        for lang in languages:
            files.append('themes/{!s}/langs/{!s}'.format(theme, lang))

    for f in files:
        # Check for unsafe characters
        if not safe_filename_re.match(f):
            continue
        content.append(get_file_contents('{!s}.js'.format(f)))

    # Restore loading functions
    content.append('tinymce.each("{!s}".split(","), function(f){{'
                   'tinymce.ScriptLoader.markDone(tinyMCE.baseURL+'
                   '"/"+f+".js");}});'.format(','.join(files)))

    unicode_content = []
    for i, c in enumerate(content):
        try:
            unicode_content.append(c.decode('latin-1'))
        except AttributeError:
            # python 3 way
            unicode_content.append(smart_text(c))
        except UnicodeDecodeError:
            try:
                unicode_content.append(c.decode('utf-8'))
            except Exception:
                print('{!s} is nor latin-1 nor utf-8.'.format(files[i]))
                raise

    # Compress
    if compress:
        content = compress_string(b''.join([c.encode('utf-8')
                                           for c in unicode_content]))
        response['Content-Encoding'] = 'gzip'
        response['Content-Length'] = str(len(content))

    response.write(content)
    timeout = 3600 * 24 * 10
    patch_response_headers(response, timeout)
    if not response.has_header('Last-Modified'):
        # Last-Modified not set since Django 1.11
        response['Last-Modified'] = http_date()
    cache.set(cacheKey, {
        'Last-Modified': response['Last-Modified'],
        'ETag': response.get('ETag', ''),
    })
    return response
Example #52
0
 def last_modified_http(self):
     """
     Return last modified date as a properly formatted string suitable for HTTP headers.
     """
     return http_date(mktime(self.last_modified.timetuple()))
Example #53
0
def serve_private_media(request, path):
    """Serve a private media file with the webserver's "sendfile" if possible.

    Here's an example of how to use this function. The 'Document' model tracks
    files. It provides a 'get_file_path' method returning the absolute path to
    the actual file. The following view serves file only to users having the
    'can_download' permission::

        @permission_required('documents.can_download')
        def download_document(request, document_id):
            path = Document.objects.get(pk=document_id).get_file_path()
            return serve_private_media(request, path)

    If ``DEBUG`` is ``False`` and ``settings.GALLERY_SENDFILE_HEADER`` is set,
    this function sets a header and doesn't send the actual contents of the
    file. Use ``'X-Accel-Redirect'`` for nginx and ``'X-SendFile'`` for Apache
    with mod_xsendfile. Otherwise, this function behaves like Django's static
    serve view.

    ``path`` must be an absolute path. Depending on your webserver's
    configuration, you might want a full path or a relative path in the
    header's value. ``settings.GALLERY_SENDFILE_ROOT`` will be stripped from
    the beginning of the path to create the header's value.
    """

    if not os.path.exists(path):
        # Don't reveal the file name on the filesystem.
        raise Http404("Requested file doesn't exist.")

    # begin copy-paste from django.views.static.serve
    statobj = os.stat(path)
    content_type, encoding = mimetypes.guess_type(path)
    content_type = content_type or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime,
                              statobj.st_size):  # pragma: no cover
        return HttpResponseNotModified()
    # pause copy-paste from django.views.static.serve

    sendfile_header = getattr(settings, 'GALLERY_SENDFILE_HEADER', '')
    sendfile_root = getattr(settings, 'GALLERY_SENDFILE_ROOT', '')

    if settings.DEBUG or not sendfile_header:
        response = StreamingHttpResponse(open(path, 'rb'),
                                         content_type=content_type)
    else:
        response = HttpResponse('', content_type=content_type)
        if sendfile_root:
            if not path.startswith(sendfile_root):
                raise ValueError(
                    "Requested file isn't under GALLERY_SENDFILE_ROOT.")
            path = path[len(sendfile_root):]
        response[sendfile_header] = path.encode(sys.getfilesystemencoding())

    # resume copy-paste from django.views.static.serve
    response["Last-Modified"] = http_date(statobj.st_mtime)
    if stat.S_ISREG(statobj.st_mode):  # pragma: no cover
        response["Content-Length"] = statobj.st_size
    if encoding:  # pragma: no cover
        response["Content-Encoding"] = encoding
    # end copy-paste from django.views.static.serve

    return response
Example #54
0
def serve(request,
          path,
          document_root=None,
          show_indexes=False,
          insecure=False):
    """
    Serve static files below a given point in the directory structure or
    from locations inferred from the static files finders.

    To use, put a URL pattern such as::

        (r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve')

    in your URLconf.

    If you provide the ``document_root`` parameter, the file won't be looked
    up with the staticfiles finders, but in the given filesystem path, e.g.::

    (r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve', {'document_root' : '/path/to/my/files/'})

    You may also set ``show_indexes`` to ``True`` if you'd like to serve a
    basic index of the directory.  This index view will use the
    template hardcoded below, but if you'd like to override it, you can create
    a template called ``static/directory_index.html``.
    """
    if not settings.DEBUG and not insecure:
        raise ImproperlyConfigured("The view to serve static files can only "
                                   "be used if the DEBUG setting is True or "
                                   "the --insecure option of 'runserver' is "
                                   "used")
    if not document_root:
        absolute_path = finders.find(path)
        if not absolute_path:
            raise Http404('"%s" could not be found' % path)
        document_root, path = os.path.split(absolute_path)
    # Clean up given path to only allow serving files below document_root.
    path = posixpath.normpath(urllib.unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')
    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)
    if os.path.isdir(fullpath):
        if show_indexes:
            return directory_index(newpath, fullpath)
        raise Http404("Directory indexes are not allowed here.")
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)
    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype, encoding = mimetypes.guess_type(fullpath)
    mimetype = mimetype or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(mimetype=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, mimetype=mimetype)
    response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
    response["Content-Length"] = len(contents)
    if encoding:
        response["Content-Encoding"] = encoding
    return response
Example #55
0
    def process_response(self, request, response):
        for url in self.IGNORE_URLS:
            if (request.path_info.startswith(url)
                    and settings.SESSION_COOKIE_NAME not in request.COOKIES
                    and self.cookie_name_fallback not in request.COOKIES):
                return response

        # Most of the code below is taken directly from Django's SessionMiddleware.
        # Some changes (marked with NOTE:) were added to support the fallback cookie.

        try:
            accessed = request.session.accessed
            modified = request.session.modified
            empty = request.session.is_empty()
        except AttributeError:
            pass
        else:
            # First check if we need to delete this cookie.
            # The session should be deleted only if the session is entirely empty
            # NOTE: This was changed to support both cookies
            if (settings.SESSION_COOKIE_NAME in request.COOKIES
                    or self.cookie_name_fallback in request.COOKIES) and empty:
                for cookie_name in (settings.SESSION_COOKIE_NAME,
                                    self.cookie_name_fallback):
                    if cookie_name in request.COOKIES:
                        response.delete_cookie(
                            cookie_name,
                            path=settings.SESSION_COOKIE_PATH,
                            domain=settings.SESSION_COOKIE_DOMAIN,
                        )
            else:
                if accessed:
                    patch_vary_headers(response, ('Cookie', ))
                if (modified
                        or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
                    if request.session.get_expire_at_browser_close():
                        max_age = None
                        expires = None
                    else:
                        max_age = request.session.get_expiry_age()
                        expires_time = time.time() + max_age
                        expires = http_date(expires_time)
                    # Save the session data and refresh the client cookie.
                    # Skip session save for 500 responses, refs #3881.
                    if response.status_code != 500:
                        try:
                            request.session.save()
                        except UpdateError:
                            raise SuspiciousOperation(
                                "The request's session was deleted before the "
                                "request completed. The user may have logged "
                                "out in a concurrent request, for example.")

                        response.set_cookie(
                            settings.SESSION_COOKIE_NAME,
                            request.session.session_key,
                            max_age=max_age,
                            expires=expires,
                            domain=settings.SESSION_COOKIE_DOMAIN,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None,
                            samesite=settings.SESSION_COOKIE_SAMESITE,
                        )

                        # NOTE: This was added to support the fallback cookie
                        if not settings.SESSION_COOKIE_SAMESITE:
                            # Forcibly set the session cookie to SameSite=None
                            # This isn't supported in Django<3.1
                            # https://github.com/django/django/pull/11894
                            response.cookies[settings.SESSION_COOKIE_NAME][
                                "samesite"] = "None"

                            # Set the fallback cookie in case the above cookie is rejected
                            response.set_cookie(
                                self.cookie_name_fallback,
                                request.session.session_key,
                                max_age=max_age,
                                expires=expires,
                                domain=settings.SESSION_COOKIE_DOMAIN,
                                path=settings.SESSION_COOKIE_PATH,
                                secure=settings.SESSION_COOKIE_SECURE or None,
                                httponly=settings.SESSION_COOKIE_HTTPONLY
                                or None,
                                samesite=settings.SESSION_COOKIE_SAMESITE,
                            )
        return response
Example #56
0
def download_translation_file(
    request,
    translation: Translation,
    fmt: Optional[str] = None,
    query_string: Optional[str] = None,
):
    if fmt is not None:
        try:
            exporter_cls = EXPORTERS[fmt]
        except KeyError:
            raise Http404("File format not supported")
        if not exporter_cls.supports(translation):
            raise Http404("File format not supported")
        exporter = exporter_cls(translation=translation)
        units = translation.unit_set.prefetch_full().order_by("position")
        if query_string:
            units = units.search(query_string).distinct()
        exporter.add_units(units)
        response = exporter.get_response(
            "{{project}}-{0}-{{language}}.{{extension}}".format(
                translation.component.slug))
    else:
        # Force flushing pending units
        try:
            translation.commit_pending("download", None)
        except WeblateLockTimeout:
            report_error(cause="Download commit")

        filenames = translation.filenames

        if len(filenames) == 1:
            extension = (
                os.path.splitext(translation.filename)[1]
                or f".{translation.component.file_format_cls.extension()}")
            if not os.path.exists(filenames[0]):
                raise Http404("File not found")
            # Create response
            response = FileResponse(
                open(filenames[0], "rb"),
                content_type=translation.component.file_format_cls.mimetype(),
            )
        else:
            extension = ".zip"
            response = zip_download(
                translation.get_filename(),
                filenames,
                translation.full_slug.replace("/", "-"),
            )

        # Construct filename (do not use real filename as it is usually not
        # that useful)
        project_slug = translation.component.project.slug
        component_slug = translation.component.slug
        language_code = translation.language.code
        filename = f"{project_slug}-{component_slug}-{language_code}{extension}"

        # Fill in response headers
        response["Content-Disposition"] = f"attachment; filename={filename}"

    if translation.stats.last_changed:
        response["Last-Modified"] = http_date(
            mktime(translation.stats.last_changed.timetuple()))

    return response
def to_http_date(dt):
    return http_date(calendar.timegm(dt.utctimetuple()))
Example #58
0
def FeedResponse(request, data, feed_type):
    feedgen = populate_feed(request, data, feed_type)
    response = HttpResponse(content_type=feedgen.content_type)
    response['Last-Modified'] = http_date(time())
    feedgen.write(response, 'utf-8')
    return response
Example #59
0
    def get(self, request, zipped_filename, embedded_filepath):
        """
        Handles GET requests and serves a static file from within the zip file.
        """
        assert VALID_STORAGE_FILENAME.match(
            zipped_filename
        ), "'{}' is not a valid content storage filename".format(
            zipped_filename)

        storage = default_storage

        # calculate the local file path to the zip file
        filename, ext = os.path.splitext(zipped_filename)
        zipped_path = generate_object_storage_name(filename, zipped_filename)

        # file size
        file_size = 0

        # if the zipfile does not exist on disk, return a 404
        if not storage.exists(zipped_path):
            return HttpResponseNotFound(
                '"%(filename)s" does not exist in storage' %
                {'filename': zipped_path})

        # if client has a cached version, use that (we can safely assume nothing has changed, due to MD5)
        if request.META.get('HTTP_IF_MODIFIED_SINCE'):
            return HttpResponseNotModified()

        zf_obj = storage.open(zipped_path)

        with zipfile.ZipFile(zf_obj) as zf:
            # if no path, or a directory, is being referenced, look for an index.html file
            if not embedded_filepath or embedded_filepath.endswith("/"):
                embedded_filepath += "index.html"

            # get the details about the embedded file, and ensure it exists
            try:
                info = zf.getinfo(embedded_filepath)
            except KeyError:
                return HttpResponseNotFound(
                    '"{}" does not exist inside "{}"'.format(
                        embedded_filepath, zipped_filename))

            # try to guess the MIME type of the embedded file being referenced
            content_type = mimetypes.guess_type(
                embedded_filepath)[0] or 'application/octet-stream'

            if not os.path.splitext(embedded_filepath)[1] == '.json':
                # generate a streaming response object, pulling data from within the zip  file
                response = FileResponse(zf.open(info),
                                        content_type=content_type)
                file_size = info.file_size
            else:
                # load the stream from json file into memory, replace the path_place_holder.
                content = zf.open(info).read()
                str_to_be_replaced = ('$' + exercises.IMG_PLACEHOLDER).encode()
                zipcontent = ('/' + request.resolver_match.url_name + "/" +
                              zipped_filename).encode()
                content_with_path = content.replace(str_to_be_replaced,
                                                    zipcontent)
                response = HttpResponse(content_with_path,
                                        content_type=content_type)
                file_size = len(content_with_path)

        # set the last-modified header to the date marked on the embedded file
        if info.date_time:
            response["Last-Modified"] = http_date(
                time.mktime(datetime.datetime(*info.date_time).timetuple()))

        #cache these resources forever; this is safe due to the MD5-naming used on content files
        response["Expires"] = "Sun, 17-Jan-2038 19:14:07 GMT"

        # set the content-length header to the size of the embedded file
        if file_size:
            response["Content-Length"] = file_size

        # ensure the browser knows not to try byte-range requests, as we don't support them here
        response["Accept-Ranges"] = "none"

        _add_access_control_headers(request, response)

        # restrict CSP to only allow resources to be loaded from the Studio host, to prevent info leakage
        # (e.g. via passing user info out as GET parameters to an attacker's server), or inadvertent data usage
        host = request.build_absolute_uri('/').strip("/")
        response[
            "Content-Security-Policy"] = "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: " + host

        return response
Example #60
0
def action(request, mode, ticket):
    mod_path, cls_name = settings.TICKET_CLASS.rsplit('.', 1)
    mod_path = mod_path.split('.').pop(0)
    tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

    if hasattr(settings, 'KEEP_IT_SIMPLE') and settings.KEEP_IT_SIMPLE:
        keep_it_simple = True
    else:
        keep_it_simple = False

    if mode == 'view':
        if request.method == 'POST':
            form = CommentForm(request.POST)
            if form.is_valid():
                com = tickets_comments()
                com.comment = form.cleaned_data['comment']
                com.ticket_id = ticket
                com.action = 6
                com.save(user=request.user)

                check_references(request, com)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 6, com.comment)

                mail_comment(request, com.pk)
                jabber_comment(request, com.pk)

            else:
                if 'resolution' in request.POST:
                    if request.POST['resolution'] and int(
                            request.POST['resolution']) > 0:
                        tic.resolution_id = request.POST['resolution']
                        tic.closed = True
                        tic.close_date = timezone.now()
                        tic.state = get_flow_end()
                        tic.save(user=request.user)

                        com = tickets_comments()
                        com.comment = _(
                            'ticket closed - resolution: %(resolution)s\n\n%(comment)s'
                        ) % {
                            'resolution':
                            ticket_resolution.objects.get(
                                pk=request.POST['resolution']).name,
                            'comment':
                            request.POST.get('close_comment', '')
                        }
                        com.ticket_id = ticket
                        com.action = 1
                        com.save(user=request.user)

                        check_references(request, com)

                        touch_ticket(request.user, ticket)

                        add_history(request, tic, 1,
                                    request.POST.get('close_comment', ''))

                        mail_comment(request, com.pk)
                        jabber_comment(request, com.pk)

                    else:
                        messages.add_message(request, messages.ERROR,
                                             _('no resolution selected'))

                else:
                    messages.add_message(request, messages.ERROR,
                                         _('comment invalid'))

            # reload ticket => last_action date has changed
            tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

        excludes = []
        form = TicketsForm(exclude_list=excludes,
                           is_stuff=request.user.is_staff,
                           user=request.user,
                           instance=tic,
                           customer=request.organisation.id,
                           view_only=True)
        close = TicketCloseForm()
        reassign = TicketReassignForm(initial={
            'assigned': tic.assigned_id,
            'state': tic.state
        })
        flows = list(
            ticket_flow_edges.objects.select_related('next').filter(
                now=tic.state).exclude(next__type=2).values_list('next',
                                                                 flat=True))
        flows.append(tic.state_id)
        reassign.fields['state'].queryset = reassign.fields[
            'state'].queryset.filter(id__in=flows)

        participants = tickets_participants.objects.select_related(
            'user').filter(ticket=ticket)
        comments = tickets_comments.objects.select_related('c_user').filter(
            ticket=ticket).order_by('c_date')

        close_allowed = ticket_flow_edges.objects.select_related(
            'next').filter(now=tic.state, next__type=2).count() > 0

        files = tickets_files.objects.filter(ticket=ticket, active_record=True)
        paginator = Paginator(files, 10)
        page = request.GET.get('page')
        try:
            files_lines = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            files_lines = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            files_lines = paginator.page(paginator.num_pages)

        add_breadcrumbs(request, ticket, '#', caption=tic.caption[:20])
        if 'YATSE' in request.GET and 'isUsingYATSE' not in request.session:
            request.session['isUsingYATSE'] = True

        return render(
            request, 'tickets/view.html', {
                'layout':
                'horizontal',
                'ticket':
                tic,
                'form':
                form,
                'close':
                close,
                'reassign':
                reassign,
                'files':
                files_lines,
                'comments':
                comments,
                'participants':
                participants,
                'close_allowed':
                close_allowed,
                'keep_it_simple':
                keep_it_simple,
                'last_action_date':
                http_date(time.mktime(tic.last_action_date.timetuple()))
            })

    elif mode == 'gallery':
        images = tickets_files.objects.filter(ticket=ticket,
                                              active_record=True)
        return render(request, 'tickets/gallery.html', {
            'layout': 'horizontal',
            'ticket': tic,
            'images': images
        })

    elif mode == 'history':
        history = tickets_history.objects.filter(ticket=ticket)
        return render(
            request, 'tickets/history.html', {
                'layout': 'horizontal',
                'ticket': tic,
                'history': history,
                'keep_it_simple': keep_it_simple
            })

    elif mode == 'reopen':
        if tic.closed:
            tic.closed = False
            tic.state = get_flow_start()
            tic.resolution = None
            tic.close_date = None
            tic.save(user=request.user)

            com = tickets_comments()
            com.comment = _('ticket reopend - resolution deleted')
            com.ticket_id = ticket
            com.action = 2
            com.save(user=request.user)

            check_references(request, com)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 2, None)

            mail_comment(request, com.pk)
            jabber_comment(request, com.pk)

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'move':
        if not tic.closed:
            old_state = tic.state

            tic.state = ticket_flow.objects.get(pk=request.POST['state'])
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            oldUser = str(User.objects.get(
                pk=tic.assigned_id)) if tic.assigned_id else None

            history_data = {
                'old': {
                    'comment': '',
                    'assigned': oldUser,
                    'state': str(old_state)
                },
                'new': {
                    'comment': _('ticket moved'),
                    'assigned': oldUser,
                    'state': str(tic.state)
                }
            }
            add_history(request, tic, 7, history_data)

        return HttpResponse('OK')

    elif mode == 'reassign':
        if not tic.closed:
            if 'assigned' in request.POST:
                if request.POST['assigned'] and int(
                        request.POST['assigned']) > 0:
                    old_assigned_user = tic.assigned
                    old_state = tic.state

                    tic.assigned_id = request.POST['assigned']
                    tic.state = ticket_flow.objects.get(
                        pk=request.POST['state'])
                    tic.save(user=request.user)

                    newUser = User.objects.get(pk=request.POST['assigned'])

                    com = tickets_comments()
                    com.comment = _(
                        'ticket reassigned to %(user)s\nstate now: %(state)s\n\n%(comment)s'
                    ) % {
                        'user': newUser,
                        'comment': request.POST.get('reassign_comment', ''),
                        'state': tic.state
                    }
                    com.ticket_id = ticket
                    com.action = 7
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, ticket)
                    if request.POST['assigned']:
                        touch_ticket(newUser, ticket)

                    mail_comment(request, com.pk)
                    jabber_comment(request, com.pk)

                    history_data = {
                        'old': {
                            'comment': '',
                            'assigned': str(old_assigned_user),
                            'state': str(old_state)
                        },
                        'new': {
                            'comment':
                            request.POST.get('reassign_comment', ''),
                            'assigned':
                            str(User.objects.get(pk=request.POST['assigned'])),
                            'state':
                            str(tic.state)
                        }
                    }
                    add_history(request, tic, 7, history_data)

                else:
                    messages.add_message(request, messages.ERROR,
                                         _('missing assigned user'))

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'edit' or (mode == 'simple' and
                            (not tic.keep_it_simple or tic.closed)
                            and keep_it_simple):
        excludes = ['resolution']
        if request.method == 'POST':
            form = TicketsForm(request.POST,
                               exclude_list=excludes,
                               is_stuff=request.user.is_staff,
                               user=request.user,
                               instance=tic,
                               customer=request.organisation.id)
            if form.is_valid():
                tic = form.save()

                if tic.keep_it_simple:
                    tic.keep_it_simple = False
                    tic.save(user=request.user)

                assigned = form.cleaned_data.get('assigned')
                if assigned:
                    touch_ticket(assigned, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = TicketsForm(exclude_list=excludes,
                               is_stuff=request.user.is_staff,
                               user=request.user,
                               instance=tic,
                               customer=request.organisation.id)
        if 'state' in form.fields:
            form.fields['state'].queryset = form.fields[
                'state'].queryset.exclude(type=2)
        return render(request, 'tickets/edit.html', {
            'ticket': tic,
            'layout': 'horizontal',
            'form': form
        })

    elif mode == 'simple':
        if request.method == 'POST':
            form = SimpleTickets(request.POST,
                                 initial={
                                     'caption': tic.caption,
                                     'description': tic.description,
                                     'priority': tic.priority,
                                     'assigned': tic.assigned
                                 })
            if form.is_valid():
                cd = form.cleaned_data
                tic.caption = cd['caption']
                tic.description = cd['description'].replace(u"\u00A0", " ")
                tic.priority = cd['priority']
                tic.assigned = cd['assigned']
                tic.deadline = cd['deadline']
                tic.show_start = cd['show_start']
                tic.component = cd['component']
                tic.save(user=request.user)

                if cd['assigned']:
                    touch_ticket(cd['assigned'], tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = SimpleTickets(
                initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned,
                    'deadline': tic.deadline,
                    'show_start': tic.show_start,
                    'component': tic.component,
                })
        return render(request, 'tickets/edit.html', {
            'ticket': tic,
            'layout': 'horizontal',
            'form': form,
            'mode': mode
        })

    elif mode == 'download':
        fileid = request.GET.get('file', -1)
        file_data = tickets_files.objects.get(id=fileid, ticket=ticket)
        src = '%s%s.dat' % (settings.FILE_UPLOAD_PATH, fileid)
        content_type = file_data.content_type
        if request.GET.get('preview') == 'yes' and os.path.isfile(
                '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
            src = '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)
            content_type = 'imgae/png'

        if request.GET.get(
                'resize',
                'no') == 'yes' and ('image' in file_data.content_type
                                    or 'pdf' in file_data.content_type):
            img = resize_image('%s' % (src), (200, 150), 75)
            output = io.BytesIO()
            img.save(output, 'PNG')
            output.seek(0)
            response = StreamingHttpResponse(output, content_type='image/png')

        else:
            response = StreamingHttpResponse(open('%s' % (src), "rb"),
                                             content_type=content_type)

        if 'noDisposition' not in request.GET:
            if request.GET.get('preview') == 'yes' and os.path.isfile(
                    '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
                response[
                    'Content-Disposition'] = 'attachment;filename="%s"' % content_type
            else:
                response[
                    'Content-Disposition'] = 'attachment;filename="%s"' % smart_str(
                        file_data.name)
        return response

    elif mode == 'upload':
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                if tickets_files.objects.filter(
                        active_record=True,
                        ticket=ticket,
                        checksum=request.FILES['file'].hash).count() > 0:
                    messages.add_message(
                        request, messages.ERROR,
                        _('File already exists: %s') %
                        request.FILES['file'].name)
                    if request.GET.get('Ajax') == '1':
                        return HttpResponse('OK')
                    return HttpResponseRedirect('/tickets/view/%s/' % ticket)
                f = tickets_files()
                f.name = request.FILES['file'].name
                f.size = request.FILES['file'].size
                f.checksum = request.FILES['file'].hash
                f.content_type = request.FILES['file'].content_type
                f.ticket_id = ticket
                f.public = True
                f.save(user=request.user)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 5, request.FILES['file'].name)

                mail_file(request, f.pk)
                jabber_file(request, f.pk)

                dest = settings.FILE_UPLOAD_PATH
                if not os.path.exists(dest):
                    os.makedirs(dest)

                with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                    for chunk in request.FILES['file'].chunks():
                        destination.write(chunk)

                if 'pdf' in f.content_type:
                    convertPDFtoImg('%s/%s.dat' % (dest, f.id),
                                    '%s/%s.preview' % (dest, f.id))
                else:
                    if 'image' not in f.content_type and isPreviewable(
                            f.content_type):
                        tmp = convertOfficeTpPDF('%s/%s.dat' % (dest, f.id))
                        convertPDFtoImg(tmp, '%s/%s.preview' % (dest, f.id))
                        if os.path.isfile(tmp):
                            os.unlink(tmp)

                return HttpResponseRedirect('/tickets/view/%s/' % tic.pk)

            else:
                msg = unicode(form.errors['file'])
                msg = re.sub('<[^<]+?>', '', msg)
                messages.add_message(request, messages.ERROR, msg)
                if request.GET.get('Ajax') == '1':
                    return HttpResponse('OK')
                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        elif request.method == 'PUT':
            # /tickets/upload/XXX/?filename=test1.txt
            upload_handlers = request.upload_handlers
            content_type = str(request.META.get('CONTENT_TYPE', ""))
            content_length = int(request.META.get('CONTENT_LENGTH', 0))

            if content_type == "":
                return HttpResponse('missing ContentType', status=400)
            if content_length == 0:
                # both returned 0
                return HttpResponse('missing ContentLength', status=400)

            content_type = content_type.split(";")[0].strip()
            try:
                charset = content_type.split(";")[1].strip()
            except IndexError:
                charset = ""

            # we can get the file name via the path, we don't actually
            file_name = request.GET['filename']
            field_name = file_name

            counters = [0] * len(upload_handlers)

            for handler in upload_handlers:
                result = handler.handle_raw_input("", request.META,
                                                  content_length, "", "")

            from django.core.files.uploadhandler import StopFutureHandlers
            for handler in upload_handlers:
                try:
                    handler.new_file(field_name, file_name, content_type,
                                     content_length, charset)
                except StopFutureHandlers:
                    break

            for i, handler in enumerate(upload_handlers):
                while True:
                    chunk = request.read(handler.chunk_size)
                    if chunk:

                        handler.receive_data_chunk(chunk, counters[i])
                        counters[i] += len(chunk)
                    else:
                        # no chunk
                        break

            for i, handler in enumerate(upload_handlers):
                file_obj = handler.file_complete(counters[i])
                if file_obj:
                    if settings.FILE_UPLOAD_VIRUS_SCAN and pyclamd:
                        # virus scan
                        try:
                            if not hasattr(pyclamd, 'scan_stream'):
                                cd = pyclamd.ClamdUnixSocket()
                            else:
                                pyclamd.init_network_socket('localhost', 3310)
                                cd = pyclamd

                            # We need to get a file object for clamav. We might have a path or we might
                            # have to read the data into memory.
                            if hasattr(file_obj, 'temporary_file_path'):
                                os.chmod(file_obj.temporary_file_path(), 0664)
                                result = cd.scan_file(
                                    file_obj.temporary_file_path())
                            else:
                                if hasattr(file_obj, 'read'):
                                    result = cd.scan_stream(file_obj.read())
                                else:
                                    result = cd.scan_stream(
                                        file_obj['content'])
                        except:
                            from socket import gethostname
                            raise Exception(
                                _(u'unable to initialize scan engine on host %s'
                                  ) % gethostname())

                        if result:
                            msg = ' '.join(result[result.keys()[0]]).replace(
                                'FOUND ', '')
                            raise Exception(
                                _(u"file is infected by virus: %s") % msg)

                    hasher = hashlib.md5()
                    # We need to get a file object for clamav. We might have a path or we might
                    # have to read the data into memory.
                    if hasattr(file_obj, 'temporary_file_path'):
                        with open(file_obj.temporary_file_path(),
                                  'rb') as afile:
                            buf = afile.read()
                            hasher.update(buf)
                        hash = hasher.hexdigest()
                    else:
                        if hasattr(file_obj, 'read'):
                            file_obj.seek(0)
                            buf = file_obj.read()
                            hasher.update(buf)
                        else:
                            hasher.update(file_obj['content'].read())
                    hash = hasher.hexdigest()

                    if tickets_files.objects.filter(active_record=True,
                                                    ticket=ticket,
                                                    checksum=hash).count() > 0:
                        raise Exception(
                            'duplicate hash value - file already exists in this ticket %s'
                            % ticket)

                    # todo: virusscan
                    f = tickets_files()
                    f.name = file_obj.name
                    f.size = file_obj.size
                    f.checksum = hash
                    f.content_type = content_type
                    f.ticket_id = ticket
                    f.public = True
                    f.save(user=request.user)

                    touch_ticket(request.user, ticket)

                    add_history(request, tic, 5, file_obj.name)

                    mail_file(request, f.pk)
                    jabber_file(request, f.pk)

                    dest = settings.FILE_UPLOAD_PATH
                    if not os.path.exists(dest):
                        os.makedirs(dest)

                    with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                        for chunk in file_obj.chunks():
                            destination.write(chunk)

                    if 'pdf' in f.content_type:
                        convertPDFtoImg('%s/%s.dat' % (dest, f.id),
                                        '%s/%s.preview' % (dest, f.id))
                    else:
                        if 'image' not in f.content_type and isPreviewable(
                                f.content_type):
                            try:
                                tmp = convertOfficeTpPDF('%s/%s.dat' %
                                                         (dest, f.id))
                                convertPDFtoImg(tmp,
                                                '%s/%s.preview' % (dest, f.id))
                                if os.path.isfile(tmp):
                                    os.unlink(tmp)
                            except:
                                pass

                        if 'audio' in f.content_type:
                            try:
                                # https://realpython.com/python-speech-recognition/
                                import speech_recognition as sr
                                AUDIO_FILE = '%s%s.dat' % (dest, f.id)
                                r = sr.Recognizer()
                                with sr.AudioFile(AUDIO_FILE) as source:
                                    audio = r.record(
                                        source)  # read the entire audio file

                                text = r.recognize_google(audio,
                                                          language='de-DE')
                                if text:
                                    com = tickets_comments()
                                    com.comment = text
                                    com.ticket_id = ticket
                                    com.action = 6
                                    com.save(user=request.user)
                            except:
                                pass

                    return HttpResponse(status=201)

                else:
                    # some indication this didn't work?
                    return HttpResponse(status=500)

        else:
            form = UploadFileForm()

        return render(request, 'tickets/file.html', {
            'ticketid': ticket,
            'layout': 'horizontal',
            'form': form
        })

    elif mode == 'delfile':
        file = tickets_files.objects.get(pk=request.GET['fileid'],
                                         ticket=ticket)
        file.delete(user=request.user)

        touch_ticket(request.user, ticket)

        add_history(request, tic, 8, file.name)

        return HttpResponseRedirect('/tickets/view/%s/#files' % tic.pk)

    elif mode == 'notify':
        tickets_participants.objects.filter(
            ticket=tic, user=request.user).update(seen=True)
        return HttpResponse('OK')

    elif mode == 'sleep':
        interval = request.GET.get('interval')
        if interval in ['1', '2', '3', '4', '5', '6', '7', '14', '21', '30']:
            old = tic.show_start
            tic.show_start = timezone.now() + datetime.timedelta(
                days=int(interval))
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 10, (tic.show_start, old))

            return HttpResponse('OK')

        else:
            raise Exception('no interval given')

    elif mode == 'ignore':
        ig = tickets_ignorants()
        ig.ticket = tic
        ig.user = request.user
        ig.save()
        return HttpResponse('OK')

    elif mode == 'todo':

        class local:
            counter = 0

        def ToDoDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[X]'
            else:
                return u'[%s]' % group[0]

        def ToDoUnDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[ ]'
            else:
                return u'[%s]' % group[0]

        form = ToDo(request.POST)
        if form.is_valid():
            desc = tic.description

            cd = form.cleaned_data
            text = cd['text']
            pos = cd['item']
            set = cd['set']
            if set:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoDone, desc)
                old = _('undone: %s') % text
                new = _('done: %s') % text
            else:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoUnDone, desc)
                new = _('undone: %s') % text
                old = _('done: %s') % text

            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 9, (new, old))

            data = {
                'set': set,
                'item': pos,
                'text': text,
            }
            return JsonResponse(data, safe=False)

    elif mode == 'update_comment':

        if request.method == 'POST':
            comment_id = request.GET.get("comment_id")
            comment = tickets_comments.objects.get(pk=comment_id)

            if comment.c_user == request.user:
                comment.comment = request.POST.get("comment_body", "")
                comment.edited = True
                comment.save(user=request.user)

        return HttpResponseRedirect("/tickets/view/%s/#comment_id-%s" %
                                    (ticket, comment_id))

    elif mode == 'last_modified':
        if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
        if if_modified_since:
            if_modified_since = parse_http_date_safe(if_modified_since)
            if time.mktime(
                    tic.last_action_date.timetuple()) > if_modified_since:
                return HttpResponse('outdated', status=200)
            else:
                return HttpResponse('not modified', status=304)

        else:
            return HttpResponse('unknown', status=412)