Exemple #1
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-None-Match must be ignored if original result would be anything
        # other than a 2XX or 304 status. 304 status would result in no change.
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
        if 200 <= response.status_code < 300 and 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-Modified-Since must be ignored if the original result was not a 200.
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
        if response.status_code == 200 and 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
Exemple #2
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:
                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
Exemple #3
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
    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
Exemple #5
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
Exemple #6
0
def image(request):
    url = request.GET.get('url')
    if not url:
        return HttpResponseNotFound('Provide a url get param')
    image_path = get_image_cache_path(url)
    if os.path.isfile(image_path):
        image_file = open(image_path, 'rb')
        return HttpResponse(image_file, content_type='image/' + os.path.splitext(image_path)[1][1:])

    try:
        response = requests.get(url)
    except ConnectionError:
        return HttpResponseNotFound('Error connecting to image host')
    if response.status_code != 200:
        return HttpResponseNotFound('Not Found')
    if 'Last-Modified' in response.headers:
        modified = parse_http_date_safe(response.headers['Last-Modified'])
    else:
        modified = time.mktime(timezone.now().utctimetuple())
    with open(image_path, 'wb') as image_file:
        image_file.write(response.content)
    os.utime(image_path, (int(modified), int(modified)))
    response = HttpResponse(response.content, content_type=response.headers['Content-Type'])
    response['Last-Modified'] = http_date(modified)
    return response
Exemple #7
0
    def process_response(self, request, response):
        if not response.streaming and not response.has_header('Content-Length'):
            response['Content-Length'] = str(len(response.content))

        # It's too late to prevent an unsafe request with a 412 response, and
        # for a HEAD request, the response body is always empty so computing
        # an accurate ETag isn't possible.
        if request.method != 'GET':
            return response

        if self.needs_etag(response) and not response.has_header('ETag'):
            set_response_etag(response)

        etag = response.get('ETag')
        last_modified = response.get('Last-Modified')
        if last_modified:
            last_modified = parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(
                request,
                etag=etag,
                last_modified=last_modified,
                response=response,
            )

        return response
Exemple #8
0
def get_conditional_response(request,
                             etag=None,
                             last_modified=None,
                             response=None):
    # Only return conditional responses on successful requests.
    if response and not (200 <= response.status_code < 300):
        return response

    # Get HTTP request headers.
    if_match_etags = parse_etags(request.META.get('HTTP_IF_MATCH', ''))
    if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
    if_unmodified_since = if_unmodified_since and parse_http_date_safe(
        if_unmodified_since)
    if_none_match_etags = parse_etags(
        request.META.get('HTTP_IF_NONE_MATCH', ''))
    if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
    if_modified_since = if_modified_since and parse_http_date_safe(
        if_modified_since)

    # Step 1 of section 6 of RFC 7232: Test the If-Match precondition.
    if if_match_etags and not _if_match_passes(etag, if_match_etags):
        return _precondition_failed(request)

    # Step 2: Test the If-Unmodified-Since precondition.
    if (not if_match_etags
            and if_unmodified_since and not _if_unmodified_since_passes(
                last_modified, if_unmodified_since)):
        return _precondition_failed(request)

    # Step 3: Test the If-None-Match precondition.
    if if_none_match_etags and not _if_none_match_passes(
            etag, if_none_match_etags):
        if request.method in ('GET', 'HEAD'):
            return _not_modified(request, response)
        else:
            return _precondition_failed(request)

    # Step 4: Test the If-Modified-Since precondition.
    if (not if_none_match_etags and if_modified_since and
            not _if_modified_since_passes(last_modified, if_modified_since)):
        if request.method in ('GET', 'HEAD'):
            return _not_modified(request, response)

    # Step 5: Test the If-Range precondition (not supported).
    # Step 6: Return original response since there isn't a conditional response.
    return response
Exemple #9
0
    def pull(self, ifmodified=False):
        """
        Pull a file served by a Geotrek server.

        Set 'if-modified-since' HTTP request header to reduce bandwidth.
        """
        headers = {}
        if self.language:
            cprint('/' + self.language, 'cyan', end='', file=self.stdout)
            headers.update({'Accept-language': self.language})

        if ifmodified:
            try:
                # If local file is empty, force retrieval
                assert getsize(self.path) > settings.MIN_BYTE_SYZE
                # Use datetime of previous file to set header
                mtime = getmtime(self.path)
                headers.update({'if-modified-since': http_date(mtime)})
            except (OSError, AssertionError):
                pass
        cprint('/%s ...' % self.url,
               'white',
               attrs=['bold'],
               end=' ',
               file=self.stdout)
        self.stdout.flush()
        self.reply = self.client.get(self.url, headers=headers)

        if self.reply.status_code in (304, ):
            cprint("%s (Up-to-date)" % self.reply.status_code,
                   'green',
                   attrs=['bold'],
                   file=self.stdout)
            return
        elif self.reply.status_code != requests.codes.ok:
            cprint("%s (Failed)" % self.reply.status_code,
                   'red',
                   attrs=['bold'],
                   file=self.stderr)
            raise IOError("Failed to retrieve %s (code: %s)" %
                          (self.reply.url, self.reply.status_code))
        else:
            cprint("%s (Download)" % self.reply.status_code,
                   'yellow',
                   file=self.stdout)

        mkdir_p(dirname(self.path_tmp))
        with open(self.path_tmp, 'wb') as f:
            f.write(self.content())
            f.write("\n")
        logger.debug("  %s\n" %
                     self.path.replace(settings.INPUT_DATA_ROOT, ''))

        last_modified = parse_http_date_safe(
            self.reply.headers.get('last-modified'))
        if last_modified:
            utime(self.path_tmp, (last_modified, last_modified))
Exemple #10
0
def not_modified_since(request, exercise):
    if (
        request.method != 'GET'
        or exercise.get('personalized', False)
        or not exercise.get('cacheable', True)
    ):
        return False
    time = parse_http_date_safe(request.META.get('HTTP_IF_MODIFIED_SINCE'))
    return time and time >= exercise['mtime']
Exemple #11
0
def check_not_modified(request, last_modified):
    """Handle 304/If-Modified-Since

    With Django v1.9.5+ could just use "django.utils.cache.get_conditional_response", but v1.9 is
    not supported by "logan" dependancy (yet).
    """

    if_modified_since = parse_http_date_safe(request.META.get('HTTP_IF_MODIFIED_SINCE'))
    return (last_modified and
            if_modified_since and
            seconds_since_epoch(last_modified) <= if_modified_since)
Exemple #12
0
    def last_modified_datetime(self):
        """
        Return the last-modified header from the most recent names update as datetime.
        :return: datetime (or None on error)
        """
        if self.last_modified:
            date_epoch = parse_http_date_safe(self.last_modified)
            if date_epoch:
                return datetime.utcfromtimestamp(date_epoch)

        return None
Exemple #13
0
    def last_modified_datetime(self):
        """
        Return the last-modified header from the most recent names update as datetime.
        :return: datetime (or None on error)
        """
        if self.last_modified:
            date_epoch = parse_http_date_safe(self.last_modified)
            if date_epoch:
                return datetime.utcfromtimestamp(date_epoch)

        return None
def get_conditional_response(request, etag=None, last_modified=None, response=None):
    # Only return conditional responses on successful requests.
    if response and not (200 <= response.status_code < 300):
        return response

    # Get HTTP request headers.
    if_match_etags = parse_etags(request.META.get('HTTP_IF_MATCH', ''))
    if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
    if if_unmodified_since:
        if_unmodified_since = parse_http_date_safe(if_unmodified_since)
    if_none_match_etags = parse_etags(request.META.get('HTTP_IF_NONE_MATCH', ''))
    if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
    if if_modified_since:
        if_modified_since = parse_http_date_safe(if_modified_since)

    # Step 1 of section 6 of RFC 7232: Test the If-Match precondition.
    if if_match_etags and not _if_match_passes(etag, if_match_etags):
        return _precondition_failed(request)

    # Step 2: Test the If-Unmodified-Since precondition.
    if (not if_match_etags and if_unmodified_since and
            not _if_unmodified_since_passes(last_modified, if_unmodified_since)):
        return _precondition_failed(request)

    # Step 3: Test the If-None-Match precondition.
    if if_none_match_etags and not _if_none_match_passes(etag, if_none_match_etags):
        if request.method in ('GET', 'HEAD'):
            return _not_modified(request, response)
        else:
            return _precondition_failed(request)

    # Step 4: Test the If-Modified-Since precondition.
    if (not if_none_match_etags and if_modified_since and
            not _if_modified_since_passes(last_modified, if_modified_since)):
        if request.method in ('GET', 'HEAD'):
            return _not_modified(request, response)

    # Step 5: Test the If-Range precondition (not supported).
    # Step 6: Return original response since there isn't a conditional response.
    return response
Exemple #15
0
def export_json(request):
    if request.GET.get("all") == "true":
        return HttpResponseJSON(Release.objects.all_as_list(), cors=True)

    mod_date = parse_http_date_safe(request.META.get("HTTP_IF_MODIFIED_SINCE"))
    if mod_date:
        mod_date = datetime.datetime.fromtimestamp(mod_date,
                                                   datetime.timezone.utc)
    else:
        mod_date = now() - datetime.timedelta(days=30)

    return HttpResponseJSON(
        Release.objects.recently_modified_list(mod_date=mod_date), cors=True)
Exemple #16
0
    def process_response(self, request, response):

        # 总会正确设置Date和Content-Length部分
        response['Date'] = http_date()
        if not response.streaming and not response.has_header(
                'Content-Length'):
            response['Content-Length'] = str(len(response.content))

        # If-None-Match must be ignored if original result would be anything
        # other than a 2XX or 304 status. 304 status would result in no change.
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
        # 比较ETag和IF_NONE部分
        if 200 <= response.status_code < 300 and 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-Modified-Since must be ignored if the original result was not a 200.
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
        # 比较Last_Modified和IF_MODIFIED部分
        if response.status_code == 200 and response.has_header(
                'Last-Modified'):
            if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
            if if_modified_since is not None:
                # 解析出Modified时间
                if_modified_since = parse_http_date_safe(if_modified_since)
            if if_modified_since is not None:
                # 解析出Last时间
                last_modified = parse_http_date_safe(response['Last-Modified'])
                # 如果符合条件就返回304.
                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
    def get_modification_date(self):
        """
        Return the date and time of the last modification to this resource as
        reported by the remote source.

        :return: The modification date and time, or None if unknown.
        :rtype:  datetime | None
        """
        if self._modification_date is None:
            metadata = self._get_metadata()
            timestamp = parse_http_date_safe(metadata.get("last-modified"))
            if timestamp:
                self._modification_date = datetime.fromtimestamp(timestamp, utc)
        return self._modification_date
Exemple #18
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))

        etag = response.get("ETag")
        last_modified = response.get("Last-Modified")
        if last_modified:
            last_modified = parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(request, etag=etag, last_modified=last_modified, response=response)

        return response
Exemple #19
0
    def list(self, request, **kwargs):
        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_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
        if if_unmodified_since:
            if_unmodified_since = parse_http_date_safe(if_unmodified_since)
        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
Exemple #20
0
def message(request, msgid):
    ensure_message_permissions(request, msgid)

    try:
        m = Message.objects.get(messageid=msgid)
    except Message.DoesNotExist:
        raise Http404('Message does not exist')

    lists = List.objects.extra(where=["listid IN (SELECT listid FROM list_threads WHERE threadid=%s)" % m.threadid]).order_by('listname')
    listmap = dict([(l.listid, l.listname) for l in lists])
    threadstruct = list(_build_thread_structure(m.threadid))
    newest = calendar.timegm(max(threadstruct, key=lambda x: x['date'])['date'].utctimetuple())
    if 'HTTP_IF_MODIFIED_SINCE' in request.META and not settings.DEBUG:
        ims = parse_http_date_safe(request.META.get("HTTP_IF_MODIFIED_SINCE"))
        if ims >= newest:
            return HttpResponseNotModified()

    responses = [t for t in threadstruct if t['parentid'] == m.id]

    if m.parentid:
        for t in threadstruct:
            if t['id'] == m.parentid:
                parent = t
                break
    else:
        parent = None
    nextprev = _get_nextprevious(listmap, m.date)

    r = render_nav(NavContext(request, lists[0].listid, lists[0].listname), 'message.html', {
        'msg': m,
        'threadstruct': threadstruct,
        'responses': responses,
        'parent': parent,
        'lists': lists,
        'nextprev': nextprev,
        'og': {
            'url': 'message-id/{}'.format(quote(m.messageid)),
            'author': m.from_name_only(),
            'time': m.date,
            'title': m.subject,
            'description': m.bodytxt,
        },
    })
    if settings.PUBLIC_ARCHIVES:
        r['xkey'] = 'pgat_{0}'.format(m.threadid)
    r['Last-Modified'] = http_date(newest)
    return r
Exemple #21
0
 def process_request(self, request):
     self.key_prefix = self.get_key_prefix(request)
     request._cache_cache_timeout = int(self.cache_timeout)
     response = super().process_request(request)
     if response:
         etag = response.get('ETag')
         last_modified = response.get('Last-Modified')
         if not (etag or last_modified):
             return response
         response = get_conditional_response(
             request,
             etag=etag,
             last_modified=last_modified and parse_http_date_safe(last_modified),
             response=response,
         )
         response['Last-Modified'] = last_modified
         return response
Exemple #22
0
    def test_attachment_raw_requires_attachment_host(self):
        resp = self._post_new_attachment()
        attachment = Attachment.objects.get(title="Test uploaded file")

        url = attachment.get_file_url()
        resp = self.client.get(url)
        eq_(301, resp.status_code)
        eq_(attachment.get_file_url(), resp["Location"])

        url = attachment.get_file_url()
        resp = self.client.get(url, HTTP_HOST=settings.ATTACHMENT_HOST)
        eq_("ALLOW-FROM: %s" % settings.DOMAIN, resp["x-frame-options"])
        eq_(200, resp.status_code)
        ok_("Last-Modified" in resp)
        ok_("1970" not in resp["Last-Modified"])
        ok_("GMT" in resp["Last-Modified"])
        ok_(parse_http_date_safe(resp["Last-Modified"]) is not None)
Exemple #23
0
    def test_attachment_raw_requires_attachment_host(self):
        resp = self._post_new_attachment()
        attachment = Attachment.objects.get(title='Test uploaded file')

        url = attachment.get_file_url()
        resp = self.client.get(url)
        eq_(301, resp.status_code)
        eq_(attachment.get_file_url(), resp['Location'])

        url = attachment.get_file_url()
        resp = self.client.get(url, HTTP_HOST=settings.ATTACHMENT_HOST)
        eq_('ALLOW-FROM: %s' % settings.DOMAIN, resp['x-frame-options'])
        eq_(200, resp.status_code)
        ok_('Last-Modified' in resp)
        ok_('1970' not in resp['Last-Modified'])
        ok_('GMT' in resp['Last-Modified'])
        ok_(parse_http_date_safe(resp['Last-Modified']) is not None)
Exemple #24
0
 def get_conditional_response(self, request):
     # etag
     etag = self.get_etag()
     if_none_match_etags = set(etag.strip("W/") for etag in parse_etags(request.META.get('HTTP_IF_NONE_MATCH', '')))
     if etag and etag.strip("W/") in if_none_match_etags:
         return self.make_not_modified_response()
     # last modified
     last_modified_dt = self.get_last_modified_dt()
     if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
     if_modified_since = if_modified_since and parse_http_date_safe(if_modified_since)
     if (
         not if_none_match_etags and
         isinstance(last_modified_dt, datetime) and
         if_modified_since and
         int(last_modified_dt.timestamp()) <= if_modified_since
     ):
         return self.make_not_modified_response()
     return self.build_and_make_response()
    def pull(self, ifmodified=False):
        """
        Pull a file served by a Geotrek server.

        Set 'if-modified-since' HTTP request header to reduce bandwidth.
        """
        headers = {}
        if self.language:
            cprint('/' + self.language, 'cyan', end='', file=self.stdout)
            headers.update({'Accept-language': self.language})

        if ifmodified:
            try:
                # If local file is empty, force retrieval
                assert getsize(self.path) > settings.MIN_BYTE_SYZE
                # Use datetime of previous file to set header
                mtime = getmtime(self.path)
                headers.update({'if-modified-since': http_date(mtime)})
            except (OSError, AssertionError):
                pass
        cprint('/%s ...' % self.url, 'white', attrs=['bold'], end=' ', file=self.stdout)
        self.stdout.flush()
        self.reply = self.client.get(self.url, headers=headers)

        if self.reply.status_code in (304,):
            cprint("%s (Up-to-date)" % self.reply.status_code, 'green', attrs=['bold'], file=self.stdout)
            return
        elif self.reply.status_code != requests.codes.ok:
            cprint("%s (Failed)" % self.reply.status_code, 'red', attrs=['bold'], file=self.stderr)
            raise IOError("Failed to retrieve %s (code: %s)" % (self.reply.url,
                                                                self.reply.status_code))
        else:
            cprint("%s (Download)" % self.reply.status_code, 'yellow', file=self.stdout)

        mkdir_p(dirname(self.path_tmp))
        with open(self.path_tmp, 'wb') as f:
            f.write(self.content())
            f.write("\n")
        logger.debug("  %s\n" % self.path.replace(settings.INPUT_DATA_ROOT, ''))

        last_modified = parse_http_date_safe(self.reply.headers.get('last-modified'))
        if last_modified:
            utime(self.path_tmp, (last_modified, last_modified))
Exemple #26
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))

        etag = response.get('ETag')
        last_modified = response.get('Last-Modified')
        if last_modified:
            last_modified = parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(
                request,
                etag=unquote_etag(etag),
                last_modified=last_modified,
                response=response,
            )

        return response
Exemple #27
0
    def get(self, request, path):
        path = path.strip("/")
        if path == "":
            listing = Item(id="")
            for input_config in self.service.config.get("inputs", []):
                if not input_config or not input_config["input"]:
                    continue
                plugin = input_config["input"]

                item = plugin.get_item("")
                item.id = plugin.name
                listing.add_item(item)

            return Response(listing.serialize())
        else:
            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 if_modified_since:
                if_modified_since = datetime.fromtimestamp(
                    if_modified_since, pytz.UTC)

            depth = int(request.GET.get("depth", 0))

            plugin, plugin_path = self.get_plugin_path(path)

            if not plugin:
                raise Http404

            item = InputPluginManager.get_item(plugin, plugin_path)

            logger.info(
                f"Trying to create listing for {plugin!r} - path:{plugin_path} - last_modified:{if_modified_since}"
            )
            item.list(depth=depth)

            if not item.is_readable and not item.is_listable:
                raise Http404

            if if_modified_since and item.modified <= if_modified_since:
                return HttpResponseNotModified()

            return Response(item.serialize())
Exemple #28
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))

        etag = response.get('ETag')
        last_modified = response.get('Last-Modified')
        if last_modified:
            last_modified = parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(
                request,
                etag=etag,
                last_modified=last_modified,
                response=response,
            )

        return response
Exemple #29
0
    def test_attachment_raw_requires_attachment_host(self):
        response = self._post_attachment()
        attachment = Attachment.objects.get(title='Test uploaded file')

        url = attachment.get_file_url()
        response = self.client.get(url)
        self.assertRedirects(response, url,
                             fetch_redirect_response=False,
                             status_code=301)

        response = self.client.get(url, HTTP_HOST=settings.ATTACHMENT_HOST)
        self.assertTrue(response.streaming)
        self.assertEqual(response['x-frame-options'],
                         'ALLOW-FROM: %s' % settings.DOMAIN)
        self.assertEqual(response.status_code, 200)
        self.assertIn('Last-Modified', response)
        self.assertNotIn('1970', response['Last-Modified'])
        self.assertIn('GMT', response['Last-Modified'])
        self.assertIsNotNone(parse_http_date_safe(response['Last-Modified']))
Exemple #30
0
        def view_func(request, **kwargs):
            response = real_view_func(request, **kwargs)

            if request.method != 'GET':
                return response

            etag = response.get('ETag')
            last_modified = response.get('Last-Modified')
            if last_modified:
                last_modified = parse_http_date_safe(last_modified)
            if etag or last_modified:
                return get_conditional_response(
                    request,
                    etag=etag,
                    last_modified=last_modified,
                    response=response,
                )

            return response
        def get_not_modified_response():
            if not request.method in ('GET', 'HEAD'):
                return None

            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 not if_modified_since:
                return None

            dt = self.last_modified(request, *args, **kwargs)
            if not dt:
                return None

            res_last_modified =  calendar.timegm(dt.utctimetuple())
            if res_last_modified and res_last_modified < if_modified_since:
                return Response(status=status.HTTP_304_NOT_MODIFIED)
            else:
                return None
Exemple #32
0
def get_conditional_response(request, response=None):
    if not (response and hasattr(cache, 'get_conditional_response')):
        # Django 1.8 does not have such method, can't do anything
        return response
    last_modified = response.get('Last-Modified')
    conditional_response = cache.get_conditional_response(
        request,
        last_modified=http.parse_http_date_safe(last_modified),
        response=response,
    )
    if conditional_response is response:
        return response
    headers = {
        header: response[header]
        for header in rfc7232_headers
        if header in response
    }
    for header, value in headers.items():
        conditional_response[header] = value
    return conditional_response
Exemple #33
0
    def test_attachment_raw_requires_attachment_host(self):
        response = self._post_attachment()
        attachment = Attachment.objects.get(title='Test uploaded file')

        url = attachment.get_file_url()
        response = self.client.get(url)
        self.assertRedirects(response,
                             url,
                             fetch_redirect_response=False,
                             status_code=301)

        response = self.client.get(url, HTTP_HOST=settings.ATTACHMENT_HOST)
        self.assertTrue(response.streaming)
        self.assertEqual(response['x-frame-options'],
                         'ALLOW-FROM: %s' % settings.DOMAIN)
        self.assertEqual(response.status_code, 200)
        self.assertIn('Last-Modified', response)
        self.assertNotIn('1970', response['Last-Modified'])
        self.assertIn('GMT', response['Last-Modified'])
        self.assertIsNotNone(parse_http_date_safe(response['Last-Modified']))
Exemple #34
0
    def process_response(self, request, response):
        # It's too late to prevent an unsafe request with a 412 response, and
        # for a HEAD request, the response body is always empty so computing
        # an accurate ETag isn't possible.
        if request.method != "GET":
            return response

        if self.needs_etag(response) and not response.has_header("ETag"):
            set_response_etag(response)

        etag = response.get("ETag")
        last_modified = response.get("Last-Modified")
        last_modified = last_modified and parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(request,
                                            etag=etag,
                                            last_modified=last_modified,
                                            response=response)

        return response
Exemple #35
0
    def process_response(self, request, response):
        # 加上时间头
        response['Date'] = http_date()
        # 不是文件流并且没有长度header则补上
        if not response.streaming and not response.has_header('Content-Length'):
            response['Content-Length'] = str(len(response.content))

        # 获得本次response的内容标示ETag
        etag = response.get('ETag')
        last_modified = response.get('Last-Modified')
        if last_modified:
            last_modified = parse_http_date_safe(last_modified)

        if etag or last_modified:
            return get_conditional_response(
                request,
                etag=unquote_etag(etag),
                last_modified=last_modified,
                response=response,
            )

        return response
Exemple #36
0
def dynamic_css(request, css):
    if css not in _dynamic_cssmap:
        raise Http404('CSS not found')
    files = _dynamic_cssmap[css]
    resp = HttpResponse(content_type='text/css')

    # We honor if-modified-since headers by looking at the most recently
    # touched CSS file.
    latestmod = 0
    for fn in files:
        try:
            stime = os.stat(fn).st_mtime
            if latestmod < stime:
                latestmod = stime
        except OSError:
            # If we somehow referred to a file that didn't exist, or
            # one that we couldn't access.
            raise Http404('CSS (sub) not found')
    if 'HTTP_IF_MODIFIED_SINCE' in request.META:
        # This code is mostly stolen from django :)
        matches = re.match(r"^([^;]+)(; length=([0-9]+))?$",
                           request.META.get('HTTP_IF_MODIFIED_SINCE'),
                           re.IGNORECASE)
        header_mtime = parse_http_date_safe(matches.group(1))
        # We don't do length checking, just the date
        if int(latestmod) <= header_mtime:
            return HttpResponseNotModified(content_type='text/css')
    resp['Last-Modified'] = http_date(latestmod)

    for fn in files:
        with open(fn) as f:
            resp.write("/* %s */\n" % fn)
            resp.write(f.read())
            resp.write("\n")

    return resp
Exemple #37
0
 def _if_modified_since(self, value):
     value = parse_http_date_safe(value)
     return self.last_modified <= value
Exemple #38
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
 def get_if_modified_since(self, request):
     if_modified_since = request.META.get(prepare_header_name("if-modified-since"))
     if if_modified_since:
         if_modified_since = parse_http_date_safe(if_modified_since)
     return if_modified_since
Exemple #40
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_unmodified_since = request.META.get("HTTP_IF_UNMODIFIED_SINCE")
            if if_unmodified_since:
                if_unmodified_since = parse_http_date_safe(if_unmodified_since)
            if_none_match = request.META.get("HTTP_IF_NONE_MATCH")
            if_match = request.META.get("HTTP_IF_MATCH")
            etags = []
            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.
            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 = None
            if not ((if_match and if_modified_since) or
                    (if_none_match and if_unmodified_since) or
                    (if_modified_since and if_unmodified_since) 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:
                        response = _precondition_failed(request)
                elif (if_match
                      and ((not res_etag and "*" in etags) or
                           (res_etag and res_etag not in etags) or
                           (res_last_modified and if_unmodified_since
                            and res_last_modified > if_unmodified_since))):
                    response = _precondition_failed(request)
                elif (not if_none_match and request.method in ("GET", "HEAD")
                      and res_last_modified and if_modified_since
                      and res_last_modified <= if_modified_since):
                    response = HttpResponseNotModified()
                elif (not if_match and res_last_modified
                      and if_unmodified_since
                      and res_last_modified > if_unmodified_since):
                    response = _precondition_failed(request)

            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
Exemple #41
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.
            if etag_func:
                res_etag = etag_func(request, *args, **kwargs)
            else:
                res_etag = None
            if last_modified_func:
                dt = last_modified_func(request, *args, **kwargs)
                if dt:
                    res_last_modified = timegm(dt.utctimetuple())
                else:
                    res_last_modified = None
            else:
                res_last_modified = None

            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)

            # 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
Exemple #42
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)
Exemple #43
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'))

        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', '7', '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)
Exemple #44
0
def parse_expires(response):
    return parse_http_date_safe(response.headers.get("Expires", "")) or 0
Exemple #45
0
 def is_modified(self, request):
     http_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
     if http_modified_since is None or self.last_timestamp is None:
         return True
     return self.last_timestamp > parse_http_date_safe(http_modified_since)
Exemple #46
0
def parse_expires(response):
    return parse_http_date_safe(response.headers.get("Expires", "")) or 0
Exemple #47
0
from django.utils.cache import get_conditional_response
Exemple #48
0
 def get_if_modified_since(self, request):
     if_modified_since = request.META.get(
         prepare_header_name("if-modified-since"))
     if if_modified_since:
         if_modified_since = parse_http_date_safe(if_modified_since)
     return if_modified_since
"""
Exemple #50
0
def get_conditional_response(request, etag=None, last_modified=None, response=None):
    # 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_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
    if if_unmodified_since:
        if_unmodified_since = parse_http_date_safe(if_unmodified_since)
    if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
    if_match = request.META.get('HTTP_IF_MATCH')
    etags = []
    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 an 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 bug #10681.
            if_none_match = None
            if_match = None

    # If-None-Match must be ignored if original result would be anything
    # other than a 2XX or 304 status. 304 status would result in no change.
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
    if response and not (200 <= response.status_code < 300):
        if_none_match = None
        if_match = None

    # If-Modified-Since must be ignored if the original result was not a 200.
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
    if response and response.status_code != 200:
        if_modified_since = None
        if_unmodified_since = None

    if not ((if_match and if_modified_since) or
            (if_none_match and if_unmodified_since) or
            (if_modified_since and if_unmodified_since) or
            (if_match and if_none_match)):
        # We only get here if no undefined combinations of headers are
        # specified.
        if ((if_none_match and (etag in etags or
                '*' in etags and etag)) and
                (not if_modified_since or
                    (last_modified and if_modified_since and
                    last_modified <= if_modified_since))):
            if request.method in ('GET', 'HEAD'):
                return _not_modified(request, response)
            else:
                return _precondition_failed(request)
        elif (if_match and ((not etag and '*' in etags) or
                (etag and etag not in etags) or
                (last_modified and if_unmodified_since and
                last_modified > if_unmodified_since))):
            return _precondition_failed(request)
        elif (not if_none_match and request.method in ('GET', 'HEAD') and
                last_modified and if_modified_since and
                last_modified <= if_modified_since):
            return _not_modified(request, response)
        elif (not if_match and
                last_modified and if_unmodified_since and
                last_modified > if_unmodified_since):
            return _precondition_failed(request)

    return response
Exemple #51
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) 将所有的 hash 抽取出来   
                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.

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

            if last_modified_func:
                dt = last_modified_func(request, *args, **kwargs)
                if dt:
                    res_last_modified = timegm(dt.utctimetuple())
                else:
                    res_last_modified = None
            else:
                res_last_modified = None

            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()
 def _if_modified_since(self, value):
     value = parse_http_date_safe(value)
     return self.last_modified <= value
Exemple #53
0
def get_conditional_response(request,
                             etag=None,
                             last_modified=None,
                             response=None):
    # 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_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
    if if_unmodified_since:
        if_unmodified_since = parse_http_date_safe(if_unmodified_since)
    if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
    if_match = request.META.get('HTTP_IF_MATCH')
    etags = []
    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 an 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 bug #10681.
            if_none_match = None
            if_match = None

    # If-None-Match must be ignored if original result would be anything
    # other than a 2XX or 304 status. 304 status would result in no change.
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
    if response and not (200 <= response.status_code < 300):
        if_none_match = None
        if_match = None

    # If-Modified-Since must be ignored if the original result was not a 200.
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
    if response and response.status_code != 200:
        if_modified_since = None
        if_unmodified_since = None

    if not ((if_match and if_modified_since) or
            (if_none_match and if_unmodified_since) or
            (if_modified_since and if_unmodified_since) or
            (if_match and if_none_match)):
        # We only get here if no undefined combinations of headers are
        # specified.
        if ((if_none_match and (etag in etags or '*' in etags and etag))
                and (not if_modified_since or
                     (last_modified and if_modified_since
                      and last_modified <= if_modified_since))):
            if request.method in ('GET', 'HEAD'):
                return _not_modified(request, response)
            else:
                return _precondition_failed(request)
        elif (if_match and
              ((not etag and '*' in etags) or (etag and etag not in etags) or
               (last_modified and if_unmodified_since
                and last_modified > if_unmodified_since))):
            return _precondition_failed(request)
        elif (not if_none_match and request.method in ('GET', 'HEAD')
              and last_modified and if_modified_since
              and last_modified <= if_modified_since):
            return _not_modified(request, response)
        elif (not if_match and last_modified and if_unmodified_since
              and last_modified > if_unmodified_since):
            return _precondition_failed(request)

    return response