示例#1
0
文件: tests.py 项目: tdelmas/exodus
    def test_returns_applications_with_report_last_update(self):
        report = Report()
        report.save()
        application = Application(name='app_name',
                                  handle='handle',
                                  report=report)
        application.save()

        client = APIClient()
        response = client.get('/api/applications')

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, application.name, 1)

        report_updated_at = application.report.updated_at
        response_application = response.json()['applications'][0]

        self.assertEqual(response_application['name'], application.name)
        self.assertEqual(response_application['handle'], application.handle)
        self.assertEqual(response_application['report_updated_at'],
                         report_updated_at.timestamp())
示例#2
0
    def post(self, request):
        success_message = ''
        report = Report()
        report.school = request.POST.get('centro', '')
        report.name = request.POST.get('name', '')
        report.level = request.POST.get('level', '')
        report.email = request.POST.get('email', '')
        report.description = request.POST.get('description', '')
        report.save()
        """
        if form.is_valid():
            form = ReportForm()
            success_message = u'¡Guardado con éxito!'

            context = {
                'form': form,
                'success_message': success_message
            }
        """
        url = request.GET.get('next', 'home')
        return redirect(url)
示例#3
0
    def test_should_not_include_more_than_X_trackers(self):
        tracker_limit = 21
        for x in range(0, tracker_limit):
            tracker = Tracker(name='Tracker{}.'.format(x))
            tracker.save()

        extra_tracker = Tracker(name='Exodus Super Tracker')
        extra_tracker.save()

        first_trackers = Tracker.objects.exclude(name=extra_tracker.name)

        report = Report()
        report.save()
        report.found_trackers = [t.id for t in first_trackers]
        report.save()

        c = Client()
        response = c.get(self.STATS_PATH)

        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, extra_tracker.name)
        for t in first_trackers:
            self.assertContains(response, t.name, 1)
示例#4
0
    def handle(self, *args, **options):

        url = options['url'][0]

        try:
            rawtext = urlopen(url).read()
        except URLError:
            print("Invalid url")
            return

        lines = rawtext.splitlines()
        stats = csv.reader(codecs.iterdecode(lines, 'utf-8'))

        firstRow = True
        regionIndex = -1
        dateIndex = -1
        casesIndex = -1
        deceasesIndex = -1
        curedIndex = -1

        hospitalizedIndex = -1
        uciIndex = -1
        accIncidenceIndex = -1
        diffCasesIndex = -1

        for row in stats:
            if firstRow:
                firstRow = False
                headings = [x.upper() for x in row]

                try:
                    regionIndex = headings.index("CCAA")
                    dateIndex = headings.index("FECHA")
                    casesIndex = headings.index("CASOS")
                    accIncidenceIndex = headings.index("IA")
                    uciIndex = headings.index("UCI")
                    deceasesIndex = headings.index("MUERTES")
                    hospitalizedIndex = headings.index("HOSPITALIZADOS")
                    curedIndex = headings.index("CURADOS")
                    diffCasesIndex = headings.index("NUEVOS")
                except ValueError:
                    print("Invalid csv headers")
                    return

                Report.objects.all().delete()  # Now its safe to drop table
            else:
                region = row[regionIndex]
                validDate = True

                try:
                    date = datetime.strptime(row[dateIndex], '%Y-%m-%d').date()
                except ValueError:
                    validDate = False
                    print("Skipped row: Invalid date for region", region, ":",
                          row[dateIndex])

                if validDate:
                    cases = strToInt(row[casesIndex])
                    deceases = strToInt(row[deceasesIndex])
                    cured = strToInt(row[curedIndex])

                    hospitalized = strToInt(row[hospitalizedIndex])
                    uci = strToInt(row[uciIndex])
                    accIncidence = strToFloat(row[accIncidenceIndex])
                    diffCases = strToInt(row[diffCasesIndex])

                    Report(
                        ca=region,
                        date=date,
                        cases=cases,
                        deceases=deceases,
                        cured=cured,
                        hospitalized=hospitalized,
                        uci=uci,
                        accIncidence=accIncidence,
                        diffCases=diffCases,
                    ).save()

        print("DONE")
示例#5
0
import pandas as pd
from reports.models import Report

data = pd.read_csv('data.csv')

for row in range(data.shape[0]):

    report = Report()

    report.alert_type = data.iloc[row]['Alert_Type']
    report.alert_name = data.iloc[row]['Alert_Name']
    report.priorty = data.iloc[row]['Priorty']
    report.malaware_family = data.iloc[row]['Malaware_family']
    report.http_hostname = data.iloc[row]['HTTP_Hostname']
    report.attack_reference = data.iloc[row]['Attack_reference']
    report.src_hostname = data.iloc[row]['Src_hostname']
    report.src_ip = data.iloc[row]['Src_ip']
    report.dst_ip = data.iloc[row]['Dst_ip']
    report.dst_country = data.iloc[row]['Dst_country']
    report.time = data.iloc[row]['time']
    report.reference_url = data.iloc[row]['reference_URL']
    report.src_country = data.iloc[row]['src_Country']
    report.dst_hostname = data.iloc[row]['Dst_Hostname']
    report.recommendation = data.iloc[row]['Recommendation']
    report.description = data.iloc[row]['description']
    report.other_tls_subject = data.iloc[row]['Other_TLS_Subject']
    report.other_tls_fingerprint = data.iloc[row]['Other_TLS_Fingerprint']
    report.other_username = data.iloc[row]['Other_Username']
    report.other_source_nt_domain = data.iloc[row]['Other_SOURCE_NT_DOMAIN']
    report.other_destination_asset = data.iloc[row]['Other_DESTINATION_ASSET']
    report.other = data.iloc[row]['OTHER']
示例#6
0
def details(request, user, project, id):
    project = Project.objects.filter(slug=project).first()
    model = Model.objects.filter(id=id).first()
    model_access_choices = ['PU', 'PR', 'LI']
    model_access_choices.remove(model.access)
    deployments = DeploymentInstance.objects.filter(model=model)

    report_generators = ReportGenerator.objects.filter(project=project)

    unfinished_reports = Report.objects.filter(status='P').order_by('created_at')
    for report in unfinished_reports:
        populate_report_by_id(report.id)

    reports = Report.objects.filter(model__id=id, status='C').order_by('-created_at')

    report_dtos = []
    for report in reports:
        report_dtos.append({
            'id': report.id,
            'description': report.description,
            'created_at': report.created_at,
            'filename': get_download_link(project.pk, 'report_{}.json'.format(report.id))
        })

    if request.method == 'POST':
        file_path = None
        form = GenerateReportForm(request.POST)
        if form.is_valid():
            generator_id = int(form.cleaned_data['generator_file'])
            generator_object = ReportGenerator.objects.filter(pk=generator_id).first()

            file_path = 'reports/{}'.format(generator_object.generator)

            instance = {
                'id': str(uuid.uuid4()),
                'path_to_file': file_path,
                'model_uid': model.uid,
                'project_name': project.slug
            }

            new_report = Report(model=model, report="", job_id=instance['id'], generator=generator_object, status='P')
            new_report.save()

            l = ProjectLog(project=project, module='MO', headline='Model - {name}'.format(name=model.name),
                           description='Newly generated Metrics #{id}'.format(id=new_report.pk))
            l.save()

            from reports.jobs import run_job

            run_job(instance)

            return HttpResponseRedirect('/{}/{}/models/'.format(user, project.slug))
    else:
        form = GenerateReportForm()

    filename = None
    readme = None
    import requests as r
    url = 'http://{}-file-controller/models/{}/readme'.format(project.slug, model.name)
    try:
        response = r.get(url)
        if response.status_code == 200 or response.status_code == 203:
            payload = response.json()
            if payload['status'] == 'OK':
                filename = payload['filename']

                md = markdown.Markdown(extensions=['extra'])
                readme = md.convert(payload['readme'])
    except Exception as e:
        logger.error("Failed to get response from {} with error: {}".format(url, e))

    return render(request, 'models_details.html', locals())
示例#7
0
 def test_string_representation(self):
     report = Report(title="My Title")
     self.assertEqual(str(report), report.title)
示例#8
0
def start_static_analysis(params):
    """
    Compute the entire static analysis
    :param params: a StaticAnalysisParameters instance
    """
    request = AnalysisRequest.objects.get(pk=params.query.id)
    request.description = _('Your request is running')
    request.save()
    storage_helper = RemoteStorageHelper(params.bucket)

    if request.apk:
        if not os.path.exists(params.tmp_dir):
            os.mkdir(params.tmp_dir)

        with open(params.apk_tmp, 'wb') as out:
            out.write(request.apk.read())
        storage_helper.put_file(params.apk_tmp, params.apk_name)
        request.apk.delete()
    else:
        if params.source == "google":
            if is_paid_app(request.handle):
                logging.warn("'{}' is a paid application".format(
                    request.handle))
                msg = _('εxodus cannot scan paid applications')
                save_error(storage_helper, params, request, msg)
                return EXIT_CODE_PAID_APP_ERROR

        # Download APK and put it on Minio storage
        dl_r = download_apk(storage_helper, request.handle, params.tmp_dir,
                            params.apk_name, params.apk_tmp, params.source)
        if not dl_r:
            logging.error("Could not download '{}'".format(request.handle))
            msg = _('Unable to download the APK')
            save_error(storage_helper, params, request, msg)
            return EXIT_CODE_DOWNLOAD_APK_ERROR

        change_description(request, _('Download APK: success'))

    # Decode the APK file
    try:
        static_analysis = StaticAnalysis(params.apk_tmp)
        static_analysis.load_apk()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to decode the APK')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_DECODE_APK_ERROR

    change_description(request, _('Decode APK: success'))

    # List and save embedded classes
    try:
        with tempfile.NamedTemporaryFile(delete=True) as fp:
            static_analysis.save_embedded_classes_in_file(fp.name)
            storage_helper.put_file(fp.name, params.class_list_file)
    except Exception as e:
        logging.info(e)
        msg = _('Unable to compute the class list')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_COMPUTE_CLASS_LIST_ERROR

    change_description(request, _('List embedded classes: success'))

    # APK
    shasum = static_analysis.get_sha256()

    # Application
    handle = static_analysis.get_package()
    version = static_analysis.get_version()
    version_code = static_analysis.get_version_code()
    app_name = static_analysis.get_app_name()

    # TODO: increase character limit in DB (see #300)
    if not version or not version_code or not app_name or \
            len(version) > 50 or len(version_code) > 50 or len(app_name) > 200:
        msg = _('Unable to create the analysis report')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_CREATE_REPORT_ERROR

    # If a report exists for the same handle, version & version_code, return it
    existing_report = Report.objects.filter(
        application__handle=handle,
        application__source=params.source,
        application__version=version,
        application__version_code=version_code).order_by(
            '-creation_date').first()

    if existing_report is not None:
        clear_analysis_files(storage_helper, params.tmp_dir, params.bucket,
                             True)
        request.description = _(
            'A report already exists for this application version')
        request.processed = True
        request.report_id = existing_report.id
        request.save()
        return existing_report.id

    # APK
    try:
        certificates = static_analysis.get_certificates()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to get certificates')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_GET_CERTFICATES_ERROR

    # Fingerprint
    try:
        perms = static_analysis.get_permissions()

        app_uid = static_analysis.get_application_universal_id()
        if len(app_uid) < 16:
            raise Exception('Unable to compute the Universal Application ID')

        icon_phash = static_analysis.get_icon_and_phash(
            storage_helper, params.icon_name, params.source)
        if len(str(icon_phash)) < 16 and not request.apk:
            raise Exception('Unable to compute the icon perceptual hash')
    except Exception as e:
        logging.info(e)
        msg = _('Unable to compute APK fingerprint')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_COMPUTE_APK_FINGERPRINT_ERROR

    # Application details
    try:
        app_info = static_analysis.get_app_info()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to get application details from Google Play')
        save_error(storage_helper, params, request, msg)
        return EXIT_CODE_GET_DETAILS_APP_ERROR

    change_description(request, _('Get application details: success'))

    # Find trackers
    trackers = static_analysis.detect_trackers()

    change_description(request, _('Tracker analysis: success'))

    report = Report(apk_file=params.apk_name,
                    storage_path='',
                    bucket=request.bucket,
                    class_list_file=params.class_list_file)
    report.save()

    app = Application(
        report=report,
        handle=handle,
        version=version,
        version_code=version_code,
        name=app_name,
        icon_phash=icon_phash,
        app_uid=app_uid,
        source=params.source,
        icon_path=params.icon_name,
    )
    if app_info is not None:
        app.name = app_info['title']
        app.creator = app_info['creator']
        app.downloads = app_info['downloads']
    app.save(force_insert=True)

    apk = Apk(application=app, name=params.apk_name, sum=shasum)
    apk.save(force_insert=True)

    for certificate in certificates:
        c = Certificate(apk=apk,
                        issuer=certificate.issuer,
                        fingerprint=certificate.fingerprint,
                        subject=certificate.subject,
                        serial_number=certificate.serial)
        c.save(force_insert=True)

    for perm in perms:
        p = Permission(application=app, name=perm)
        p.save(force_insert=True)

    report.found_trackers.set(trackers)

    change_description(request, _('Static analysis complete'))
    clear_analysis_files(storage_helper, params.tmp_dir, params.bucket, False)
    request.processed = True
    request.report_id = report.id
    request.save()
    return report.id
示例#9
0
def start_static_analysis(analysis):
    """
    Compute the entire static analysis
    :param analysis: a StaticAnalysis instance
    """
    request = AnalysisRequest.objects.get(pk=analysis.query.id)
    request.description = _('Your request is running')
    request.save()
    storage_helper = RemoteStorageHelper(analysis.bucket)

    # Download APK and put it on Minio storage
    dl_r = download_apk(storage_helper, request.handle, analysis.tmp_dir, analysis.apk_name, analysis.apk_tmp)
    if not dl_r:
        msg = _('Unable to download the APK')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    change_description(request, _('Download APK: success'))

    # Decode the APK file
    try:
        static_analysis = StaticAnalysis(analysis.apk_tmp)
        static_analysis.load_apk()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to decode the APK')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    change_description(request, _('Decode APK: success'))

    # List and save embedded classes
    try:
        with tempfile.NamedTemporaryFile(delete=True) as fp:
            static_analysis.save_embedded_classes_in_file(fp.name)
            storage_helper.put_file(fp.name, analysis.class_list_file)
    except Exception as e:
        logging.info(e)
        msg = _('Unable to compute the class list')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    change_description(request, _('List embedded classes: success'))

    # APK
    shasum = static_analysis.get_sha256()

    # Application
    handle = static_analysis.get_package()
    version = static_analysis.get_version()
    version_code = static_analysis.get_version_code()

    # If a report exists for the same handle, version & version_code, return it
    existing_report = Report.objects.filter(
        application__handle=handle,
        application__version=version,
        application__version_code=version_code
    ).order_by('-creation_date').first()

    if existing_report is not None:
        clear_analysis_files(storage_helper, analysis.tmp_dir, analysis.bucket, True)
        request.description = _('A report already exists for this application version')
        request.processed = True
        request.report_id = existing_report.id
        request.save()
        return existing_report.id

    # APK
    try:
        certificates = static_analysis.get_certificates()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to get certificates')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    # Fingerprint
    try:
        perms = static_analysis.get_permissions()

        app_uid = static_analysis.get_application_universal_id()
        if len(app_uid) < 16:
            raise Exception('Unable to compute the Universal Application ID')

        icon_file, icon_phash = static_analysis.get_icon_and_phash(storage_helper, analysis.icon_name)
        if len(str(icon_phash)) < 16:
            raise Exception('Unable to compute the icon perceptual hash')
    except Exception as e:
        logging.info(e)
        msg = _('Unable to compute APK fingerprint')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    # Application details
    try:
        app_info = static_analysis.get_app_info()
    except Exception as e:
        logging.info(e)
        msg = _('Unable to get application details from Google Play')
        exit_code = save_error(storage_helper, analysis, request, msg)
        return exit_code

    change_description(request, _('Get application details: success'))

    # Find trackers
    trackers = static_analysis.detect_trackers()

    change_description(request, _('Tracker analysis: success'))

    report = Report(
        apk_file=analysis.apk_name,
        storage_path='',
        bucket=request.bucket,
        class_list_file=analysis.class_list_file
    )
    report.save()

    net_analysis = NetworkAnalysis(report=report)
    net_analysis.save()

    app = Application(
        report=report,
        handle=handle,
        version=version,
        version_code=version_code,
        name=static_analysis.get_app_name(),
        icon_phash=icon_phash,
        app_uid=app_uid
    )
    if app_info is not None:
        app.name = app_info['title']
        app.creator = app_info['creator']
        app.downloads = app_info['downloads']
    if icon_file != '':
        app.icon_path = analysis.icon_name
    app.save(force_insert=True)

    apk = Apk(
        application=app,
        name=analysis.apk_name,
        sum=shasum
    )
    apk.save(force_insert=True)

    for certificate in certificates:
        c = Certificate(
            apk=apk,
            issuer=certificate.issuer,
            fingerprint=certificate.fingerprint,
            subject=certificate.subject,
            serial_number=certificate.serial
        )
        c.save(force_insert=True)

    for perm in perms:
        p = Permission(
            application=app,
            name=perm
        )
        p.save(force_insert=True)

    report.found_trackers = trackers
    report.save()

    change_description(request, _('Static analysis complete'))
    clear_analysis_files(storage_helper, analysis.tmp_dir, analysis.bucket, False)
    request.processed = True
    request.report_id = report.id
    request.save()
    return report.id
示例#10
0
    def construct_report(self, idrssd, report_json):
        report_json['date'] = datetime.strptime(report_json['date'],
                                                '%m%d%Y').date()
        report_json['zipcode'] = report_json.pop('zip')

        return Report(idrssd=idrssd, **report_json)
示例#11
0
def send(request):

    # Obtenemos los campos comunes entre reportes
    report_type = request.POST.get('form_type', "")
    doc_name = request.POST.get('nombre_dr', "")
    patient_name = request.POST.get('nombre_pac', "")
    consult_date = request.POST.get('fecha', "")
    observ = request.POST.get('observaciones', "")

    # Variables comunes
    url = 'https://android.googleapis.com/gcm/send'
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'key=AIzaSyCH7B7qMMbLnQdj6WG1yuvPp3SlsLHtBds'
    }

    # Creamos un objeto del tipo reporte del que heredará la info el reporte específico
    rep = Report(doc_name=doc_name,
                 patient_name=patient_name,
                 consult_date=consult_date,
                 report_type=report_type,
                 observ=observ)
    rep.save()

    if report_type == "psicologico":

        # Obtenemos campos únicos de reporte psicologico
        patient_state = request.POST.get('estado_pac', "")
        suggest = request.POST.get('sugerencias', "")

        psy = PsyReport(report=rep,
                        patient_state=patient_state,
                        suggest=suggest)
        psy.save()

        print >> sys.stderr, psy.report
        # Payload del reporte psicologico
        payload = {
            "data": {
                "id": psy.report.id,
                "tipo": report_type,
                "fecha": consult_date,
                "doctor": doc_name,
                "paciente": patient_name,
                "observaciones": observ,
                "sugerencias": suggest
            },
            "registration_ids": [
                "APA91bHDXfzISMoo6OfqhhODnU7TeNzqCxeE7lYZHhdI801wazh1e7vbITZVTqwKU5avNW0myInlZW3Aat3S8gzqawN9G5fQEkMVNvqkDHRRYt1IDsFrPuc"
            ]
        }
    elif report_type == "nutricional":

        # Obtenemos campos únicos de reporte nutricional
        weight = request.POST.get('peso', "")
        height = request.POST.get('talla', "")
        pressure = request.POST.get('presion', "")
        risk_factors = request.POST.get('fac_riesgo', "")
        appetite = request.POST.get('est_apetito', "")
        diet = request.POST.get('dieta', "")

        nut = NutReport(report=rep,
                        weight=weight,
                        height=height,
                        pressure=pressure,
                        risk_factors=risk_factors,
                        appetite=appetite,
                        diet=diet)
        nut.save()

        # Payload del reporte psicologico
        payload = {
            "data": {
                "id": nut.report.id,
                "tipo": report_type,
                "fecha": consult_date,
                "doctor": doc_name,
                "paciente": patient_name,
                "observaciones": observ,
                "peso": weight,
                "talla": height,
                "presion": pressure,
                "fac_riesgo": risk_factors,
                "est_apetito": appetite,
                "dieta": diet
            },
            "registration_ids": [
                "APA91bHDXfzISMoo6OfqhhODnU7TeNzqCxeE7lYZHhdI801wazh1e7vbITZVTqwKU5avNW0myInlZW3Aat3S8gzqawN9G5fQEkMVNvqkDHRRYt1IDsFrPuc"
            ]
        }
    # El envío de la notificación es común para los reportes
    try:
        #r = requests.post(url, data=json.dumps(payload))
        r = requests.post(url, headers=headers, data=json.dumps(payload))
    except requests.exceptions.ConnectionError:
        if report_type == "psicologico":
            return render(request, 'reports/psychological.html', {
                'error_message':
                "No hay conexión a internet, intente más tarde",
            })
        elif report_type == "nutricional":
            return render(request, 'reports/nutritional.html', {
                'error_message':
                "No hay conexión a internet, intente más tarde",
            })
    else:
        print >> sys.stderr, "POST request response: ", r.status_code
        if r.status_code == 200:
            code = 0
        else:
            code = 1

        return HttpResponseRedirect(
            reverse('reports:results', args=(rep.id, code)))

        pass
示例#12
0
 def test_str(self):
     my_title = Report(title="Basic Title for test")
     self.assertEquals(str(my_title), "Basic Title for test")
示例#13
0
def submit(request):

    if not request.GET.has_key('imei'):
        return HttpResponse("Expected additional parameters")

    imei = request.GET['imei']
    nmea_str = request.GET['rmc']
    nmea_list = nmea_str.split(",")

    #Sanav sentence is of type GPRMC with a couple extra attributes for voltage and report type
    #imei - first parameter before sentence, provides a unique id for the device
    #NMEA type - $GPRMC
    #UTC time - 095838.000 hhmmss.sss
    #Status - A
    #Lat - 2458.9733 ddmm.mmmm Degree Decimal Minute
    #Lat dir - N
    #Lon - 12125.6583 ddmm.mmmm Degree Decimal Minute
    #Lon dir - E
    #Speed knots - 0.41
    #Course - 79.21
    #UTC Date - 220905 ddmmyy
    #Mag. deviation - blank
    #Checksum - *30
    #Voltage - 3777mv
    #Report type - POLL

    rep_time = nmea_list[1]
    rep_lat = nmea_list[3]
    rep_lat_dir = nmea_list[4]
    rep_lon = nmea_list[5]
    rep_lon_dir = nmea_list[6]
    rep_date = nmea_list[9]

    r = Report()
    r.imei = imei
    r.nmea_type = nmea_list[0][1:]
    r.status = nmea_list[2]
    r.speed = nmea_list[7]
    r.course = nmea_list[8]
    r.voltage = nmea_list[12][0:-2]
    r.rep_type = nmea_list[13]
    r.nmea_sentence = nmea_str

    #parse and build location
    lon_dd = float(rep_lon[:-7]) + float(rep_lon[-7:]) / 60.0
    if rep_lon_dir == 'W':
        lon_dd *= -1
    lat_dd = float(rep_lat[:-7]) + float(rep_lat[-7:]) / 60.0
    if rep_lat_dir == 'S':
        lat_dd *= -1
    r.loc = Point(lon_dd, lat_dd)

    #parse and build timestamp
    year = int(rep_date[4:6])
    month = int(rep_date[2:4])
    day = int(rep_date[0:2])
    hour = int(rep_time[0:2])
    minute = int(rep_time[2:4])
    sec = int(rep_time[4:6])
    ms = int(rep_time[7:])
    r.timestamp = datetime.datetime(year, month, day, hour, minute, sec, ms)

    r.save()

    return HttpResponse("Report logged")