Esempio n. 1
0
    def _fill_event(self, event_type, trigger, trigger_id):
        """
        Here I'm testing only encrypted_tip because trigger a bigger
        amount of %KeyWords%
        """
        self.assertEqual(event_type, u'encrypted_tip')
        self.assertEqual(trigger, 'Tip')

        if event_type == u'encrypted_tip' and trigger == 'Tip':

            receiver_dict = yield admin.get_receiver(self.createdReceiver['id'])
            context_dict = yield admin.get_context(self.createdContext['id'])
            notif_dict = yield admin.get_notification()

            yield admin.import_memory_variables()
            node_dict = yield admin.admin_serialize_node()

            tip_dict = yield self.get_a_fucking_random_submission()

            self.event = Event(
                type = u'encrypted_tip',
                trigger = 'Tip',
                notification_settings = notif_dict,
                node_info = node_dict,
                receiver_info = receiver_dict,
                context_info = context_dict,
                plugin = None,
                trigger_info = tip_dict,
                trigger_parent = None
            )
Esempio n. 2
0
    def _fill_event(self, event_type, trigger, trigger_id):
        """
        Here I'm testing only encrypted_tip because trigger a bigger
        amount of %KeyWords%
        """
        self.assertEqual(event_type, u'encrypted_tip')
        self.assertEqual(trigger, 'Tip')

        if event_type == u'encrypted_tip' and trigger == 'Tip':

            receiver_dict = yield admin.get_receiver(
                self.createdReceiver['id'])
            context_dict = yield admin.get_context(self.createdContext['id'])
            notif_dict = yield admin.get_notification()

            yield admin.import_memory_variables()
            node_dict = yield admin.admin_serialize_node()

            tip_dict = yield self.get_a_fucking_random_submission()

            self.event = Event(type=u'encrypted_tip',
                               trigger='Tip',
                               notification_settings=notif_dict,
                               node_info=node_dict,
                               receiver_info=receiver_dict,
                               context_info=context_dict,
                               plugin=None,
                               trigger_info=tip_dict,
                               trigger_parent=None)
Esempio n. 3
0
    def _fill_event_dict(self, event_type, event_trigger):
        """
        A notification is based on the Node, Context and Receiver values,
        that has to be taken from the database.
        """
        receiver_dict = yield admin.get_receiver(self.createdReceiver['id'])
        context_dict = yield admin.get_context(self.createdContext['id'])
        steps_dict = yield admin.get_context_steps(self.createdContext['id'])
        notif_dict = yield admin.notification.get_notification()

        yield admin.import_memory_variables()
        node_dict = yield admin.admin_serialize_node()

        # is a mock 'trigger_info' and 'trigger_parent' at the moment
        self.tip['name'] = ' foo '
        self.tip['size'] = ' 123 '
        self.tip['content_type'] = ' application/javascript '
        self.tip['creation_date'] = context_dict['creation_date']
        self.tip['type'] = ' sorry maker '
        # this is requested in the file cases

        self.event = Event(type = event_type,
                           trigger = event_trigger,
                           notification_settings = notif_dict,
                           node_info = node_dict,
                           receiver_info = receiver_dict,
                           context_info = context_dict,
                steps_info = steps_dict,
                           plugin = None,
                           trigger_info = self.tip,
                           trigger_parent = self.tip )
Esempio n. 4
0
    def update_node_properties(self):
        node_desc = yield admin.admin_serialize_node('en')
        self.assertEqual(node_desc['can_postpone_expiration'], False)
        node_desc['can_postpone_expiration'] = True

        stuff = u"³²¼½¬¼³²"
        for attrname in models.Node.localized_strings:
            node_desc[attrname] = stuff

        node_desc = yield admin.update_node(node_desc, True, 'en')
        self.assertEqual(node_desc['can_postpone_expiration'], True)
Esempio n. 5
0
    def update_node_properties(self):
        node_desc = yield admin.admin_serialize_node('en')
        self.assertEqual(node_desc['can_postpone_expiration'], False)
        node_desc['can_postpone_expiration'] = True

        stuff = u"³²¼½¬¼³²"
        for attrname in models.Node.localized_strings:
            node_desc[attrname] = stuff

        node_desc = yield admin.update_node(node_desc, True, 'en')
        self.assertEqual(node_desc['can_postpone_expiration'], True)
Esempio n. 6
0
    def update_node_properties(self):
        node_desc = yield admin.admin_serialize_node()
        self.assertEqual(node_desc['postpone_superpower'], False)
        node_desc['postpone_superpower'] = True

        stuff = u"³²¼½¬¼³²"
        for attrname in models.Node.localized_strings:
            node_desc[attrname] = stuff

        node_desc = yield admin.update_node(node_desc)
        self.assertEqual(node_desc['postpone_superpower'], True)
Esempio n. 7
0
    def update_node_properties(self):
        node_desc = yield admin.admin_serialize_node()
        self.assertEqual(node_desc['postpone_superpower'], False)
        node_desc['postpone_superpower'] = True

        stuff = u"³²¼½¬¼³²"
        for attrname in models.Node.localized_strings:
            node_desc[attrname] = stuff

        node_desc = yield admin.update_node(node_desc)
        self.assertEqual(node_desc['postpone_superpower'], True)
Esempio n. 8
0
    def operation(self):
        expired_or_expiring = yield self.pgp_validation_check()

        admin_user = yield admin_serialize_user('admin')

        node_desc = yield admin_serialize_node(admin_user['language'])

        notification_settings = yield get_notification(admin_user['language'])

        if expired_or_expiring:
            yield self.send_admin_pgp_alerts(node_desc, admin_user, notification_settings, expired_or_expiring)

            for receiver_desc in expired_or_expiring:
                yield self.send_pgp_alerts(node_desc, receiver_desc, notification_settings)
Esempio n. 9
0
    def operation(self):
        expired_or_expiring = yield self.pgp_validation_check()

        admin_user = yield admin_serialize_user('admin')

        node_desc = yield admin_serialize_node(admin_user['language'])

        notification_settings = yield get_notification(admin_user['language'])

        if expired_or_expiring:
            yield self.send_admin_pgp_alerts(node_desc, admin_user, notification_settings, expired_or_expiring)

            for receiver_desc in expired_or_expiring:
                yield self.send_pgp_alerts(node_desc, receiver_desc, notification_settings)
Esempio n. 10
0
    def post(self, rtip_id, compression):
        files_dict = yield download_all_files(self.current_user.user_id,
                                              rtip_id)

        if compression is None:
            compression = 'zipdeflated'

        opts = get_compression_opts(compression)

        node_dict = yield admin.admin_serialize_node(self.request.language)
        receiver_dict = yield get_receiver_from_rtip(rtip_id,
                                                     self.request.language)
        rtip_dict = yield get_rtip_info(rtip_id, self.request.language)
        collection_tip_dict = yield get_collection_info(rtip_id)
        context_dict = yield admin.get_context(rtip_dict['context_id'], 'en')
        notif_dict = yield admin.notification.get_notification(
            self.request.language)

        mock_event = Event(
            type=u'zip_collection',
            trigger='Download',
            node_info=node_dict,
            receiver_info=receiver_dict,
            context_info=context_dict,
            tip_info=rtip_dict,
            subevent_info=collection_tip_dict,
            do_mail=False,
        )

        formatted_coll = Templating().format_template(
            notif_dict['zip_description'], mock_event).encode('utf-8')

        files_dict.append({
            'buf': formatted_coll,
            'name': "COLLECTION_INFO.txt"
        })

        self.set_status(200)

        self.set_header('X-Download-Options', 'noopen')
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition',
                        'attachment; filename=\"%s\"' % opts['filename'])

        if compression in ['zipstored', 'zipdeflated']:
            for data in ZipStream(files_dict, opts['compression_type']):
                self.write(data)

        self.finish()
Esempio n. 11
0
    def post(self, rtip_id, compression):
        files_dict = yield download_all_files(self.current_user.user_id, rtip_id)

        if compression is None:
            compression = 'zipdeflated'

        opts = get_compression_opts(compression)

        node_dict = yield admin.admin_serialize_node(self.request.language)
        receiver_dict = yield get_receiver_from_rtip(rtip_id, self.request.language)
        rtip_dict = yield get_rtip_info(rtip_id, self.request.language)
        collection_tip_dict = yield get_collection_info(rtip_id)
        context_dict = yield admin.get_context(rtip_dict['context_id'], 'en')
        notif_dict = yield admin.notification.get_notification(self.request.language)

        mock_event = Event(
            type=u'zip_collection',
            trigger='Download',
            node_info=node_dict,
            receiver_info=receiver_dict,
            context_info=context_dict,
            tip_info=rtip_dict,
            subevent_info=collection_tip_dict,
            do_mail=False,
        )

        formatted_coll = Templating().format_template(notif_dict['zip_description'], mock_event).encode('utf-8')

        files_dict.append(
            {
               'buf': formatted_coll,
               'name': "COLLECTION_INFO.txt"
            }
        )

        self.set_status(200)

        self.set_header('X-Download-Options', 'noopen')
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition', 'attachment; filename=\"%s\"' % opts['filename'])

        if compression in ['zipstored', 'zipdeflated']:
            for data in ZipStream(files_dict, opts['compression_type']):
                self.write(data)

        self.finish()
Esempio n. 12
0
    def test_keywords_conversion(self):
        yield self.perform_full_submission_actions()

        self.receiver_dict = yield admin.get_receiver(
            self.dummyReceiver_1['id'], 'en')
        self.context_dict = yield admin.get_context(self.dummyContext['id'],
                                                    'en')
        self.notif_dict = yield admin.notification.get_notification('en')
        self.node_dict = yield admin.admin_serialize_node('en')
        self.rtip_dict = self.dummyRTips[0]['itip']

        self.templates = {}
        for t, keywords_list in templates_desc.iteritems():

            self.templates[t] = ""

            for kwl in keywords_list:
                for keyword in kwl:
                    self.templates[t] += " " + keyword + " / "

        for template_name, template in self.templates.iteritems():
            # look for appropriate event_type, event_trigger
            event_type = u''
            event_trigger = ''
            for e_t, e_tri in supported_event_types.iteritems():
                if template_name.startswith(e_t):
                    event_type = e_t
                    event_trigger = e_tri
                    break

            if not event_type:
                # we've nothing to do not!
                continue

            self._fill_event_dict(event_type, event_trigger)

            # with the event, we can finally call the template filler
            gentext = Templating().format_template(template, self.event)

            if template_name != 'ping_mail_template' and template_name != 'ping_mail_title':
                self.assertSubstring(self.context_dict['name'], gentext)
                self.assertSubstring(self.node_dict['public_site'], gentext)
                self.assertSubstring(self.node_dict['hidden_service'], gentext)
Esempio n. 13
0
    def test_keywords_conversion(self):
        yield self.perform_full_submission_actions()

        self.receiver_dict = yield admin.get_receiver(self.dummyReceiver_1['id'], 'en')
        self.context_dict = yield admin.get_context(self.dummyContext['id'], 'en')
        self.steps_dict = yield admin.get_context_steps(self.dummyContext['id'], 'en')
        self.notif_dict = yield admin.notification.get_notification('en')
        self.node_dict = yield admin.admin_serialize_node('en')
        self.rtip_dict = self.dummyRTips[0]['itip']

        self.templates = {}
        for t, keywords_list in templates_desc.iteritems():

            self.templates[t] = ""

            for kwl in keywords_list:
                for keyword in kwl:
                    self.templates[t] += " " + keyword + " / "

        for template_name, template in self.templates.iteritems():
            # look for appropriate event_type, event_trigger
            event_type = u''
            event_trigger = ''
            for e_t, e_tri in supported_event_types.iteritems():
                if template_name.startswith(e_t):
                    event_type = e_t
                    event_trigger = e_tri
                    break

            if not event_type:
                # we've nothing to do not!
                continue

            self._fill_event_dict(event_type, event_trigger)

            # with the event, we can finally call the template filler
            gentext = Templating().format_template(template, self.event)

            if template_name != 'ping_mail_template' and template_name != 'ping_mail_title':
                self.assertSubstring(self.context_dict['name'], gentext)
                self.assertSubstring(self.node_dict['public_site'], gentext)
                self.assertSubstring(self.node_dict['hidden_service'], gentext)
Esempio n. 14
0
    def _fill_event_dict(self, event_type, event_trigger):
        """
        A notification is based on the Node, Context and Receiver values,
        that has to be taken from the database.
        """
        receiver_dict = yield admin.get_receiver(self.createdReceiver['id'],
                                                 'en')
        context_dict = yield admin.get_context(self.createdContext['id'], 'en')
        steps_dict = yield admin.get_context_steps(self.createdContext['id'],
                                                   'en')
        notif_dict = yield admin.notification.get_notification('en')

        node_dict = yield admin.admin_serialize_node('en')

        self.subevent = {}

        # this is requested in the file cases
        if event_type == 'ping_mail':
            self.subevent = {'counter': 42}
        elif event_type == 'admin_pgp_expiration_alert':
            self.subevent = {'expired_or_expiring': [receiver_dict]}
        else:
            self.subevent['name'] = ' foo '
            self.subevent['size'] = ' 123 '
            self.subevent['content_type'] = ' application/javascript '
            self.subevent['creation_date'] = context_dict['creation_date']
            self.subevent['type'] = ' sorry maker '

        self.event = Event(type=event_type,
                           trigger=event_trigger,
                           node_info=node_dict,
                           receiver_info=receiver_dict,
                           context_info=context_dict,
                           steps_info=steps_dict,
                           tip_info=self.tip,
                           subevent_info=self.subevent,
                           do_mail=False)
Esempio n. 15
0
    def post(self, rtip_id, compression):

        files_dict = yield download_all_files(self.current_user.user_id, rtip_id)

        if not files_dict:
            raise errors.DownloadLimitExceeded

        if compression is None:
            compression = 'zipstored'

        opts = get_compression_opts(compression)

        node_dict = yield admin.admin_serialize_node()
        receiver_dict = yield get_receiver_from_rtip(rtip_id)
        rtip_dict = yield get_rtip_info(rtip_id)
        collection_tip_dict = yield get_collection_info(rtip_id)
        context_dict = yield admin.get_context(rtip_dict['context_id'])
        notif_dict = yield admin.get_notification()

        mock_event = Event(
            type = u'zip_collection',
            trigger = 'Download',
            notification_settings = notif_dict,
            node_info = node_dict,
            receiver_info = receiver_dict,
            context_info = context_dict,
            plugin = None,
            trigger_info = collection_tip_dict,
            trigger_parent = rtip_dict
        )

        formatted_coll = Templating().format_template(notif_dict['zip_description'], mock_event).encode('utf-8')
        # log.debug("Generating collection content with: %s" % formatted_coll)
        files_dict.append(
            { 'buf'  : formatted_coll,
              'name' : "COLLECTION_INFO.txt"
            })

        self.set_status(200)

        self.set_header('X-Download-Options', 'noopen')
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition','attachment; filename=\"%s\"' %opts['filename'])

        if compression in ['zipstored', 'zipdeflated']:
            for data in ZipStream(files_dict, opts['compression_type']):
                self.write(data)

        elif compression in ['tar', 'targz', 'tarbz2']:
            collectionstreamer = CollectionStreamer(self)
            tar = tarfile.open("collection." + compression, 'w|'+opts['compression_type'], collectionstreamer)
            for f in files_dict:
                if 'path' in f:
                    try:
                        tar.add(f['path'], f['name'])
                    except (OSError, IOError) as excpd:
                        log.err("OSError while adding %s to files collection: %s" % (f['path'], excpd))

                elif 'buf' in f:
                    tarinfo = tarfile.TarInfo(f['name'])
                    tarinfo.size = len(f['buf'])
                    tar.addfile(tarinfo, StringIO.StringIO(f['buf']))

            tar.close()

        self.finish()
Esempio n. 16
0
    def create_tip_notification_events(self, store):
        """
        This transaction will return all a list of tuples containing the tips
        for which the notification event has not been run.

        Returns:

            events: a list of tuples containing (tip_id, an instance of
                :class:`globaleaks.plugins.base.Event`).

        """
        events = []

        # settings.notification_plugins contain a list of supported plugin
        # at the moment only 1. so [0] is used. but different context/receiver
        # may use different code-plugin:
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_tips = store.find(models.ReceiverTip,
            models.ReceiverTip.mark == models.ReceiverTip._marker[0]
        )

        node_desc = admin.admin_serialize_node(store.find(models.Node).one(),
            GLSetting.memory_copy.default_language)

        if not_notified_tips.count():
            log.debug("Receiver Tips found to be notified: %d" % not_notified_tips.count() )

        for rtip in not_notified_tips:

            if not rtip.internaltip or not rtip.internaltip.context:
                log.err("(tip_notification) Integrity failure: missing InternalTip|Context")
                continue

            context_desc = admin.admin_serialize_context(rtip.internaltip.context, GLSetting.memory_copy.default_language)

            receiver_desc = admin.admin_serialize_receiver(rtip.receiver, GLSetting.memory_copy.default_language)
            if  not receiver_desc.has_key('notification_fields') or\
                not rtip.receiver.notification_fields.has_key('mail_address'):
                log.err("Receiver %s lack of email address!" % rtip.receiver.name)
                continue

            # check if the receiver has the Tip notification enabled or not
            if not receiver_desc['tip_notification']:
                log.debug("Receiver %s has tip notification disabled" % rtip.receiver.user.username)
                rtip.mark = models.ReceiverTip._marker[3] # 'disabled'
                store.commit()
                continue

            tip_desc = serialize_receivertip(rtip)

            event = Event(type=u'tip', trigger='Tip',
                            notification_settings=self.notification_settings,
                            trigger_info=tip_desc,
                            node_info=node_desc,
                            receiver_info=receiver_desc,
                            context_info=context_desc,
                            plugin=plugin)
            events.append((unicode(rtip.id), event))

        return events
Esempio n. 17
0
    def create_file_notification_events(self, store):
        """
        Creates events for performing notification of newly added files..

        Returns:
            events: a list of tuples containing ((receiverfile_id, receiver_id), an instance of
                :class:`globaleaks.plugins.base.Event`).

        """
        events = []
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_rfiles = store.find(models.ReceiverFile,
            models.ReceiverFile.mark == models.ReceiverFile._marker[0]
        )

        node_desc = admin.admin_serialize_node(store.find(models.Node).one(), GLSetting.memory_copy.default_language)

        if not_notified_rfiles.count():
            log.debug("Receiverfiles found to be notified: %d" % not_notified_rfiles.count() )

        for rfile in not_notified_rfiles:

            if not rfile.internalfile:
                log.err("(file_notification) Integrity check failure (InternalFile)")
                continue

            file_desc = serialize_internalfile(rfile.internalfile)

            if  not rfile.internalfile or \
                not rfile.internalfile.internaltip or \
                not rfile.internalfile.internaltip.context:
                log.err("(file_notification) Integrity check failure (File+Tip)")
                continue

            context_desc = admin.admin_serialize_context(rfile.internalfile.internaltip.context,
                GLSetting.memory_copy.default_language)

            receiver_desc = admin.admin_serialize_receiver(rfile.receiver, GLSetting.memory_copy.default_language)
            if  not receiver_desc.has_key('notification_fields') or \
                not rfile.receiver.notification_fields.has_key('mail_address'):
                log.err("Receiver %s lack of email address!" % rfile.receiver.user.name)
                continue

            # check if the receiver has the File notification enabled or not
            if not rfile.receiver.file_notification:
                log.debug("Receiver %s has file notification disabled: %s skipped" % (
                    rfile.receiver.user.username, rfile.internalfile.name ))
                rfile.mark = models.ReceiverFile._marker[3] # 'disabled'
                store.commit()
                continue

            # by ticket https://github.com/globaleaks/GlobaLeaks/issues/444
            # send notification of file only if notification of tip is already on send status
            if rfile.receiver_tip.mark == models.ReceiverTip._marker[0]: # 'not notified'
                rfile.mark = models.ReceiverFile._marker[4] # 'skipped'
                log.debug("Skipped notification of %s (for %s) because Tip not yet notified" %
                          (rfile.internalfile.name, rfile.receiver.name) )
                store.commit()
                continue

            event = Event(type=u'file', trigger='File',
                notification_settings=self.notification_settings,
                trigger_info=file_desc,
                node_info=node_desc,
                receiver_info=receiver_desc,
                context_info=context_desc,
                plugin=plugin)

            events.append(((unicode(rfile.id), unicode(rfile.receiver.id)), event))

        return events
Esempio n. 18
0
    def create_comment_notification_events(self, store):
        """
        Creates events for performing notification of newly added comments.

        Returns:
            events: a list of tuples containing ((comment_id, receiver_id), an instance of
                :class:`globaleaks.plugins.base.Event`).


        """
        events = []
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_comments = store.find(models.Comment,
            models.Comment.mark == models.Comment._marker[0]
        )

        node_desc = admin.admin_serialize_node(store.find(models.Node).one(), GLSetting.memory_copy.default_language)

        if not_notified_comments.count():
            log.debug("Comments found to be notified: %d" % not_notified_comments.count() )

        for comment in not_notified_comments:

            if comment.internaltip is None or comment.internaltip.receivers is None:
                log.err("Comment %s has internaltip or receivers broken reference" % comment.id)
                comment.mark = models.Comment._marker[2] # 'unable to notify'
                continue

            # for every comment, iter on the associated receiver
            log.debug("Comments receiver: %d" % comment.internaltip.receivers.count())

            comment_desc = tip.serialize_comment(comment)

            if not comment.internaltip.context:
                log.err("(comment_notification) Integrity check failure Context")
                continue

            context_desc = admin.admin_serialize_context(comment.internaltip.context, GLSetting.memory_copy.default_language)

            # XXX BUG! All notification is marked as correctly send,
            # This can't be managed by callback, and can't be managed by actual DB design
            comment.mark = models.Comment._marker[1] # 'notified'

            for receiver in comment.internaltip.receivers:

                receiver_desc = admin.admin_serialize_receiver(receiver, GLSetting.memory_copy.default_language)
                if  not receiver_desc.has_key('notification_fields') or\
                    not receiver.notification_fields.has_key('mail_address'):
                    log.err("Receiver %s lack of email address!" % receiver.name)
                    continue

                # if the comment author is the one to be notified: skip the notification
                # ----- BUG, remind,
                # if two receiver has the same name, and one has notification disabled
                # also the homonymous would get the notification dropped.
                if comment._types == models.Comment._types[0] and comment.author == receiver.name:
                    log.debug("Receiver is the Author (%s): skipped" % receiver.user.username)
                    continue

                # check if the receiver has the Comment notification enabled or not
                if not receiver.comment_notification:
                    log.debug("Receiver %s has comment notification disabled: skipped [source: %s]" % (
                        receiver.user.username, comment.author))
                    continue

                event = Event(type=u'comment', trigger='Comment',
                    notification_settings=self.notification_settings,
                    trigger_info=comment_desc,
                    node_info=node_desc,
                    receiver_info=receiver_desc,
                    context_info=context_desc,
                    plugin=plugin)

                events.append(((unicode(comment.id), unicode(receiver.id)), event))

        return events
Esempio n. 19
0
    def post(self, rtip_id, compression):

        files_dict = yield download_all_files(self.current_user.user_id,
                                              rtip_id)

        if not files_dict:
            raise errors.DownloadLimitExceeded

        if compression is None:
            compression = 'zipstored'

        opts = get_compression_opts(compression)

        node_dict = yield admin.admin_serialize_node()
        receiver_dict = yield get_receiver_from_rtip(rtip_id)
        rtip_dict = yield get_rtip_info(rtip_id)
        collection_tip_dict = yield get_collection_info(rtip_id)
        context_dict = yield admin.get_context(rtip_dict['context_id'])
        notif_dict = yield admin.get_notification()

        mock_event = Event(type=u'zip_collection',
                           trigger='Download',
                           notification_settings=notif_dict,
                           node_info=node_dict,
                           receiver_info=receiver_dict,
                           context_info=context_dict,
                           plugin=None,
                           trigger_info=collection_tip_dict,
                           trigger_parent=rtip_dict)

        formatted_coll = Templating().format_template(
            notif_dict['zip_description'], mock_event).encode('utf-8')
        # log.debug("Generating collection content with: %s" % formatted_coll)
        files_dict.append({
            'buf': formatted_coll,
            'name': "COLLECTION_INFO.txt"
        })

        self.set_status(200)

        self.set_header('X-Download-Options', 'noopen')
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition',
                        'attachment; filename=\"%s\"' % opts['filename'])

        if compression in ['zipstored', 'zipdeflated']:
            for data in ZipStream(files_dict, opts['compression_type']):
                self.write(data)

        elif compression in ['tar', 'targz', 'tarbz2']:
            collectionstreamer = CollectionStreamer(self)
            tar = tarfile.open("collection." + compression,
                               'w|' + opts['compression_type'],
                               collectionstreamer)
            for f in files_dict:
                if 'path' in f:
                    try:
                        tar.add(f['path'], f['name'])
                    except (OSError, IOError) as excpd:
                        log.err(
                            "OSError while adding %s to files collection: %s" %
                            (f['path'], excpd))

                elif 'buf' in f:
                    tarinfo = tarfile.TarInfo(f['name'])
                    tarinfo.size = len(f['buf'])
                    tar.addfile(tarinfo, StringIO.StringIO(f['buf']))

            tar.close()

        self.finish()