diff --git a/.gitignore b/.gitignore index af8b3db4..f41a6125 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ env/ /scripts/ldap.* .DS_Store +__pycache__ +*.pyc diff --git a/.travis.yml b/.travis.yml index 5f91473e..c3d3a42c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ before_install: - cp aurora/aurora/config.py.example aurora/aurora/config.py - docker-compose up -d - sleep 60s + - docker-compose exec web pip install coverage install: true before_script: - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter diff --git a/Dockerfile b/Dockerfile index d41c791d..79996f4a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:2.7 +FROM python:3.6 ENV PYTHONUNBUFFERED 1 diff --git a/aurora/aurora/settings.py b/aurora/aurora/settings.py index d828a58b..24d26363 100644 --- a/aurora/aurora/settings.py +++ b/aurora/aurora/settings.py @@ -11,7 +11,6 @@ """ import os -import sys from aurora import config as CF @@ -22,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '=*+t-qchu_$#hhf9m-n45s7p=@n46(zmf^mof$+cdaa0t6h8pq' +SECRET_KEY = "=*+t-qchu_$#hhf9m-n45s7p=@n46(zmf^mof$+cdaa0t6h8pq" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = CF.DEBUG @@ -33,58 +32,58 @@ # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django_cron', - 'rest_framework', - 'drf_yasg', - 'bag_transfer', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django_cron", + "rest_framework", + 'health_check', + "bag_transfer", ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'bag_transfer.middleware.AuthenticationMiddlewareJWT', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "bag_transfer.middleware.AuthenticationMiddlewareJWT", ] -ROOT_URLCONF = 'aurora.urls' +ROOT_URLCONF = "aurora.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'bag_transfer', 'templates')], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'bag_transfer.context_processors.gtm_id', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [os.path.join(BASE_DIR, "bag_transfer", "templates")], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "bag_transfer.context_processors.gtm_id", ], }, }, ] -LOGIN_REDIRECT_URL = 'app_home' +LOGIN_REDIRECT_URL = "app_home" -WSGI_APPLICATION = 'aurora.wsgi.application' +WSGI_APPLICATION = "aurora.wsgi.application" REST_FRAMEWORK = { - 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', - 'PAGE_SIZE': 50, - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', + "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", + "PAGE_SIZE": 50, + "DEFAULT_AUTHENTICATION_CLASSES": ( + "rest_framework_jwt.authentication.JSONWebTokenAuthentication", + "rest_framework.authentication.SessionAuthentication", ), } @@ -92,37 +91,29 @@ # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { - 'default': CF.DEFAULT_DB, + "default": CF.DEFAULT_DB, } -AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', -) +AUTHENTICATION_BACKENDS = ("django.contrib.auth.backends.ModelBackend",) # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, + {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, + {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, + {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, ] -AUTH_USER_MODEL = 'bag_transfer.User' -LOGIN_REDIRECT_URL = '/app' +AUTH_USER_MODEL = "bag_transfer.User" +LOGIN_REDIRECT_URL = "/app" # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" TIME_ZONE = CF.TIME_ZONE USE_I18N = True USE_L10N = True @@ -131,7 +122,7 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ -STATIC_URL = '/static/' +STATIC_URL = "/static/" STATIC_ROOT = CF.STATIC_ROOT STORAGE_ROOT_DIR = CF.STORAGE_ROOT_DIR DELIVERY_QUEUE_DIR = CF.DELIVERY_QUEUE_DIR @@ -151,8 +142,8 @@ "django_cron.backends.lock.file.FileLock", ] -#Django Cron Lock -DJANGO_CRON_LOCK_BACKEND="django_cron.backends.lock.file.FileLock" +# Django Cron Lock +DJANGO_CRON_LOCK_BACKEND = "django_cron.backends.lock.file.FileLock" # Email EMAIL_HOST = CF.EMAIL_HOST @@ -173,8 +164,8 @@ # Post-accession callbacks -DELIVERY_URL = getattr(CF, 'DELIVERY_URL', None) -API_KEY = getattr(CF, 'API_KEY', None) +DELIVERY_URL = getattr(CF, "DELIVERY_URL", None) +API_KEY = getattr(CF, "API_KEY", None) # ArchivesSpace configs ASPACE = CF.ASPACE diff --git a/aurora/aurora/urls.py b/aurora/aurora/urls.py index da7f48ee..9dd41ae9 100644 --- a/aurora/aurora/urls.py +++ b/aurora/aurora/urls.py @@ -15,30 +15,61 @@ """ from django.conf.urls import url, include from django.contrib import admin -from bag_transfer.users.views import * -from bag_transfer.users.form import UserPasswordResetForm, UserSetPasswordForm +from bag_transfer.users.views import ( + SplashView, + UserPasswordResetView, + UserPasswordResetDoneView, + UserPasswordResetConfirmView, + UserPasswordResetCompleteView, +) from django.contrib.auth import views as auth_views from bag_transfer.transfers.views import MainView urlpatterns = [ - url(r'^admin/', admin.site.urls), - url(r'^app/$', MainView.as_view(), name='app_home'), - url(r'^app/transfers/', include('bag_transfer.transfers.urls', namespace='transfers')), - url(r'^app/orgs/', include('bag_transfer.orgs.urls', namespace='orgs')), - url(r'^app/users/', include('bag_transfer.users.urls', namespace='users')), - url(r'^reset-password/$', UserPasswordResetView.as_view( - email_template_name='users/password_reset_email.html', - subject_template_name='users/password_reset_subject.txt' - ), name='password_reset'), - url(r'^reset-password/done/$', UserPasswordResetDoneView.as_view(), name='password_reset_done'), - url(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', - UserPasswordResetConfirmView.as_view(), name='password_reset_confirm'), - url(r'^reset/done/$', UserPasswordResetCompleteView.as_view(), name='password_reset_complete'), - url(r'^app/accession/', include('bag_transfer.accession.urls', namespace='accession')), - url(r'^app/appraise/', include('bag_transfer.appraise.urls', namespace='appraise')), - url(r'^app/rights/', include('bag_transfer.rights.urls', namespace='rights')), - url(r'^$', SplashView.as_view()), - url(r'^login/$', auth_views.login, {'template_name': 'users/login.html'}, name='login'), - url(r'^logout/$', auth_views.logout, {'next_page': '/login'}, name='logout'), - url(r'^api/', include('bag_transfer.api.urls')), + url(r"^admin/", admin.site.urls), + url(r"^app/$", MainView.as_view(), name="app_home"), + url( + r"^app/transfers/", + include("bag_transfer.transfers.urls", namespace="transfers"), + ), + url(r"^app/orgs/", include("bag_transfer.orgs.urls", namespace="orgs")), + url(r"^app/users/", include("bag_transfer.users.urls", namespace="users")), + url( + r"^reset-password/$", + UserPasswordResetView.as_view( + email_template_name="users/password_reset_email.html", + subject_template_name="users/password_reset_subject.txt", + ), + name="password_reset", + ), + url( + r"^reset-password/done/$", + UserPasswordResetDoneView.as_view(), + name="password_reset_done", + ), + url( + r"^reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$", + UserPasswordResetConfirmView.as_view(), + name="password_reset_confirm", + ), + url( + r"^reset/done/$", + UserPasswordResetCompleteView.as_view(), + name="password_reset_complete", + ), + url( + r"^app/accession/", + include("bag_transfer.accession.urls", namespace="accession"), + ), + url(r"^app/appraise/", include("bag_transfer.appraise.urls", namespace="appraise")), + url(r"^app/rights/", include("bag_transfer.rights.urls", namespace="rights")), + url(r"^$", SplashView.as_view()), + url( + r"^login/$", + auth_views.LoginView.as_view(template_name="users/login.html"), + name="login", + ), + url(r"^logout/$", auth_views.LogoutView.as_view(next_page="/login"), name="logout"), + url(r"^api/", include("bag_transfer.api.urls")), + url(r'^status/', include('health_check.api.urls')), ] diff --git a/aurora/aurora/wsgi.py b/aurora/aurora/wsgi.py index 7273d59a..36dde206 100644 --- a/aurora/aurora/wsgi.py +++ b/aurora/aurora/wsgi.py @@ -8,9 +8,15 @@ """ import os +import sys from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_electron.settings") +path = '/data/htdocs/aurora/aurora' + +if path not in sys.path: + sys.path.append(path) + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aurora.settings") application = get_wsgi_application() diff --git a/aurora/bag_transfer/accession/db_functions.py b/aurora/bag_transfer/accession/db_functions.py index 528fcd74..e39338a4 100644 --- a/aurora/bag_transfer/accession/db_functions.py +++ b/aurora/bag_transfer/accession/db_functions.py @@ -1,16 +1,14 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db.models import CharField, Aggregate class GroupConcat(Aggregate): - function = 'GROUP_CONCAT' - template = '%(function)s(%(distinct)s%(expressions)s)' + function = "GROUP_CONCAT" + template = "%(function)s(%(distinct)s%(expressions)s)" def __init__(self, expression, distinct=False, **extra): super(GroupConcat, self).__init__( expression, - distinct='DISTINCT ' if distinct else '', + distinct="DISTINCT " if distinct else "", output_field=CharField(), - **extra) + **extra + ) diff --git a/aurora/bag_transfer/accession/forms.py b/aurora/bag_transfer/accession/forms.py index d0c2ae01..fc4c8419 100644 --- a/aurora/bag_transfer/accession/forms.py +++ b/aurora/bag_transfer/accession/forms.py @@ -7,42 +7,52 @@ class AccessionForm(forms.ModelForm): class Meta: model = Accession - exclude = ('accession_date',) + exclude = ("accession_date",) labels = { - 'resource': 'Related Resource', - 'title': 'Title', - 'start_date': 'Start Date', - 'end_date': 'End Date', - 'description': 'Content Description', - 'access_restrictions': 'Access Restrictions Note', - 'use_restrictions': 'Use Restrictions Note', + "resource": "Related Resource", + "title": "Title", + "start_date": "Start Date", + "end_date": "End Date", + "description": "Content Description", + "access_restrictions": "Access Restrictions Note", + "use_restrictions": "Use Restrictions Note", } help_texts = {} widgets = { - 'title': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type': 'date'}), - 'end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type': 'date'}), - 'description': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), - 'access_restrictions': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), - 'use_restrictions': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), - 'resource': forms.widgets.HiddenInput(), - 'accession_number': forms.widgets.HiddenInput(), - 'extent_files': forms.widgets.HiddenInput(), - 'extent_size': forms.widgets.HiddenInput(), - 'acquisition_type': forms.widgets.HiddenInput(), - 'appraisal_note': forms.widgets.HiddenInput(), - 'organization': forms.widgets.HiddenInput(), - 'language': forms.widgets.HiddenInput(), - 'creators': forms.widgets.MultipleHiddenInput(), + "title": forms.widgets.TextInput(attrs={"class": "form-control"}), + "start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "description": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + "access_restrictions": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + "use_restrictions": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + "resource": forms.widgets.HiddenInput(), + "accession_number": forms.widgets.HiddenInput(), + "extent_files": forms.widgets.HiddenInput(), + "extent_size": forms.widgets.HiddenInput(), + "acquisition_type": forms.widgets.HiddenInput(), + "appraisal_note": forms.widgets.HiddenInput(), + "organization": forms.widgets.HiddenInput(), + "language": forms.widgets.HiddenInput(), + "creators": forms.widgets.MultipleHiddenInput(), } CreatorsFormSet = forms.modelformset_factory( RecordCreators, - fields=('name', 'type'), + fields=("name", "type"), extra=0, widgets={ - 'name': forms.widgets.TextInput(attrs={'class': 'form-control col-sm-8'}), - 'type': forms.widgets.Select(attrs={'class': 'form-control'}) + "name": forms.widgets.TextInput(attrs={"class": "form-control col-sm-8"}), + "type": forms.widgets.Select(attrs={"class": "form-control"}), }, ) diff --git a/aurora/bag_transfer/accession/models.py b/aurora/bag_transfer/accession/models.py index cf0bedc3..1dce9c99 100644 --- a/aurora/bag_transfer/accession/models.py +++ b/aurora/bag_transfer/accession/models.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models from bag_transfer.models import Organization, RecordCreators, LanguageCode @@ -20,7 +17,13 @@ class Accession(models.Model): resource = models.CharField(max_length=255) acquisition_type = models.CharField(max_length=200) appraisal_note = models.TextField(blank=True, null=True) - organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='accession', null=True, blank=True) + organization = models.ForeignKey( + Organization, + on_delete=models.CASCADE, + related_name="accession", + null=True, + blank=True, + ) language = models.ForeignKey(LanguageCode, on_delete=models.CASCADE) created = models.DateTimeField(auto_now_add=True) last_modified = models.DateTimeField(auto_now=True) @@ -29,10 +32,12 @@ class Accession(models.Model): RECORD_CREATED = 30 COMPLETE = 40 PROCESS_STATUS_CHOICES = ( - (CREATED, 'Accession created'), - (DELIVERED, 'Accession transfers delivered to queue'), - (RECORD_CREATED, 'Accession record created in ArchivesSpace'), - (COMPLETE, 'Accession complete') + (CREATED, "Accession created"), + (DELIVERED, "Accession transfers delivered to queue"), + (RECORD_CREATED, "Accession record created in ArchivesSpace"), + (COMPLETE, "Accession complete"), + ) + process_status = models.PositiveSmallIntegerField( + choices=PROCESS_STATUS_CHOICES, default=10, null=True, blank=True ) - process_status = models.PositiveSmallIntegerField(choices=PROCESS_STATUS_CHOICES, default=10, null=True, blank=True) archivesspace_identifier = models.CharField(max_length=255, blank=True, null=True) diff --git a/aurora/bag_transfer/accession/urls.py b/aurora/bag_transfer/accession/urls.py index dbe5a12b..82dca773 100644 --- a/aurora/bag_transfer/accession/urls.py +++ b/aurora/bag_transfer/accession/urls.py @@ -1,9 +1,20 @@ from django.conf.urls import url -from bag_transfer.accession.views import * +from bag_transfer.accession.views import ( + AccessionView, + AccessionCreateView, + AccessionDetailView, + SavedAccessionsDatatableView, +) + +app_name = 'accessions' urlpatterns = [ - url(r'^$', AccessionView.as_view(), name='list'), - url(r'^(?P\d+)/$', AccessionDetailView.as_view(), name='detail'), - url(r'^add/', AccessionCreateView.as_view(), name='add'), - url(r'^saved-datatable/$', SavedAccessionsDatatableView.as_view(), name='saved-datatable'), + url(r"^$", AccessionView.as_view(), name="list"), + url(r"^(?P\d+)/$", AccessionDetailView.as_view(), name="detail"), + url(r"^add/", AccessionCreateView.as_view(), name="add"), + url( + r"^saved-datatable/$", + SavedAccessionsDatatableView.as_view(), + name="saved-datatable", + ), ] diff --git a/aurora/bag_transfer/accession/views.py b/aurora/bag_transfer/accession/views.py index d595c3ee..a1aa0031 100644 --- a/aurora/bag_transfer/accession/views.py +++ b/aurora/bag_transfer/accession/views.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from dateutil import tz import json import requests @@ -10,7 +7,6 @@ from django.db.models import CharField, F from django.db.models.functions import Concat from django.contrib import messages -from django.http import HttpResponse from django.shortcuts import render, redirect, reverse from aurora import settings @@ -22,7 +18,12 @@ from bag_transfer.lib.view_helpers import file_size from bag_transfer.mixins.formatmixins import JSONResponseMixin from bag_transfer.mixins.authmixins import ArchivistMixin, AccessioningArchivistMixin -from bag_transfer.models import Archives, RecordCreators, Organization, BAGLog, LanguageCode +from bag_transfer.models import ( + Archives, + RecordCreators, + BAGLog, + LanguageCode, +) from bag_transfer.rights.models import RightsStatement @@ -33,41 +34,58 @@ class AccessionView(ArchivistMixin, JSONResponseMixin, ListView): def get(self, request, *args, **kwargs): if request.is_ajax(): return self.handle_ajax_request(request) - return render(request, self.template_name, { - 'uploads': Archives.objects.filter( - process_status=Archives.ACCEPTED).annotate( - transfer_group=Concat('organization', 'metadata__record_type', - GroupConcat('metadata__record_creators'), - output_field=CharField())).order_by('transfer_group'), - 'accessions': Accession.objects.all(), - 'meta_page_title': 'Accessioning Queue', - 'deliver': True if settings.DELIVERY_URL else False, - }) + return render( + request, + self.template_name, + { + "uploads": Archives.objects.filter(process_status=Archives.ACCEPTED) + .annotate( + transfer_group=Concat( + "organization", + "metadata__record_type", + GroupConcat("metadata__record_creators"), + output_field=CharField(), + ) + ) + .order_by("transfer_group"), + "accessions": Accession.objects.all(), + "meta_page_title": "Accessioning Queue", + "deliver": True if settings.DELIVERY_URL else False, + }, + ) def handle_ajax_request(self, request): + """Handles JavaScript AJAX requests.""" rdata = {} - rdata['success'] = 0 - if request.user.has_privs('ACCESSIONER'): - if 'accession_id' in request.GET: + rdata["success"] = 0 + if request.user.has_privs("ACCESSIONER"): + if "accession_id" in request.GET: try: - accession = Accession.objects.get(pk=request.GET['accession_id']) - accession_data = AccessionSerializer(accession, context={'request': request}) + accession = Accession.objects.get(pk=request.GET["accession_id"]) + accession_data = AccessionSerializer( + accession, context={"request": request} + ) resp = requests.post( settings.DELIVERY_URL, - data=json.dumps(accession_data.data, indent=4, sort_keys=True, default=str), - headers={'Content-Type': 'application/json', 'apikey': settings.API_KEY} + data=json.dumps( + accession_data.data, indent=4, sort_keys=True, default=str + ), + headers={ + "Content-Type": "application/json", + "apikey": settings.API_KEY, + }, ) resp.raise_for_status() accession.process_status = Accession.DELIVERED accession.save() - rdata['success'] = 1 + rdata["success"] = 1 except Exception as e: - rdata['error'] = str(e) + rdata["error"] = str(e) return self.render_to_json_response(rdata) class AccessionDetailView(AccessioningArchivistMixin, DetailView): - template_name = 'accession/detail.html' + template_name = "accession/detail.html" model = Accession @@ -77,13 +95,17 @@ class AccessionCreateView(AccessioningArchivistMixin, JSONResponseMixin, View): form_class = AccessionForm def post(self, request, *args, **kwargs): + """Saves accessions, and delivers data to DELIVERY_URL if configured.""" form = self.form_class(request.POST) creators_formset = CreatorsFormSet(request.POST) - id_list = map(int, request.GET.get('transfers').split(',')) + id_list = list(map(int, request.GET.get("transfers").split(","))) transfers_list = Archives.objects.filter(pk__in=id_list) - rights_statements = RightsStatement.objects.filter( - archive__in=id_list).annotate(rights_group=F('rights_basis')).order_by('rights_group') - if (form.is_valid() and creators_formset.is_valid()): + rights_statements = ( + RightsStatement.objects.filter(archive__in=id_list) + .annotate(rights_group=F("rights_basis")) + .order_by("rights_group") + ) + if form.is_valid() and creators_formset.is_valid(): form.process_status = Accession.CREATED accession = form.save() creators_formset.save() @@ -92,50 +114,68 @@ def post(self, request, *args, **kwargs): statement.accession = accession statement.save() for transfer in transfers_list: - BAGLog.log_it('BACC', transfer) + BAGLog.log_it("BACC", transfer) transfer.process_status = Archives.ACCESSIONING_STARTED transfer.accession = accession transfer.save() - messages.success(request, '
Accession created successfully!') + messages.success(request, "
Accession created successfully!") if settings.DELIVERY_URL: try: - accession_data = AccessionSerializer(accession, context={'request': request}) + accession_data = AccessionSerializer( + accession, context={"request": request} + ) resp = requests.post( settings.DELIVERY_URL, - data=json.dumps(accession_data.data, indent=4, sort_keys=True, default=str), - headers={'Content-Type': 'application/json', 'apikey': settings.API_KEY} + data=json.dumps( + accession_data.data, indent=4, sort_keys=True, default=str + ), + headers={ + "Content-Type": "application/json", + "apikey": settings.API_KEY, + }, ) resp.raise_for_status() accession.process_status = Accession.DELIVERED accession.save() - messages.success(request, 'Accession data delivered.') + messages.success(request, "Accession data delivered.") except Exception as e: print(e) - messages.error(request, 'Error delivering accession data: {}'.format(e)) - return redirect('accession:detail', accession.pk) + messages.error( + request, "Error delivering accession data: {}".format(e) + ) + return redirect("accession:detail", accession.pk) messages.error( request, - "There was a problem with your submission. Please correct the error(s) below and try again.") - return render(request, self.template_name, { - 'meta_page_title': 'Create Accession Record', - 'form': form, - 'creators_formset': creators_formset, - 'rights_statements': rights_statements, - 'transfers': transfers_list - }) + "There was a problem with your submission. Please correct the error(s) below and try again.", + ) + return render( + request, + self.template_name, + { + "meta_page_title": "Create Accession Record", + "form": form, + "creators_formset": creators_formset, + "rights_statements": rights_statements, + "transfers": transfers_list, + }, + ) def get(self, request, *args, **kwargs): + """Performs initial grouping of transfer data.""" if request.is_ajax(): return self.handle_ajax_request(request) else: - id_list = map(int, request.GET.get('transfers').split(',')) + id_list = list(map(int, request.GET.get("transfers").split(","))) transfers_list = Archives.objects.filter(pk__in=id_list) - rights_statements = RightsStatement.objects.filter( - archive__in=id_list).annotate(rights_group=F('rights_basis')).order_by('rights_group') + rights_statements = ( + RightsStatement.objects.filter(archive__in=id_list) + .annotate(rights_group=F("rights_basis")) + .order_by("rights_group") + ) # should this get the source_organization from bag_data instead? Need to coordinate with data in other views organization = transfers_list[0].organization - notes = {'appraisal': []} - dates = {'start': [], 'end': []} + notes = {"appraisal": []} + dates = {"start": [], "end": []} creators_list = [] descriptions_list = [] languages_list = [] @@ -143,13 +183,19 @@ def get(self, request, *args, **kwargs): extent_size = 0 for transfer in transfers_list: bag_data = transfer.get_bag_data() - extent_size = extent_size + int(bag_data.get('payload_oxum', '0.0').split('.')[0]) - extent_files = extent_files + int(bag_data.get('payload_oxum', '0.0').split('.')[1]) - dates['start'].append(bag_data.get('date_start', '')) - dates['end'].append(bag_data.get('date_end', '')) - notes['appraisal'].append(bag_data.get('appraisal_note', '')) - descriptions_list.append(bag_data.get('internal_sender_description', '')) - for language in bag_data.get('language', []): + extent_size = extent_size + int( + bag_data.get("payload_oxum", "0.0").split(".")[0] + ) + extent_files = extent_files + int( + bag_data.get("payload_oxum", "0.0").split(".")[1] + ) + dates["start"].append(bag_data.get("date_start", "")) + dates["end"].append(bag_data.get("date_end", "")) + notes["appraisal"].append(bag_data.get("appraisal_note", "")) + descriptions_list.append( + bag_data.get("internal_sender_description", "") + ) + for language in bag_data.get("language", []): languages_list.append(language) creators_list += transfer.get_records_creators() for statement in rights_statements: @@ -157,96 +203,155 @@ def get(self, request, *args, **kwargs): rights_granted = statement.get_rights_granted_objects() if not statement.rights_basis.lower() in notes: notes[statement.rights_basis.lower()] = [] - notes[statement.rights_basis.lower()].append(next(value for key, value in rights_info.__dict__.iteritems() if '_note' in key.lower())) + notes[statement.rights_basis.lower()].append( + next( + value + for key, value in rights_info.__dict__.items() + if "_note" in key.lower() + ) + ) for grant in rights_granted: - notes[statement.rights_basis.lower()].append(grant.rights_granted_note) + notes[statement.rights_basis.lower()].append( + grant.rights_granted_note + ) record_creators = list(set(creators_list)) languages_list = list(set(languages_list)) - language = LanguageCode.objects.get_or_create(code='und')[0] + language = LanguageCode.objects.get_or_create(code="und")[0] if len(languages_list) == 1: LanguageCode.objects.get_or_create(code=languages_list[0])[0] if len(languages_list) > 1: - language = LanguageCode.objects.get_or_create(code='mul')[0] - title = '{} {}'.format(organization, bag_data.get('record_type', '')) + language = LanguageCode.objects.get_or_create(code="mul")[0] + title = "{} {}".format(organization, bag_data.get("record_type", "")) if len(record_creators) > 0: - title = '{}, {} {}'.format( - organization, ', '.join([creator.name for creator in record_creators]), - bag_data.get('record_type', '')) - form = AccessionForm(initial={ - 'title': title, - 'start_date': sorted(dates.get('start', []))[0], - 'end_date': sorted(dates.get('end', []))[-1], - 'description': ' '.join(set(descriptions_list)), - 'extent_files': extent_files, - 'extent_size': extent_size, - 'access_restrictions': ' '.join(set(notes.get('other', [])+notes.get('license', [])+notes.get('statute', []))), - 'use_restrictions': ' '.join(set(notes.get('copyright', []))), - 'acquisition_type': organization.acquisition_type, - 'appraisal_note': ' '.join(set(notes.get('appraisal', []))), - 'organization': organization, - 'language': language, - 'creators': record_creators, - }) + title = "{}, {} {}".format( + organization, + ", ".join([creator.name for creator in record_creators]), + bag_data.get("record_type", ""), + ) + form = AccessionForm( + initial={ + "title": title, + "start_date": sorted(dates.get("start", []))[0], + "end_date": sorted(dates.get("end", []))[-1], + "description": " ".join(set(descriptions_list)), + "extent_files": extent_files, + "extent_size": extent_size, + "access_restrictions": " ".join( + set( + notes.get("other", []) + + notes.get("license", []) + + notes.get("statute", []) + ) + ), + "use_restrictions": " ".join(set(notes.get("copyright", []))), + "acquisition_type": organization.acquisition_type, + "appraisal_note": " ".join(set(notes.get("appraisal", []))), + "organization": organization, + "language": language, + "creators": record_creators, + } + ) creators_formset = CreatorsFormSet( - queryset=RecordCreators.objects.filter(name__in=record_creators)) - return render(request, self.template_name, { - 'form': form, - 'creators_formset': creators_formset, - 'meta_page_title': 'Create Accession Record', - 'transfers': transfers_list, - 'rights_statements': rights_statements, - }) + queryset=RecordCreators.objects.filter(name__in=record_creators) + ) + return render( + request, + self.template_name, + { + "form": form, + "creators_formset": creators_formset, + "meta_page_title": "Create Accession Record", + "transfers": transfers_list, + "rights_statements": rights_statements, + }, + ) def handle_ajax_request(self, request): + """Handles JavaScript AJAX requests.""" rdata = {} - rdata['success'] = False - if 'resource_id' in request.GET: + rdata["success"] = False + if "resource_id" in request.GET: try: client = ArchivesSpaceClient( - settings.ASPACE['baseurl'], settings.ASPACE['username'], - settings.ASPACE['password'], settings.ASPACE['repo_id']) - resp = client.get_resource(request.GET.get('resource_id')) - rdata['title'] = "{} ({})".format(resp['title'], resp['id_0']) - rdata['uri'] = resp['uri'] - rdata['success'] = True + settings.ASPACE["baseurl"], + settings.ASPACE["username"], + settings.ASPACE["password"], + settings.ASPACE["repo_id"], + ) + resp = client.get_resource(request.GET.get("resource_id")) + rdata["title"] = "{} ({})".format(resp["title"], resp["id_0"]) + rdata["uri"] = resp["uri"] + rdata["success"] = True except Exception as e: - rdata['error'] = str(e) + rdata["error"] = str(e) return self.render_to_json_response(rdata) class SavedAccessionsDatatableView(ArchivistMixin, BaseDatatableView): + """Handles processing of requests for Accessions in datatable, making page + load time more performant.""" model = Accession - columns = ['title', 'created', 'extent_files', 'accession_transfers__machine_file_identifier', 'extent_size'] - order_columns = ['title', 'created', 'extent_files', 'accession_transfers__machine_file_identifier', 'extent_size'] + columns = [ + "title", + "created", + "extent_files", + "accession_transfers__machine_file_identifier", + "extent_size", + ] + order_columns = [ + "title", + "created", + "extent_files", + "accession_transfers__machine_file_identifier", + "extent_size", + ] max_display_length = 500 - def get_filter_method(self): return self.FILTER_ICONTAINS + def get_filter_method(self): + return self.FILTER_ICONTAINS def title(self, accession): - return "{} ({})".format(accession.title, accession.accession_number) if accession.accession_number else accession.title + return ( + "{} ({})".format(accession.title, accession.accession_number) + if accession.accession_number + else accession.title + ) def transfers(self, accession): transfers = accession.accession_transfers.count() - label = 'transfer' if transfers == 1 else 'transfers' + label = "transfer" if transfers == 1 else "transfers" return "{} {}".format(transfers, label) def button(self, accession): button = "Accession not delivered" if self.request.user.can_accession(): - button = 'Deliver Accession' \ - if (accession.process_status < Accession.DELIVERED) \ - else '

'+accession.get_process_status_display()+'

' + button = ( + 'Deliver Accession' + if (accession.process_status < Accession.DELIVERED) + else '

' + + accession.get_process_status_display() + + "

" + ) return button def prepare_results(self, qs): json_data = [] for accession in qs: - json_data.append([ - "{}{} 0: - values = NameArraySerializer(BagItProfileBagInfoValues.objects.filter(bagit_profile_baginfo=obj), many=True).data + values = NameArraySerializer( + BagItProfileBagInfoValues.objects.filter(bagit_profile_baginfo=obj), + many=True, + ).data return { field_name: { - 'required': obj.required, - 'repeatable': obj.repeatable, - 'values': values, + "required": obj.required, + "repeatable": obj.repeatable, + "values": values, } } else: return { - field_name: { - 'required': obj.required, - 'repeatable': obj.repeatable, - } + field_name: {"required": obj.required, "repeatable": obj.repeatable} } @@ -189,73 +294,106 @@ def to_representation(self, obj): class BagItProfileSerializer(serializers.BaseSerializer): - def to_representation(self, obj): bag_info = {} bag_info_values = BagItProfileBagInfo.objects.filter(bagit_profile=obj) for bi in bag_info_values: bag_info.update(BagItProfileBagInfoSerializer(bi).data) - accept_bagit_version = NameArraySerializer(AcceptBagItVersion.objects.filter(bagit_profile=obj), many=True).data - accept_serialization = NameArraySerializer(AcceptSerialization.objects.filter(bagit_profile=obj), many=True).data - manifests_required = NameArraySerializer(ManifestsRequired.objects.filter(bagit_profile=obj), many=True).data - tag_files_required = NameArraySerializer(TagFilesRequired.objects.filter(bagit_profile=obj), many=True).data - tag_manifests_required = NameArraySerializer(TagManifestsRequired.objects.filter(bagit_profile=obj), many=True).data + accept_bagit_version = NameArraySerializer( + AcceptBagItVersion.objects.filter(bagit_profile=obj), many=True + ).data + accept_serialization = NameArraySerializer( + AcceptSerialization.objects.filter(bagit_profile=obj), many=True + ).data + manifests_allowed = NameArraySerializer( + ManifestsAllowed.objects.filter(bagit_profile=obj), many=True + ).data + manifests_required = NameArraySerializer( + ManifestsRequired.objects.filter(bagit_profile=obj), many=True + ).data + tag_files_required = NameArraySerializer( + TagFilesRequired.objects.filter(bagit_profile=obj), many=True + ).data + tag_manifests_required = NameArraySerializer( + TagManifestsRequired.objects.filter(bagit_profile=obj), many=True + ).data return { - 'BagIt-Profile-Info': { + "BagIt-Profile-Info": { "Version": obj.version, "External-Description": obj.external_description, "Contact-Email": obj.contact_email, "BagIt-Profile-Identifier": obj.bagit_profile_identifier, - "Source-Organization": obj.source_organization.name + "Source-Organization": obj.source_organization.name, }, - 'Bag-Info': bag_info, - 'Manifests-Required': manifests_required, - 'Allow-Fetch.txt': obj.allow_fetch, - 'Serialization': obj.serialization, - 'Accept-Serialization': accept_serialization, - 'Accept-BagIt-Version': accept_bagit_version, - 'Tag-Files-Required': tag_files_required, - 'Tag-Manifests-Required': tag_manifests_required, + "Bag-Info": bag_info, + "Manifests-Allowed": manifests_allowed, + "Manifests-Required": manifests_required, + "Allow-Fetch.txt": obj.allow_fetch, + "Serialization": obj.serialization, + "Accept-Serialization": accept_serialization, + "Accept-BagIt-Version": accept_bagit_version, + "Tag-Files-Required": tag_files_required, + "Tag-Manifests-Required": tag_manifests_required, } class BagItProfileListSerializer(serializers.HyperlinkedModelSerializer): - class Meta: model = BagItProfile fields = ("url", "external_description", "version", "applies_to_organization") class OrganizationSerializer(serializers.HyperlinkedModelSerializer): - bagit_profiles = serializers.HyperlinkedIdentityField(read_only=True, view_name='organization-bagit-profiles') - rights_statements = serializers.HyperlinkedIdentityField(read_only=True, view_name='organization-rights-statements') + bagit_profiles = serializers.HyperlinkedIdentityField( + read_only=True, view_name="organization-bagit-profiles" + ) + rights_statements = serializers.HyperlinkedIdentityField( + read_only=True, view_name="organization-rights-statements" + ) class Meta: model = Organization - fields = ('url', 'id', 'is_active', 'name', 'machine_name', - 'acquisition_type', 'bagit_profiles', 'rights_statements') + fields = ( + "url", + "id", + "is_active", + "name", + "machine_name", + "acquisition_type", + "bagit_profiles", + "rights_statements", + ) class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User - fields = ('url', 'username', 'email', 'is_staff', 'is_active', 'date_joined', 'organization') + fields = ( + "url", + "username", + "email", + "is_staff", + "is_active", + "date_joined", + "organization", + ) class AccessionSerializer(serializers.HyperlinkedModelSerializer): creators = RecordCreatorsSerializer(many=True, read_only=True) - transfers = ArchivesListSerializer(source='accession_transfers', many=True, read_only=True) + transfers = ArchivesListSerializer( + source="accession_transfers", many=True, read_only=True + ) organization = serializers.StringRelatedField(read_only=True) rights_statements = RightsStatementSerializer(many=True, read_only=True) language = serializers.StringRelatedField(read_only=True) class Meta: model = Accession - fields = '__all__' + fields = "__all__" class AccessionListSerializer(serializers.HyperlinkedModelSerializer): - class Meta: model = Accession - fields = ('url', 'title', 'accession_number', 'created', 'last_modified') + fields = ("url", "title", "accession_number", "created", "last_modified") diff --git a/aurora/bag_transfer/api/urls.py b/aurora/bag_transfer/api/urls.py index 6ee8961e..debee350 100644 --- a/aurora/bag_transfer/api/urls.py +++ b/aurora/bag_transfer/api/urls.py @@ -1,33 +1,34 @@ from django.conf.urls import url, include - +from rest_framework.schemas import get_schema_view from rest_framework.routers import DefaultRouter from rest_framework_jwt.views import obtain_jwt_token -from drf_yasg.views import get_schema_view -from drf_yasg import openapi -from bag_transfer.api.views import AccessionViewSet, OrganizationViewSet, ArchivesViewSet, BAGLogViewSet, BagItProfileViewSet, UserViewSet +from bag_transfer.api.views import ( + AccessionViewSet, + OrganizationViewSet, + ArchivesViewSet, + BAGLogViewSet, + BagItProfileViewSet, + UserViewSet, +) router = DefaultRouter() -router.register(r'accessions', AccessionViewSet, 'accession') -router.register(r'bagit_profiles', BagItProfileViewSet, 'bagitprofile') -router.register(r'events', BAGLogViewSet, 'baglog') -router.register(r'orgs', OrganizationViewSet, 'organization') -router.register(r'transfers', ArchivesViewSet, 'archives') -router.register(r'users', UserViewSet, 'user') +router.register(r"accessions", AccessionViewSet, "accession") +router.register(r"bagit_profiles", BagItProfileViewSet, "bagitprofile") +router.register(r"events", BAGLogViewSet, "baglog") +router.register(r"orgs", OrganizationViewSet, "organization") +router.register(r"transfers", ArchivesViewSet, "archives") +router.register(r"users", UserViewSet, "user") + schema_view = get_schema_view( - openapi.Info( - title="Aurora API", - default_version='v1', - description="API for Aurora", - contact=openapi.Contact(email="archive@rockarch.org"), - license=openapi.License(name="MIT License"), - ), - validators=['flex', 'ssv'], - public=False, + title="Aurora API", + description=("API endpoints for Aurora, an application to receive, " + "virus check and validate transfers of digital archival records, and allow " + "archivists to appraise and accession those records."), ) urlpatterns = [ - url(r'^schema(?P\.json|\.yaml)$', schema_view.without_ui(cache_timeout=None), name='schema-json'), - url(r'^', include(router.urls)), - url(r'^get-token/', obtain_jwt_token), + url(r'^schema/', schema_view, name='schema'), + url(r"^", include(router.urls)), + url(r"^get-token/", obtain_jwt_token), ] diff --git a/aurora/bag_transfer/api/views.py b/aurora/bag_transfer/api/views.py index 2a6ca8c5..bd753940 100644 --- a/aurora/bag_transfer/api/views.py +++ b/aurora/bag_transfer/api/views.py @@ -1,12 +1,17 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from rest_framework import viewsets, generics, mixins -from rest_framework.decorators import detail_route, list_route +from rest_framework.decorators import action from rest_framework.response import Response from bag_transfer.lib.cleanup import CleanupRoutine -from bag_transfer.models import Organization, Archives, BAGLog, BagInfoMetadata, BagItProfile, ManifestsRequired, User +from bag_transfer.models import ( + Organization, + Archives, + BAGLog, + BagInfoMetadata, + BagItProfile, + ManifestsRequired, + User, +) from bag_transfer.mixins.authmixins import ArchivistMixin, OrgReadViewMixin from bag_transfer.accession.models import Accession from bag_transfer.api.serializers import * @@ -15,6 +20,7 @@ class OrganizationViewSet(OrgReadViewMixin, viewsets.ReadOnlyModelViewSet): """Endpoint for organizations""" + serializer_class = OrganizationSerializer def get_queryset(self): @@ -23,42 +29,54 @@ def get_queryset(self): queryset = queryset.filter(id=self.request.user.organization.id) return queryset - @detail_route() + @action(detail=True) def bagit_profiles(self, request, *args, **kwargs): org = self.get_object() bagit_profiles = BagItProfile.objects.filter(applies_to_organization=org) - serializer = BagItProfileSerializer(bagit_profiles, context={'request': request}, many=True) + serializer = BagItProfileSerializer( + bagit_profiles, context={"request": request}, many=True + ) return Response(serializer.data) - @detail_route(url_path='bagit_profiles/(?P[0-9]+)') + @action(detail=True, url_path="bagit_profiles/(?P[0-9]+)") def bagit_profiles_detail(self, request, number=None, *args, **kwargs): org = self.get_object() bagit_profile = BagItProfile.objects.get(id=number) - serializer = BagItProfileSerializer(bagit_profile, context={'request': request}) + serializer = BagItProfileSerializer(bagit_profile, context={"request": request}) return Response(serializer.data) - @detail_route() + @action(detail=True) def rights_statements(self, request, *args, **kwargs): org = self.get_object() - rights_statements = RightsStatement.objects.filter(archive__isnull=True, organization=org) - serializer = RightsStatementSerializer(rights_statements, context={'request': request}, many=True) + rights_statements = RightsStatement.objects.filter( + archive__isnull=True, organization=org + ) + serializer = RightsStatementSerializer( + rights_statements, context={"request": request}, many=True + ) return Response(serializer.data) class BagItProfileViewSet(viewsets.ReadOnlyModelViewSet): """Endpoint for BagIt profiles""" - queryset = BagItProfile.objects.all() + queryset = BagItProfile.objects.all().order_by("id") def get_serializer_class(self): - if self.action == 'list': + if self.action == "list": return BagItProfileListSerializer - if self.action == 'retrieve': + if self.action == "retrieve": return BagItProfileSerializer return BagItProfileSerializer -class ArchivesViewSet(OrgReadViewMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet): +class ArchivesViewSet( + OrgReadViewMixin, + mixins.ListModelMixin, + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + viewsets.GenericViewSet, +): """Endpoint for transfers""" def dispatch(self, *args, **kwargs): @@ -68,21 +86,21 @@ def get_queryset(self): queryset = queryset = Archives.objects.all() if not self.request.user.is_archivist(): queryset = queryset.filter(organization=self.request.user.organization) - process_status = self.request.GET.get('process_status', "") + process_status = self.request.GET.get("process_status", "") if process_status != "": queryset = queryset.filter(process_status=int(process_status)) return queryset def get_serializer_class(self): - if self.action == 'list': + if self.action == "list": return ArchivesListSerializer - if self.action == 'retrieve': + if self.action == "retrieve": return ArchivesSerializer return ArchivesSerializer def update(self, request, pk=None, *args, **kwargs): try: - identifier = request.data.get('identifier') + identifier = request.data.get("identifier") CleanupRoutine(identifier).run() return super(ArchivesViewSet, self).update(request, *args, **kwargs) except Exception as e: @@ -91,12 +109,15 @@ def update(self, request, pk=None, *args, **kwargs): class BAGLogViewSet(OrgReadViewMixin, viewsets.ReadOnlyModelViewSet): """Endpoint for events""" + serializer_class = BAGLogSerializer def get_queryset(self): queryset = BAGLog.objects.all() if not self.request.user.is_archivist(): - queryset = queryset.filter(archive__organization=self.request.user.organization) + queryset = queryset.filter( + archive__organization=self.request.user.organization + ) return queryset @@ -109,28 +130,34 @@ def get_queryset(self): queryset = queryset.filter(organization=self.request.user.organization) return queryset - @list_route() + @action(detail=False) def current(self, request, *args, **kwargs): user = User.objects.get(id=request.user.pk) - serializer = UserSerializer(user, context={'request': request}) + serializer = UserSerializer(user, context={"request": request}) return Response(serializer.data) -class AccessionViewSet(OrgReadViewMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet): +class AccessionViewSet( + OrgReadViewMixin, + mixins.ListModelMixin, + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + viewsets.GenericViewSet, +): """Endpoint for Accessions""" def get_queryset(self): queryset = Accession.objects.all() if not self.request.user.is_archivist(): queryset = queryset.filter(organization=self.request.user.organization) - process_status = self.request.GET.get('process_status', "") + process_status = self.request.GET.get("process_status", "") if process_status != "": queryset = queryset.filter(process_status=int(process_status)) return queryset def get_serializer_class(self): - if self.action == 'list': + if self.action == "list": return AccessionListSerializer - if self.action == 'retrieve': + if self.action == "retrieve": return AccessionSerializer return AccessionSerializer diff --git a/aurora/bag_transfer/appraise/urls.py b/aurora/bag_transfer/appraise/urls.py index 92446f38..8362c64c 100644 --- a/aurora/bag_transfer/appraise/urls.py +++ b/aurora/bag_transfer/appraise/urls.py @@ -1,7 +1,9 @@ from django.conf.urls import url from bag_transfer.appraise.views import AppraiseView, AppraiseDataTableView +app_name = 'appraise' + urlpatterns = [ - url(r'^$', AppraiseView.as_view(), name='list'), - url(r'^datatable/$', AppraiseDataTableView.as_view(), name='datatable'), + url(r"^$", AppraiseView.as_view(), name="list"), + url(r"^datatable/$", AppraiseDataTableView.as_view(), name="datatable"), ] diff --git a/aurora/bag_transfer/appraise/views.py b/aurora/bag_transfer/appraise/views.py index 6f9a741f..3d53ed4d 100644 --- a/aurora/bag_transfer/appraise/views.py +++ b/aurora/bag_transfer/appraise/views.py @@ -1,13 +1,8 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals from django_datatables_view.base_datatable_view import BaseDatatableView from dateutil import tz -import json -from django.http import HttpResponse from django.views import View -from django.views.generic import TemplateView, UpdateView -from django.shortcuts import render, redirect +from django.shortcuts import render from bag_transfer.lib.files_helper import remove_file_or_dir from bag_transfer.lib.mailer import Mailer @@ -20,85 +15,113 @@ class AppraiseView(ArchivistMixin, JSONResponseMixin, View): template_name = "appraise/main.html" def handle_note_request(self, request, upload, rdata): - if request.GET.get('req_type') == 'edit': - rdata['appraisal_note'] = upload.appraisal_note - elif request.GET.get('req_type') == 'submit': - upload.appraisal_note = request.GET.get('appraisal_note') - elif request.GET.get('req_type') == 'delete': + if request.GET.get("req_type") == "edit": + rdata["appraisal_note"] = upload.appraisal_note + elif request.GET.get("req_type") == "submit": + upload.appraisal_note = request.GET.get("appraisal_note") + elif request.GET.get("req_type") == "delete": upload.appraisal_note = None def handle_appraisal_request(self, request, upload): appraisal_decision = 0 - appraisal_decision = int(request.GET.get('appraisal_decision')) - upload.process_status = (Archives.ACCEPTED if appraisal_decision else Archives.REJECTED) - BAGLog.log_it(('BACPT' if appraisal_decision else 'BREJ'), upload) + appraisal_decision = int(request.GET.get("appraisal_decision")) + upload.process_status = ( + Archives.ACCEPTED if appraisal_decision else Archives.REJECTED + ) + BAGLog.log_it(("BACPT" if appraisal_decision else "BREJ"), upload) if not appraisal_decision: remove_file_or_dir(upload.machine_file_path) if upload.user_uploaded: email = Mailer() email.to = [upload.user_uploaded.email] - email.setup_message('TRANS_REJECT', upload) + email.setup_message("TRANS_REJECT", upload) email.send() def get(self, request, *args, **kwargs): if request.is_ajax(): rdata = {} - rdata['success'] = 0 + rdata["success"] = 0 if request.user.is_archivist(): try: - upload = Archives.objects.get(pk=request.GET.get('upload_id')) + upload = Archives.objects.get(pk=request.GET.get("upload_id")) except Archives.DoesNotExist as e: - rdata['emess'] = e + rdata["emess"] = e return self.render_to_json_response(rdata) - if request.GET.get('req_form') == 'detail': - rdata['object'] = upload.id - rdata['success'] = 1 + if request.GET.get("req_form") == "detail": + rdata["object"] = upload.id + rdata["success"] = 1 - elif (request.GET.get('req_form') == 'appraise' and - request.user.can_appraise()): - if request.GET.get('req_type') == 'decision': + elif ( + request.GET.get("req_form") == "appraise" + and request.user.can_appraise() + ): + if request.GET.get("req_type") == "decision": self.handle_appraisal_request(request, upload) else: self.handle_note_request(request, upload, rdata) upload.save() - rdata['success'] = 1 + rdata["success"] = 1 return self.render_to_json_response(rdata) - return render(request, self.template_name, { - 'meta_page_title': 'Appraisal Queue', - 'uploads_count': len(Archives.objects.filter(process_status=Archives.VALIDATED).order_by('created_time')) - }) + return render( + request, + self.template_name, + { + "meta_page_title": "Appraisal Queue", + "uploads_count": len( + Archives.objects.filter(process_status=Archives.VALIDATED).order_by( + "created_time" + ) + ), + }, + ) class AppraiseDataTableView(ArchivistMixin, BaseDatatableView): model = Archives - columns = ['bag_it_name', 'organization__name', 'metadata__record_creators__name', 'metadata__record_type', 'machine_file_upload_time', 'bag_it_name'] - order_columns = ['bag_it_name', 'organization__name', 'metadata__record_creators__name', 'metadata__record_type', 'machine_file_upload_time', 'bag_it_name'] + columns = [ + "bag_it_name", + "organization__name", + "metadata__record_creators__name", + "metadata__record_type", + "machine_file_upload_time", + "bag_it_name", + ] + order_columns = [ + "bag_it_name", + "organization__name", + "metadata__record_creators__name", + "metadata__record_type", + "machine_file_upload_time", + "bag_it_name", + ] max_display_length = 500 - def get_filter_method(self): return self.FILTER_ICONTAINS + def get_filter_method(self): + return self.FILTER_ICONTAINS def appraise_buttons(self, bag): buttons = '' if self.request.user.can_appraise(): if bag.appraisal_note: - btn_class = 'btn-primary' - note_class = 'edit-note' + btn_class = "btn-primary" + note_class = "edit-note" aria_label = 'aria-label="Note exists"' - note_text = 'Edit' + note_text = "Edit" else: - btn_class = 'btn-info' - note_class = '' - aria_label = '' - note_text = 'Add' + btn_class = "btn-info" + note_class = "" + aria_label = "" + note_text = "Add" buttons = 'Accept\ Reject\ {} Note\ - '\ - .format(btn_class, note_class, aria_label, note_text) + '.format( + btn_class, note_class, aria_label, note_text + ) return buttons def get_initial_queryset(self): @@ -107,17 +130,21 @@ def get_initial_queryset(self): def prepare_results(self, qs): json_data = [] for transfer in qs: - creators = '' + creators = "" bag_info_data = transfer.get_bag_data() if bag_info_data: - creators = ('
').join(bag_info_data.get('record_creators')) - json_data.append([ - transfer.bag_or_failed_name(), - transfer.organization.name, - creators, - bag_info_data.get('record_type'), - transfer.machine_file_upload_time.astimezone(tz.tzlocal()).strftime('%b %e, %Y %I:%M %p'), - self.appraise_buttons(transfer), - transfer.id - ]) + creators = ("
").join(bag_info_data.get("record_creators")) + json_data.append( + [ + transfer.bag_or_failed_name(), + transfer.organization.name, + creators, + bag_info_data.get("record_type"), + transfer.machine_file_upload_time.astimezone(tz.tzlocal()).strftime( + "%b %e, %Y %I:%M %p" + ), + self.appraise_buttons(transfer), + transfer.id, + ] + ) return json_data diff --git a/aurora/bag_transfer/apps.py b/aurora/bag_transfer/apps.py index 9ba7c51c..e31d1a7a 100644 --- a/aurora/bag_transfer/apps.py +++ b/aurora/bag_transfer/apps.py @@ -1,11 +1,8 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.apps import AppConfig class BagTransferConfig(AppConfig): - name = 'bag_transfer' + name = "bag_transfer" def ready(self): import bag_transfer.signals diff --git a/aurora/bag_transfer/context_processors.py b/aurora/bag_transfer/context_processors.py index 15e95800..0f7eb14a 100644 --- a/aurora/bag_transfer/context_processors.py +++ b/aurora/bag_transfer/context_processors.py @@ -1,6 +1,6 @@ -# bag_transfer/context_processors.py - from django.conf import settings + def gtm_id(request): - return {'gtm_id': settings.GTM_ID} + """Adds Google Tag Manager ID to requests.""" + return {"gtm_id": settings.GTM_ID} diff --git a/aurora/bag_transfer/lib/RAC_CMD.py b/aurora/bag_transfer/lib/RAC_CMD.py index 3e1a5d3d..65a15060 100644 --- a/aurora/bag_transfer/lib/RAC_CMD.py +++ b/aurora/bag_transfer/lib/RAC_CMD.py @@ -1,70 +1,80 @@ -import sys -from subprocess import * -import grp, pwd +from subprocess import CalledProcessError, check_output, STDOUT +import grp +import pwd def set_server_password(user, password): - command = 'sudo usermod --password $(echo {} | openssl passwd -1 -stdin) {}'.format(password, user) - output = None + command = "sudo usermod --password $(echo {} | openssl passwd -crypt -stdin) {}".format( + password, user + ) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - raise RuntimeError("command '{}' returned with error (code {}): {}".format(e.cmd, e.returncode, e.output)) + raise RuntimeError( + "command '{}' returned with error (code {}): {}".format( + e.cmd, e.returncode, e.output + ) + ) return True def add_org(organization_machine_name): - command = 'sudo /usr/local/bin/RACaddorg {}'.format(organization_machine_name) - output = None + command = "sudo /usr/local/bin/RACaddorg {}".format(organization_machine_name) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - raise RuntimeError("command '{}' returned with error (code {}): {}".format(e.cmd, e.returncode, e.output)) + raise RuntimeError( + "command '{}' returned with error (code {}): {}".format( + e.cmd, e.returncode, str(e.output) + ) + ) return True def add_user(username): - # try add user has_ERR = False - home = '/home/{}'.format(username) - shell = '/bin/bash' - command = 'sudo useradd {} -d {} -m -g {} -s {}'.format(username, home, 'users', shell) + home = "/home/{}".format(username) + shell = "/bin/bash" + command = "sudo useradd {} -d {} -m -g {} -s {}".format( + username, home, "users", shell + ) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - print "command '{}' returned with error (code {}): {}".format(e.cmd, e.returncode, e.output) - # error codes not isolated.. - if 'Account created' in e.output: + print( + "command '{}' returned with error (code {}): {}".format( + e.cmd, e.returncode, str(e.output) + ) + ) + if "Account created" in str(e.output): pass - elif 'already exists' in e.output: + elif "already exists" in str(e.output): pass else: has_ERR = True - # raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode,e.output)) - - return (True if not has_ERR else False) + return True if not has_ERR else False def add2grp(organization_machine_name, machine_user_id): has_ERR = False - command = 'sudo usermod -a -G {} {}'.format(organization_machine_name, machine_user_id) - output = None + command = "sudo usermod -a -G {} {}".format( + organization_machine_name, machine_user_id + ) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - print e.output + print(e.output) has_ERR = True - return (True if not has_ERR else False) + return True if not has_ERR else False def delete_system_group(organization_machine_name): has_ERR = False - command = 'groupdel {}'.format(organization_machine_name) - output = None + command = "groupdel {}".format(organization_machine_name) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - print e.output + print(e.output) has_ERR = True return not has_ERR @@ -72,19 +82,17 @@ def delete_system_group(organization_machine_name): def del_from_org(machine_user_id): ugroups = [g for g in user_groups(machine_user_id)] has_ERR = False - + for group in ugroups: - if group == 'users': + if group == "users": continue - command = 'sudo gpasswd -d {} {}'.format(machine_user_id,group) - output = None + command = "sudo gpasswd -d {} {}".format(machine_user_id, group) try: output = check_output(command, shell=True, stderr=STDOUT) except CalledProcessError as e: - print e - print e.output + print(e.output) has_ERR = True - return (True if not has_ERR else False) + return True if not has_ERR else False def user_groups(user): diff --git a/aurora/bag_transfer/lib/bag_checker.py b/aurora/bag_transfer/lib/bag_checker.py index ac7361fa..96f9be56 100644 --- a/aurora/bag_transfer/lib/bag_checker.py +++ b/aurora/bag_transfer/lib/bag_checker.py @@ -1,41 +1,38 @@ -import bagit -import bagit_profile -from iso639 import languages -import iso8601 import glob import json -from os.path import isfile, join +from os.path import isfile from django.conf import settings -from django.urls import reverse +import iso8601 +import bagit +import bagit_profile +from iso639 import languages -from aurora import config from bag_transfer.lib import files_helper as FH -from bag_transfer.models import BAGLog, Archives - +from bag_transfer.models import BAGLog -class bagChecker(): +class bagChecker: def __init__(self, archiveObj): self.tmp_path = settings.TRANSFER_EXTRACT_TMP - self.bag_dates_to_validate = ['Date_Start', 'Date_End', 'Bagging_Date'] + self.bag_dates_to_validate = ["Date_Start", "Date_End", "Bagging_Date"] self.archiveObj = archiveObj self.archive_extracted = self._extract_archive() - self.archive_path = '{}{}'.format(self.tmp_path, self.archiveObj.bag_it_name) - self.ecode = '' + self.archive_path = "{}{}".format(self.tmp_path, self.archiveObj.bag_it_name) + self.ecode = "" self.bag = {} self.bag_info_data = {} - self.bag_exception = '' + self.bag_exception = "" def _extract_archive(self): - if self.archiveObj.machine_file_type == 'TAR': + if self.archiveObj.machine_file_type == "TAR": if not FH.tar_extract_all(self.archiveObj.machine_file_path, self.tmp_path): return False - elif self.archiveObj.machine_file_type == 'ZIP': + elif self.archiveObj.machine_file_type == "ZIP": if not FH.zip_extract_all(self.archiveObj.machine_file_path, self.tmp_path): return False - elif self.archiveObj.machine_file_type == 'OTHER': + elif self.archiveObj.machine_file_type == "OTHER": if not FH.dir_extract_all(self.archiveObj.machine_file_path, self.tmp_path): return False else: @@ -46,31 +43,35 @@ def _is_generic_bag(self): try: self.bag = bagit.Bag(self.archive_path) self.bag.validate() - + except ValueError as e: + self.bag_exception = "Error during BagIt validation (likely caused by presence of unsupported md5 checksum): {}".format(e) + return False except Exception as e: - print e - self.bag_exception = e + self.bag_exception = "Error during BagIt validation: {}".format(e) return False else: - # save manifest - for filename in glob.glob('{}/manifest-*.txt'.format(self.archive_path)): - with open(filename, 'r') as manifest_file: + for filename in glob.glob("{}/manifest-*.txt".format(self.archive_path)): + with open(filename, "r") as manifest_file: self.archiveObj.manifest = manifest_file.read() - self._retrieve_bag_info_key_val() # run now to prevent multiple calls below + self._retrieve_bag_info_key_val() # run now to prevent multiple calls below return True def _is_rac_bag(self): """Assumes a valid bag/bag info; returns true if passes rac profile""" - if 'BagIt_Profile_Identifier' not in self.bag_info_data: - self.bag_exception = 'No BagIt Profile to validate against' + if "BagIt_Profile_Identifier" not in self.bag_info_data: + self.bag_exception = "No BagIt Profile to validate against" return False else: try: - profile = bagit_profile.Profile(self.bag_info_data['BagIt_Profile_Identifier']) + profile = bagit_profile.Profile( + self.bag_info_data["BagIt_Profile_Identifier"] + ) except BaseException: - self.bag_exception = "Cannot retrieve BagIt Profile from URL {}".format(self.bag_info_data['BagIt_Profile_Identifier']) + self.bag_exception = "Cannot retrieve BagIt Profile from URL {}".format( + self.bag_info_data["BagIt_Profile_Identifier"] + ) return False else: @@ -83,30 +84,47 @@ def _is_rac_bag(self): except Exception as e: self.bag_exception = "Error in bag-info.txt: {}".format(e.value) return False + try: + profile.validate_payload_manifests_allowed(self.bag) + except Exception as e: + self.bag_exception = "An unallowed manifest was found: {}".format( + e.value + ) + return False try: profile.validate_manifests_required(self.bag) except Exception as e: - self.bag_exception = "Required manifests not found: {}".format(e.value) + self.bag_exception = "Required manifests not found: {}".format( + e.value + ) return False try: profile.validate_tag_manifests_required(self.bag) except Exception as e: - self.bag_exception = "Required tag manifests not found: {}".format(e.value) + self.bag_exception = "Required tag manifests not found: {}".format( + e.value + ) return False try: profile.validate_tag_files_required(self.bag) except Exception as e: - self.bag_exception = "Required tag files not found: {}".format(e.value) + self.bag_exception = "Required tag files not found: {}".format( + e.value + ) return False try: profile.validate_allow_fetch(self.bag) except Exception as e: - self.bag_exception = "fetch.txt is present but is not allowed: {}".format(e.value) + self.bag_exception = "fetch.txt is present but is not allowed: {}".format( + e.value + ) return False try: profile.validate_accept_bagit_version(self.bag) except Exception as e: - self.bag_exception = "Required BagIt version not found: {}".format(e.value) + self.bag_exception = "Required BagIt version not found: {}".format( + e.value + ) return False return True @@ -116,28 +134,28 @@ def _is_rac_bag(self): def _has_valid_datatypes(self): """Assumes a valid bag/bag info; returns true if all datatypes in bag pass""" dates = [] - for k,v in self.bag_info_data.iteritems(): + for k, v in self.bag_info_data.items(): if k in self.bag_dates_to_validate: dates.append(v) - langz = self.bag_info_data.get('Language', None) + langz = self.bag_info_data.get("Language", None) if dates: for date in dates: try: iso8601.parse_date(date) except Exception as e: - print e - self.bag_exception = e + print("Invalid date value: {}".format(date)) + self.bag_exception = "Invalid date value: {}".format(date) return False if langz: - if type(langz) is not list: + if not isinstance(langz, list): langz = [langz] for language in langz: try: languages.get(part2b=language) except KeyError as e: - print e + print("Invalid language value: {}".format(language)) self.bag_exception = "Invalid language value: {}".format(language) return False return True @@ -145,7 +163,7 @@ def _has_valid_datatypes(self): def _has_valid_metadata_file(self): """checks if the metadata file path and is json is correct if exist""" - metadata_file = "/".join([str(self.bag), 'data', 'metadata.json']) + metadata_file = "/".join([str(self.bag), "data", "metadata.json"]) if not isfile(metadata_file): return True @@ -153,53 +171,53 @@ def _has_valid_metadata_file(self): try: return json.loads(FH.get_file_contents(metadata_file)) except ValueError as e: - # self.bag_exception = 'optional metadata file is not valid json' + print("Error parsing metadata file: {}".format(e)) return False def bag_passed_all(self): if not self.archive_extracted: - self.ecode = 'EXERR' - print 'Extract error' + self.ecode = "EXERR" + print("Extract error") return self.bag_failed() if not self._is_generic_bag(): - print 'Bag validation failed' - self.ecode = 'GBERR' + print("Bag validation failed") + self.ecode = "GBERR" return self.bag_failed() if not self.bag_info_data: - print 'Unreadable bag-info' + print("Unreadable bag-info") # log internal error here return self.bag_failed() - BAGLog.log_it('PBAG', self.archiveObj) + BAGLog.log_it("PBAG", self.archiveObj) if not self._is_rac_bag(): - self.ecode = 'RBERR' - print 'Bag Profile validation failed' + self.ecode = "RBERR" + print("Bag Profile validation failed") return self.bag_failed() if not self._has_valid_datatypes(): - self.ecode = 'DTERR' - print 'Datatype validation failed' + self.ecode = "DTERR" + print("Datatype validation failed") return self.bag_failed() if not self._has_valid_metadata_file(): - self.ecode = 'MDERR' - print 'Invalid metadata file' + self.ecode = "MDERR" + print("Invalid metadata file") return self.bag_failed() if not self.archiveObj.save_bag_data(self.bag_info_data): - self.ecode = 'BIERR' - print 'Failed to save bag-info data' + self.ecode = "BIERR" + print("Failed to save bag-info data") return self.bag_failed() if not self.archiveObj.assign_rights(): - self.ecode = 'RSERR' - print 'Failed to assign rights' + self.ecode = "RSERR" + print("Failed to assign rights") return self.bag_failed() - BAGLog.log_it('PBAGP', self.archiveObj) + BAGLog.log_it("PBAGP", self.archiveObj) self.cleanup() return True @@ -218,4 +236,6 @@ def _retrieve_bag_info_key_val(self): if not self.bag.is_valid(): return False - self.bag_info_data = FH.get_fields_from_file('{}/{}'.format(self.archive_path,'bag-info.txt')) + self.bag_info_data = FH.get_fields_from_file( + "{}/{}".format(self.archive_path, "bag-info.txt") + ) diff --git a/aurora/bag_transfer/lib/cleanup.py b/aurora/bag_transfer/lib/cleanup.py index a6a7eafd..b2420b5c 100644 --- a/aurora/bag_transfer/lib/cleanup.py +++ b/aurora/bag_transfer/lib/cleanup.py @@ -1,12 +1,11 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals from os.path import join, isfile from os import remove from aurora import settings -class CleanupError(Exception): pass +class CleanupError(Exception): + pass class CleanupRoutine: diff --git a/aurora/bag_transfer/lib/clients.py b/aurora/bag_transfer/lib/clients.py index b570dd3d..2a0398c0 100644 --- a/aurora/bag_transfer/lib/clients.py +++ b/aurora/bag_transfer/lib/clients.py @@ -2,39 +2,48 @@ from requests import Session -class ArchivesSpaceClientError(Exception): pass +class ArchivesSpaceClientError(Exception): + pass -class ArchivesSpaceClient(): - +class ArchivesSpaceClient: def __init__(self, baseurl, username, password, repo_id): self.repo_id = repo_id self.baseurl = baseurl self.session = Session() - self.session.headers.update({'Accept': 'application/json'}) + self.session.headers.update({"Accept": "application/json"}) try: self.authorize(username, password) except Exception as e: - raise ArchivesSpaceClientError("Couldn't authenticate user credentials for ArchivesSpace: {}".format(e)) + raise ArchivesSpaceClientError( + "Couldn't authenticate user credentials for ArchivesSpace: {}".format(e) + ) def get_resource(self, resource_id, *args, **kwargs): resp = self.session.get( - "/".join([self.baseurl.rstrip("/"), '/repositories/{repo_id}/resources/{resource_id}']).format( - repo_id=self.repo_id, resource_id=resource_id)) + "/".join( + [ + self.baseurl.rstrip("/"), + "/repositories/{repo_id}/resources/{resource_id}", + ] + ).format(repo_id=self.repo_id, resource_id=resource_id) + ) if resp.status_code == 200: return resp.json() else: - raise ArchivesSpaceClientError(resp.json()['error']) + raise ArchivesSpaceClientError(resp.json()["error"]) def authorize(self, username, password): resp = self.session.post( - "/".join([self.baseurl.rstrip("/"), 'users/{username}/login']).format(username=username), - params={"password": password, "expiring": False} + "/".join([self.baseurl.rstrip("/"), "users/{username}/login"]).format( + username=username + ), + params={"password": password, "expiring": False}, ) if resp.status_code != 200: raise ArchivesSpaceClientError((resp.status_code)) else: - session_token = json.loads(resp.text)['session'] - self.session.headers['X-ArchivesSpace-Session'] = session_token + session_token = json.loads(resp.text)["session"] + self.session.headers["X-ArchivesSpace-Session"] = session_token return session_token diff --git a/aurora/bag_transfer/lib/cron.py b/aurora/bag_transfer/lib/cron.py index dd75ab0b..75f93ebb 100644 --- a/aurora/bag_transfer/lib/cron.py +++ b/aurora/bag_transfer/lib/cron.py @@ -1,15 +1,13 @@ -import datetime import json -from os import listdir, mkdir +from os import mkdir from os.path import join -import subprocess from django_cron import CronJobBase, Schedule from aurora import settings from bag_transfer.api.serializers import ArchivesSerializer from bag_transfer.lib import files_helper as FH -from bag_transfer.lib.transfer_routine import * +from bag_transfer.lib.transfer_routine import TransferRoutine from bag_transfer.lib.bag_checker import bagChecker import bag_transfer.lib.log_print as Pter from bag_transfer.models import Archives, Organization, User, BAGLog @@ -20,119 +18,163 @@ class DiscoverTransfers(CronJobBase): RUN_EVERY_MINS = 0 schedule = Schedule(run_every_mins=RUN_EVERY_MINS) - code = 'transfers.discover_transfers' + code = "transfers.discover_transfers" def do(self): + result = True Pter.cron_open(self.code) - BAGLog.log_it('CSTR') + BAGLog.log_it("CSTR") transferRoutine = TransferRoutine(1) to_process = transferRoutine.transfers - if (to_process): + if to_process: for upload_list in to_process: + try: + email = Mailer() - email = Mailer() + machine_file_identifier = Archives().gen_identifier() + org = Organization.is_org_active(upload_list["org"]) + user = User.is_user_active(upload_list["upload_user"], org) - machine_file_identifier = Archives().gen_identifier() - if not machine_file_identifier: - print 'shouldnt overwrite file, need to make sure this file doesnt get discovered again' - continue - - org = Organization().is_org_active(upload_list['org']) - if not org: - org = None - - user = User().is_user_active(upload_list['upload_user'], org) - if not user: - user = None - else: email.to = [user.email] - new_arc = Archives.initial_save( - org, - user, - upload_list['file_path'], - upload_list['file_size'], - upload_list['file_modtime'], - machine_file_identifier, - upload_list['file_type'], - upload_list['bag_it_name'] - ) - - BAGLog.log_it('ASAVE', new_arc) - print "\nValidating transfer {}".format(new_arc.machine_file_identifier) - - if upload_list['auto_fail']: - new_arc.setup_save(upload_list) - new_arc.process_status = Archives.INVALID - BAGLog.log_it(upload_list['auto_fail_code'], new_arc) - email.setup_message('TRANS_FAIL_VAL', new_arc) - email.send() - FH.remove_file_or_dir(new_arc.machine_file_path) - - else: - bag = bagChecker(new_arc) - if bag.bag_passed_all(): - print "Transfer {} is valid".format(new_arc.machine_file_identifier) - new_arc.process_status = Archives.VALIDATED - new_arc.bag_it_valid = True - BAGLog.log_it('APASS', new_arc) - email.setup_message('TRANS_PASS_ALL',new_arc) - email.send() - FH.move_file_or_dir('/data/tmp/{}'.format(new_arc.bag_it_name), '{}{}'.format(settings.STORAGE_ROOT_DIR, new_arc.machine_file_identifier)) - FH.remove_file_or_dir(new_arc.machine_file_path) - new_arc.machine_file_path = '{}{}'.format(settings.STORAGE_ROOT_DIR, new_arc.machine_file_identifier) - else: - print "Transfer {} is invalid".format(new_arc.machine_file_identifier) + new_arc = Archives.initial_save( + org, + user, + upload_list["file_path"], + upload_list["file_size"], + upload_list["file_modtime"], + machine_file_identifier, + upload_list["file_type"], + upload_list["bag_it_name"], + ) + + BAGLog.log_it("ASAVE", new_arc) + print( + "\nValidating transfer {}".format(new_arc.machine_file_identifier) + ) + + if upload_list["auto_fail"]: + new_arc.setup_save(upload_list) new_arc.process_status = Archives.INVALID - BAGLog.log_it(bag.ecode, new_arc) - email.setup_message('TRANS_FAIL_VAL',new_arc) + BAGLog.log_it(upload_list["auto_fail_code"], new_arc) + email.setup_message("TRANS_FAIL_VAL", new_arc) email.send() FH.remove_file_or_dir(new_arc.machine_file_path) - new_arc.save() - - # Delete tmp files - FH.remove_file_or_dir('/data/tmp/{}'.format(new_arc.bag_it_name)) - + else: + bag = bagChecker(new_arc) + if bag.bag_passed_all(): + print( + "Transfer {} is valid".format( + new_arc.machine_file_identifier + ) + ) + new_arc.process_status = Archives.VALIDATED + new_arc.bag_it_valid = True + BAGLog.log_it("APASS", new_arc) + email.setup_message("TRANS_PASS_ALL", new_arc) + email.send() + FH.move_file_or_dir( + "/data/tmp/{}".format(new_arc.bag_it_name), + "{}{}".format( + settings.STORAGE_ROOT_DIR, + new_arc.machine_file_identifier, + ), + ) + FH.remove_file_or_dir(new_arc.machine_file_path) + new_arc.machine_file_path = "{}{}".format( + settings.STORAGE_ROOT_DIR, new_arc.machine_file_identifier + ) + else: + print( + "Transfer {} is invalid".format( + new_arc.machine_file_identifier + ) + ) + new_arc.process_status = Archives.INVALID + BAGLog.log_it(bag.ecode, new_arc) + email.setup_message("TRANS_FAIL_VAL", new_arc) + email.send() + FH.remove_file_or_dir(new_arc.machine_file_path) + + new_arc.save() + FH.remove_file_or_dir("/data/tmp/{}".format(new_arc.bag_it_name)) + except Exception as e: + print("Error discovering transfer {}: {}".format(machine_file_identifier, str(e))) + result = False Pter.cron_close(self.code) + return result class DeliverTransfers(CronJobBase): RUN_EVERY_MINS = 1 schedule = Schedule(run_every_mins=RUN_EVERY_MINS) - code = 'transfers.deliver_transfers' + code = "transfers.deliver_transfers" def do(self): + result = True Pter.cron_open(self.code) - for archive in Archives.objects.filter(process_status=Archives.ACCESSIONING_STARTED): + for archive in Archives.objects.filter( + process_status=Archives.ACCESSIONING_STARTED + ): try: + FH.update_bag_info( + join(settings.STORAGE_ROOT_DIR, archive.machine_file_identifier), + {"Origin": "aurora"} + ) tar_filename = "{}.tar.gz".format(archive.machine_file_identifier) FH.make_tarfile( join(settings.STORAGE_ROOT_DIR, tar_filename), - join(settings.STORAGE_ROOT_DIR, archive.machine_file_identifier)) + join(settings.STORAGE_ROOT_DIR, archive.machine_file_identifier), + ) - mkdir(join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier)) + mkdir( + join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier) + ) FH.move_file_or_dir( join(settings.STORAGE_ROOT_DIR, tar_filename), - join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier, tar_filename)) + join( + settings.DELIVERY_QUEUE_DIR, + archive.machine_file_identifier, + tar_filename, + ), + ) - archive_json = ArchivesSerializer(archive, context={'request': None}).data - with open(join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier, "{}.json".format(archive.machine_file_identifier)), 'wb') as f: + archive_json = ArchivesSerializer( + archive, context={"request": None} + ).data + with open( + join( + settings.DELIVERY_QUEUE_DIR, + archive.machine_file_identifier, + "{}.json".format(archive.machine_file_identifier), + ), + "w", + ) as f: json.dump(archive_json, f, indent=4, sort_keys=True, default=str) FH.make_tarfile( - join(settings.DELIVERY_QUEUE_DIR, "{}.tar.gz".format(archive.machine_file_identifier)), - join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier)) + join( + settings.DELIVERY_QUEUE_DIR, + "{}.tar.gz".format(archive.machine_file_identifier), + ), + join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier), + ) - FH.remove_file_or_dir(join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier)) + FH.remove_file_or_dir( + join(settings.DELIVERY_QUEUE_DIR, archive.machine_file_identifier) + ) archive.process_status = Archives.DELIVERED + print(archive.machine_file_identifier) archive.save() except Exception as e: - print "Error delivering transfer {}: {}".format(archive, str(e)) + print("Error delivering transfer {}: {}".format(archive, str(e))) + result = False Pter.cron_close(self.code) + return result diff --git a/aurora/bag_transfer/lib/files_helper.py b/aurora/bag_transfer/lib/files_helper.py index b00259db..efbc5ef6 100644 --- a/aurora/bag_transfer/lib/files_helper.py +++ b/aurora/bag_transfer/lib/files_helper.py @@ -7,12 +7,8 @@ import psutil import pwd -from django.conf import settings -from aurora import config -from bag_transfer.models import BAGLog, Organization +import bagit -import bag_transfer.lib.log_print as Pter -from bag_transfer.lib.virus_scanner import VirusScan def open_files_list(): """Return a list of files open on the linux system""" @@ -25,6 +21,7 @@ def open_files_list(): path_list.append(fileObj.path) return path_list + def files_in_unserialized(dirpath, CK_SUBDIRS=False): files = [] @@ -36,13 +33,13 @@ def files_in_unserialized(dirpath, CK_SUBDIRS=False): # build list from all files in Infinite sub dirs while True: - #resolve new dir to check + # resolve new dir to check if not to_check: break live_dir = to_check[0] for path in os.listdir(live_dir): - fullpath = "{}/{}".format(live_dir,path) + fullpath = "{}/{}".format(live_dir, path) if os.path.isdir(fullpath): dirpaths.append(fullpath) @@ -59,7 +56,7 @@ def files_in_unserialized(dirpath, CK_SUBDIRS=False): d = os.listdir(dire) if d: for contents in d: - fullpath = "{}/{}".format(dire,contents) + fullpath = "{}/{}".format(dire, contents) if os.path.isfile(fullpath): files.append(fullpath) @@ -70,12 +67,15 @@ def files_in_unserialized(dirpath, CK_SUBDIRS=False): return files + def file_owner(file_path): return pwd.getpwuid(os.stat(file_path).st_uid).pw_name + def file_modified_time(file_path): return datetime.datetime.fromtimestamp(os.path.getmtime(file_path)) + def get_dir_size(start_path): """returns size of contents of dir https://stackoverflow.com/questions/1392413/calculating-a-directory-size-using-python""" total_size = 0 @@ -84,33 +84,36 @@ def get_dir_size(start_path): fp = os.path.join(dirpath, f) total_size += os.path.getsize(fp) for d in dirnames: - dp = os.path.join(dirpath,d) + dp = os.path.join(dirpath, d) total_size += os.path.getsize(dp) - return (total_size if total_size else False) + return total_size if total_size else False + def splitext_(file_path): # https://stackoverflow.com/questions/37896386/how-to-get-file-extension-correctly - if len(file_path.split('.')) > 2: - return file_path.split('.')[0],'.'.join(file_path.split('.')[-2:]) + if len(file_path.split(".")) > 2: + return file_path.split(".")[0], ".".join(file_path.split(".")[-2:]) return os.path.splitext(file_path) + def zip_has_top_level_only(file_path): items = [] - with zipfile.ZipFile(file_path, 'r') as zfile: + with zipfile.ZipFile(file_path, "r") as zfile: items = zfile.namelist() - top_dir = items[0].split('/')[0] + top_dir = items[0].split("/")[0] for item in items[1:]: - if item.split('/')[0] != top_dir: + if item.split("/")[0] != top_dir: return False return top_dir + def tar_has_top_level_only(file_path): items = [] - with tarfile.open(file_path,'r:*') as tfile: + with tarfile.open(file_path, "r:*") as tfile: items = tfile.getnames() if not tfile.getmembers()[0].isdir(): return False @@ -119,10 +122,11 @@ def tar_has_top_level_only(file_path): # items 0 should be the first of every split top_dir = items[0] for item in items: - if item.split('/')[0] != top_dir: + if item.split("/")[0] != top_dir: return False return top_dir + def anon_extract_all(file_path, tmp_dir): """determine which path type, return extraction results""" # is it a dir @@ -130,11 +134,11 @@ def anon_extract_all(file_path, tmp_dir): return dir_extract_all(file_path, tmp_dir) else: # is it a tar - if file_path.endswith('tar.gz') or file_path.endswith('.tar'): + if file_path.endswith("tar.gz") or file_path.endswith(".tar"): return tar_extract_all(file_path, tmp_dir) # is it a zip - if file_path.endswith('.zip'): + if file_path.endswith(".zip"): return zip_extract_all(file_path, tmp_dir) return False @@ -143,53 +147,53 @@ def anon_extract_all(file_path, tmp_dir): def zip_extract_all(file_path, tmp_dir): extracted = False try: - zf = zipfile.ZipFile(file_path,'r') + zf = zipfile.ZipFile(file_path, "r") zf.extractall(tmp_dir) zf.close() extracted = True except Exception as e: - print e + print(e) return extracted + def tar_extract_all(file_path, tmp_dir): extracted = False try: - tf = tarfile.open(file_path, 'r:*') + tf = tarfile.open(file_path, "r:*") tf.extractall(tmp_dir) tf.close() extracted = True except Exception as e: - print e + print(e) return extracted + def dir_extract_all(file_path, tmp_dir): extracted = False try: # notice forward slash missing - if is_dir_or_file('{}{}'.format(tmp_dir, file_path.split('/')[-1])): - rmtree('{}{}'.format(tmp_dir, file_path.split('/')[-1])) - copytree(file_path, '{}{}'.format(tmp_dir, file_path.split('/')[-1])) + if is_dir_or_file("{}{}".format(tmp_dir, file_path.split("/")[-1])): + rmtree("{}{}".format(tmp_dir, file_path.split("/")[-1])) + copytree(file_path, "{}{}".format(tmp_dir, file_path.split("/")[-1])) extracted = True except Exception as e: - print e + print(e) return extracted + def get_fields_from_file(file_path): fields = {} try: - patterns = [ - '(?P[\w\-]+)', - '(?P.+)' - ] - with open(file_path, 'rb') as f: + patterns = ["(?P[\w\-]+)", "(?P.+)"] + with open(file_path, "r") as f: for line in f.readlines(): - line = line.strip('\n') + line = line.strip("\n") row_search = re.search(":?(\s)?".join(patterns), line) if row_search: - key = row_search.group('key').replace('-','_').strip() - val = row_search.group('val').strip() + key = row_search.group("key").replace("-", "_").strip() + val = row_search.group("val").strip() if key in fields: listval = [fields[key]] listval.append(val) @@ -197,60 +201,77 @@ def get_fields_from_file(file_path): else: fields[key] = val except Exception as e: - print e + print(e) return fields + def remove_file_or_dir(file_path): if os.path.isfile(file_path): try: os.remove(file_path) except Exception as e: - print e + print(e) return False elif os.path.isdir(file_path): try: rmtree(file_path) except Exception as e: - print e + print(e) return False return True + def move_file_or_dir(src, dest): try: move(src, dest) except Exception as e: - print e + print(e) return False + def is_dir_or_file(file_path): - if os.path.isdir(file_path): return True - if os.path.isfile(file_path): return True + if os.path.isdir(file_path): + return True + if os.path.isfile(file_path): + return True return False + def all_paths_exist(list_of_paths): for p in list_of_paths: if not is_dir_or_file(p): return False return True + def get_file_contents(f): """returns contents of file as str""" - data = '' + data = "" try: - with open(f, 'r') as open_file: + with open(f, "r") as open_file: data = open_file.read() except Exception as e: - print e + print(e) finally: return data + def chown_path_to_root(file_path): if is_dir_or_file(file_path): - root_uid = pwd.getpwnam('root').pw_uid + root_uid = pwd.getpwnam("root").pw_uid os.chown(file_path, root_uid, root_uid) + def make_tarfile(output_filename, source_dir): - with tarfile.open(output_filename, 'w:gz') as tar: + with tarfile.open(output_filename, "w:gz") as tar: tar.add(source_dir, arcname=os.path.basename(source_dir)) + + +def update_bag_info(bag_path, data): + """Adds metadata to `bag-info.txt`""" + bag = bagit.Bag(bag_path) + for k,v in data.items(): + bag.info[k] = v + bag.save() diff --git a/aurora/bag_transfer/lib/log_print.py b/aurora/bag_transfer/lib/log_print.py index 337e99a5..a29195c0 100644 --- a/aurora/bag_transfer/lib/log_print.py +++ b/aurora/bag_transfer/lib/log_print.py @@ -1,10 +1,10 @@ import datetime -long_wrapper_str = '##########################################' -medium_wrapper_str = '###############' +long_wrapper_str = "##########################################" +medium_wrapper_str = "###############" -def plines(lst, WRAPPER=0, tab=0, pref='',line_after=False): +def plines(lst, WRAPPER=0, tab=0, pref="", line_after=False): if WRAPPER: if WRAPPER == 1: @@ -16,34 +16,22 @@ def plines(lst, WRAPPER=0, tab=0, pref='',line_after=False): for l in lst: if pref: - l = "{} : {}".format(pref,l) - print l if not tab else "{}{}".format('\t'*tab,l) - if WRAPPER in [1,3]: - print '\n' + l = "{} : {}".format(pref, l) + print(l if not tab else "{}{}".format("\t" * tab, l)) + if WRAPPER in [1, 3]: + print("\n") else: if line_after: - print '\n' - - -def flines(lst, start=False,end=False,tab=2,pref='',line_after=False): - - if start: - tab=1 - pref = 'func STR' - elif end: - tab=1 - pref = 'func END' - - plines(lst,tab=tab,pref=pref,line_after=line_after) + print("\n") def cron_open(cron_code): - plines(['{} cron start'.format(cron_code).upper(), datetime.datetime.now()], 1) + plines(["{} cron start".format(cron_code).upper(), datetime.datetime.now()], 1) def cron_close(cron_code): - plines(['{} cron end'.format(cron_code).upper(), datetime.datetime.now()], 1) + plines(["{} cron end".format(cron_code).upper(), datetime.datetime.now()], 1) def spacer(): - print '\n' + print("\n") diff --git a/aurora/bag_transfer/lib/mailer.py b/aurora/bag_transfer/lib/mailer.py index 83e86e8b..430812d3 100644 --- a/aurora/bag_transfer/lib/mailer.py +++ b/aurora/bag_transfer/lib/mailer.py @@ -3,8 +3,8 @@ from django.urls import reverse -class Mailer(): - def __init__(self, subject='', to=[], text_content=''): +class Mailer: + def __init__(self, subject="", to=[], text_content=""): self.subject = subject self.from_email = CF.EMAIL_HOST_USER self.to = to @@ -13,20 +13,32 @@ def __init__(self, subject='', to=[], text_content=''): self.email = {} def send(self): - if not self.subject or not self.from_email or not self.to or not self.text_content: - print 'All Fields required werent present' + if ( + not self.subject + or not self.from_email + or not self.to + or not self.text_content + ): + print("All Fields required werent present") return False send_to = self.to if CF.EMAIL_OVERRIDE and CF.EMAIL_OVERRIDE_USERS: - self.text_content = "TEST EMAIL: SHOULD BE SENT TO {}\r\n\r\n{}".format(",".join(self.to), self.text_content) + self.text_content = "TEST EMAIL: SHOULD BE SENT TO {}\r\n\r\n{}".format( + ",".join(self.to), self.text_content + ) send_to = CF.EMAIL_OVERRIDE_USERS - footer = "\r\n".join(["Rockefeller Archive Center", - "15 Dayton Avenue, Sleepy Hollow, NY 10591", - "(914) 366-6300", "archive@rockarch.org", - "https://rockarch.org"]) + footer = "\r\n".join( + [ + "Rockefeller Archive Center", + "15 Dayton Avenue, Sleepy Hollow, NY 10591", + "(914) 366-6300", + "archive@rockarch.org", + "https://rockarch.org", + ] + ) self.text_content += "\r\n\r\n\r\n{}".format(footer) @@ -35,67 +47,79 @@ def send(self): self.text_content, self.from_email, send_to, - reply_to=[self.from_email] + reply_to=[self.from_email], ) try: self.email.send(fail_silently=False) except Exception as e: - print e + print(e) return False else: return True def setup_message(self, mess_code, archive_obj={}): - if mess_code == 'TRANS_PASS_ALL': - self.subject = 'Transfer {} passed all validation'.format(archive_obj.bag_or_failed_name()) - - lcodes = archive_obj.get_bag_validations() + if mess_code == "TRANS_PASS_ALL": + self.subject = "Transfer {} passed all validation".format( + archive_obj.bag_or_failed_name() + ) eparts = [ - 'The transfer {} with the bag name {} was received at {} and has passed all automated validation checks:', - 'This transfer is now awaiting archival appraisal and accessioning.', - 'You can view the current status of this transfer at {}' + "The transfer {} with the bag name {} was received at {} and has passed all automated validation checks:", + "This transfer is now awaiting archival appraisal and accessioning.", + "You can view the current status of this transfer at {}", ] self.text_content = "\r\n\r\n".join(eparts).format( archive_obj.bag_or_failed_name(), archive_obj.bag_it_name, archive_obj.machine_file_upload_time, - CF.BASE_URL + reverse('transfers:detail', kwargs={'pk': archive_obj.pk}) + CF.BASE_URL + + reverse("transfers:detail", kwargs={"pk": archive_obj.pk}), + ) + elif mess_code == "TRANS_FAIL_VAL": + self.subject = "Transfer {} failed validation".format( + archive_obj.bag_or_failed_name() ) - elif mess_code == 'TRANS_FAIL_VAL': - self.subject = 'Transfer {} failed validation'.format(archive_obj.bag_or_failed_name()) eparts = [ - 'An error occurred for the transfer with bag name {} during {} at {}.', - 'The transfer has been deleted from our systems.', - 'Please review the complete error log at {}, correct any errors, and try sending the transfer again.' + "An error occurred for the transfer with bag name {} during {} at {}.", + "The transfer has been deleted from our systems.", + "Please review the complete error log at {}, correct any errors, and try sending the transfer again.", ] - error_obj = archive_obj.get_bag_failure(LAST_ONLY=True) + error_obj = archive_obj.get_bag_failure(last_only=True) self.text_content = "\r\n\r\n".join(eparts).format( archive_obj.bag_or_failed_name(), - (error_obj.code.code_desc if error_obj else '--'), - (error_obj.created_time if error_obj else '--'), - CF.BASE_URL + reverse('transfers:detail', kwargs={'pk': archive_obj.pk}) + (error_obj.code.code_desc if error_obj else "--"), + (error_obj.created_time if error_obj else "--"), + CF.BASE_URL + + reverse("transfers:detail", kwargs={"pk": archive_obj.pk}), ) # additional errs additional_errors = archive_obj.get_additional_errors() if additional_errors: - self.text_content += '\r\n\r\nAdditional Error Information:\r\n\r\n' + self.text_content += "\r\n\r\nAdditional Error Information:\r\n\r\n" for err in additional_errors: - self.text_content += '{}\r\n\r\n'.format(err) + self.text_content += "{}\r\n\r\n".format(err) - elif mess_code == 'TRANS_REJECT': - self.subject = 'Transfer {} was rejected'.format(archive_obj.bag_or_failed_name()) + elif mess_code == "TRANS_REJECT": + self.subject = "Transfer {} was rejected".format( + archive_obj.bag_or_failed_name() + ) eparts = [ - 'An appraisal archivist rejected transfer {}. The transfer has been deleted from our systems.'.format(archive_obj.bag_or_failed_name()) + "An appraisal archivist rejected transfer {}. The transfer has been deleted from our systems.".format( + archive_obj.bag_or_failed_name() + ) ] if archive_obj.appraisal_note: - eparts.append('The reason for this action was: {}'.format(archive_obj.appraisal_note)) + eparts.append( + "The reason for this action was: {}".format( + archive_obj.appraisal_note + ) + ) self.text_content = "\r\n\r\n".join(eparts) diff --git a/aurora/bag_transfer/lib/transfer_routine.py b/aurora/bag_transfer/lib/transfer_routine.py index 80dc6d9f..7221c98c 100644 --- a/aurora/bag_transfer/lib/transfer_routine.py +++ b/aurora/bag_transfer/lib/transfer_routine.py @@ -1,4 +1,5 @@ import os +import re import shutil from pwd import getpwuid import datetime @@ -8,9 +9,20 @@ from django.conf import settings from django.utils.timezone import make_aware -from bag_transfer.models import Organization - -from bag_transfer.lib.files_helper import * +from bag_transfer.models import BAGLog, Organization + +from bag_transfer.lib.files_helper import ( + all_paths_exist, + files_in_unserialized, + get_dir_size, + is_dir_or_file, + open_files_list, + remove_file_or_dir, + tar_extract_all, + tar_has_top_level_only, + zip_extract_all, + zip_has_top_level_only, +) import bag_transfer.lib.log_print as Pter from bag_transfer.lib.virus_scanner import VirusScan @@ -32,7 +44,7 @@ def setup_routine(self): # pull active organizations if not self.has_active_organizations(): self.has_setup_err = True - Pter.plines(['No active organizations in database']) + Pter.plines(["No active organizations in database"]) return False # do active orgs dirs exist (processing / upload) @@ -41,13 +53,13 @@ def setup_routine(self): # are there active orgs left? if not self.active_organizations: self.has_setup_err = True - Pter.plines(['No active organizations that are set up correctly']) + Pter.plines(["No active organizations that are set up correctly"]) return False # build contents dictionary of all files / dirs in active org uploads self.build_contents_dictionary() if not self.routine_contents_dictionary: - Pter.plines(['No files discovered in uploads directory']) + Pter.plines(["No files discovered in uploads directory"]) return False return True @@ -55,7 +67,11 @@ def setup_routine(self): def run_routine(self): # discovery phase: searches active orgs dirs for files/dir in uploads if not self.setup_routine(): - Pter.plines(['Transfer Routine Setup didn\'t yield results so the routine will stop here']) + Pter.plines( + [ + "Transfer Routine Setup didn't yield results so the routine will stop here" + ] + ) else: # Move Files to Processing self._move_transfers_to_processing_dir() @@ -63,7 +79,7 @@ def run_routine(self): # STEP 1: get list of uploads to process by checking orgs processing dir self._discover_paths_in_processing_dir() if not self.organizations_processing_paths: - Pter.plines(['didnt find anything in processing so ending routine']) + Pter.plines(["didnt find anything in processing so ending routine"]) return False # STEP 2: VALIDATION ROUTINES @@ -71,7 +87,7 @@ def run_routine(self): transObj = TransferFileObject(file_path) if not transObj.is_processible(): - BAGLog.log_it('DEXT') + BAGLog.log_it("DEXT") continue if not transObj.passes_filename(): @@ -98,10 +114,10 @@ def run_routine(self): ##################### def has_active_organizations(self): self._setup_active_organizations() - return (True if self.active_organizations else False) + return True if self.active_organizations else False def _setup_active_organizations(self): - self.active_organizations = Organization.objects.filter(is_active = True) + self.active_organizations = Organization.objects.filter(is_active=True) def verify_organizations_paths(self): ck = 0 @@ -113,8 +129,12 @@ def verify_organizations_paths(self): # TODO: PLACE ERR # remove org from Routine and log if ck > 0: - self.active_organizations = [org for org in self.active_organizations if org not in orgs_to_remove] - Pter.plines(['{} orgs were removed from routine'.format(len(orgs_to_remove))]) + self.active_organizations = [ + org for org in self.active_organizations if org not in orgs_to_remove + ] + Pter.plines( + ["{} orgs were removed from routine".format(len(orgs_to_remove))] + ) def build_contents_dictionary(self): org_dir_contents = {} @@ -126,16 +146,16 @@ def build_contents_dictionary(self): item_path = "{}{}".format(upload_dir, item) if org.machine_name not in org_dir_contents: org_dir_contents[org.machine_name] = { - 'files': [], - 'dirs': [], - 'count': 0 + "files": [], + "dirs": [], + "count": 0, } if os.path.isfile(item_path): - org_dir_contents[org.machine_name]['files'].append(item_path) - org_dir_contents[org.machine_name]['count'] +=1 + org_dir_contents[org.machine_name]["files"].append(item_path) + org_dir_contents[org.machine_name]["count"] += 1 elif os.path.isdir(item_path): - org_dir_contents[org.machine_name]['dirs'].append(item_path) - org_dir_contents[org.machine_name]['count'] +=1 + org_dir_contents[org.machine_name]["dirs"].append(item_path) + org_dir_contents[org.machine_name]["count"] += 1 if org_dir_contents: self.routine_contents_dictionary = org_dir_contents @@ -150,30 +170,38 @@ def _purge_routine_contents_dictionary(self): def _org_contents_in_lsof(self): """Returns list of files to remove from current processing, based on lsof log (open files)""" rm_list = [] - for org, obj in self.routine_contents_dictionary.iteritems(): + for org, obj in self.routine_contents_dictionary.items(): # Get open files open_files = open_files_list() - if obj['count'] < 1: + if obj["count"] < 1: continue # Get files - for f in obj['files']: + for f in obj["files"]: if f in open_files: - rm_list.append((org,0,f)) + rm_list.append((org, 0, f)) # get directory - for d in obj['dirs']: + for d in obj["dirs"]: # check files in directory are on list for fls in files_in_unserialized(d, True): if fls in open_files: rm_list.append((org, 1, d)) return rm_list - def _dump_from_routine_contents(self,cObj): + def _dump_from_routine_contents(self, cObj): """Removes items from processing list""" for obj in cObj: if obj[1] == 0 and os.path.isfile(obj[2]): - self.routine_contents_dictionary[obj[0]]['files'] = [x for x in self.routine_contents_dictionary[obj[0]]['files'] if x != obj[2]] + self.routine_contents_dictionary[obj[0]]["files"] = [ + x + for x in self.routine_contents_dictionary[obj[0]]["files"] + if x != obj[2] + ] elif obj[1] == 1 and os.path.isdir(obj[2]): - self.routine_contents_dictionary[obj[0]]['dirs'] = [x for x in self.routine_contents_dictionary[obj[0]]['dirs'] if x != obj[2]] + self.routine_contents_dictionary[obj[0]]["dirs"] = [ + x + for x in self.routine_contents_dictionary[obj[0]]["dirs"] + if x != obj[2] + ] ##################### # END SETUP METHODS @@ -181,11 +209,11 @@ def _dump_from_routine_contents(self,cObj): def _move_transfers_to_processing_dir(self): """Moves transfers prebuilt in setup to processiong dir""" - print "Moving transfers to processing directory" - for org, obj in self.routine_contents_dictionary.iteritems(): - mergedlist = obj['files'] + obj['dirs'] + print("Moving transfers to processing directory") + for org, obj in self.routine_contents_dictionary.items(): + mergedlist = obj["files"] + obj["dirs"] for f in mergedlist: - processing_path = f.replace('upload', 'processing') + processing_path = f.replace("upload", "processing") # todo: would prefer a try/except cause these are system resource dependent # ck for processing file existence so we can cleanly rm then mv instead of mv to overwrite (notice colisions on dirs that already existed) if is_dir_or_file(processing_path): @@ -195,8 +223,13 @@ def _move_transfers_to_processing_dir(self): def _discover_paths_in_processing_dir(self): for org in self.active_organizations: org_processing_path = org.org_machine_upload_paths()[1] - org_paths = ["{}{}".format(org_processing_path,x) for x in os.listdir(org_processing_path)] - self.organizations_processing_paths = self.organizations_processing_paths + org_paths + org_paths = [ + "{}{}".format(org_processing_path, x) + for x in os.listdir(org_processing_path) + ] + self.organizations_processing_paths = ( + self.organizations_processing_paths + org_paths + ) #################### # START VALIDATION METHODS @@ -204,24 +237,21 @@ def _discover_paths_in_processing_dir(self): class TransferFileObject(object): - FILE_TYPE_OTHER = 'OTHER' - FILE_TYPE_ZIP = 'ZIP' - FILE_TYPE_TAR = 'TAR' - AUTO_FAIL_DEXT = 'DEXT' - AUTO_FAIL_BFNM = 'BFNM' - AUTO_FAIL_VIRUS = 'VIRUS' - AUTO_FAIL_BDIR = 'BDIR' - AUTO_FAIL_BTAR = 'BTAR' - AUTO_FAIL_BTAR2 = 'BTAR2' - AUTO_FAIL_ZIP = 'BZIP' - AUTO_FAIL_ZIP2 = 'BZIP2' - AUTO_FAIL_FSERR = 'FSERR' - ACCEPTABLE_FILE_EXT = { - FILE_TYPE_TAR: ['tar.gz', '.tar'], - FILE_TYPE_ZIP: ['.zip'] - } - PATH_TYPE_DIR = 'isdir' - PATH_TYPE_FILE = 'isfile' + FILE_TYPE_OTHER = "OTHER" + FILE_TYPE_ZIP = "ZIP" + FILE_TYPE_TAR = "TAR" + AUTO_FAIL_DEXT = "DEXT" + AUTO_FAIL_BFNM = "BFNM" + AUTO_FAIL_VIRUS = "VIRUS" + AUTO_FAIL_BDIR = "BDIR" + AUTO_FAIL_BTAR = "BTAR" + AUTO_FAIL_BTAR2 = "BTAR2" + AUTO_FAIL_ZIP = "BZIP" + AUTO_FAIL_ZIP2 = "BZIP2" + AUTO_FAIL_FSERR = "FSERR" + ACCEPTABLE_FILE_EXT = {FILE_TYPE_TAR: [".gz", ".tar"], FILE_TYPE_ZIP: [".zip"]} + PATH_TYPE_DIR = "isdir" + PATH_TYPE_FILE = "isfile" def __init__(self, file_path): self._is_processible = False @@ -229,16 +259,20 @@ def __init__(self, file_path): self.transfer_filesize_max = settings.TRANSFER_FILESIZE_MAX * 1000 self.file_path = file_path self.auto_fail = False - self.auto_fail_code = '' - self.bag_it_name = '' + self.auto_fail_code = "" + self.bag_it_name = "" self.file_type = self.FILE_TYPE_OTHER self.file_size = 0 - self.file_path_ext = '' + self.file_path_ext = "" self.path_type = self.PATH_TYPE_FILE - self.org_machine_name = '' + self.org_machine_name = "" self.virus_scanner = {} - if self.path_still_exist() and self._resolve_org_machine_name() and self._resolve_virus_scan_connection(): + if ( + self.path_still_exist() + and self._resolve_org_machine_name() + and self._resolve_virus_scan_connection() + ): self._generate_file_info() self._is_processible = True @@ -262,7 +296,7 @@ def _resolve_org_machine_name(self): def _resolve_virus_scan_connection(self): self.virus_scanner = VirusScan() if not self.virus_scanner.is_ready(): - BAGLog.log_it('VCONN') + BAGLog.log_it("VCONN") return False return True @@ -273,13 +307,18 @@ def resolve_file_type(self): if os.path.isdir(self.file_path): self.file_type = self.FILE_TYPE_OTHER self.path_type = self.PATH_TYPE_DIR - self.bag_it_name = self.file_path.split('/')[-1] + self.bag_it_name = self.file_path.split("/")[-1] else: # get extension - self.file_path_ext = splitext_(self.file_path)[-1] + self.file_path_ext = os.path.splitext(self.file_path)[-1] # check extension vs Acceptable list - if not any(self.file_path_ext in sl for sl in self.ACCEPTABLE_FILE_EXT.values()): - self.set_auto_fail_with_code(self.AUTO_FAIL_BDIR) # ACTUALLY NOT Acurate + if not any( + self.file_path_ext in sl + for sl in list(self.ACCEPTABLE_FILE_EXT.values()) + ): + self.set_auto_fail_with_code( + self.AUTO_FAIL_BDIR + ) # ACTUALLY NOT Acurate else: passed = False if self.file_path_ext in self.ACCEPTABLE_FILE_EXT[self.FILE_TYPE_TAR]: @@ -288,7 +327,7 @@ def resolve_file_type(self): if tarfile.is_tarfile(self.file_path): passed = True except Exception as e: - print e + print("Error validating tar file: {}".format(e)) if not passed: self.set_auto_fail_with_code(self.AUTO_FAIL_BTAR) else: @@ -307,7 +346,7 @@ def resolve_file_type(self): if not self.bag_it_name: self.set_auto_fail_with_code(self.AUTO_FAIL_ZIP2) - return (False if self.auto_fail else True) + return False if self.auto_fail else True def resolve_file_size(self): @@ -331,7 +370,7 @@ def resolve_file_size(self): file_size = get_dir_size(tmp_dir_path) remove_file_or_dir(tmp_dir_path) - if not file_size or (type(file_size) is tuple and not file_size[0]): + if not file_size or (isinstance(file_size, tuple) and not file_size[0]): self.file_size = 0 return self.set_auto_fail_with_code(self.AUTO_FAIL_FSERR) @@ -339,19 +378,23 @@ def resolve_file_size(self): return True def _generate_file_info(self): - self.file_owner = self._get_file_owner() - self.file_modtime = self._get_file_modified_time() - self.file_date = self.file_modtime.date() - self.file_time = self.file_modtime.time() + self.file_owner = self._get_file_owner() + self.file_modtime = self._get_file_modified_time() + self.file_date = self.file_modtime.date() + self.file_time = self.file_modtime.time() def _get_file_owner(self): return getpwuid(os.stat(self.file_path).st_uid).pw_name def _get_file_modified_time(self): - return make_aware(datetime.datetime.fromtimestamp(os.path.getmtime(self.file_path))) + return make_aware( + datetime.datetime.fromtimestamp(os.path.getmtime(self.file_path)) + ) def passes_filename(self): - is_valid = re.match('^[a-zA-Z0-9\-\_\/\.\s]+$', self.file_path.split('/')[-1]) # again with filename + is_valid = re.match( + "^[a-zA-Z0-9\-\_\/\.\s]+$", self.file_path.split("/")[-1] + ) if not is_valid: return self.set_auto_fail_with_code(self.AUTO_FAIL_BFNM) return True @@ -365,7 +408,7 @@ def passes_virus_scan(self): try: self.virus_scanner.scan(self.file_path) except Exception as e: - print e + print("Error scanning for viruses".format(e)) # again need actionable to reloop return False if not self.virus_scanner.scan_result: @@ -388,17 +431,17 @@ def set_auto_fail_with_code(self, code): def render_transfer_record(self): """Called after processing fails validation or succeeds, generates dictionary for next step""" return { - 'date': self.file_date, - 'time': self.file_time, - 'file_path': self.file_path, - 'file_name': self.file_path.split('/')[-1], - 'file_type': self.file_type, - 'org': self.org_machine_name, - 'file_modtime': self.file_modtime, - 'file_size': self.file_size, - 'upload_user': self.file_owner, - 'auto_fail': self.auto_fail, - 'auto_fail_code': self.auto_fail_code, - 'bag_it_name': self.bag_it_name, - 'virus_scanresult': self.virus_scanner.scan_result - } + "date": self.file_date, + "time": self.file_time, + "file_path": self.file_path, + "file_name": self.file_path.split("/")[-1], + "file_type": self.file_type, + "org": self.org_machine_name, + "file_modtime": self.file_modtime, + "file_size": self.file_size, + "upload_user": self.file_owner, + "auto_fail": self.auto_fail, + "auto_fail_code": self.auto_fail_code, + "bag_it_name": self.bag_it_name, + "virus_scanresult": self.virus_scanner.scan_result, + } diff --git a/aurora/bag_transfer/lib/view_helpers.py b/aurora/bag_transfer/lib/view_helpers.py index 629298f2..38767b14 100644 --- a/aurora/bag_transfer/lib/view_helpers.py +++ b/aurora/bag_transfer/lib/view_helpers.py @@ -1,14 +1,14 @@ def file_size(num): - for unit in ['B', 'KB', 'MB', 'GB']: + for unit in ["B", "KB", "MB", "GB"]: if abs(num) < 1024.0: return "%3.1f %s" % (num, unit) num /= 1024.0 def label_class(status): - label_class = 'green' + label_class = "green" if status in [10, 20]: - label_class = 'yellow' + label_class = "yellow" elif status in [30, 60]: - label_class = 'red' + label_class = "red" return label_class diff --git a/aurora/bag_transfer/lib/virus_scanner.py b/aurora/bag_transfer/lib/virus_scanner.py index 4b81e524..fd8823d2 100644 --- a/aurora/bag_transfer/lib/virus_scanner.py +++ b/aurora/bag_transfer/lib/virus_scanner.py @@ -19,8 +19,8 @@ def conn(self): connected = True except pyclamd.ConnectionError as e: - print e - print 'trying ClamdNetworkSocket' + print(e) + print("trying ClamdNetworkSocket") try: self.clamObj = pyclamd.ClamdNetworkSocket() @@ -28,8 +28,10 @@ def conn(self): connected = True except pyclamd.ConnectionError as e: # todo: can chain an email here - print e - print 'could not connect to clamd server either by unix or network socket' + print(e) + print( + "could not connect to clamd server either by unix or network socket" + ) return connected def scan(self, file_or_dir): diff --git a/aurora/bag_transfer/middleware.py b/aurora/bag_transfer/middleware.py index 499d7709..1cc2ee17 100644 --- a/aurora/bag_transfer/middleware.py +++ b/aurora/bag_transfer/middleware.py @@ -1,28 +1,33 @@ -from rest_framework.request import Request -from rest_framework_jwt.authentication import JSONWebTokenAuthentication - from django.utils.deprecation import MiddlewareMixin from django.utils.functional import SimpleLazyObject from django.contrib.auth.middleware import get_user +from rest_framework.request import Request +from rest_framework_jwt.authentication import JSONWebTokenAuthentication + def get_user_jwt(request): user = get_user(request) - if user.is_authenticated(): + if user.is_authenticated: return user try: user_jwt = JSONWebTokenAuthentication().authenticate(Request(request)) if user_jwt is not None: request.csrf_processing_done = True return user_jwt[0] - except: + except Exception: pass return user class AuthenticationMiddlewareJWT(MiddlewareMixin): + """Checks for the presence of a JSON Web Token and, if found, authenticates + using that token.""" def process_request(self, request): - assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'." + assert hasattr( + request, "session" + ), "The Django authentication middleware requires session middleware to be installed. \ + Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'." request.user = SimpleLazyObject(lambda: get_user_jwt(request)) diff --git a/aurora/bag_transfer/migrations/0002_auto_20180425_1045.py b/aurora/bag_transfer/migrations/0002_auto_20180425_1045.py index 27ab13cf..cbf49eb0 100644 --- a/aurora/bag_transfer/migrations/0002_auto_20180425_1045.py +++ b/aurora/bag_transfer/migrations/0002_auto_20180425_1045.py @@ -22,7 +22,7 @@ def create_baglogs(apps, schema_editor): ('RBERR', 'BE', "Transfer failed BagIt Profile validation", "Transfer deleted"), ('GBERR', 'BE', "Transfer failed BagIt validation", "Transfer deleted"), ('EXERR', 'BE', "Problem extracting serialized transfer", "Transfer deleted"), - ('BDIR', 'BE', "Problem with directory of unserialized transfer", "Transfer deleted"), + ('BDIR', 'BE', "Unrecognized transfer type", "Transfer deleted"), ('BZIP2', 'BE', "ZIP file has more than one top level directory", "Transfer deleted"), ('BZIP', 'BE', "Invalid ZIP file", "Transfer deleted"), ('BTAR2', 'BE', "TAR file has more than one top level directory", "Transfer deleted"), diff --git a/aurora/bag_transfer/migrations/0027_auto_20200118_1108.py b/aurora/bag_transfer/migrations/0027_auto_20200118_1108.py new file mode 100644 index 00000000..b1479d3b --- /dev/null +++ b/aurora/bag_transfer/migrations/0027_auto_20200118_1108.py @@ -0,0 +1,41 @@ +# Generated by Django 2.2.7 on 2020-01-18 16:08 + +from django.conf import settings +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('bag_transfer', '0026_auto_20190918_2154'), + ] + + operations = [ + migrations.AddField( + model_name='baginfometadata', + name='origin', + field=models.CharField(default='aurora', max_length=10), + ), + migrations.AlterField( + model_name='archives', + name='accession', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='accession_transfers', to='bag_transfer.Accession'), + ), + migrations.AlterField( + model_name='archives', + name='user_uploaded', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='user', + name='last_name', + field=models.CharField(max_length=150, verbose_name='last name'), + ), + migrations.AlterField( + model_name='user', + name='username', + field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'), + ), + ] diff --git a/aurora/bag_transfer/migrations/0028_auto_20200427_1518.py b/aurora/bag_transfer/migrations/0028_auto_20200427_1518.py new file mode 100644 index 00000000..e30e6b3a --- /dev/null +++ b/aurora/bag_transfer/migrations/0028_auto_20200427_1518.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.7 on 2020-04-27 19:18 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('bag_transfer', '0027_auto_20200118_1108'), + ] + + operations = [ + migrations.AlterField( + model_name='manifestsrequired', + name='name', + field=models.CharField(choices=[('sha256', 'sha256'), ('sha512', 'sha512')], max_length=20), + ), + migrations.AlterField( + model_name='tagmanifestsrequired', + name='name', + field=models.CharField(choices=[('sha256', 'sha256'), ('sha512', 'sha512')], max_length=20), + ), + migrations.CreateModel( + name='ManifestsAllowed', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(choices=[('sha256', 'sha256'), ('sha512', 'sha512')], max_length=20)), + ('bagit_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='manifests_allowed', to='bag_transfer.BagItProfile')), + ], + ), + ] diff --git a/aurora/bag_transfer/migrations/0029_auto_20200430_1735.py b/aurora/bag_transfer/migrations/0029_auto_20200430_1735.py new file mode 100644 index 00000000..9ff4a41c --- /dev/null +++ b/aurora/bag_transfer/migrations/0029_auto_20200430_1735.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-04-30 21:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bag_transfer', '0028_auto_20200427_1518'), + ] + + operations = [ + migrations.AlterField( + model_name='acceptbagitversion', + name='name', + field=models.CharField(choices=[('0.96', '0.96'), ('0.97', '0.97'), ('1.0', '1.0')], max_length=5), + ), + ] diff --git a/aurora/bag_transfer/mixins/authmixins.py b/aurora/bag_transfer/mixins/authmixins.py index 42528d14..84390f0c 100644 --- a/aurora/bag_transfer/mixins/authmixins.py +++ b/aurora/bag_transfer/mixins/authmixins.py @@ -1,6 +1,10 @@ -from django.urls import reverse, reverse_lazy +from django.urls import reverse_lazy -from braces.views import GroupRequiredMixin, StaffuserRequiredMixin, SuperuserRequiredMixin, LoginRequiredMixin, UserPassesTestMixin +from braces.views import ( + SuperuserRequiredMixin, + LoginRequiredMixin, + UserPassesTestMixin, +) from bag_transfer.accession.models import Accession from bag_transfer.rights.models import RightsStatement @@ -8,11 +12,11 @@ class LoggedInMixinDefaults(LoginRequiredMixin): - login_url = '/app' + login_url = "/app" class ArchivistMixin(LoggedInMixinDefaults, UserPassesTestMixin): - authenticated_redirect_url = reverse_lazy(u"app_home") + authenticated_redirect_url = reverse_lazy("app_home") def test_func(self, user): if user.is_staff: @@ -22,29 +26,33 @@ def test_func(self, user): class AppraisalArchivistMixin(ArchivistMixin, UserPassesTestMixin): def test_func(self, user): - return user.has_privs('APPRAISER') + return user.has_privs("APPRAISER") class AccessioningArchivistMixin(ArchivistMixin, UserPassesTestMixin): def test_func(self, user): - return user.has_privs('ACCESSIONER') + return user.has_privs("ACCESSIONER") class ManagingArchivistMixin(ArchivistMixin, UserPassesTestMixin): def test_func(self, user): - return user.has_privs('MANAGING') + return user.has_privs("MANAGING") class SysAdminMixin(LoggedInMixinDefaults, SuperuserRequiredMixin): - authenticated_redirect_url = reverse_lazy(u"app_home") + authenticated_redirect_url = reverse_lazy("app_home") # UNUSED class SelfOrManagerMixin(LoggedInMixinDefaults, UserPassesTestMixin): - authenticated_redirect_url = reverse_lazy(u"app_home") + authenticated_redirect_url = reverse_lazy("app_home") def test_func(self, user): - return (user.is_superuser or user.in_group('managing_archivists') or self.kwargs.get('pk') == str(user.pk)) + return ( + user.is_superuser + or user.in_group("managing_archivists") + or self.kwargs.get("pk") == str(user.pk) + ) class OrgReadViewMixin(LoggedInMixinDefaults, UserPassesTestMixin): @@ -55,46 +63,49 @@ def test_func(self, user): organization = None # Most views are using generics, which in return pass models, so we can hook those in and target the org to remove access to reg users not in org - if self.request.method == 'GET': - if hasattr(self, 'suffix'): - if self.suffix == 'List': + if self.request.method == "GET": + if hasattr(self, "suffix"): + if self.suffix == "List": return True - if hasattr(self, 'model'): + if hasattr(self, "model"): if self.model == User: # all staff validate to true above, should pass if == request.user try: - u = User.objects.get(pk=self.kwargs.get('pk')) - if self.request.user == u: return True + u = User.objects.get(pk=self.kwargs.get("pk")) + if self.request.user == u: + return True except User.DoesNotExist as e: - print e + print(e) elif self.model == Organization: try: - org = Organization.objects.get(pk=self.kwargs.get('pk')) + org = Organization.objects.get(pk=self.kwargs.get("pk")) organization = org except Organization.DoesNotExist as e: - print e + print(e) elif self.model == RightsStatement: try: - rights_statement = RightsStatement.objects.get(pk=self.kwargs.get('pk')) + rights_statement = RightsStatement.objects.get( + pk=self.kwargs.get("pk") + ) organization = rights_statement.organization except RightsStatement.DoesNotExist as e: - print e + print(e) elif self.model == Archives: try: - archive = Archives.objects.get(pk=self.kwargs.get('pk')) + archive = Archives.objects.get(pk=self.kwargs.get("pk")) organization = archive.organization except Archives.DoesNotExist as e: - print e + print(e) elif self.model == Accession: try: - accession = Accession.objects.get(pk=self.kwargs.get('pk')) + accession = Accession.objects.get(pk=self.kwargs.get("pk")) organization = accession.organization except Accession.DoesNotExist as e: - print e + print(e) if organization and self.request.user.organization == organization: return True diff --git a/aurora/bag_transfer/mixins/formatmixins.py b/aurora/bag_transfer/mixins/formatmixins.py index a10ac6a3..e0f7df02 100644 --- a/aurora/bag_transfer/mixins/formatmixins.py +++ b/aurora/bag_transfer/mixins/formatmixins.py @@ -5,15 +5,15 @@ class CSVResponseMixin(object): - csv_filename = 'transfers-{}.csv'.format(datetime.datetime.now()) + csv_filename = "transfers-{}.csv".format(datetime.datetime.now()) def get_csv_filename(self): return self.csv_filename def render_to_csv(self, data): - response = HttpResponse(content_type='text/csv') + response = HttpResponse(content_type="text/csv") cd = 'attachment; filename="{0}"'.format(self.get_csv_filename()) - response['Content-Disposition'] = cd + response["Content-Disposition"] = cd writer = csv.writer(response) for row in data: @@ -26,14 +26,12 @@ class JSONResponseMixin: """ A mixin that can be used to render a JSON response. """ + def render_to_json_response(self, context, **response_kwargs): """ Returns a JSON response, transforming 'context' to make the payload. """ - return JsonResponse( - self.get_data(context), - **response_kwargs - ) + return JsonResponse(self.get_data(context), **response_kwargs) def get_data(self, context): """ diff --git a/aurora/bag_transfer/models.py b/aurora/bag_transfer/models.py index 67cb9221..119d162f 100644 --- a/aurora/bag_transfer/models.py +++ b/aurora/bag_transfer/models.py @@ -1,34 +1,44 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import iso8601 -import datetime -from dateutil.relativedelta import relativedelta from uuid import uuid4 - from django.apps import apps from django.conf import settings -from django.contrib import messages from django.contrib.auth.models import AbstractUser from django.db import models from django.urls import reverse -from django.utils.translation import gettext as _ + +from dateutil.relativedelta import relativedelta +import iso8601 from bag_transfer.lib import RAC_CMD class Organization(models.Model): + """Organizations are the main entities responsible for transferring records. + They have relationships to Users, BagItProfiles and RightsStatements.""" + is_active = models.BooleanField(default=True) name = models.CharField(max_length=60, unique=True) - machine_name = models.CharField(max_length=30, unique=True, default="orgXXX will be created here") + machine_name = models.CharField( + max_length=30, unique=True, default="orgXXX will be created here" + ) created_time = models.DateTimeField(auto_now_add=True) modified_time = models.DateTimeField(auto_now=True) ACQUISITION_TYPE_CHOICES = ( - ('donation', 'Donation'), - ('deposit', 'Deposit'), - ('transfer', 'Transfer'), + ("donation", "Donation"), + ("deposit", "Deposit"), + ("transfer", "Transfer"), ) - acquisition_type = models.CharField(max_length=25, choices=ACQUISITION_TYPE_CHOICES, null=True, blank=True) + acquisition_type = models.CharField( + max_length=25, choices=ACQUISITION_TYPE_CHOICES, null=True, blank=True + ) + + class Meta: + ordering = ["name"] + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("orgs:edit", kwargs={"pk": self.pk}) def rights_statements(self): return self.rightsstatement_set.filter(archive__isnull=True) @@ -37,7 +47,7 @@ def bagit_profiles(self): return BagItProfile.objects.filter(applies_to_organization=self) def org_users(self): - return User.objects.filter(organization=self).order_by('username') + return User.objects.filter(organization=self).order_by("username") def active_users(self): return User.objects.filter(organization=self, is_active=True) @@ -45,203 +55,175 @@ def active_users(self): def inactive_users(self): return User.objects.filter(organization=self, is_active=False) + def org_machine_upload_paths(self): + """Returns a list containing the organizations' upload and processing paths.""" + return [ + "{}{}/upload/".format(settings.TRANSFER_UPLOADS_ROOT, self.machine_name), + "{}{}/processing/".format( + settings.TRANSFER_UPLOADS_ROOT, self.machine_name + ), + ] + def org_root_dir(self): return "%s%s".format(settings.TRANSFER_UPLOADS_ROOT, self.machine_name) - def construct_machine_name(self): - return "".join(c for c in self.name.lower() if c.isalnum()).rstrip() - def save(self, *args, **kwargs): + """Adds additional behaviors to the default save function.""" if self.pk is None: - self.machine_name = self.construct_machine_name() + """Save new Organization instances.""" + self.machine_name = "".join( + c for c in self.name.lower() if c.isalnum() + ).rstrip() RAC_CMD.add_org(self.machine_name) else: - # SET USERS INACTIVE WHEN ORG IS SET TO INACTIVE orig = Organization.objects.get(pk=self.pk) if orig.is_active != self.is_active and not self.is_active: - # what if ORG is RAC + """Sets all users of org to inactive.""" for u in self.org_users(): if u.is_active: u.is_active = False u.save() - print 'USER {} set to inactive!'.format(u.username) - super(Organization, self).save(*args, **kwargs) @staticmethod def users_by_org(): - orgs = Organization.objects.all().order_by('name') - if not orgs: return False - data = [] - - for org in orgs: - data.append({ - 'org': org, - 'users': org.org_users() - }) - return data + """Returns a list containing dicts of organizations and the users + associated with them.""" + orgs = Organization.objects.all().order_by("name") + if not orgs: + return False + return [{"org": org, "users": org.org_users()} for org in orgs] @staticmethod def is_org_active(org): - - # DOES ORG EXIST - organization = {} + """Returns an active organization object based on its machine_name, + or None if that object does not exist.""" try: - organization = Organization.objects.get(machine_name=org) - except Organization.DoesNotExist as e: - print e - if not organization: - print 'org doesnt exist log and continue to next file' - return False - - # ORG ACTIVE - if not organization.is_active: - print 'org not acitve, log and continue' - return False - return organization - - def org_machine_upload_paths(self): - return [ - '{}{}/upload/'.format(settings.TRANSFER_UPLOADS_ROOT, self.machine_name), - '{}{}/processing/'.format(settings.TRANSFER_UPLOADS_ROOT, self.machine_name) - ] - - def __unicode__(self): - return self.name - - def get_absolute_url(self): - return reverse('orgs:edit', kwargs={'pk': self.pk}) - - class Meta: - ordering = ['name'] + org = Organization.objects.get( + machine_name=org, is_active=True + ) + except Organization.DoesNotExist: + org = None + return org class User(AbstractUser): + """Users can belong to one or more groups, each of which has specific permissions.""" - appraiser_groups = [u"appraisal_archivists", u"managing_archivists"] - accessioner_groups = [u"accessioning_archivists", u"managing_archivists"] - managing_group = [u"managing_archivists"] + APPRAISER_GROUPS = ["appraisal_archivists", "managing_archivists"] + ACCESSIONER_GROUPS = ["accessioning_archivists", "managing_archivists"] + MANAGER_GROUPS = ["managing_archivists"] - organization = models.ForeignKey(Organization, null=True, blank=False) + organization = models.ForeignKey(Organization, null=True, blank=False, on_delete=models.CASCADE) is_machine_account = models.BooleanField(default=True) is_org_admin = models.BooleanField(default=False) - - AbstractUser._meta.get_field('email').blank = False - AbstractUser._meta.get_field('email')._unique = True - AbstractUser._meta.get_field('first_name').blank = False - AbstractUser._meta.get_field('last_name').blank = False - AbstractUser._meta.get_field('username').blank = False + AbstractUser._meta.get_field("email").blank = False + AbstractUser._meta.get_field("email")._unique = True + AbstractUser._meta.get_field("first_name").blank = False + AbstractUser._meta.get_field("last_name").blank = False + AbstractUser._meta.get_field("username").blank = False class Meta: - ordering = ['username'] + ordering = ["username"] + + def get_absolute_url(self): + return reverse("users:detail", kwargs={"pk": self.pk}) - def in_group(self, GRP): - return User.objects.filter(pk=self.pk, groups__name=GRP).exists() + def in_group(self, grp): + return User.objects.filter(pk=self.pk, groups__name=grp).exists() def is_archivist(self): - """friendlier way to check if staff""" + """Alias for `is_staff`.""" return self.is_staff def has_privs(self, priv_type=None): - """resolves group clusters for user object""" + """Resolves group clusters for Users.""" if not self.is_staff: return False if self.is_superuser: return True groups = [] - if priv_type == 'APPRAISER': - groups = User.appraiser_groups - elif priv_type == 'ACCESSIONER': - groups = User.accessioner_groups - elif priv_type == 'MANAGING': - groups = User.managing_group - - if not groups: return False + if priv_type == "APPRAISER": + groups = User.APPRAISER_GROUPS + elif priv_type == "ACCESSIONER": + groups = User.ACCESSIONER_GROUPS + elif priv_type == "MANAGING": + groups = User.MANAGER_GROUPS + + if not groups: + return False return self.groups.filter(name__in=groups).exists() def is_manager(self): - return self.groups.filter(name='managing_archivists').exists() + return self.groups.filter(name__in=User.MANAGER_GROUPS).exists() - def can_appraise(self): + def permissions_by_group(self, group): if self.is_superuser: return True - return self.groups.filter(name__in=['appraisal_archivists', 'managing_archivists']).exists() + return self.groups.filter(name__in=group).exists() + + def can_appraise(self): + return self.permissions_by_group(User.APPRAISER_GROUPS) def can_accession(self): - if self.is_superuser: - return True - return self.groups.filter(name__in=['accessioning_archivists', 'managing_archivists']).exists() + return self.permissions_by_group(User.ACCESSIONER_GROUPS) def save(self, *args, **kwargs): + """Adds additional behaviors to default save.""" if self.pk is None: + """Sets default random password for new users.""" if RAC_CMD.add_user(self.username): if RAC_CMD.add2grp(self.organization.machine_name, self.username): self.set_password(User.objects.make_random_password()) super(User, self).save(*args, **kwargs) else: + """Updates user's group if necessary.""" orig = User.objects.get(pk=self.pk) if orig.organization != self.organization: - if RAC_CMD.del_from_org(self.username): - if RAC_CMD.add2grp(self.organization.machine_name, self.username): - print 'GROUP CHANGED' - # SHOULD ACTUALLY REMOVE ANY GROUPS THAT MATCH REGEX ORGXXX - if orig.organization: - pass - else: - if RAC_CMD.add2grp(self.organization.machine_name, self.username): - print 'GROUP CHANGED' - + RAC_CMD.del_from_org(self.username) + RAC_CMD.add2grp(self.organization.machine_name, self.username) super(User, self).save(*args, **kwargs) def total_uploads(self): - return Archives.objects.filter(process_status__gte=Archives.TRANSFER_COMPLETED, user_uploaded=self).count() + """Returns the number of uploads associated with a user.""" + return Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, user_uploaded=self + ).count() @staticmethod - def is_user_active(u, org): - user = {} + def is_user_active(usr, org): + """Returns an active user object based on a username and organization, + or None if that User does not exist.""" try: - user = User.objects.get(username=u, organization=org) - except User.DoesNotExist as e: - print e - if not user: - print 'No user matching that username or organization' - return False - if not user.is_active: - print 'User is inactive' - return False + user = User.objects.get(username=usr, organization=org, is_active=True) + except User.DoesNotExist: + user = None return user - def get_absolute_url(self): - return reverse('users:detail', kwargs={'pk': self.pk}) - class RecordCreators(models.Model): name = models.CharField(max_length=100) TYPE_CHOICES = ( - ('family', 'Family'), - ('organization', 'Organization'), - ('person', 'Person'), + ("family", "Family"), + ("organization", "Organization"), + ("person", "Person"), ) type = models.CharField(max_length=50, choices=TYPE_CHOICES) - def __unicode__(self): + def __str__(self): return self.name class LanguageCode(models.Model): code = models.CharField(max_length=3) - def __unicode__(self): + def __str__(self): return self.code class Archives(models.Model): - machine_file_types = ( - ('ZIP', 'zip'), - ('TAR', 'tar'), - ('OTHER', 'OTHER') - ) + machine_file_types = (("ZIP", "zip"), ("TAR", "tar"), ("OTHER", "OTHER")) TRANSFER_STARTED = 10 TRANSFER_COMPLETED = 20 INVALID = 30 @@ -252,20 +234,22 @@ class Archives(models.Model): DELIVERED = 85 ACCESSIONING_COMPLETE = 90 processing_statuses = ( - (TRANSFER_STARTED, 'Transfer Started'), - (TRANSFER_COMPLETED, 'Transfer Completed'), - (INVALID, 'Invalid'), - (VALIDATED, 'Validated'), - (REJECTED, 'Rejected'), - (ACCEPTED, 'Accepted'), - (ACCESSIONING_STARTED, 'Accessioning Started'), - (DELIVERED, 'In Accession Queue'), - (ACCESSIONING_COMPLETE, 'Accession Complete') + (TRANSFER_STARTED, "Transfer Started"), + (TRANSFER_COMPLETED, "Transfer Completed"), + (INVALID, "Invalid"), + (VALIDATED, "Validated"), + (REJECTED, "Rejected"), + (ACCEPTED, "Accepted"), + (ACCESSIONING_STARTED, "Accessioning Started"), + (DELIVERED, "In Accession Queue"), + (ACCESSIONING_COMPLETE, "Accession Complete"), ) - accession = models.ForeignKey('Accession', related_name="accession_transfers", null=True, blank=True) - organization = models.ForeignKey(Organization, related_name="transfers") - user_uploaded = models.ForeignKey(User, null=True) + accession = models.ForeignKey( + "Accession", related_name="accession_transfers", null=True, blank=True, on_delete=models.SET_NULL + ) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="transfers") + user_uploaded = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) machine_file_path = models.CharField(max_length=255) machine_file_size = models.CharField(max_length=30) machine_file_upload_time = models.DateTimeField() @@ -276,21 +260,35 @@ class Archives(models.Model): appraisal_note = models.TextField(blank=True, null=True) manifest = models.TextField(blank=True, null=True) additional_error_info = models.CharField(max_length=255, null=True, blank=True) - process_status = models.PositiveSmallIntegerField(choices=processing_statuses, default=TRANSFER_COMPLETED) + process_status = models.PositiveSmallIntegerField( + choices=processing_statuses, default=TRANSFER_COMPLETED + ) archivesspace_identifier = models.CharField(max_length=255, null=True, blank=True) - archivesspace_parent_identifier = models.CharField(max_length=255, null=True, blank=True) - created_time = models.DateTimeField(auto_now_add=True) # process time + archivesspace_parent_identifier = models.CharField( + max_length=255, null=True, blank=True + ) + created_time = models.DateTimeField(auto_now_add=True) modified_time = models.DateTimeField(auto_now=True) - def __unicode__(self): - return '{}: {}'.format(self.pk, self.bag_or_failed_name()) + class Meta: + ordering = ["machine_file_upload_time"] + + def __str__(self): + return "{}: {}".format(self.pk, self.bag_or_failed_name()) def bag_or_failed_name(self): + """Returns a title string for the bag. Useful if you don't know whether + or not the bag is valid.""" if self.bag_it_valid: bag_info_data = self.get_bag_data() - return "{} ({})".format(bag_info_data.get('title'), bag_info_data.get('external_identifier')) \ - if bag_info_data.get('external_identifier') else bag_info_data.get('title') - return self.machine_file_path.split('/')[-1] + return ( + "{} ({})".format( + bag_info_data.get("title"), bag_info_data.get("external_identifier") + ) + if bag_info_data.get("external_identifier") + else bag_info_data.get("title") + ) + return self.machine_file_path.split("/")[-1] def rights_statements(self): return self.rightsstatement_set.all() @@ -300,11 +298,22 @@ def gen_identifier(): """returns a unique identifier""" iden = str(uuid4()) if Archives.objects.filter(machine_file_identifier=iden).exists(): - self.gen_identifier() + Archives.gen_identifier() return iden @classmethod - def initial_save(cls, org, user, file_path, file_size, file_modtime, identifier, file_type, bag_it_name): + def initial_save( + cls, + org, + user, + file_path, + file_size, + file_modtime, + identifier, + file_type, + bag_it_name, + ): + """Adds default value to enable save.""" archive = cls( organization=org, user_uploaded=user, @@ -314,25 +323,34 @@ def initial_save(cls, org, user, file_path, file_size, file_modtime, identifier, machine_file_identifier=identifier, machine_file_type=file_type, bag_it_name=bag_it_name, - process_status=cls.TRANSFER_COMPLETED + process_status=cls.TRANSFER_COMPLETED, ) archive.save() return archive def get_error_codes(self): if self.bag_it_valid: - return '' + return "" return [b.code.code_desc for b in self.get_errors()] def get_errors(self): + """Returns errors for an Archive.""" if self.bag_it_valid: return None - return [b for b in BAGLog.objects.filter(archive=self).exclude(code__code_short__in=['ASAVE','PBAG'])] + return [ + b + for b in BAGLog.objects.filter(archive=self).exclude( + code__code_short__in=["ASAVE", "PBAG"] + ) + ] def get_bag_validations(self): + """Returns all validations (BagIt, BagIt Profile) for an Archive.""" if not self.bag_it_valid: return False - items = BAGLog.objects.filter(archive=self, code__code_short__in=['PBAG', 'PBAGP']) + items = BAGLog.objects.filter( + archive=self, code__code_short__in=["PBAG", "PBAGP"] + ) if not items or len(items) < 2: return False data = {} @@ -340,24 +358,28 @@ def get_bag_validations(self): data[item.code.code_short] = item.created_time return data - def get_bag_failure(self, LAST_ONLY=True): + def get_bag_failure(self, last_only=True): + """Returns list of bag failures.""" if self.bag_it_valid: return False - flist = ['BE',] + flist = [ + "BE", + ] get_error_obj = BAGLog.objects.filter(archive=self, code__code_type__in=flist) if not get_error_obj: return False - return get_error_obj[0] if LAST_ONLY else get_error_obj + return get_error_obj[0] if last_only else get_error_obj def get_additional_errors(self): + """Returns additional error information""" errs = [] codes = [] - failures = self.get_bag_failure(LAST_ONLY=False) + failures = self.get_bag_failure(last_only=False) for fails in failures: codes.append(fails.code.code_short) - if 'BZIP2' in codes or 'BTAR2' in codes: - errs.append('Transfer contained more than one top level directory') + if "BZIP2" in codes or "BTAR2" in codes: + errs.append("Transfer contained more than one top level directory") if self.additional_error_info: errs.append(self.additional_error_info) @@ -367,47 +389,61 @@ def get_transfer_logs(self): return BAGLog.objects.filter(archive=self) def setup_save(self, obj): - """Builds additional info where more info is required than ecode short""" + """Builds additional info where it is required.""" - if obj['auto_fail_code'] == 'VIRUS': + if obj["auto_fail_code"] == "VIRUS": # IF CONTAINS a VIRUS, BUILD additional info - self.additional_error_info = 'Virus found in: {}'.format([k for k in obj['virus_scanresult']][0]) - elif obj['auto_fail_code'] == 'FSERR': - self.additional_error_info = 'Bag size ({}) is larger then maximum allow size ({})'.format(obj['file_size'], (settings.TRANSFER_FILESIZE_MAX * 1000)) + self.additional_error_info = "Virus found in: {}".format( + [k for k in obj["virus_scanresult"]][0] + ) + elif obj["auto_fail_code"] == "FSERR": + self.additional_error_info = "Bag size ({}) is larger then maximum allow size ({})".format( + obj["file_size"], (settings.TRANSFER_FILESIZE_MAX * 1000) + ) def save_mtm_fields(self, cls, field, model_field, metadata): + """Handle saving of many-to-many fields.""" obj_list = [] if field in metadata: - if type(metadata[field]) is list: + if isinstance(metadata[field], list): for f in metadata[field]: new_obj = cls.objects.get_or_create(**{model_field: f})[0] obj_list.append(new_obj) - elif len(metadata[field].strip()): + elif metadata[field].strip(): new_obj = cls.objects.get_or_create(**{model_field: metadata[field]})[0] obj_list.append(new_obj) return obj_list def save_bag_data(self, metadata): + """Saves data from a bag-info.txt file, passed as a dict.""" if not metadata: return False try: - creators_list = self.save_mtm_fields(RecordCreators, 'Record_Creators', 'name', metadata) - language_list = self.save_mtm_fields(LanguageCode, 'Language', 'code', metadata) + creators_list = self.save_mtm_fields( + RecordCreators, "Record_Creators", "name", metadata + ) + language_list = self.save_mtm_fields( + LanguageCode, "Language", "code", metadata + ) item = BagInfoMetadata( archive=self, - source_organization=Organization.objects.get(name=metadata['Source_Organization']), - external_identifier=metadata.get('External_Identifier', ''), - internal_sender_description=metadata.get('Internal_Sender_Description', ''), - title=metadata.get('Title', ''), - date_start=iso8601.parse_date(metadata.get('Date_Start', '')), - date_end=iso8601.parse_date(metadata.get('Date_End', '')), - record_type=metadata.get('Record_Type', ''), - bagging_date=iso8601.parse_date(metadata.get('Bagging_Date', '')), - bag_count=metadata.get('Bag_Count', ''), - bag_group_identifier=metadata.get('Bag_Group_Identifier', ''), - payload_oxum=metadata.get('Payload_Oxum', ''), - bagit_profile_identifier=metadata.get('BagIt_Profile_Identifier', '') + source_organization=Organization.objects.get( + name=metadata["Source_Organization"] + ), + external_identifier=metadata.get("External_Identifier", ""), + internal_sender_description=metadata.get( + "Internal_Sender_Description", "" + ), + title=metadata.get("Title", ""), + date_start=iso8601.parse_date(metadata.get("Date_Start", "")), + date_end=iso8601.parse_date(metadata.get("Date_End", "")), + record_type=metadata.get("Record_Type", ""), + bagging_date=iso8601.parse_date(metadata.get("Bagging_Date", "")), + bag_count=metadata.get("Bag_Count", ""), + bag_group_identifier=metadata.get("Bag_Group_Identifier", ""), + payload_oxum=metadata.get("Payload_Oxum", ""), + bagit_profile_identifier=metadata.get("BagIt_Profile_Identifier", ""), ) item.save() for c in creators_list: @@ -416,16 +452,21 @@ def save_bag_data(self, metadata): item.language.add(l) item.save() except Exception as e: - print e + print("Error saving bag data: {}".format(str(e))) return False else: - return True # this at least assumes nothing blew up + return True def get_bag_data(self): + """Returns a dict containing bag-info.txt data for an Archive.""" bag_data = BagInfoMetadata.objects.filter(archive=self.pk).first() - excluded_fields = ['id', 'pk', 'archive'] - mtm_fields = ['record_creators', 'language'] - field_names = [field.name for field in BagInfoMetadata._meta.get_fields() if field.name not in excluded_fields] + excluded_fields = ["id", "pk", "archive"] + mtm_fields = ["record_creators", "language"] + field_names = [ + field.name + for field in BagInfoMetadata._meta.get_fields() + if field.name not in excluded_fields + ] values = {} for field_name in sorted(field_names): if field_name in mtm_fields: @@ -442,77 +483,102 @@ def get_bag_data(self): return values def get_records_creators(self): + """Returns a list of creators associated with an Archive.""" bag_data = BagInfoMetadata.objects.filter(archive=self.pk).first() + creators = [] if bag_data: - return list(bag_data.record_creators.all()) - else: - return [] + creators = list(bag_data.record_creators.all()) + return creators def assign_rights(self): + """Assigns rights to an Archive.""" try: bag_data = self.get_bag_data() - RightsStatement = apps.get_model('bag_transfer', 'RightsStatement') - rights_statements = RightsStatement.objects.filter(organization=self.organization, applies_to_type__name=bag_data['record_type'], archive__isnull=True) + RightsStatement = apps.get_model("bag_transfer", "RightsStatement") + rights_statements = RightsStatement.objects.filter( + organization=self.organization, + applies_to_type__name=bag_data["record_type"], + archive__isnull=True, + ) for statement in rights_statements: + """Close and save new rights statement.""" rights_info = statement.get_rights_info_object() rights_granted = statement.get_rights_granted_objects() - # Clone and save rights statement statement.pk = None statement.archive = self statement.save() - # Assign dates to rights basis and save - if statement.rights_basis == 'Other': - start_date_key = 'other_rights_applicable_start_date' - end_date_key = 'other_rights_applicable_end_date' - start_date_period_key = 'other_rights_start_date_period' - end_date_period_key = 'other_rights_end_date_period' + + """Assign dates to rights basis and save.""" + if statement.rights_basis == "Other": + start_date_key = "other_rights_applicable_start_date" + end_date_key = "other_rights_applicable_end_date" + start_date_period_key = "other_rights_start_date_period" + end_date_period_key = "other_rights_end_date_period" else: - start_date_key = '{}_applicable_start_date'.format(statement.rights_basis.lower()) - end_date_key = '{}_applicable_end_date'.format(statement.rights_basis.lower()) - start_date_period_key = '{}_start_date_period'.format(statement.rights_basis.lower()) - end_date_period_key = '{}_end_date_period'.format(statement.rights_basis.lower()) + start_date_key = "{}_applicable_start_date".format( + statement.rights_basis.lower() + ) + end_date_key = "{}_applicable_end_date".format( + statement.rights_basis.lower() + ) + start_date_period_key = "{}_start_date_period".format( + statement.rights_basis.lower() + ) + end_date_period_key = "{}_end_date_period".format( + statement.rights_basis.lower() + ) if not getattr(rights_info, start_date_key): if getattr(rights_info, start_date_period_key): period = getattr(rights_info, start_date_period_key) else: period = 0 - setattr(rights_info, start_date_key, bag_data['date_start'] + relativedelta(years=period)) + setattr( + rights_info, + start_date_key, + bag_data["date_start"] + relativedelta(years=period), + ) if not getattr(rights_info, end_date_key): if getattr(rights_info, end_date_period_key): period = getattr(rights_info, end_date_period_key) else: period = 0 - setattr(rights_info, end_date_key, bag_data['date_end'] + relativedelta(years=period)) + setattr( + rights_info, + end_date_key, + bag_data["date_end"] + relativedelta(years=period), + ) rights_info.pk = None rights_info.rights_statement = statement rights_info.save() - # Assign dates to rights granted and save + + """Assign dates to rights granted and save.""" for granted in rights_granted: if not granted.start_date: - if getattr(granted, 'start_date_period'): - period = getattr(granted, 'start_date_period') + if getattr(granted, "start_date_period"): + period = getattr(granted, "start_date_period") else: period = 0 - granted.start_date = bag_data['date_start'] + relativedelta(years=period) + granted.start_date = bag_data["date_start"] + relativedelta( + years=period + ) if not granted.end_date: - if getattr(granted, 'end_date_period'): - period = getattr(granted, 'end_date_period') + if getattr(granted, "end_date_period"): + period = getattr(granted, "end_date_period") else: period = 0 - granted.end_date = bag_data['date_end'] + relativedelta(years=period) + granted.end_date = bag_data["date_end"] + relativedelta( + years=period + ) granted.pk = None granted.rights_statement = statement granted.save() return True except Exception as e: - print e + print("Error saving rights statement: {}".format(str(e))) return False else: return True - class Meta: - ordering = ['machine_file_upload_time'] - class BAGLogCodes(models.Model): """ @@ -527,64 +593,72 @@ class BAGLogCodes(models.Model): Each code has a next_action field to provide information about additional system actions that have occurred as a result of the successful or failed process or activity. """ - eCat_bagit_validation = ['BTAR2','BZIP2',] - eCat_rac_profile = ['FSERR','MDERR','DTERR'] + + BAGIT_VALIDATIONS = [ + "BTAR2", + "BZIP2", + ] + RAC_VALIDATIONS = ["FSERR", "MDERR", "DTERR"] code_short = models.CharField(max_length=5) code_types = ( - ('BE', 'Bag Error'), - ('GE', 'General Error'), - ('I', 'Info'), - ('S', 'Success'), + ("BE", "Bag Error"), + ("GE", "General Error"), + ("I", "Info"), + ("S", "Success"), ) code_type = models.CharField(max_length=15, choices=code_types) code_desc = models.CharField(max_length=60) next_action = models.CharField(max_length=255, null=True, blank=True) - def __unicode__(self): - return "{} : {}".format(self.code_short,self.code_desc) + def __str__(self): + return "{} : {}".format(self.code_short, self.code_desc) class BAGLog(models.Model): - code = models.ForeignKey(BAGLogCodes) - archive = models.ForeignKey(Archives, blank=True, null=True, related_name='events') + """Log objects containing information about system or user actions.""" + + code = models.ForeignKey(BAGLogCodes, on_delete=models.CASCADE) + archive = models.ForeignKey(Archives, blank=True, null=True, on_delete=models.CASCADE, related_name="events") log_info = models.CharField(max_length=255, null=True, blank=True) created_time = models.DateTimeField(auto_now_add=True) class Meta: - ordering = ['-created_time'] + ordering = ["-created_time"] - def __unicode__(self): + def __str__(self): val = "-- : {}".format(self.code.code_desc) if self.archive: - val = "{} : {}".format(self.archive.bag_or_failed_name(), self.code.code_desc) + val = "{} : {}".format( + self.archive.bag_or_failed_name(), self.code.code_desc + ) return val @classmethod def log_it(cls, code, archive=None): + """Creates BagLog object for event.""" try: - item = cls( - code=BAGLogCodes.objects.get(code_short=code), - archive=archive - ).save() + cls(code=BAGLogCodes.objects.get(code_short=code), archive=archive).save() if archive: - if code in BAGLogCodes.eCat_bagit_validation: - cls.log_it('GBERR', archive) + if code in BAGLogCodes.BAGIT_VALIDATIONS: + cls.log_it("GBERR", archive) - if code in BAGLogCodes.eCat_rac_profile: - cls.log_it('RBERR', archive) + if code in BAGLogCodes.RAC_VALIDATIONS: + cls.log_it("RBERR", archive) return True except Exception as e: - print e + print("Error creating BagLog: {}".format(str(e))) else: return False class BagInfoMetadata(models.Model): - archive = models.OneToOneField(Archives, related_name='metadata') - source_organization = models.ForeignKey(Organization, blank=True,null=True,) + """Metadata from a bag-info.txt file.""" + + archive = models.OneToOneField(Archives, on_delete=models.CASCADE, related_name="metadata") + source_organization = models.ForeignKey(Organization, blank=True, null=True, on_delete=models.CASCADE) external_identifier = models.CharField(max_length=256) internal_sender_description = models.TextField() title = models.CharField(max_length=256) @@ -598,89 +672,99 @@ class BagInfoMetadata(models.Model): bag_group_identifier = models.CharField(max_length=256) payload_oxum = models.CharField(max_length=20) bagit_profile_identifier = models.URLField() + origin = models.CharField(max_length=10, default="aurora") class BagItProfile(models.Model): - applies_to_organization = models.ForeignKey(Organization, related_name='applies_to_organization') - source_organization = models.ForeignKey(Organization, related_name='source_organization') + applies_to_organization = models.ForeignKey( + Organization, on_delete=models.CASCADE, related_name="applies_to_organization" + ) + source_organization = models.ForeignKey( + Organization, on_delete=models.CASCADE, related_name="source_organization" + ) external_description = models.TextField(blank=True) version = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) bagit_profile_identifier = models.URLField(blank=True) contact_email = models.EmailField() allow_fetch = models.BooleanField(default=False) SERIALIZATION_CHOICES = ( - ('forbidden', 'forbidden'), - ('required', 'required'), - ('optional', 'optional'), + ("forbidden", "forbidden"), + ("required", "required"), + ("optional", "optional"), + ) + serialization = models.CharField( + choices=SERIALIZATION_CHOICES, max_length=25, default="optional" ) - serialization = models.CharField(choices=SERIALIZATION_CHOICES, max_length=25, default='optional') + + +class ManifestsAllowed(models.Model): + MANIFESTS_REQUIRED_CHOICES = (("sha256", "sha256"), ("sha512", "sha512")) + name = models.CharField(choices=MANIFESTS_REQUIRED_CHOICES, max_length=20) + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="manifests_allowed") class ManifestsRequired(models.Model): - MANIFESTS_REQUIRED_CHOICES = ( - ('sha256', 'sha256'), - ('md5', 'md5') - ) + MANIFESTS_REQUIRED_CHOICES = (("sha256", "sha256"), ("sha512", "sha512")) name = models.CharField(choices=MANIFESTS_REQUIRED_CHOICES, max_length=20) - bagit_profile = models.ForeignKey(BagItProfile, related_name='manifests_required') + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="manifests_required") class AcceptSerialization(models.Model): ACCEPT_SERIALIZATION_CHOICES = ( - ('application/zip', 'application/zip'), - ('application/x-tar', 'application/x-tar'), - ('application/x-gzip', 'application/x-gzip'), + ("application/zip", "application/zip"), + ("application/x-tar", "application/x-tar"), + ("application/x-gzip", "application/x-gzip"), ) name = models.CharField(choices=ACCEPT_SERIALIZATION_CHOICES, max_length=25) - bagit_profile = models.ForeignKey(BagItProfile, related_name='accept_serialization') + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="accept_serialization") class AcceptBagItVersion(models.Model): BAGIT_VERSION_NAME_CHOICES = ( - ('0.96', '0.96'), - ('0.97', '0.97'), + ("0.96", "0.96"), + ("0.97", "0.97"), + ("1.0", "1.0"), ) name = models.CharField(choices=BAGIT_VERSION_NAME_CHOICES, max_length=5) - bagit_profile = models.ForeignKey(BagItProfile, related_name="accept_bagit_version") + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="accept_bagit_version") class TagManifestsRequired(models.Model): - TAG_MANIFESTS_REQUIRED_CHOICES = ( - ('sha256', 'sha256'), - ('md5', 'md5') - ) + TAG_MANIFESTS_REQUIRED_CHOICES = (("sha256", "sha256"), ("sha512", "sha512")) name = models.CharField(choices=TAG_MANIFESTS_REQUIRED_CHOICES, max_length=20) - bagit_profile = models.ForeignKey(BagItProfile, related_name="tag_manifests_required") + bagit_profile = models.ForeignKey( + BagItProfile, on_delete=models.CASCADE, related_name="tag_manifests_required" + ) class TagFilesRequired(models.Model): name = models.CharField(max_length=256) - bagit_profile = models.ForeignKey(BagItProfile, related_name="tag_files_required") + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="tag_files_required") class BagItProfileBagInfo(models.Model): - bagit_profile = models.ForeignKey(BagItProfile, related_name="bag_info") + bagit_profile = models.ForeignKey(BagItProfile, on_delete=models.CASCADE, related_name="bag_info") FIELD_CHOICES = ( - ('bag_count', 'Bag-Count'), - ('bag_group_identifier', 'Bag-Group-Identifier'), - ('bag_size', 'Bag-Size'), - ('bagging_date', 'Bagging-Date'), - ('contact_email', 'Contact-Email'), - ('contact_name', 'Contact-Name'), - ('contact_phone', 'Contact-Phone'), - ('date_end', 'Date-End'), - ('date_start', 'Date-Start'), - ('external_description', 'External-Description'), - ('external_identifier', 'External-Identifier'), - ('internal_sender_description', 'Internal-Sender-Description'), - ('internal_sender_identifier', 'Internal-Sender-Identifier'), - ('language', 'Language'), - ('organization_address', 'Organization-Address'), - ('payload_oxum', 'Payload-Oxum'), - ('record_creators', 'Record-Creators'), - ('record_type', 'Record-Type'), - ('source_organization', 'Source-Organization'), - ('title', 'Title'), + ("bag_count", "Bag-Count"), + ("bag_group_identifier", "Bag-Group-Identifier"), + ("bag_size", "Bag-Size"), + ("bagging_date", "Bagging-Date"), + ("contact_email", "Contact-Email"), + ("contact_name", "Contact-Name"), + ("contact_phone", "Contact-Phone"), + ("date_end", "Date-End"), + ("date_start", "Date-Start"), + ("external_description", "External-Description"), + ("external_identifier", "External-Identifier"), + ("internal_sender_description", "Internal-Sender-Description"), + ("internal_sender_identifier", "Internal-Sender-Identifier"), + ("language", "Language"), + ("organization_address", "Organization-Address"), + ("payload_oxum", "Payload-Oxum"), + ("record_creators", "Record-Creators"), + ("record_type", "Record-Type"), + ("source_organization", "Source-Organization"), + ("title", "Title"), ) field = models.CharField(choices=FIELD_CHOICES, max_length=100) required = models.NullBooleanField(default=False, null=True) @@ -688,23 +772,23 @@ class BagItProfileBagInfo(models.Model): class BagItProfileBagInfoValues(models.Model): - bagit_profile_baginfo = models.ForeignKey(BagItProfileBagInfo) + bagit_profile_baginfo = models.ForeignKey(BagItProfileBagInfo, on_delete=models.CASCADE) name = models.CharField(max_length=256) class Meta: - ordering = ['name'] + ordering = ["name"] class DashboardMonthData(models.Model): year = models.PositiveSmallIntegerField() month_label = models.CharField(max_length=15) sort_date = models.PositiveIntegerField() - organization = models.ForeignKey(Organization) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE) upload_count = models.PositiveSmallIntegerField(default=0) upload_size = models.FloatField(default=0) class DashboardRecordTypeData(models.Model): - organization = models.ForeignKey(Organization) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE) label = models.CharField(max_length=255) count = models.PositiveSmallIntegerField(default=0) diff --git a/aurora/bag_transfer/orgs/form.py b/aurora/bag_transfer/orgs/form.py index 1b72ebf3..a55c4118 100644 --- a/aurora/bag_transfer/orgs/form.py +++ b/aurora/bag_transfer/orgs/form.py @@ -1,9 +1,16 @@ from django import forms -from django.contrib.auth.forms import PasswordChangeForm, SetPasswordForm -from django.utils.translation import ugettext, ugettext_lazy as _ - -from bag_transfer.models import BagItProfile, BagItProfileBagInfo, BagItProfileBagInfoValues, ManifestsRequired, AcceptSerialization, AcceptBagItVersion, TagManifestsRequired, TagFilesRequired +from bag_transfer.models import ( + BagItProfile, + BagItProfileBagInfo, + BagItProfileBagInfoValues, + ManifestsAllowed, + ManifestsRequired, + AcceptSerialization, + AcceptBagItVersion, + TagManifestsRequired, + TagFilesRequired, +) class BagItProfileForm(forms.ModelForm): @@ -11,22 +18,29 @@ class Meta: model = BagItProfile exclude = [] labels = { - 'external_description': 'Description', - 'allow_fetch': 'Allow Fetch.txt?', - 'serialization': 'Serialization allowed?' + "external_description": "Description", + "allow_fetch": "Allow Fetch.txt?", + "serialization": "Serialization allowed?", } widgets = { - 'applies_to_organization': forms.widgets.HiddenInput(), - 'contact_email': forms.widgets.HiddenInput(), - 'source_organization': forms.widgets.HiddenInput(), - 'version': forms.widgets.HiddenInput(), - 'bagit_profile_identifier': forms.widgets.HiddenInput(), - 'external_description': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), - 'serialization': forms.widgets.Select(attrs={'class': 'form-control', 'aria-labelledby': 'id_serialization-label'}), + "applies_to_organization": forms.widgets.HiddenInput(), + "contact_email": forms.widgets.HiddenInput(), + "source_organization": forms.widgets.HiddenInput(), + "version": forms.widgets.HiddenInput(), + "bagit_profile_identifier": forms.widgets.HiddenInput(), + "external_description": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + "serialization": forms.widgets.Select( + attrs={ + "class": "form-control", + "aria-labelledby": "id_serialization-label", + } + ), } help_texts = { - 'external_description': 'A short description of this BagIt Profile.', - 'serialization': 'Specify whether serialization of bags is required, forbidden, or optional.', + "external_description": "A short description of this BagIt Profile.", + "serialization": "Specify whether serialization of bags is required, forbidden, or optional.", } @@ -35,64 +49,118 @@ class Meta: model = BagItProfileBagInfo exclude = [] labels = { - 'field': 'Field', - 'required': 'Required?', - 'repeatable': 'Repeatable?', + "field": "Field", + "required": "Required?", + "repeatable": "Repeatable?", } widgets = { - 'field': forms.widgets.Select(attrs={'class': 'form-control multi-value'}), - 'required': forms.widgets.CheckboxInput(), - 'repeatable': forms.widgets.CheckboxInput(), + "field": forms.widgets.Select(attrs={"class": "form-control multi-value"}), + "required": forms.widgets.CheckboxInput(), + "repeatable": forms.widgets.CheckboxInput(), } class BagItProfileBagInfoValuesForm(forms.ModelForm): class Meta: model = BagItProfileBagInfoValues - fields = ('name',) - widgets = {'name': forms.widgets.TextInput(attrs={'class': 'form-control multi-value', 'aria-labelledby': 'values-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.TextInput( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "values-label", + } + ) + } + + +class ManifestsAllowedForm(forms.ModelForm): + class Meta: + model = ManifestsAllowed + fields = ("name",) + widgets = { + "name": forms.widgets.Select( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "manifests_allowed-label", + } + ) + } class ManifestsRequiredForm(forms.ModelForm): class Meta: model = ManifestsRequired - fields = ('name',) - widgets = {'name': forms.widgets.Select(attrs={'class': 'form-control multi-value', 'aria-labelledby': 'manifests-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.Select( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "manifests-label", + } + ) + } class AcceptSerializationForm(forms.ModelForm): class Meta: model = AcceptSerialization - fields = ('name',) - widgets = {'name': forms.widgets.Select(attrs={'class': 'form-control multi-value', 'aria-labelledby': 'serialization-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.Select( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "serialization-label", + } + ) + } class AcceptBagItVersionForm(forms.ModelForm): class Meta: model = AcceptBagItVersion - fields = ('name',) - widgets = {'name': forms.widgets.Select(attrs={'class': 'form-control multi-value', 'aria-labelledby': 'version-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.Select( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "version-label", + } + ) + } class TagManifestsRequiredForm(forms.ModelForm): class Meta: model = TagManifestsRequired - fields = ('name',) - widgets = {'name': forms.widgets.Select(attrs={'class': 'form-control multi-value', 'aria-labelledby': 'tag_manifests-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.Select( + attrs={ + "class": "form-control multi-value", + "aria-labelledby": "tag_manifests-label", + } + ) + } class TagFilesRequiredForm(forms.ModelForm): class Meta: model = TagFilesRequired - fields = ('name',) - widgets = {'name': forms.widgets.TextInput(attrs={'class': 'form-control', 'aria-labelledby': 'tag_files-label'})} + fields = ("name",) + widgets = { + "name": forms.widgets.TextInput( + attrs={"class": "form-control", "aria-labelledby": "tag_files-label"} + ) + } + BagItProfileBagInfoValuesFormset = forms.inlineformset_factory( BagItProfileBagInfo, BagItProfileBagInfoValues, - fields=('name',), + fields=("name",), extra=1, - form=BagItProfileBagInfoValuesForm + form=BagItProfileBagInfoValuesForm, ) @@ -102,21 +170,19 @@ def add_fields(self, form, index): super(BaseBagInfoFormset, self).add_fields(form, index) form.nested = BagItProfileBagInfoValuesFormset( - instance=form.instance, - data=form.data if form.is_bound else None, - files=form.files if form.is_bound else None, - prefix='nested_%s_%s' % ( - form.prefix, - BagItProfileBagInfoValuesFormset.get_default_prefix()), - - ) + instance=form.instance, + data=form.data if form.is_bound else None, + files=form.files if form.is_bound else None, + prefix="nested_%s_%s" + % (form.prefix, BagItProfileBagInfoValuesFormset.get_default_prefix()), + ) def is_valid(self): result = super(BaseBagInfoFormset, self).is_valid() if self.is_bound: for form in self.forms: - if hasattr(form, 'nested'): + if hasattr(form, "nested"): result = result and form.nested.is_valid() return result @@ -124,27 +190,37 @@ def save(self, commit=True): result = super(BaseBagInfoFormset, self).save(commit=commit) for form in self.forms: - if hasattr(form, 'nested'): + if hasattr(form, "nested"): if not self._should_delete_form(form): try: form.nested.save(commit=commit) - except: + except Exception: result = False return result + BagItProfileBagInfoFormset = forms.inlineformset_factory( BagItProfile, BagItProfileBagInfo, - fields=('field', 'required', 'repeatable'), + fields=("field", "required", "repeatable"), extra=1, form=BagItProfileBagInfoForm, - formset=BaseBagInfoFormset + formset=BaseBagInfoFormset, +) + +ManifestsAllowedFormset = forms.inlineformset_factory( + BagItProfile, + ManifestsAllowed, + fields=("name",), + extra=1, + max_num=2, + form=ManifestsAllowedForm, ) ManifestsRequiredFormset = forms.inlineformset_factory( BagItProfile, ManifestsRequired, - fields=('name',), + fields=("name",), extra=1, max_num=2, form=ManifestsRequiredForm, @@ -153,7 +229,7 @@ def save(self, commit=True): AcceptSerializationFormset = forms.inlineformset_factory( BagItProfile, AcceptSerialization, - fields=('name',), + fields=("name",), extra=1, max_num=3, form=AcceptSerializationForm, @@ -162,7 +238,7 @@ def save(self, commit=True): AcceptBagItVersionFormset = forms.inlineformset_factory( BagItProfile, AcceptBagItVersion, - fields=('name',), + fields=("name",), extra=1, max_num=2, form=AcceptBagItVersionForm, @@ -171,7 +247,7 @@ def save(self, commit=True): TagManifestsRequiredFormset = forms.inlineformset_factory( BagItProfile, TagManifestsRequired, - fields=('name',), + fields=("name",), extra=1, max_num=2, form=TagManifestsRequiredForm, @@ -180,7 +256,7 @@ def save(self, commit=True): TagFilesRequiredFormset = forms.inlineformset_factory( BagItProfile, TagFilesRequired, - fields=('name',), + fields=("name",), extra=1, form=TagFilesRequiredForm, ) diff --git a/aurora/bag_transfer/orgs/urls.py b/aurora/bag_transfer/orgs/urls.py index 062159dc..eaaa06ec 100644 --- a/aurora/bag_transfer/orgs/urls.py +++ b/aurora/bag_transfer/orgs/urls.py @@ -1,14 +1,39 @@ -from django.conf.urls import url, include -from bag_transfer.orgs.views import * +from django.conf.urls import url +from bag_transfer.orgs.views import ( + BagItProfileAPIAdminView, + BagItProfileDetailView, + BagItProfileManageView, + OrganizationCreateView, + OrganizationDetailView, + OrganizationEditView, + OrganizationListView, +) -urlpatterns = [ +app_name = "orgs" - url(r'^add/$', OrganizationCreateView.as_view(), name='add'), - url(r'^(?P\d+)/$', OrganizationDetailView.as_view(), name='detail'), - url(r'^$', OrganizationListView.as_view(), name='list'), - url(r'^(?P\d+)/edit/$', OrganizationEditView.as_view(), name='edit'), - url(r'^(?P\d+)/bagit_profiles/add/$', BagItProfileManageView.as_view(), name='bagit-profiles-add'), - url(r'^(?P\d+)/bagit_profiles/(?P\d+)/$', BagItProfileDetailView.as_view(), name='bagit-profiles-detail'), - url(r'^(?P\d+)/bagit_profiles/(?P\d+)/edit$', BagItProfileManageView.as_view(), name='bagit-profiles-edit'), - url(r'^(?P\d+)/bagit_profiles/(?P\d+)/(?P(delete))/$', BagItProfileAPIAdminView.as_view(), name='bagit-profiles-api'), +urlpatterns = [ + url(r"^add/$", OrganizationCreateView.as_view(), name="add"), + url(r"^(?P\d+)/$", OrganizationDetailView.as_view(), name="detail"), + url(r"^$", OrganizationListView.as_view(), name="list"), + url(r"^(?P\d+)/edit/$", OrganizationEditView.as_view(), name="edit"), + url( + r"^(?P\d+)/bagit_profiles/add/$", + BagItProfileManageView.as_view(), + name="bagit-profiles-add", + ), + url( + r"^(?P\d+)/bagit_profiles/(?P\d+)/$", + BagItProfileDetailView.as_view(), + name="bagit-profiles-detail", + ), + url( + r"^(?P\d+)/bagit_profiles/(?P\d+)/edit$", + BagItProfileManageView.as_view(), + name="bagit-profiles-edit", + ), + url( + r"^(?P\d+)/bagit_profiles/(?P\d+)/(?P(delete))/$", + BagItProfileAPIAdminView.as_view(), + name="bagit-profiles-api", + ), ] diff --git a/aurora/bag_transfer/orgs/views.py b/aurora/bag_transfer/orgs/views.py index 2ea4fa59..f0097c73 100644 --- a/aurora/bag_transfer/orgs/views.py +++ b/aurora/bag_transfer/orgs/views.py @@ -1,208 +1,312 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from decimal import * +from decimal import Decimal from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.http import Http404 from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse -from django.views.generic import ListView, UpdateView, CreateView, DetailView, TemplateView +from django.views.generic import ( + ListView, + UpdateView, + CreateView, + DetailView, + TemplateView, +) -from bag_transfer.models import Archives, Organization, User, BagItProfile -from bag_transfer.orgs.form import * -from bag_transfer.mixins.authmixins import * +from bag_transfer.models import Archives, Organization, BagItProfile +from bag_transfer.orgs.form import ( + AcceptSerializationFormset, + AcceptBagItVersionFormset, + BagItProfileForm, + BagItProfileBagInfoFormset, + ManifestsAllowedFormset, + ManifestsRequiredFormset, + TagFilesRequiredFormset, + TagManifestsRequiredFormset, +) +from bag_transfer.mixins.authmixins import ( + ArchivistMixin, + ManagingArchivistMixin, + OrgReadViewMixin, +) from bag_transfer.mixins.formatmixins import JSONResponseMixin class OrganizationCreateView(ManagingArchivistMixin, SuccessMessageMixin, CreateView): - template_name = 'orgs/create.html' + template_name = "orgs/create.html" model = Organization - fields = ['name', 'acquisition_type'] + fields = ["name", "acquisition_type"] success_message = "New Organization Saved!" def get_context_data(self, **kwargs): context = super(CreateView, self).get_context_data(**kwargs) - context['meta_page_title'] = 'Add Organization' - context['acquisition_types'] = Organization.ACQUISITION_TYPE_CHOICES + context["meta_page_title"] = "Add Organization" + context["acquisition_types"] = Organization.ACQUISITION_TYPE_CHOICES return context def get_success_url(self): - return reverse('orgs:detail', kwargs={'pk': self.object.pk}) + return reverse("orgs:detail", kwargs={"pk": self.object.pk}) class OrganizationDetailView(OrgReadViewMixin, DetailView): - template_name = 'orgs/detail.html' + template_name = "orgs/detail.html" model = Organization def get_context_data(self, **kwargs): context = super(OrganizationDetailView, self).get_context_data(**kwargs) - context['meta_page_title'] = self.object.name - context['uploads'] = [] - archives = Archives.objects.filter(process_status__gte=Archives.TRANSFER_COMPLETED, - organization=context['object']).order_by('-created_time')[:8] + context["meta_page_title"] = self.object.name + context["uploads"] = [] + archives = Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, + organization=context["object"], + ).order_by("-created_time")[:8] for archive in archives: archive.bag_info_data = archive.get_bag_data() - context['uploads'].append(archive) - context['uploads_count'] = Archives.objects.filter(process_status__gte=Archives.TRANSFER_COMPLETED, - organization=context['object']).count() + context["uploads"].append(archive) + context["uploads_count"] = Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, + organization=context["object"], + ).count() return context class OrganizationEditView(ManagingArchivistMixin, SuccessMessageMixin, UpdateView): - template_name = 'orgs/update.html' + template_name = "orgs/update.html" model = Organization - fields = ['is_active', 'name', 'acquisition_type'] + fields = ["is_active", "name", "acquisition_type"] success_message = "Organization Saved!" def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(**kwargs) - context['meta_page_title'] = 'Edit Organization' - context['acquisition_types'] = Organization.ACQUISITION_TYPE_CHOICES + context["meta_page_title"] = "Edit Organization" + context["acquisition_types"] = Organization.ACQUISITION_TYPE_CHOICES return context def get_success_url(self): - return reverse('orgs:detail', kwargs={'pk': self.object.pk}) + return reverse("orgs:detail", kwargs={"pk": self.object.pk}) class OrganizationListView(ArchivistMixin, ListView): - template_name = 'orgs/list.html' + template_name = "orgs/list.html" model = Organization def get_context_data(self, **kwargs): context = super(OrganizationListView, self).get_context_data(**kwargs) - context['meta_page_title'] = 'Organizations' + context["meta_page_title"] = "Organizations" return context class BagItProfileManageView(TemplateView): - template_name = 'bagit_profiles/manage.html' + template_name = "bagit_profiles/manage.html" model = BagItProfile def get(self, request, *args, **kwargs): - applies_to_organization = Organization.objects.get(pk=self.kwargs.get('pk')) + applies_to_organization = Organization.objects.get(pk=self.kwargs.get("pk")) source_organization = self.request.user.organization profile = None - if 'profile_pk' in kwargs: - profile = get_object_or_404(BagItProfile, pk=self.kwargs.get('profile_pk')) + if "profile_pk" in kwargs: + profile = get_object_or_404(BagItProfile, pk=self.kwargs.get("profile_pk")) form = BagItProfileForm(instance=profile) else: form = BagItProfileForm( initial={ - 'applies_to_organization': applies_to_organization, - 'source_organization': source_organization, - 'contact_email': 'archive@rockarch.org', + "applies_to_organization": applies_to_organization, + "source_organization": source_organization, + "contact_email": "archive@rockarch.org", } ) - bag_info_formset = BagItProfileBagInfoFormset(instance=profile, prefix='bag_info') - manifests_formset = ManifestsRequiredFormset(instance=profile, prefix='manifests') - serialization_formset = AcceptSerializationFormset(instance=profile, prefix='serialization') - version_formset = AcceptBagItVersionFormset(instance=profile, prefix='version') - tag_manifests_formset = TagManifestsRequiredFormset(instance=profile, prefix='tag_manifests') - tag_files_formset = TagFilesRequiredFormset(instance=profile, prefix='tag_files') - return render(request, self.template_name, { - 'form': form, - 'bag_info_formset': bag_info_formset, - 'manifests_formset': manifests_formset, - 'serialization_formset': serialization_formset, - 'version_formset': version_formset, - 'tag_manifests_formset': tag_manifests_formset, - 'tag_files_formset': tag_files_formset, - 'meta_page_title': 'BagIt Profile', - 'organization': applies_to_organization, - }) + bag_info_formset = BagItProfileBagInfoFormset( + instance=profile, prefix="bag_info" + ) + manifests_allowed_formset = ManifestsAllowedFormset( + instance=profile, prefix="manifests_allowed" + ) + manifests_formset = ManifestsRequiredFormset( + instance=profile, prefix="manifests" + ) + serialization_formset = AcceptSerializationFormset( + instance=profile, prefix="serialization" + ) + version_formset = AcceptBagItVersionFormset(instance=profile, prefix="version") + tag_manifests_formset = TagManifestsRequiredFormset( + instance=profile, prefix="tag_manifests" + ) + tag_files_formset = TagFilesRequiredFormset( + instance=profile, prefix="tag_files" + ) + return render( + request, + self.template_name, + { + "form": form, + "bag_info_formset": bag_info_formset, + "manifests_allowed_formset": manifests_allowed_formset, + "manifests_formset": manifests_formset, + "serialization_formset": serialization_formset, + "version_formset": version_formset, + "tag_manifests_formset": tag_manifests_formset, + "tag_files_formset": tag_files_formset, + "meta_page_title": "BagIt Profile", + "organization": applies_to_organization, + }, + ) def post(self, request, *args, **kwargs): instance = None - organization = Organization.objects.get(pk=self.kwargs.get('pk')) - if self.kwargs.get('profile_pk'): - instance = get_object_or_404(BagItProfile, pk=self.kwargs.get('profile_pk')) + organization = Organization.objects.get(pk=self.kwargs.get("pk")) + if self.kwargs.get("profile_pk"): + instance = get_object_or_404(BagItProfile, pk=self.kwargs.get("profile_pk")) form = BagItProfileForm(request.POST, instance=instance) if form.is_valid(): if BagItProfile.objects.filter( - applies_to_organization=form.cleaned_data['applies_to_organization'], - contact_email=form.cleaned_data['contact_email'], - source_organization=form.cleaned_data['source_organization'], - version=form.cleaned_data['version'], - bagit_profile_identifier=form.cleaned_data['bagit_profile_identifier'], - external_description=form.cleaned_data['external_description'], - serialization=form.cleaned_data['serialization'], - ).exists(): + applies_to_organization=form.cleaned_data["applies_to_organization"], + contact_email=form.cleaned_data["contact_email"], + source_organization=form.cleaned_data["source_organization"], + version=form.cleaned_data["version"], + bagit_profile_identifier=form.cleaned_data["bagit_profile_identifier"], + external_description=form.cleaned_data["external_description"], + serialization=form.cleaned_data["serialization"], + ).exists(): bagit_profile = BagItProfile.objects.filter( - applies_to_organization=form.cleaned_data['applies_to_organization'], - contact_email=form.cleaned_data['contact_email'], - source_organization=form.cleaned_data['source_organization'], - version=form.cleaned_data['version'], - bagit_profile_identifier=form.cleaned_data['bagit_profile_identifier'], - external_description=form.cleaned_data['external_description'], - serialization=form.cleaned_data['serialization'], - )[0] + applies_to_organization=form.cleaned_data[ + "applies_to_organization" + ], + contact_email=form.cleaned_data["contact_email"], + source_organization=form.cleaned_data["source_organization"], + version=form.cleaned_data["version"], + bagit_profile_identifier=form.cleaned_data[ + "bagit_profile_identifier" + ], + external_description=form.cleaned_data["external_description"], + serialization=form.cleaned_data["serialization"], + )[0] else: bagit_profile = form.save() - bag_info_formset = BagItProfileBagInfoFormset(request.POST, instance=bagit_profile, prefix='bag_info') - manifests_formset = ManifestsRequiredFormset(request.POST, instance=bagit_profile, prefix='manifests') - serialization_formset = AcceptSerializationFormset(request.POST, instance=bagit_profile, prefix='serialization') - version_formset = AcceptBagItVersionFormset(request.POST, instance=bagit_profile, prefix='version') - tag_manifests_formset = TagManifestsRequiredFormset(request.POST, instance=bagit_profile, prefix='tag_manifests') - tag_files_formset = TagFilesRequiredFormset(request.POST, instance=bagit_profile, prefix='tag_files') - forms_to_save = [bag_info_formset, manifests_formset, serialization_formset, version_formset, tag_manifests_formset, tag_files_formset] + bag_info_formset = BagItProfileBagInfoFormset( + request.POST, instance=bagit_profile, prefix="bag_info" + ) + manifests_allowed_formset = ManifestsAllowedFormset( + request.POST, instance=bagit_profile, prefix="manifests_allowed" + ) + manifests_formset = ManifestsRequiredFormset( + request.POST, instance=bagit_profile, prefix="manifests" + ) + serialization_formset = AcceptSerializationFormset( + request.POST, instance=bagit_profile, prefix="serialization" + ) + version_formset = AcceptBagItVersionFormset( + request.POST, instance=bagit_profile, prefix="version" + ) + tag_manifests_formset = TagManifestsRequiredFormset( + request.POST, instance=bagit_profile, prefix="tag_manifests" + ) + tag_files_formset = TagFilesRequiredFormset( + request.POST, instance=bagit_profile, prefix="tag_files" + ) + forms_to_save = [ + bag_info_formset, + manifests_allowed_formset, + manifests_formset, + serialization_formset, + version_formset, + tag_manifests_formset, + tag_files_formset, + ] for formset in forms_to_save: if not formset.is_valid(): - messages.error(request, "There was a problem with your submission. Please correct the error(s) below and try again.") - return render(request, self.template_name, { - 'organization': bagit_profile.applies_to_organization, - 'form': form, - 'bag_info_formset': bag_info_formset, - 'manifests_formset': manifests_formset, - 'serialization_formset': serialization_formset, - 'version_formset': version_formset, - 'tag_manifests_formset': tag_manifests_formset, - 'tag_files_formset': tag_files_formset, - 'meta_page_title': 'BagIt Profile', - }) + messages.error( + request, + "There was a problem with your submission. Please correct the error(s) below and try again.", + ) + return render( + request, + self.template_name, + { + "organization": bagit_profile.applies_to_organization, + "form": form, + "bag_info_formset": bag_info_formset, + "manifests_allowed_formset": manifests_allowed_formset, + "manifests_formset": manifests_formset, + "serialization_formset": serialization_formset, + "version_formset": version_formset, + "tag_manifests_formset": tag_manifests_formset, + "tag_files_formset": tag_files_formset, + "meta_page_title": "BagIt Profile", + }, + ) for formset in forms_to_save: formset.save() bagit_profile.version = bagit_profile.version + Decimal(1) - bagit_profile.bagit_profile_identifier = request.build_absolute_uri(reverse('bagitprofile-detail', kwargs={'pk': bagit_profile.id, 'format': 'json'})) + bagit_profile.bagit_profile_identifier = request.build_absolute_uri( + reverse( + "bagitprofile-detail", + kwargs={"pk": bagit_profile.id, "format": "json"}, + ) + ) bagit_profile.save() - messages.success(request, 'BagIt Profile for {} saved'.format(bagit_profile.applies_to_organization.name)) - return redirect('orgs:detail', bagit_profile.applies_to_organization.pk) - print form.errors - messages.error(request, "There was a problem with your submission. Please correct the error(s) below and try again.") - return render(request, self.template_name, { - 'form': BagItProfileForm(request.POST, instance=instance), - 'organization': organization, - 'bag_info_formset': BagItProfileBagInfoFormset(request.POST, prefix='bag_info'), - 'manifests_formset': ManifestsRequiredFormset(request.POST, prefix='manifests'), - 'serialization_formset': AcceptSerializationFormset(request.POST, prefix='serialization'), - 'version_formset': AcceptBagItVersionFormset(request.POST, prefix='version'), - 'tag_manifests_formset': TagManifestsRequiredFormset(request.POST, prefix='tag_manifests'), - 'tag_files_formset': TagFilesRequiredFormset(request.POST, prefix='tag_files'), - 'meta_page_title': 'BagIt Profile', - }) + messages.success( + request, + "BagIt Profile for {} saved".format( + bagit_profile.applies_to_organization.name + ), + ) + return redirect("orgs:detail", bagit_profile.applies_to_organization.pk) + print(form.errors) + messages.error( + request, + "There was a problem with your submission. Please correct the error(s) below and try again.", + ) + return render( + request, + self.template_name, + { + "form": BagItProfileForm(request.POST, instance=instance), + "organization": organization, + "bag_info_formset": BagItProfileBagInfoFormset( + request.POST, prefix="bag_info" + ), + "manifests__allowed_formset": ManifestsAllowedFormset( + request.POST, prefix="manifests_allowed" + ), + "manifests_formset": ManifestsRequiredFormset( + request.POST, prefix="manifests" + ), + "serialization_formset": AcceptSerializationFormset( + request.POST, prefix="serialization" + ), + "version_formset": AcceptBagItVersionFormset( + request.POST, prefix="version" + ), + "tag_manifests_formset": TagManifestsRequiredFormset( + request.POST, prefix="tag_manifests" + ), + "tag_files_formset": TagFilesRequiredFormset( + request.POST, prefix="tag_files" + ), + "meta_page_title": "BagIt Profile", + }, + ) class BagItProfileDetailView(ArchivistMixin, DetailView): - template_name = 'bagit_profiles/detail.html' + template_name = "bagit_profiles/detail.html" model = BagItProfile def get_object(self): - return BagItProfile.objects.get(id=self.kwargs['profile_pk']) + return BagItProfile.objects.get(id=self.kwargs["profile_pk"]) class BagItProfileAPIAdminView(ManagingArchivistMixin, JSONResponseMixin, TemplateView): - def render_to_response(self, context, **kwargs): if not self.request.is_ajax(): raise Http404 - resp = {'success': 0} + resp = {"success": 0} - if 'action' in self.kwargs: - obj = get_object_or_404(BagItProfile, pk=context['profile_pk']) - if self.kwargs['action'] == 'delete': + if "action" in self.kwargs: + obj = get_object_or_404(BagItProfile, pk=context["profile_pk"]) + if self.kwargs["action"] == "delete": obj.delete() - resp['success'] = 1 + resp["success"] = 1 return self.render_to_json_response(resp, **kwargs) diff --git a/aurora/bag_transfer/rights/forms.py b/aurora/bag_transfer/rights/forms.py index a6cc3d19..e16b4574 100644 --- a/aurora/bag_transfer/rights/forms.py +++ b/aurora/bag_transfer/rights/forms.py @@ -1,80 +1,109 @@ from django import forms -from django.utils.translation import ugettext, ugettext_lazy as _ -from django.forms.models import inlineformset_factory, formset_factory +from django.forms.models import inlineformset_factory -from bag_transfer.rights.models import * -from bag_transfer.models import Organization +from bag_transfer.rights.models import ( + RightsStatement, + RightsStatementCopyright, + RightsStatementLicense, + RightsStatementOther, + RightsStatementStatute, + RightsStatementRightsGranted, +) class RightsForm(forms.ModelForm): class Meta: model = RightsStatement - fields = ('applies_to_type', 'rights_basis', 'organization') + fields = ("applies_to_type", "rights_basis", "organization") labels = { - 'rights_basis': 'Rights Basis', - 'applies_to_type': 'Applies to Record Type(s)' - } + "rights_basis": "Rights Basis", + "applies_to_type": "Applies to Record Type(s)", + } help_texts = { - 'applies_to_type': 'The record types for which this rights statement applies. If no options are available here, values must first be added in this organization\'s BagIt Profile.' + "applies_to_type": "The record types for which this rights statement applies. If no options are available here, values must first be added in this organization's BagIt Profile." } widgets = { - 'rights_basis': forms.widgets.Select(attrs={'class': 'form-control'}), - 'applies_to_type': forms.widgets.CheckboxSelectMultiple(attrs={'class': 'list-unstyled'}), - 'organization': forms.widgets.HiddenInput() + "rights_basis": forms.widgets.Select(attrs={"class": "form-control"}), + "applies_to_type": forms.widgets.CheckboxSelectMultiple( + attrs={"class": "list-unstyled"} + ), + "organization": forms.widgets.HiddenInput(), } def __init__(self, *args, **kwargs): - applies_to_type_choices = kwargs.pop('applies_to_type_choices', None) - organization = kwargs.pop('organization', None) + applies_to_type_choices = kwargs.pop("applies_to_type_choices", None) + organization = kwargs.pop("organization", None) super(RightsForm, self).__init__(*args, **kwargs) if applies_to_type_choices: - self.fields['applies_to_type'].choices = list(applies_to_type_choices) - self.fields['applies_to_type'].widget.choices = list(applies_to_type_choices) - if 'instance' in kwargs: - self.initial['applies_to_type'] = kwargs['instance'].applies_to_type.all() + self.fields["applies_to_type"].choices = list(applies_to_type_choices) + self.fields["applies_to_type"].widget.choices = list( + applies_to_type_choices + ) + if "instance" in kwargs: + self.initial["applies_to_type"] = kwargs[ + "instance" + ].applies_to_type.all() else: - self.fields['applies_to_type'].choices = [] - self.fields['applies_to_type'].widget.choices = [] + self.fields["applies_to_type"].choices = [] + self.fields["applies_to_type"].widget.choices = [] if organization: - self.initial['organization'] = organization + self.initial["organization"] = organization class RightsGrantedForm(forms.ModelForm): class Meta: model = RightsStatementRightsGranted fields = ( - 'act', 'restriction', 'start_date_period', 'end_date_period', - 'start_date', 'end_date', 'end_date_open', 'rights_granted_note') + "act", + "restriction", + "start_date_period", + "end_date_period", + "start_date", + "end_date", + "end_date_open", + "rights_granted_note", + ) labels = { - 'act': 'Act', - 'restriction': 'Restriction(s)', - 'start_date': 'Start Date', - 'end_date': 'End Date', - 'start_date_period': 'Years After Start Date', - 'end_date_period': 'Years After End Date', - 'end_date_open': 'Open end date?', - 'rights_granted_note': 'Note' - } + "act": "Act", + "restriction": "Restriction(s)", + "start_date": "Start Date", + "end_date": "End Date", + "start_date_period": "Years After Start Date", + "end_date_period": "Years After End Date", + "end_date_open": "Open end date?", + "rights_granted_note": "Note", + } help_texts = { - 'act': "The action the preservation repository is allowed to take; eg. replicate, migrate, modify, use, disseminate, delete.", + "act": "The action the preservation repository is allowed to take; eg. replicate, migrate, modify, use, disseminate, delete.", # 'start_date': "The beginning date of the rights or restrictions Use 'Start Date Period' for dates which should be calculated based on dates of each transfer.", # 'end_date': "The ending date of the rights or restrictions. Use 'End Date Period' for dates which should be calculated based on dates of each transfer.", # 'start_date_period': "The number of years after the start date when this grant or restriction begins to apply. Will be used to calculate date ranges based on dates for each transfer.", # 'end_date_period': "The number of years after the end date when this grant or restriction no longer applies. Will be used to calculate date ranges based on dates for each transfer.", - 'end_date_open': "Select if this grant or restriction applies in perpetuity.", - 'rights_granted_note': "A prose description of the action or restriction." - } + "end_date_open": "Select if this grant or restriction applies in perpetuity.", + "rights_granted_note": "A prose description of the action or restriction.", + } widgets = { - 'act': forms.widgets.Select(attrs={'class': 'form-control'}), - 'restriction': forms.widgets.Select(attrs={'class': 'form-control'}), - 'start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'start_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'end_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'rights_granted_note': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), } + "act": forms.widgets.Select(attrs={"class": "form-control"}), + "restriction": forms.widgets.Select(attrs={"class": "form-control"}), + "start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "start_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "end_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "rights_granted_note": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + } class RightsBasisForm(forms.ModelForm): @@ -87,155 +116,226 @@ class RightsCopyrightForm(RightsBasisForm): class Meta: model = RightsStatementCopyright fields = ( - 'copyright_status', 'copyright_jurisdiction', - 'copyright_status_determination_date', 'copyright_start_date_period', - 'copyright_end_date_period', 'copyright_applicable_start_date', - 'copyright_applicable_end_date', 'copyright_end_date_open', 'copyright_note' - ) + "copyright_status", + "copyright_jurisdiction", + "copyright_status_determination_date", + "copyright_start_date_period", + "copyright_end_date_period", + "copyright_applicable_start_date", + "copyright_applicable_end_date", + "copyright_end_date_open", + "copyright_note", + ) labels = { - 'copyright_status': 'Copyright Status', - 'copyright_jurisdiction': 'Copyright Jurisdiction', - 'copyright_status_determination_date': 'Copyright Status Determination Date', - 'copyright_applicable_start_date': 'Start Date', - 'copyright_applicable_end_date': 'End Date', - 'copyright_start_date_period': 'Years After Start Date', - 'copyright_end_date_period': 'Years After End Date', - 'copyright_end_date_open': 'Open end date?', - 'copyright_note': 'Note' - } + "copyright_status": "Copyright Status", + "copyright_jurisdiction": "Copyright Jurisdiction", + "copyright_status_determination_date": "Copyright Status Determination Date", + "copyright_applicable_start_date": "Start Date", + "copyright_applicable_end_date": "End Date", + "copyright_start_date_period": "Years After Start Date", + "copyright_end_date_period": "Years After End Date", + "copyright_end_date_open": "Open end date?", + "copyright_note": "Note", + } help_texts = { - 'copyright_status': "A coded designation of the copyright status of the object at the time the rights statement is recorded.", - 'copyright_jurisdiction': "The country whose copyright laws apply. Use values from ISO 3166.", - 'copyright_status_determination_date': "The date that the copyright status recorded in 'copyright status' was determined.", + "copyright_status": "A coded designation of the copyright status of the object at the time the rights statement is recorded.", + "copyright_jurisdiction": "The country whose copyright laws apply. Use values from ISO 3166.", + "copyright_status_determination_date": "The date that the copyright status recorded in 'copyright status' was determined.", # 'copyright_applicable_start_date': "The date when this copyright begins to apply. Use 'Start Date Period' for dates which should be calculated based on dates of each transfer.", # 'copyright_applicable_end_date': "The date when this copyright no longer applies. Use 'End Date Period' for dates which should be calculated based on dates of each transfer.", # 'copyright_start_date_period': "The number of years after the start date when copyright begins to apply. Will be used to calculate date ranges based on dates for each transfer.", # 'copyright_end_date_period': "The number of years after the end date when copyright no longer applies. Will be used to calculate date ranges based on dates for each transfer.", - 'copyright_end_date_open': "Select if this copyright applies in perpetuity.", - 'copyright_note': "A prose description of the copyright." - } + "copyright_end_date_open": "Select if this copyright applies in perpetuity.", + "copyright_note": "A prose description of the copyright.", + } widgets = { - 'copyright_status': forms.widgets.Select(attrs={'class': 'form-control'}), - 'copyright_jurisdiction': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'copyright_status_determination_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'copyright_applicable_start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'copyright_applicable_end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'copyright_start_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control', }), - 'copyright_end_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control', }), - 'copyright_note': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), } + "copyright_status": forms.widgets.Select(attrs={"class": "form-control"}), + "copyright_jurisdiction": forms.widgets.TextInput( + attrs={"class": "form-control"} + ), + "copyright_status_determination_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "copyright_applicable_start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "copyright_applicable_end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "copyright_start_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "copyright_end_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "copyright_note": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + } class RightsStatuteForm(RightsBasisForm): class Meta: model = RightsStatementStatute fields = ( - 'statute_jurisdiction', 'statute_citation', 'statute_determination_date', - 'statute_start_date_period', 'statute_end_date_period', - 'statute_applicable_start_date', 'statute_applicable_end_date', - 'statute_end_date_open', 'statute_note' - ) + "statute_jurisdiction", + "statute_citation", + "statute_determination_date", + "statute_start_date_period", + "statute_end_date_period", + "statute_applicable_start_date", + "statute_applicable_end_date", + "statute_end_date_open", + "statute_note", + ) labels = { - 'statute_jurisdiction': 'Statute Jurisdiction', - 'statute_citation': 'Statute Citation', - 'statute_determination_date': 'Statute Determination Date', - 'statute_applicable_start_date': 'Start Date', - 'statute_applicable_end_date': 'End Date', - 'statute_start_date_period': 'Years After Start Date', - 'statute_end_date_period': 'Years After End Date', - 'statute_end_date_open': 'Open end date?', - 'statute_note': 'Note' - } + "statute_jurisdiction": "Statute Jurisdiction", + "statute_citation": "Statute Citation", + "statute_determination_date": "Statute Determination Date", + "statute_applicable_start_date": "Start Date", + "statute_applicable_end_date": "End Date", + "statute_start_date_period": "Years After Start Date", + "statute_end_date_period": "Years After End Date", + "statute_end_date_open": "Open end date?", + "statute_note": "Note", + } help_texts = { - 'statute_jurisdiction': "The country or other political body enacting the statute.", - 'statute_citation': "An identifying designation for the statute.", - 'statute_determination_date': "The date that the determination was made that the statue authorized the permission(s) noted.", + "statute_jurisdiction": "The country or other political body enacting the statute.", + "statute_citation": "An identifying designation for the statute.", + "statute_determination_date": "The date that the determination was made that the statue authorized the permission(s) noted.", # 'statute_applicable_start_date': "The date when the statute begins to apply. Use 'Start Date Period' for dates which should be calculated based on dates of each transfer.", # 'statute_applicable_end_date': "The date when the statute ceasees to apply. Use 'End Date Period' for dates which should be calculated based on dates of each transfer.", # 'statute_start_date_period': "The number of years after the start date when the statute begins to apply. Will be used to calculate date ranges based on dates for each transfer", # 'statute_end_date_period': "The number of years after the end date when the statute no longer applies. Will be used to calculate date ranges based on dates for each transfer", - 'statute_end_date_open': "Select if this statute applies in perpetuity.", - 'statute_note': "A prose description of the statute." - } + "statute_end_date_open": "Select if this statute applies in perpetuity.", + "statute_note": "A prose description of the statute.", + } widgets = { - 'statute_jurisdiction': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'statute_citation': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'statute_determination_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'statute_applicable_start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'statute_applicable_end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'statute_start_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'statute_end_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'statute_note': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}) } + "statute_jurisdiction": forms.widgets.TextInput( + attrs={"class": "form-control"} + ), + "statute_citation": forms.widgets.TextInput( + attrs={"class": "form-control"} + ), + "statute_determination_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "statute_applicable_start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "statute_applicable_end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "statute_start_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "statute_end_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "statute_note": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + } class RightsOtherRightsForm(RightsBasisForm): class Meta: model = RightsStatementOther fields = ( - 'other_rights_basis', 'other_rights_start_date_period', - 'other_rights_end_date_period', 'other_rights_applicable_start_date', - 'other_rights_applicable_end_date', 'other_rights_end_date_open', - 'other_rights_note' - ) + "other_rights_basis", + "other_rights_start_date_period", + "other_rights_end_date_period", + "other_rights_applicable_start_date", + "other_rights_applicable_end_date", + "other_rights_end_date_open", + "other_rights_note", + ) labels = { - 'other_rights_basis': 'Other Rights Basis', - 'other_rights_applicable_start_date': 'Start Date', - 'other_rights_applicable_end_date': 'End Date', - 'other_rights_start_date_period': 'Years After Start Date', - 'other_rights_end_date_period': 'Years After End Date', - 'other_rights_end_date_open': 'Open end date?', - 'other_rights_note': 'Note' - } + "other_rights_basis": "Other Rights Basis", + "other_rights_applicable_start_date": "Start Date", + "other_rights_applicable_end_date": "End Date", + "other_rights_start_date_period": "Years After Start Date", + "other_rights_end_date_period": "Years After End Date", + "other_rights_end_date_open": "Open end date?", + "other_rights_note": "Note", + } help_texts = { - 'other_rights_basis': "The designation of the basis for the rights or permission described in the rights statement identifier.", + "other_rights_basis": "The designation of the basis for the rights or permission described in the rights statement identifier.", # 'other_rights_applicable_start_date': "The date when the rights begins to apply. Use 'Start Date Period' for dates which should be calculated based on dates of each transfer.", # 'other_rights_applicable_end_date': "The date when the rights no longer applies. Use 'End Date Period' for dates which should be calculated based on dates of each transfer.", # 'other_rights_start_date_period': "The number of years after the start date when these rights begin to apply. Will be used to calculate date ranges based on dates for each transfer.", # 'other_rights_end_date_period': "The number of years after the end date when these rights no longer apply. Will be used to calculate date ranges based on dates for each transfer.", - 'other_rights_end_date_open': "Select if these rights apply in perpetuity.", - 'other_rights_note': "A prose description of the rights." - } + "other_rights_end_date_open": "Select if these rights apply in perpetuity.", + "other_rights_note": "A prose description of the rights.", + } widgets = { - 'other_rights_basis': forms.widgets.Select(attrs={'class': 'form-control'}), - 'other_rights_applicable_start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'other_rights_applicable_end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'other_rights_start_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'other_rights_end_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'other_rights_note': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}) - } + "other_rights_basis": forms.widgets.Select(attrs={"class": "form-control"}), + "other_rights_applicable_start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "other_rights_applicable_end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "other_rights_start_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "other_rights_end_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "other_rights_note": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + } class RightsLicenseForm(RightsBasisForm): class Meta: model = RightsStatementLicense fields = ( - 'license_terms', 'license_start_date_period', - 'license_end_date_period', 'license_applicable_start_date', - 'license_applicable_end_date', 'license_end_date_open', 'license_note' - ) + "license_terms", + "license_start_date_period", + "license_end_date_period", + "license_applicable_start_date", + "license_applicable_end_date", + "license_end_date_open", + "license_note", + ) labels = { - 'license_terms': 'Licence Terms', - 'license_applicable_start_date': 'Start Date', - 'license_applicable_end_date': 'End Date', - 'license_start_date_period': 'Years After Start Date', - 'license_end_date_period': 'Years After End Date', - 'license_end_date_open': 'Open end date?', - 'license_note': 'Note', + "license_terms": "Licence Terms", + "license_applicable_start_date": "Start Date", + "license_applicable_end_date": "End Date", + "license_start_date_period": "Years After Start Date", + "license_end_date_period": "Years After End Date", + "license_end_date_open": "Open end date?", + "license_note": "Note", } help_texts = { - 'license_terms': "Text describing the license or agreement by which permission was granted.", + "license_terms": "Text describing the license or agreement by which permission was granted.", # 'license_applicable_start_date': "The date when the license begins to apply. Use 'Start Date Period' for dates which should be calculated based on dates of each transfer.", # 'license_applicable_end_date': "The end date when the license no longer applies. Use 'End Date Period' for dates which should be calculated based on dates of each transfer.", # 'license_start_date_period': "The number of years after the start date when the license begins to apply. Will be used to calculate date ranges based on dates for each transfer.", # 'license_end_date_period': "The number of years after the end date when this license no longer applies. Will be used to calculate date ranges based on dates for each transfer.", - 'license_end_date_open': "Select if this license applies in perpetuity.", - 'license_note': "A prose description of the license."} + "license_end_date_open": "Select if this license applies in perpetuity.", + "license_note": "A prose description of the license.", + } widgets = { - 'license_terms': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'license_applicable_start_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'license_applicable_end_date': forms.widgets.DateInput(attrs={'class': 'form-control', 'type':'date'}), - 'license_start_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'license_end_date_period': forms.widgets.NumberInput(attrs={'class': 'form-control'}), - 'license_note': forms.widgets.Textarea(attrs={'class': 'form-control', 'rows': 3}), } + "license_terms": forms.widgets.TextInput(attrs={"class": "form-control"}), + "license_applicable_start_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "license_applicable_end_date": forms.widgets.DateInput( + attrs={"class": "form-control", "type": "date"} + ), + "license_start_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "license_end_date_period": forms.widgets.NumberInput( + attrs={"class": "form-control"} + ), + "license_note": forms.widgets.Textarea( + attrs={"class": "form-control", "rows": 3} + ), + } # create inline formsets for child elements @@ -254,7 +354,7 @@ class Meta: extra=1, max_num=1, can_delete=False, - form=RightsStatuteForm + form=RightsStatuteForm, ) LicenseFormSet = inlineformset_factory( @@ -263,7 +363,7 @@ class Meta: extra=1, max_num=1, can_delete=False, - form=RightsLicenseForm + form=RightsLicenseForm, ) OtherFormSet = inlineformset_factory( @@ -272,7 +372,7 @@ class Meta: extra=1, max_num=1, can_delete=False, - form=RightsOtherRightsForm + form=RightsOtherRightsForm, ) RightsGrantedFormSet = inlineformset_factory( @@ -280,5 +380,5 @@ class Meta: RightsStatementRightsGranted, extra=1, max_num=1, - form=RightsGrantedForm + form=RightsGrantedForm, ) diff --git a/aurora/bag_transfer/rights/models.py b/aurora/bag_transfer/rights/models.py index f4002352..2c40cdb5 100644 --- a/aurora/bag_transfer/rights/models.py +++ b/aurora/bag_transfer/rights/models.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from datetime import datetime from django.db import models @@ -13,35 +10,44 @@ # https://github.com/artefactual/archivematica/blob/stable/1.6.x/src/dashboard/src/main/models.py#L475-L675 class RecordType(models.Model): class Meta: - ordering = ['name'] + ordering = ["name"] name = models.CharField(max_length=100) - def __unicode__(self): return self.name + def __str__(self): + return self.name class RightsStatement(models.Model): - organization = models.ForeignKey(Organization) - archive = models.ForeignKey(Archives, null=True, blank=True) - accession = models.ForeignKey(Accession, null=True, blank=True, related_name="rights_statements") + organization = models.ForeignKey(Organization, on_delete=models.CASCADE) + archive = models.ForeignKey( + Archives, null=True, blank=True, on_delete=models.CASCADE + ) + accession = models.ForeignKey( + Accession, + null=True, + blank=True, + on_delete=models.CASCADE, + related_name="rights_statements", + ) applies_to_type = models.ManyToManyField(RecordType) RIGHTS_BASIS_CHOICES = ( - ('Copyright', 'Copyright'), - ('Statute', 'Statute'), - ('License', 'License'), - ('Other', 'Other') + ("Copyright", "Copyright"), + ("Statute", "Statute"), + ("License", "License"), + ("Other", "Other"), ) rights_basis = models.CharField(choices=RIGHTS_BASIS_CHOICES, max_length=64) - def __unicode__(self): - return '{}: {}'.format(self.organization, self.rights_basis) + def __str__(self): + return "{}: {}".format(self.organization, self.rights_basis) def get_rights_info_object(self): - if self.rights_basis == 'Copyright': + if self.rights_basis == "Copyright": data = RightsStatementCopyright.objects.get(rights_statement=self.pk) - elif self.rights_basis == 'License': + elif self.rights_basis == "License": data = RightsStatementLicense.objects.get(rights_statement=self.pk) - elif self.rights_basis == 'Statute': + elif self.rights_basis == "Statute": data = RightsStatementStatute.objects.get(rights_statement=self.pk) else: data = RightsStatementOther.objects.get(rights_statement=self.pk) @@ -53,29 +59,36 @@ def get_rights_granted_objects(self): def get_table_data(self): data = {} rights_info = self.get_rights_info_object() - data['notes'] = ', '.join([value for key, value in rights_info.__dict__.items() if '_note' in key.lower()]) + data["notes"] = ", ".join( + [ + value + for key, value in list(rights_info.__dict__.items()) + if "_note" in key.lower() + ] + ) return data def get_date_keys(self): - if self.rights_basis == 'Other': - start_date_key = 'other_rights_applicable_start_date' - end_date_key = 'other_rights_applicable_end_date' + if self.rights_basis == "Other": + start_date_key = "other_rights_applicable_start_date" + end_date_key = "other_rights_applicable_end_date" else: - start_date_key = '{}_applicable_start_date'.format(self.rights_basis.lower()) - end_date_key = '{}_applicable_end_date'.format(self.rights_basis.lower()) - return {'start': start_date_key, 'end': end_date_key} + start_date_key = "{}_applicable_start_date".format( + self.rights_basis.lower() + ) + end_date_key = "{}_applicable_end_date".format(self.rights_basis.lower()) + return {"start": start_date_key, "end": end_date_key} @staticmethod def merge_rights(statement_list): - def merge_dates(merge_list, dates, merge_to): start_dates = [] end_dates = [] for merge_item in merge_list: - start_dates.append(getattr(merge_item, dates['start'])) - end_dates.append(getattr(merge_item, dates['end'])) - setattr(merge_to, dates['start'], sorted(start_dates)[0]) - setattr(merge_to, dates['end'], sorted(end_dates)[-1]) + start_dates.append(getattr(merge_item, dates["start"])) + end_dates.append(getattr(merge_item, dates["end"])) + setattr(merge_to, dates["start"], sorted(start_dates)[0]) + setattr(merge_to, dates["end"], sorted(end_dates)[-1]) statements_by_type = {} merged_statements = [] @@ -97,16 +110,33 @@ def merge_dates(merge_list, dates, merge_to): rights_info_to_merge.append(statement.get_rights_info_object()) rights_granted_objects = statement.get_rights_granted_objects() for rights_granted in rights_granted_objects: - if not '{}{}'.format(rights_granted.act, rights_granted.restriction) in rights_granted_groups: - rights_granted_groups['{}{}'.format(rights_granted.act, rights_granted.restriction)] = [] - rights_granted_groups['{}{}'.format(rights_granted.act, rights_granted.restriction)].append(rights_granted) + if ( + not "{}{}".format( + rights_granted.act, rights_granted.restriction + ) + in rights_granted_groups + ): + rights_granted_groups[ + "{}{}".format( + rights_granted.act, rights_granted.restriction + ) + ] = [] + rights_granted_groups[ + "{}{}".format( + rights_granted.act, rights_granted.restriction + ) + ].append(rights_granted) date_keys = merged_statement.get_date_keys() merge_dates(rights_info_to_merge, date_keys, merged_rights_info) for granted_group in rights_granted_groups: merged_group = rights_granted_groups[granted_group][0] - merge_dates(rights_granted_groups[granted_group], {'start':'start_date','end':'end_date'}, merged_group) + merge_dates( + rights_granted_groups[granted_group], + {"start": "start_date", "end": "end_date"}, + merged_group, + ) merged_rights_granted.append(merged_group) # Save statement @@ -130,25 +160,31 @@ def merge_dates(merge_list, dates, merge_to): class RightsStatementCopyright(models.Model): - rights_statement = models.ForeignKey(RightsStatement) + rights_statement = models.ForeignKey(RightsStatement, on_delete=models.CASCADE) PREMIS_COPYRIGHT_STATUSES = ( - ('copyrighted', 'copyrighted'), - ('public domain', 'public domain'), - ('unknown', 'unknown'), + ("copyrighted", "copyrighted"), + ("public domain", "public domain"), + ("unknown", "unknown"), + ) + copyright_status = models.CharField( + choices=PREMIS_COPYRIGHT_STATUSES, default="unknown", max_length=64 + ) + copyright_jurisdiction = models.CharField(max_length=2, default="us") + copyright_status_determination_date = models.DateField( + blank=True, null=True, default=datetime.now ) - copyright_status = models.CharField(choices=PREMIS_COPYRIGHT_STATUSES, default='unknown', max_length=64) - copyright_jurisdiction = models.CharField(max_length=2, default='us') - copyright_status_determination_date = models.DateField(blank=True, null=True, default=datetime.now) copyright_applicable_start_date = models.DateField(blank=True, null=True) copyright_applicable_end_date = models.DateField(blank=True, null=True) - copyright_start_date_period = models.PositiveSmallIntegerField(blank=True, null=True) + copyright_start_date_period = models.PositiveSmallIntegerField( + blank=True, null=True + ) copyright_end_date_period = models.PositiveSmallIntegerField(blank=True, null=True) copyright_end_date_open = models.BooleanField(default=False) copyright_note = models.TextField() class RightsStatementLicense(models.Model): - rights_statement = models.ForeignKey(RightsStatement) + rights_statement = models.ForeignKey(RightsStatement, on_delete=models.CASCADE) license_terms = models.TextField(blank=True, null=True) license_applicable_start_date = models.DateField(blank=True, null=True) license_applicable_end_date = models.DateField(blank=True, null=True) @@ -159,15 +195,15 @@ class RightsStatementLicense(models.Model): class RightsStatementRightsGranted(models.Model): - rights_statement = models.ForeignKey(RightsStatement) + rights_statement = models.ForeignKey(RightsStatement, on_delete=models.CASCADE) ACT_CHOICES = ( - ('publish', 'Publish'), - ('disseminate', 'Disseminate'), - ('replicate', 'Replicate'), - ('migrate', 'Migrate'), - ('modify', 'Modify'), - ('use', 'Use'), - ('delete', 'Delete'), + ("publish", "Publish"), + ("disseminate", "Disseminate"), + ("replicate", "Replicate"), + ("migrate", "Migrate"), + ("modify", "Modify"), + ("use", "Use"), + ("delete", "Delete"), ) act = models.CharField(choices=ACT_CHOICES, max_length=64) start_date = models.DateField(blank=True, null=True) @@ -177,19 +213,19 @@ class RightsStatementRightsGranted(models.Model): end_date_open = models.BooleanField(default=False) rights_granted_note = models.TextField(blank=True, null=True) RESTRICTION_CHOICES = ( - ('allow', 'Allow'), - ('disallow', 'Disallow'), - ('conditional', 'Conditional'), + ("allow", "Allow"), + ("disallow", "Disallow"), + ("conditional", "Conditional"), ) restriction = models.CharField(choices=RESTRICTION_CHOICES, max_length=64) - def __unicode__(self): - return '{}: {}'.format(self.act, self.restriction) + def __str__(self): + return "{}: {}".format(self.act, self.restriction) class RightsStatementStatute(models.Model): - rights_statement = models.ForeignKey(RightsStatement) - statute_jurisdiction = models.CharField(max_length=2, default='us') + rights_statement = models.ForeignKey(RightsStatement, on_delete=models.CASCADE) + statute_jurisdiction = models.CharField(max_length=2, default="us") statute_citation = models.TextField() statute_determination_date = models.DateField(blank=True, null=True) statute_applicable_start_date = models.DateField(blank=True, null=True) @@ -201,15 +237,21 @@ class RightsStatementStatute(models.Model): class RightsStatementOther(models.Model): - rights_statement = models.ForeignKey(RightsStatement) + rights_statement = models.ForeignKey(RightsStatement, on_delete=models.CASCADE) OTHER_RIGHTS_BASIS_CHOICES = ( - ('Donor', 'Donor'), - ('Policy', 'Policy'), + ("Donor", "Donor"), + ("Policy", "Policy"), + ) + other_rights_basis = models.CharField( + choices=OTHER_RIGHTS_BASIS_CHOICES, max_length=64 ) - other_rights_basis = models.CharField(choices=OTHER_RIGHTS_BASIS_CHOICES, max_length=64) other_rights_applicable_start_date = models.DateField(blank=True, null=True) other_rights_applicable_end_date = models.DateField(blank=True, null=True) - other_rights_start_date_period = models.PositiveSmallIntegerField(blank=True, null=True) - other_rights_end_date_period = models.PositiveSmallIntegerField(blank=True, null=True) + other_rights_start_date_period = models.PositiveSmallIntegerField( + blank=True, null=True + ) + other_rights_end_date_period = models.PositiveSmallIntegerField( + blank=True, null=True + ) other_rights_end_date_open = models.BooleanField(default=False) other_rights_note = models.TextField() diff --git a/aurora/bag_transfer/rights/urls.py b/aurora/bag_transfer/rights/urls.py index 24c97838..08276eaa 100644 --- a/aurora/bag_transfer/rights/urls.py +++ b/aurora/bag_transfer/rights/urls.py @@ -1,11 +1,17 @@ from django.conf.urls import url, include -from bag_transfer.rights.views import * +from bag_transfer.rights.views import ( + RightsAPIAdminView, + RightsDetailView, + RightsManageView, +) -urlpatterns = [ - - url(r'^add/$', RightsManageView.as_view(), name='add'), - url(r'^(?P\d+)/$', RightsDetailView.as_view(), name='detail'), - url(r'^(?P\d+)/edit$', RightsManageView.as_view(), name='edit'), - url(r'^(?P\d+)/(?P(delete))/$', RightsAPIAdminView.as_view(), name='api'), +app_name = 'rights' +urlpatterns = [ + url(r"^add/$", RightsManageView.as_view(), name="add"), + url(r"^(?P\d+)/$", RightsDetailView.as_view(), name="detail"), + url(r"^(?P\d+)/edit$", RightsManageView.as_view(), name="edit"), + url( + r"^(?P\d+)/(?P(delete))/$", RightsAPIAdminView.as_view(), name="api" + ), ] diff --git a/aurora/bag_transfer/rights/views.py b/aurora/bag_transfer/rights/views.py index 2209ac4e..f9178c48 100644 --- a/aurora/bag_transfer/rights/views.py +++ b/aurora/bag_transfer/rights/views.py @@ -1,36 +1,44 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.http import Http404 from django.contrib import messages -from django.views.generic import CreateView, UpdateView, DetailView, TemplateView -from django.shortcuts import render, redirect, render_to_response, get_object_or_404 - -from bag_transfer.models import BagItProfile, BagItProfileBagInfo, BagItProfileBagInfoValues -from bag_transfer.rights.models import * -from bag_transfer.rights.forms import * -from bag_transfer.mixins.authmixins import * +from django.views.generic import CreateView, DetailView, TemplateView +from django.shortcuts import render, redirect, get_object_or_404 + +from bag_transfer.models import ( + BagItProfile, + BagItProfileBagInfo, + BagItProfileBagInfoValues, + Organization, +) +from bag_transfer.rights.models import RecordType, RightsStatement +from bag_transfer.rights.forms import CopyrightFormSet, LicenseFormSet, StatuteFormSet, OtherFormSet, RightsGrantedFormSet, RightsForm +from bag_transfer.mixins.authmixins import ManagingArchivistMixin, OrgReadViewMixin from bag_transfer.mixins.formatmixins import JSONResponseMixin class RightsManageView(ManagingArchivistMixin, CreateView): - template_name = 'rights/manage.html' + template_name = "rights/manage.html" model = RightsStatement form_class = RightsForm def get_formset(self, rights_basis): - if rights_basis == 'Copyright': + if rights_basis == "Copyright": return {"key": "copyright_form", "class": CopyrightFormSet} - elif rights_basis == 'License': + elif rights_basis == "License": return {"key": "license_form", "class": LicenseFormSet} - elif rights_basis == 'Statute': + elif rights_basis == "Statute": return {"key": "statute_form", "class": StatuteFormSet} else: return {"key": "other_form", "class": OtherFormSet} def get_applies_to_type_choices(self, organization): values = BagItProfileBagInfoValues.objects.filter( - bagit_profile_baginfo__in=BagItProfileBagInfo.objects.filter(bagit_profile__in=BagItProfile.objects.filter(applies_to_organization=organization), field='record_type')) + bagit_profile_baginfo__in=BagItProfileBagInfo.objects.filter( + bagit_profile__in=BagItProfile.objects.filter( + applies_to_organization=organization + ), + field="record_type", + ) + ) applies_to_type_choices = [] for v in values: record_type = RecordType.objects.get_or_create(name=v.name)[0] @@ -38,58 +46,110 @@ def get_applies_to_type_choices(self, organization): return sorted(applies_to_type_choices, key=lambda tup: tup[1]) def get(self, request, *args, **kwargs): - if self.kwargs.get('pk'): - rights_statement = RightsStatement.objects.get(pk=self.kwargs.get('pk')) + if self.kwargs.get("pk"): + rights_statement = RightsStatement.objects.get(pk=self.kwargs.get("pk")) organization = rights_statement.organization applies_to_type_choices = self.get_applies_to_type_choices(organization) formset_data = self.get_formset(rights_statement.rights_basis) - formset = formset_data['class'](instance=rights_statement) - basis_form = RightsForm(applies_to_type_choices=applies_to_type_choices, instance=rights_statement, organization=organization) + formset = formset_data["class"](instance=rights_statement) + basis_form = RightsForm( + applies_to_type_choices=applies_to_type_choices, + instance=rights_statement, + organization=organization, + ) granted_formset = RightsGrantedFormSet(instance=rights_statement) - return render(request, self.template_name, { - 'organization': organization, formset_data['key']: formset, - 'basis_form': basis_form, 'granted_formset': granted_formset}) + return render( + request, + self.template_name, + { + "organization": organization, + formset_data["key"]: formset, + "basis_form": basis_form, + "granted_formset": granted_formset, + }, + ) else: - organization = Organization.objects.get(pk=self.request.GET.get('org')) + organization = Organization.objects.get(pk=self.request.GET.get("org")) applies_to_type_choices = self.get_applies_to_type_choices(organization) - basis_form = RightsForm(applies_to_type_choices=applies_to_type_choices, organization=organization) - return render(request, self.template_name, { - 'copyright_form': CopyrightFormSet(), 'license_form': LicenseFormSet(), - 'statute_form': StatuteFormSet(), 'other_form': OtherFormSet(), - 'organization': organization, 'basis_form': basis_form, - 'granted_formset': RightsGrantedFormSet()}) + basis_form = RightsForm( + applies_to_type_choices=applies_to_type_choices, + organization=organization, + ) + return render( + request, + self.template_name, + { + "copyright_form": CopyrightFormSet(), + "license_form": LicenseFormSet(), + "statute_form": StatuteFormSet(), + "other_form": OtherFormSet(), + "organization": organization, + "basis_form": basis_form, + "granted_formset": RightsGrantedFormSet(), + }, + ) def post(self, request, *args, **kwargs): - applies_to_type = request.POST.getlist('applies_to_type') + applies_to_type = request.POST.getlist("applies_to_type") - if not self.kwargs.get('pk'): - organization = Organization.objects.get(pk=self.request.GET.get('org')) + if not self.kwargs.get("pk"): + organization = Organization.objects.get(pk=self.request.GET.get("org")) applies_to_type_choices = self.get_applies_to_type_choices(organization) - form = RightsForm(request.POST, applies_to_type_choices=applies_to_type_choices, organization=organization) + form = RightsForm( + request.POST, + applies_to_type_choices=applies_to_type_choices, + organization=organization, + ) if not form.is_valid(): - messages.error(request, "There was a problem with your submission. Please correct the error(s) below and try again.") - return render(request, self.template_name, { - 'copyright_form': CopyrightFormSet(), 'license_form': LicenseFormSet(), - 'statute_form': StatuteFormSet(), 'other_form': OtherFormSet(), - 'organization': organization, 'basis_form': form}) + messages.error( + request, + "There was a problem with your submission. Please correct the error(s) below and try again.", + ) + return render( + request, + self.template_name, + { + "copyright_form": CopyrightFormSet(), + "license_form": LicenseFormSet(), + "statute_form": StatuteFormSet(), + "other_form": OtherFormSet(), + "organization": organization, + "basis_form": form, + }, + ) rights_statement = form.save(commit=False) else: - rights_statement = RightsStatement.objects.get(pk=self.kwargs.get('pk')) + rights_statement = RightsStatement.objects.get(pk=self.kwargs.get("pk")) organization = rights_statement.organization applies_to_type_choices = self.get_applies_to_type_choices(organization) formset_data = self.get_formset(rights_statement.rights_basis) - basis_formset = formset_data['class'](request.POST, instance=rights_statement) - rights_granted_formset = RightsGrantedFormSet(request.POST, instance=rights_statement) + basis_formset = formset_data["class"](request.POST, instance=rights_statement) + rights_granted_formset = RightsGrantedFormSet( + request.POST, instance=rights_statement + ) for formset in [rights_granted_formset, basis_formset]: if not formset.is_valid(): - messages.error(request, "There was a problem with your submission. Please correct the error(s) below and try again.") - form = RightsForm(request.POST, applies_to_type_choices=applies_to_type_choices, organization=organization) - return render(request, self.template_name, { - formset_data['key']: formset_data['class'](request.POST), - 'organization': organization, 'basis_form': form, - 'granted_formset': rights_granted_formset}) + messages.error( + request, + "There was a problem with your submission. Please correct the error(s) below and try again.", + ) + form = RightsForm( + request.POST, + applies_to_type_choices=applies_to_type_choices, + organization=organization, + ) + return render( + request, + self.template_name, + { + formset_data["key"]: formset_data["class"](request.POST), + "organization": organization, + "basis_form": form, + "granted_formset": rights_granted_formset, + }, + ) rights_statement.save() rights_statement.applies_to_type.clear() @@ -101,32 +161,33 @@ def post(self, request, *args, **kwargs): formset.save() messages.success(request, "Rights statement saved!") - return redirect('orgs:detail', organization.pk) + return redirect("orgs:detail", organization.pk) class RightsAPIAdminView(ManagingArchivistMixin, JSONResponseMixin, TemplateView): - def render_to_response(self, context, **kwargs): if not self.request.is_ajax(): raise Http404 - resp = {'success': 0} + resp = {"success": 0} - if 'action' in self.kwargs: - obj = get_object_or_404(RightsStatement,pk=context['pk']) - if self.kwargs['action'] == 'delete': + if "action" in self.kwargs: + obj = get_object_or_404(RightsStatement, pk=context["pk"]) + if self.kwargs["action"] == "delete": obj.delete() - resp['success'] = 1 + resp["success"] = 1 return self.render_to_json_response(resp, **kwargs) class RightsDetailView(OrgReadViewMixin, DetailView): - template_name = 'rights/detail.html' + template_name = "rights/detail.html" model = RightsStatement def get_context_data(self, *args, **kwargs): context = super(RightsDetailView, self).get_context_data(**kwargs) - context['meta_page_title'] = '{} PREMIS rights statement'.format(self.object.organization) - context['rights_basis_info'] = self.object.get_rights_info_object - context['rights_granted_info'] = self.object.get_rights_granted_objects + context["meta_page_title"] = "{} PREMIS rights statement".format( + self.object.organization + ) + context["rights_basis_info"] = self.object.get_rights_info_object + context["rights_granted_info"] = self.object.get_rights_granted_objects return context diff --git a/aurora/bag_transfer/signals.py b/aurora/bag_transfer/signals.py index e0b94260..46d32137 100644 --- a/aurora/bag_transfer/signals.py +++ b/aurora/bag_transfer/signals.py @@ -1,31 +1,48 @@ -from __future__ import division from datetime import date from dateutil.relativedelta import relativedelta -import pwd -import os -from django.db.models.signals import m2m_changed, pre_delete, post_delete, post_save +from django.db.models.signals import m2m_changed, pre_delete, post_save from django.dispatch import receiver from bag_transfer.accession.models import Accession from bag_transfer.lib.files_helper import chown_path_to_root from bag_transfer.lib.RAC_CMD import delete_system_group -from bag_transfer.models import Archives, User, BagInfoMetadata, Organization, DashboardMonthData, DashboardRecordTypeData +from bag_transfer.models import ( + Archives, + User, + BagInfoMetadata, + Organization, + DashboardMonthData, + DashboardRecordTypeData, +) @receiver(pre_delete, sender=Organization) def delete_organization(sender, instance, **kwargs): - - # update group of upload path to root + """Clean up system resources when an organization is deleted.""" chown_path_to_root(instance.org_machine_upload_paths()[0]) - - # remove system group delete_system_group(instance.machine_name) @receiver(m2m_changed, sender=User.groups.through) def set_is_staff(sender, instance, **kwargs): - instance.is_staff = True if (any(name in ['managing_archivists', 'accessioning_archivists', 'appraisal_archivists'] for name in instance.groups.values_list('name', flat=True)) or (instance.is_superuser)) else False + """Ensure `is_staff` attribute is correctly set when User instances are saved.""" + instance.is_staff = ( + True + if ( + any( + name + in [ + "managing_archivists", + "accessioning_archivists", + "appraisal_archivists", + ] + for name in instance.groups.values_list("name", flat=True) + ) + or (instance.is_superuser) + ) + else False + ) instance.save() @@ -45,26 +62,39 @@ def dashboard_data(sender, instance, **kwargs): month_label=current.strftime("%B"), sort_date=int(str(current.year) + str(current.month)), year=current.year, - organization=organization + organization=organization, )[0] data.upload_count = Archives.objects.filter( organization=organization, machine_file_upload_time__year=current.year, - machine_file_upload_time__month=current.month).count() - data.upload_size = sum(map(int, Archives.objects.filter( - organization=organization, - machine_file_upload_time__year=current.year, - machine_file_upload_time__month=current.month).values_list('machine_file_size', flat=True)))/1000000000 + machine_file_upload_time__month=current.month, + ).count() + data.upload_size = ( + sum( + map( + int, + Archives.objects.filter( + organization=organization, + machine_file_upload_time__year=current.year, + machine_file_upload_time__month=current.month, + ).values_list("machine_file_size", flat=True), + ) + ) + / 1000000000 + ) data.save() current += relativedelta(months=1) if instance.process_status >= sender.VALIDATED: for organization in Organization.objects.all(): - for label in set(BagInfoMetadata.objects.all().values_list('record_type', flat=True)): + for label in set( + BagInfoMetadata.objects.all().values_list("record_type", flat=True) + ): data = DashboardRecordTypeData.objects.get_or_create( - organization=organization, - label=label + organization=organization, label=label )[0] - data.count = Archives.objects.filter(organization=organization, metadata__record_type=label).count() + data.count = Archives.objects.filter( + organization=organization, metadata__record_type=label + ).count() data.save() @@ -76,7 +106,9 @@ def update_accession_status(sender, instance, **kwargs): """ if instance.process_status == Archives.ACCESSIONING_COMPLETE: accession = instance.accession - last_update = sorted(set([t.process_status for t in accession.accession_transfers.all()]))[0] + last_update = sorted( + set([t.process_status for t in accession.accession_transfers.all()]) + )[0] if last_update == Archives.ACCESSIONING_COMPLETE: accession.process_status = Accession.COMPLETE accession.save() diff --git a/aurora/bag_transfer/templates/appraise/main.html b/aurora/bag_transfer/templates/appraise/main.html index c901b8a4..2ffcdbd9 100644 --- a/aurora/bag_transfer/templates/appraise/main.html +++ b/aurora/bag_transfer/templates/appraise/main.html @@ -46,219 +46,193 @@ var url = '{% url 'appraise:list' %}'; var appraise_table = ''; - $(function () { - $.fn.dataTable.moment( 'MMM D, YYYY h:mm A' ); - $('#appraise_table').DataTable({ - 'columnDefs': [ - { - width: "20%", - targets: [5] - } - ], - 'createdRow': function(row, data, dataIndex) { - $(row).attr('data-transfer-id', data[6]); - $(row).attr('data-transfer-name', data[0]); - }, - 'order' : [[4, 'desc']], - 'stateSave' : true, - 'paging' : true, - 'lengthChange': false, - 'searching' : true, - 'ordering' : true, - 'info' : true, - 'autoWidth' : true, - 'pageLength' : 25, - 'processing': true, - 'serverSide': true, - fixedHeader: { - headerOffset: $('.navbar').outerHeight() - }, - 'ajax': '{% url "appraise:datatable" %}' - }) - - $("#appraise_table tbody").on("click", ".appraisal-note", function(e) { - e.preventDefault(); - - var bag_name = $(this).closest('tr').attr('data-transfer-name'); - var upload_id = $(this).closest('tr').attr('data-transfer-id'); - - if (!$(this).hasClass('edit-note')){ - activateModal(upload_id, 'Add', bag_name); - return false; +$(function () { + $.fn.dataTable.moment( 'MMM D, YYYY h:mm A' ); + $('#appraise_table').DataTable({ + 'columnDefs': [ + { + width: "20%", + targets: [5] } + ], + 'createdRow': function(row, data, dataIndex) { + $(row).attr('data-transfer-id', data[6]); + $(row).attr('data-transfer-name', data[0]); + }, + 'order' : [[4, 'desc']], + 'stateSave' : true, + 'paging' : true, + 'lengthChange': false, + 'searching' : true, + 'ordering' : true, + 'info' : true, + 'autoWidth' : true, + 'pageLength' : 25, + 'processing': true, + 'serverSide': true, + fixedHeader: { + headerOffset: $('.navbar').outerHeight() + }, + 'ajax': '{% url "appraise:datatable" %}' + }) - var data = { - 'req_type' : 'edit', - 'req_form' : 'appraise', - 'upload_id': upload_id - }; - - $.get(url,data, function(resp){ - if (resp.success){ - activateModal(upload_id, 'Edit', bag_name, resp.appraisal_note); - } else { - alert('Something went wrong! Please try again.'); - } - }); - - return false; - }); - - $("#appraise_table tbody").on("click", ".transfer-detail", function(e) { - e.preventDefault(); - - var bag_name = $(this).closest('tr').attr('data-transfer-name'); - var upload_id = $(this).closest('tr').attr('data-transfer-id'); - - var data = { - 'req_form' : 'detail', - 'upload_id': upload_id - }; - - $.get(url, data, function(resp){ - if (resp.success){ - dmodal.find('.bag-name').text(bag_name); - transfer_url = '{% url "transfers:detail" pk=1 %}'; - transfer_url = transfer_url.replace('1', upload_id); - $.get(transfer_url, function(resp){ - dmodal.find('.content').replaceWith($(resp).find('main.content')) - dmodal.modal('show'); - }) - } else { - alert('Something went wrong.. Please try again..'); - } - }); - - return false; - }); - - $('#appraisal-note-form').submit(function(e){ + // Open appraisal note modal + $("#appraise_table tbody").on("click", ".appraisal-note", function(e) { e.preventDefault(); - var frm = $(this) - var data = { - 'upload_id': frm.find('.upload_id').val(), - 'appraisal_note': frm.find('.appraisal_note').val(), - 'req_form' : 'appraise', - 'req_type' : 'submit' - } - - //empty check, no need to submit - if (data.appraisal_note.length < 2){ - alert('Note is too short!'); + var bagData = getDataFromAttributes($(this).closest('tr')) + if (!$(this).hasClass('edit-note')){ + activateModal(bagData.upload_id, 'Add', bagData.bag_name); return false; } - - //AJAX submit - $.get(url,data,function(resp){ - if (resp.success){ - amodal.modal('hide'); - resolveRowCallback(data.upload_id, 'add'); - } - }); - - return false; - }); - - $('#delete-note').on('click', function(e){ - e.preventDefault(); - var frm = $('#appraisal-note-form') var data = { - 'upload_id': frm.find('.upload_id').val(), - 'appraisal_note': frm.find('.appraisal_note').val(), + 'req_type' : 'edit', 'req_form' : 'appraise', - 'req_type' : 'delete' - } - - //AJAX submit - $.get(url,data,function(resp){ + 'upload_id': bagData.upload_id + }; + $.get(url, data, function(resp){ if (resp.success){ - amodal.modal('hide'); - resolveRowCallback(data.upload_id, 'delete'); + activateModal(bagData.upload_id, 'Edit', bagData.bag_name, resp.appraisal_note); + } else { + alert('Something went wrong! Please try again.'); } }); - return false; - }); + }); - $("#appraise_table tbody").on("click", ".appraisal-accept", function(e){ + // Show transfer details modal + $("#appraise_table tbody").on("click", ".transfer-detail", function(e) { e.preventDefault(); - var upload_row = $(this).closest('tr'); - var upload_id = upload_row.attr('data-transfer-id'); + var bagData = getDataFromAttributes($(this).closest('tr')) var data = { - 'req_form': 'appraise', - 'req_type': 'decision', - 'upload_id': upload_id, - 'appraisal_decision': 1 - } - + 'req_form' : 'detail', + 'upload_id': bagData.upload_id + }; $.get(url, data, function(resp){ if (resp.success){ - $( upload_row ).remove(); // remove row - name = $(upload_row).children('td').first().text() - displayMessage('success', 'Transfer '+name+' accepted.', true); + dmodal.find('.bag-name').text(bagData.bag_name); + transfer_url = '{% url "transfers:detail" pk=1 %}'; + transfer_url = transfer_url.replace('1', bagData.upload_id); + $.get(transfer_url, function(resp){ + dmodal.find('.content').replaceWith($(resp).find('main.content')) + dmodal.modal('show'); + }) } else { - displayMessage('danger', 'Something went wrong! Please try again.', false); + alert('Something went wrong.. Please try again.'); } }); + return false; + }); - }); + // Confirm reject transfer + $("#appraise_table tbody").on("click", ".appraisal-reject", function(e) { + e.preventDefault(); + var bagData = getDataFromAttributes($(this).closest('tr')) + cmodal.find('.bag-name').text(bagData.bag_name); + cmodal.find('.upload_id').val(bagData.upload_id) + cmodal.modal('show'); + return false; + }) - $("#appraise_table tbody").on("click", ".appraisal-reject", function(e) { - e.preventDefault(); + // Delete appraisal note + $('#delete-note').on('click', function(e){ + e.preventDefault(); + var data = prepareNoteData($('#appraisal-note-form'), 'delete') + saveNote(data, amodal); + resolveRowCallback(data.upload_id, 'delete') + return false; + }); - var bag_name = $(this).closest('tr').attr('data-transfer-name'); - var upload_id = $(this).closest('tr').attr('data-transfer-id'); + // Add or edit appraisal note + $('#appraisal-note-form').submit(function(e){ + e.preventDefault(); + var data = prepareNoteData($(this), 'submit') + saveNote(data, amodal); + resolveRowCallback(data.upload_id, 'add') + return false; + }); - cmodal.find('.bag-name').text(bag_name); - cmodal.find('.upload_id').val(upload_id) - cmodal.modal('show'); + // Accept transfer + $("#appraise_table tbody").on("click", ".appraisal-accept", function(e){ + e.preventDefault(); + var upload_row = $(this).closest('tr'); + var bagData = getDataFromAttributes(upload_row); + handleAppraisalDecision(upload_row, bagData.upload_id, 1); + }); - return false; - }) + // Reject transfer + $("#confirm-reject-form").submit(function(e){ + e.preventDefault(); + var data = prepareNoteData($(this), 'submit') + var upload_row = $("#appraise_table tbody").find('tr[data-transfer-id='+data.upload_id+']'); + saveNote(data, cmodal); + handleAppraisalDecision(upload_row, data.upload_id, 0); + }); +}) + +function handleAppraisalDecision(upload_row, upload_id, code) { + var decision = (code == 1) ? 'accepted':'rejected' + var data = { + 'req_form': 'appraise', + 'req_type': 'decision', + 'upload_id': upload_id, + 'appraisal_decision': code + } + $.get(url, data, function(resp){ + if (resp.success){ + handleRemoveRow(upload_row, decision) + } else { + displayMessage('danger', 'Something went wrong! Please try again.', false); + } + }); +} - $("#confirm-reject-form").submit(function(e){ - e.preventDefault(); - var frm = $(this) - var upload_id = frm.find('.upload_id').val() - var upload_row = $("#appraise_table tbody").find('tr[data-transfer-id='+upload_id+']'); - var data = { - 'upload_id': upload_id, - 'appraisal_note': frm.find('.appraisal_note').val(), - 'req_form' : 'appraise', - 'req_type' : 'submit' - } +function prepareNoteData(form, req_type) { + return { + 'upload_id': form.find('.upload_id').val(), + 'appraisal_note': form.find('.appraisal_note').val(), + 'req_form' : 'appraise', + 'req_type' : req_type + } +} + +function getDataFromAttributes(rootElement) { + return { + bag_name: rootElement.attr('data-transfer-name'), + upload_id: rootElement.attr('data-transfer-id') + } +} + +function handleRemoveRow(row, action) { + var cls = (action == 'accepted') ? 'success':'danger' + var name = $(row).children('td').first().text() + $(row).remove() + displayMessage(cls, 'Transfer '+name+' '+action+'.', true); +} - // empty check, no need to submit - if (data.appraisal_note.length && data.appraisal_note.length < 2){ - alert('Note is too short!'); +function saveNote(data, modal) { + if (checkNoteLength(data.appraisal_note)) { + $.get(url,data,function(resp){ + if (resp.success){ + modal.modal('hide'); + return true; + } else { return false; } - - $.get(url,data,function(resp){ - if (resp.success) { - cmodal.modal('hide'); - var data = { - 'req_form': 'appraise', - 'req_type': 'decision', - 'upload_id': upload_id, - 'appraisal_decision': 0 - } - $.get(url, data, function(resp){ - if (resp.success){ - $(upload_row).remove() - name = $(upload_row).children('td').first().text() - displayMessage('danger', 'Transfer '+name+' rejected.', true); - } else { - displayMessage('danger', 'Something went wrong! Please try again.', false); - } - }); - } - }); }); - }) + } +} + +function checkNoteLength(note) { + if (note.length && note.length < 2){ + alert('Note is too short!'); + return false; + } else { + return true; + } +} +// setups up and opens appraisal note modal function activateModal(uid, label, bag_name, appraisal_note) { - // setups up and opens modal amodal.find('.upload_id').val(uid); amodal.find('.add-or-edit-label').text(label); amodal.find('.bag-name').text(bag_name); diff --git a/aurora/bag_transfer/templates/bagit_profiles/detail.html b/aurora/bag_transfer/templates/bagit_profiles/detail.html index bfea6fc0..7d8fb89e 100644 --- a/aurora/bag_transfer/templates/bagit_profiles/detail.html +++ b/aurora/bag_transfer/templates/bagit_profiles/detail.html @@ -2,7 +2,7 @@ {% load tz %} {% block h1_title %} - BagIt Profile {{object.applies_to_organization}} + BagIt Profile {{object.applies_to_organization.name}} Back To Organization {% endblock %} @@ -20,7 +20,7 @@

Profile Information

{{object.external_description}}
{% endif %}
Creator
-
{{object.source_organization}}
+
{{object.source_organization.name}}
Contact Email
{{object.contact_email}}
BagIt Profile Identifier
@@ -41,6 +41,10 @@

Technical Information

{{object.allow_fetch|yesno:"Yes,No"}}
Serialization Allowed?
{{object.serialization}}
+ {% if object.manifests_allowed.all %} +
Manifests Allowed
+
{% for s in object.manifests_allowed.all %}{{s.name}}{% if not forloop.last %}
{% endif %}{% endfor %}
+ {% endif %} {% if object.manifests_required.all %}
Manifests Required
{% for s in object.manifests_required.all %}{{s.name}}{% if not forloop.last %}
{% endif %}{% endfor %}
diff --git a/aurora/bag_transfer/templates/bagit_profiles/manage.html b/aurora/bag_transfer/templates/bagit_profiles/manage.html index 4f9661ad..9d7d2bf8 100644 --- a/aurora/bag_transfer/templates/bagit_profiles/manage.html +++ b/aurora/bag_transfer/templates/bagit_profiles/manage.html @@ -22,6 +22,17 @@

General Information

{% include 'bagit_profiles/baginfo_form_fields.html' %} +
+
+ + {{ manifests_allowed_formset.management_form }} + {{ manifests_allowed_formset.non_form_errors }} + {% for form in manifests_allowed_formset %} + {% include 'bagit_profiles/repeating_form.html' %} + {% endfor %} +

Select allowed algorithm(s) for manifest files. If no value is selected any algorithm is valid.

+
+
@@ -30,7 +41,7 @@

General Information

{% for form in manifests_formset %} {% include 'bagit_profiles/repeating_form.html' %} {% endfor %} -

Select a required algorithm for manifest files. If no value is selected any algorithm is valid.

+

Select a required algorithm for manifest files. At least one value must be selected in order for bags to be valid.

diff --git a/aurora/bag_transfer/templates/parts/rights_table.html b/aurora/bag_transfer/templates/parts/rights_table.html index 841cabea..665c9f13 100644 --- a/aurora/bag_transfer/templates/parts/rights_table.html +++ b/aurora/bag_transfer/templates/parts/rights_table.html @@ -11,7 +11,7 @@ {% for statement in org.rights_statements %} - {% for t in statement.applies_to_type.all %}{{t}}{% if not forloop.last %}
{%endif%}{% endfor %} + {% for t in statement.applies_to_type.all %}{{t.name}}{% if not forloop.last %}
{%endif%}{% endfor %} {{statement.rights_basis}} {{statement.get_table_data.notes}} diff --git a/aurora/bag_transfer/templates/transfers/left_sidebar.html b/aurora/bag_transfer/templates/transfers/left_sidebar.html index f9afd229..fc5c8749 100644 --- a/aurora/bag_transfer/templates/transfers/left_sidebar.html +++ b/aurora/bag_transfer/templates/transfers/left_sidebar.html @@ -53,7 +53,7 @@
  • - + OpenAPI Schema
  • diff --git a/aurora/bag_transfer/templatetags/util.py b/aurora/bag_transfer/templatetags/util.py index 3215d6b7..4a964f22 100644 --- a/aurora/bag_transfer/templatetags/util.py +++ b/aurora/bag_transfer/templatetags/util.py @@ -1,5 +1,4 @@ from django import template -from django.contrib.auth.models import Group from bag_transfer.lib.view_helpers import label_class from bag_transfer.models import Archives @@ -25,4 +24,4 @@ def progress_class(status): @register.filter def progress_percentage(status): - return int(round(float(status)/Archives.ACCESSIONING_COMPLETE * 100)) + return int(round(float(status) / Archives.ACCESSIONING_COMPLETE * 100)) diff --git a/aurora/bag_transfer/test/helpers.py b/aurora/bag_transfer/test/helpers.py index e860bd9c..5030e85c 100644 --- a/aurora/bag_transfer/test/helpers.py +++ b/aurora/bag_transfer/test/helpers.py @@ -1,16 +1,37 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from datetime import datetime -from os import path, chdir, makedirs, listdir, rename +from os import path, listdir, rename, chown import pwd import random import string from django.contrib.auth.models import Group -from bag_transfer.models import * +from bag_transfer.models import ( + AcceptBagItVersion, + AcceptSerialization, + Archives, + BagItProfile, + BagItProfileBagInfo, + BagItProfileBagInfoValues, + BAGLogCodes, + LanguageCode, + ManifestsAllowed, + ManifestsRequired, + Organization, + RecordCreators, + TagFilesRequired, + TagManifestsRequired, + User, +) from bag_transfer.test import setup as org_setup -from bag_transfer.rights.models import * -from aurora import config, settings +from bag_transfer.rights.models import ( + RecordType, + RightsStatement, + RightsStatementCopyright, + RightsStatementLicense, + RightsStatementOther, + RightsStatementStatute, + RightsStatementRightsGranted, +) +from aurora import settings from bag_transfer.lib import files_helper as FH from bag_transfer.lib.transfer_routine import TransferRoutine @@ -21,15 +42,15 @@ #################################### -# Returns a random string of specified length def random_string(length): - return ''.join(random.choice(string.ascii_letters) for m in range(length)) + """Returns a random string of specified length.""" + return "".join(random.choice(string.ascii_letters) for m in range(length)) -# Feturns a random date in a given year def random_date(year): + """Returns a random date in a given year.""" try: - return datetime.strptime('{} {}'.format(random.randint(1, 366), year), '%j %Y') + return datetime.strptime("{} {}".format(random.randint(1, 366), year), "%j %Y") # accounts for leap year values except ValueError: @@ -37,55 +58,56 @@ def random_date(year): def random_name(prefix, suffix): - return "{} {} {}".format( - prefix, - random.choice(string.letters), - suffix - ) + """Returns a random name.""" + return "{} {} {}".format(prefix, random.choice(string.ascii_letters), suffix) #################################### # CREATE TEST OBJECTS #################################### -# Creates a RecordType object for each value in list provided. -# If no list is given, RecordTypes created from a default list def create_test_record_types(record_types=None): + """Creates a RecordType object for each value in list provided. + If no list is given, RecordTypes are create for each item in a default list.""" objects = [] if record_types is None: record_types = [ - "administrative records", "board materials", - "communications and publications", "grant records", - "annual reports"] + "administrative records", + "board materials", + "communications and publications", + "grant records", + "annual reports", + ] for record_type in record_types: - object = RecordType.objects.create( - name=record_type - ) + object = RecordType.objects.create(name=record_type) objects.append(object) - print 'Test record type {record_type} created'.format(record_type=object.name) + print("Test record type {record_type} created".format(record_type=object.name)) return objects -# Creates a Group for each value in a list of names. -# If no list is given, Groups are created from a default list def create_test_groups(names=None): + """Creates a Group for each value in a list of names. + If no list is given, Groups are created for each item in a default list.""" groups = [] if names is None: - names = ['appraisal_archivists', 'accessioning_archivists', 'managing_archivists'] + names = [ + "appraisal_archivists", + "accessioning_archivists", + "managing_archivists", + ] for name in names: if not Group.objects.filter(name=name).exists(): group = Group(name=name) group.save() groups.append(group) - print 'Test group {group} created'.format(group=group.name) + print("Test group {group} created".format(group=group.name)) else: - print 'Test group {group} already exists'.format(group=name) + print("Test group {group} already exists".format(group=name)) group = Group.objects.get(name=name) groups.append(group) return groups -# Review def create_test_orgs(org_count=1): """creates random orgs based on org_count""" if org_count < 1: @@ -95,21 +117,27 @@ def create_test_orgs(org_count=1): while True: if len(generated_orgs) == org_count: break - new_org_name = random_name(random.choice(org_setup.POTUS_NAMES), random.choice(org_setup.COMPANY_SUFFIX)) + new_org_name = random_name( + random.choice(org_setup.POTUS_NAMES), + random.choice(org_setup.COMPANY_SUFFIX), + ) try: - org_exist = Organization.objects.get(name=new_org_name) + Organization.objects.get(name=new_org_name) continue - except Organization.DoesNotExist as e: + except Organization.DoesNotExist: pass test_org = Organization( - name=new_org_name, - machine_name='org{}'.format((len(generated_orgs)+1)) - ) + name=new_org_name, machine_name="org{}".format((len(generated_orgs) + 1)) + ) test_org.save() generated_orgs.append(test_org) - print 'Test organization {} -- {} created'.format(test_org.name, test_org.machine_name) + print( + "Test organization {} -- {} created".format( + test_org.name, test_org.machine_name + ) + ) return generated_orgs @@ -121,89 +149,87 @@ def delete_test_orgs(orgs=[]): def create_test_baglogcodes(): baglogcodes = ( - ('ASAVE', 'I'), - ('PBAG', 'S'), - ('PBAGP', 'S'), - ('GBERR', 'BE'), - ('DTERR', 'BE'), - ('MDERR', 'BE'), + ("ASAVE", "I"), + ("PBAG", "S"), + ("PBAGP", "S"), + ("GBERR", "BE"), + ("DTERR", "BE"), + ("MDERR", "BE"), + ("RBERR", "BE"), + ("BIERR", "BE"), ) code_objects = [] for code in baglogcodes: if not BAGLogCodes.objects.filter(code_short=code[0]).exists(): bag_log_code = BAGLogCodes( - code_short=code[0], - code_type=code[1], - code_desc=random_string(50), + code_short=code[0], code_type=code[1], code_desc=random_string(50), ) bag_log_code.save() code_objects.append(bag_log_code) return code_objects -# Creates test user given a username and organization. -# If no username is given, the default username supplied in settings is used. -# If no organization is given, an organization is randomly chosen. def create_test_user(username=None, org=None): + """Creates test user given a username and organization. + If no username is given, the default username supplied in settings is used. + If no organization is given, an organization is randomly chosen. + """ if username is None: - username = settings.TEST_USER['USERNAME'] + username = settings.TEST_USER["USERNAME"] if org is None: org = random.choice(Organization.objects.all()) test_user = User( - username=username, - email='{}@example.org'.format(username), - organization=org) + username=username, email="{}@example.org".format(username), organization=org + ) test_user.save() - print 'Test user {username} created'.format(username=username) + print("Test user {username} created".format(username=username)) return test_user -# Creates Archive objects by running bags through TransferRoutine def create_test_archive(transfer, org): + """Creates Archive objects by running bags through TransferRoutine.""" machine_file_identifier = Archives().gen_identifier() archive = Archives.initial_save( org, None, - transfer['file_path'], - transfer['file_size'], - transfer['file_modtime'], + transfer["file_path"], + transfer["file_size"], + transfer["file_modtime"], machine_file_identifier, - transfer['file_type'], - transfer['bag_it_name'] + transfer["file_type"], + transfer["bag_it_name"], ) # updating the name since the bag info reflects ford - archive.organization.name = 'Ford Foundation' + archive.organization.name = "Ford Foundation" archive.organization.save() return archive -# Creates target bags to be picked up by a TransferRoutine based on a string. -# This allows processing of bags serialized in multiple formats at once. -def create_target_bags(target_str, test_bags_dir, org): +def create_target_bags(target_str, test_bags_dir, org, username=None): + """Creates target bags to be picked up by a TransferRoutine based on a string. + # This allows processing of bags serialized in multiple formats at once.""" moved_bags = [] target_bags = [b for b in listdir(test_bags_dir) if b.startswith(target_str)] if len(target_bags) < 1: return False - # setting ownership of paths to root - root_uid = pwd.getpwnam('root').pw_uid index = 0 for bags in target_bags: FH.anon_extract_all( - path.join(test_bags_dir,bags), - org.org_machine_upload_paths()[0] + path.join(test_bags_dir, bags), org.org_machine_upload_paths()[0] ) # Renames extracted path -- add index suffix to prevent collision - created_path = path.join(org.org_machine_upload_paths()[0], bags.split('.')[0]) - new_path = '{}{}'.format(created_path, index) + created_path = path.join(org.org_machine_upload_paths()[0], bags.split(".")[0]) + new_path = "{}{}".format(created_path, index) rename(created_path, new_path) index += 1 - # chowning path to root - FH.chown_path_to_root(new_path) + # chowning path + uid = pwd.getpwnam(username).pw_uid if username else pwd.getpwnam("root").pw_uid + chown(new_path, uid, -1) moved_bags.append(new_path) return moved_bags @@ -216,80 +242,102 @@ def run_transfer_routine(): return tr -# Creates a rights statement given a record type, organization and rights basis. -# If any one of these values are not given, random values are assigned. def create_rights_statement(record_type=None, org=None, rights_basis=None): - record_type = record_type if record_type else random.choice(RecordType.objects.all()) + """Creates a rights statement given a record type, organization and rights basis. + If any one of these values are not given, random values are assigned.""" + record_type = ( + record_type if record_type else random.choice(RecordType.objects.all()) + ) if org is None: org = random.choice(Organization.objects.all()) if rights_basis is None: - rights_basis = random.choices(['Copyright', 'Statute', 'License', 'Other']) - rights_statement = RightsStatement( - organization=org, - rights_basis=rights_basis, - ) + rights_basis = random.choices(["Copyright", "Statute", "License", "Other"]) + rights_statement = RightsStatement(organization=org, rights_basis=rights_basis,) rights_statement.save() rights_statement.applies_to_type.add(record_type) -# Creates a rights info object given a rights statement -# If no rights statement is given, a random value is selected def create_rights_info(rights_statement=None): - rights_statement = rights_statement if rights_statement else random.choice(RightsStatement.objects.all()) - if rights_statement.rights_basis == 'Statute': + """Creates a rights info object given a rights statement + If no rights statement is given, a random value is selected""" + rights_statement = ( + rights_statement + if rights_statement + else random.choice(RightsStatement.objects.all()) + ) + if rights_statement.rights_basis == "Statute": rights_info = RightsStatementStatute( statute_citation=random_string(50), statute_applicable_start_date=random_date(1960), statute_applicable_end_date=random_date(1990), statute_end_date_period=20, - statute_note=random_string(40) + statute_note=random_string(40), ) - elif rights_statement.rights_basis == 'Other': + elif rights_statement.rights_basis == "Other": rights_info = RightsStatementOther( - other_rights_basis=random.choice(['Donor', 'Policy']), + other_rights_basis=random.choice(["Donor", "Policy"]), other_rights_applicable_start_date=random_date(1978), other_rights_end_date_period=20, other_rights_end_date_open=True, - other_rights_note=random_string(50) + other_rights_note=random_string(50), ) - elif rights_statement.rights_basis == 'Copyright': + elif rights_statement.rights_basis == "Copyright": rights_info = RightsStatementCopyright( - copyright_status=random.choice(['copyrighted', 'public domain', 'unknown']), + copyright_status=random.choice(["copyrighted", "public domain", "unknown"]), copyright_applicable_start_date=random_date(1950), copyright_end_date_period=40, - copyright_note=random_string(70) + copyright_note=random_string(70), ) - elif rights_statement.rights_basis == 'License': + elif rights_statement.rights_basis == "License": rights_info = RightsStatementLicense( license_applicable_start_date=random_date(1980), license_start_date_period=10, license_end_date_open=True, - license_note=random_string(60) + license_note=random_string(60), ) rights_info.rights_statement = rights_statement rights_info.save() def create_rights_granted(rights_statement=None, granted_count=1): - """Creates one or more rights granted objects, based on the grant count, if no rights statement is given, a random value is selected""" - rights_statement = rights_statement if rights_statement else random.choice(RightsStatement.objects.all()) + """Creates one or more rights granted objects, based on the grant count. + If no rights statement is given, a random value is selected.""" + rights_statement = ( + rights_statement + if rights_statement + else random.choice(RightsStatement.objects.all()) + ) all_rights_granted = [] - for x in xrange(granted_count): + for x in range(granted_count): rights_granted = RightsStatementRightsGranted( rights_statement=rights_statement, - act=random.choice(['publish', 'disseminate','replicate', 'migrate', 'modify', 'use', 'delete']), + act=random.choice( + [ + "publish", + "disseminate", + "replicate", + "migrate", + "modify", + "use", + "delete", + ] + ), start_date=random_date(1984), end_date_period=15, rights_granted_note=random_string(100), - restriction=random.choice(['allow', 'disallow', 'conditional']) - ) + restriction=random.choice(["allow", "disallow", "conditional"]), + ) rights_granted.save() all_rights_granted.append(rights_granted) return all_rights_granted def create_test_bagitprofile(applies_to_organization=None): - applies_to_organization = applies_to_organization if applies_to_organization else random.choice(Organization.objects.all()) + applies_to_organization = ( + applies_to_organization + if applies_to_organization + else random.choice(Organization.objects.all()) + ) profile = BagItProfile( applies_to_organization=applies_to_organization, source_organization=random.choice(Organization.objects.all()), @@ -297,66 +345,93 @@ def create_test_bagitprofile(applies_to_organization=None): version=1, contact_email="test@example.org", allow_fetch=random.choice([True, False]), - serialization=random.choice(['forbidden', 'required', 'optional']) + serialization=random.choice(["forbidden", "required", "optional"]), ) profile.save() return profile +def create_test_manifestsallowed(bagitprofile=None): + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) + manifests_required = ManifestsAllowed( + bagit_profile=bagitprofile, name=random.choice(["sha256", "sha512"]) + ) + manifests_required.save() + return manifests_required + + def create_test_manifestsrequired(bagitprofile=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) manifests_required = ManifestsRequired( - bagit_profile=bagitprofile, - name=random.choice(['sha256', 'md5'])) + bagit_profile=bagitprofile, name=random.choice(["sha256", "sha512"]) + ) manifests_required.save() return manifests_required def create_test_acceptserialization(bagitprofile=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) accept_serialization = AcceptSerialization( bagit_profile=bagitprofile, - name=random.choice(['application/zip', 'application/x-tar', 'application/x-gzip'])) + name=random.choice( + ["application/zip", "application/x-tar", "application/x-gzip"] + ), + ) accept_serialization.save() return accept_serialization def create_test_acceptbagitversion(bagitprofile=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) acceptbagitversion = AcceptBagItVersion( - name=random.choice(['0.96', 0.97]), - bagit_profile=bagitprofile) + name=random.choice(["0.96", 0.97]), bagit_profile=bagitprofile + ) acceptbagitversion.save() return acceptbagitversion def create_test_tagmanifestsrequired(bagitprofile=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) tagmanifestsrequired = TagManifestsRequired( - name=random.choice(['sha256', 'md5']), - bagit_profile=bagitprofile) + name=random.choice(["sha256", "sha512"]), bagit_profile=bagitprofile + ) tagmanifestsrequired.save() return tagmanifestsrequired def create_test_tagfilesrequired(bagitprofile=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) tagfilesrequired = TagFilesRequired( - name=random_string(150), - bagit_profile=bagitprofile) + name=random_string(150), bagit_profile=bagitprofile + ) tagfilesrequired.save() return tagfilesrequired def create_test_bagitprofilebaginfo(bagitprofile=None, field=None): - bagitprofile = bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + bagitprofile = ( + bagitprofile if bagitprofile else random.choice(BagItProfile.objects.all()) + ) if field is None: field = random.choice(org_setup.BAGINFO_FIELD_CHOICES) bag_info = BagItProfileBagInfo( bagit_profile=bagitprofile, field=field, required=random.choice([True, False]), - repeatable=random.choice([True, False])) + repeatable=random.choice([True, False]), + ) bag_info.save() return bag_info @@ -364,10 +439,10 @@ def create_test_bagitprofilebaginfo(bagitprofile=None, field=None): def create_test_bagitprofilebaginfovalues(baginfo=None): baginfo = baginfo if baginfo else random.choice(BagItProfileBagInfo.objects.all()) values = [] - for i in xrange(random.randint(1, 5)): + for i in range(random.randint(1, 5)): bag_info_value = BagItProfileBagInfoValues( - bagit_profile_baginfo=baginfo, - name=random_string(25)) + bagit_profile_baginfo=baginfo, name=random_string(25) + ) bag_info_value.save() values.append(bag_info_value) return values @@ -375,10 +450,8 @@ def create_test_bagitprofilebaginfovalues(baginfo=None): def create_test_record_creators(count=1): record_creators = [] - for n in xrange(count): - record_creator = RecordCreators( - name=random_string(50) - ) + for n in range(count): + record_creator = RecordCreators(name=random_string(50)) record_creator.save() record_creators.append(record_creator) return record_creators @@ -386,10 +459,8 @@ def create_test_record_creators(count=1): def create_test_languages(count=1): languages = [] - for n in xrange(count): - language = LanguageCode( - code=random_string(3) - ) + for n in range(count): + language = LanguageCode(code=random_string(3)) language.save() languages.append(language) return languages @@ -399,26 +470,26 @@ def get_accession_data(creator=None): creator = creator if creator else create_test_record_creators()[0] language = create_test_languages()[0] accession_data = { - 'use_restrictions': random_string(100), - 'access_restrictions': random_string(100), - 'resource': 'http://example.org', - 'description': random_string(150), - 'end_date': random_date(1990), - 'extent_size': '17275340', - 'acquisition_type': random.choice(['donation', 'deposit', 'gift']), - 'title': random_string(255), - 'accession_number': '2018.184', - 'start_date': random_date(1960), - 'extent_files': '14', - 'appraisal_note': random_string(150), - 'language': language.id, - 'creators': [creator.id], - 'form-0-id': creator.id, - 'form-MIN_NUM_FORMS': 0, - 'form-0-name': creator.name, - 'form-TOTAL_FORMS': 1, - 'form-INITIAL_FORMS': 1, - 'form-MAX_NUM_FORMS': 1000, - 'form-0-type': 'organization', + "use_restrictions": random_string(100), + "access_restrictions": random_string(100), + "resource": "http://example.org", + "description": random_string(150), + "end_date": random_date(1990), + "extent_size": "17275340", + "acquisition_type": random.choice(["donation", "deposit", "gift"]), + "title": random_string(255), + "accession_number": "2018.184", + "start_date": random_date(1960), + "extent_files": "14", + "appraisal_note": random_string(150), + "language": language.id, + "creators": [creator.id], + "form-0-id": creator.id, + "form-MIN_NUM_FORMS": 0, + "form-0-name": creator.name, + "form-TOTAL_FORMS": 1, + "form-INITIAL_FORMS": 1, + "form-MAX_NUM_FORMS": 1000, + "form-0-type": "organization", } return accession_data diff --git a/aurora/bag_transfer/test/setup.py b/aurora/bag_transfer/test/setup.py index e27e1adb..0ca8b537 100644 --- a/aurora/bag_transfer/test/setup.py +++ b/aurora/bag_transfer/test/setup.py @@ -1,135 +1,138 @@ import random -from bag_transfer.rights.models import RightsStatementCopyright, RightsStatementLicense, RightsStatementOther, RightsStatementStatute +from bag_transfer.rights.models import ( + RightsStatementCopyright, + RightsStatementLicense, + RightsStatementOther, + RightsStatementStatute, +) -POTUS_NAMES = [ - 'Ford', - 'Obama', - 'Trump', - 'Bush', - 'Clinton' -] -COMPANY_SUFFIX = [ - 'Foundation', 'Group', 'Org' -] +POTUS_NAMES = ["Ford", "Obama", "Trump", "Bush", "Clinton"] +COMPANY_SUFFIX = ["Foundation", "Group", "Org"] TEST_ORG_COUNT = 3 # tuple of tuples # (str that test bag starts with, ecode, test on bag checker, test on transfer routine) -bags_ref = ( +BAGS_REF = ( # ('invalid 0) @@ -74,118 +84,136 @@ def test_bagitprofiles(self): profile = random.choice(self.bagitprofiles) org = profile.applies_to_organization - response = self.client.get(reverse('orgs:bagit-profiles-add', kwargs={'pk': self.orgs[0].pk})) + response = self.client.get( + reverse("orgs:bagit-profiles-add", kwargs={"pk": self.orgs[0].pk}) + ) self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('orgs:bagit-profiles-edit', kwargs={'pk': org.pk, 'profile_pk': profile.pk})) + response = self.client.get( + reverse( + "orgs:bagit-profiles-edit", + kwargs={"pk": org.pk, "profile_pk": profile.pk}, + ) + ) self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('organization-bagit-profiles', kwargs={'pk': org.pk})) + response = self.client.get( + reverse("organization-bagit-profiles", kwargs={"pk": org.pk}) + ) self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('bagitprofile-list')) + response = self.client.get(reverse("bagitprofile-list")) self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('organization-bagit-profiles/(?P[0-9]+)', kwargs={'pk': org.pk, 'number': profile.pk})) + response = self.client.get( + reverse( + "organization-bagit-profiles-detail", + kwargs={"pk": org.pk, "number": profile.pk}, + ) + ) self.assertEqual(response.status_code, 200) # Creating new BagItProfile organization = random.choice(self.orgs) new_request = self.client.post( - reverse('orgs:bagit-profiles-add', kwargs={'pk': organization.pk}), { - 'contact_email': 'archive@rockarch.org', - 'source_organization': self.user.org.pk, - 'applies_to_organization': organization.pk, - 'allow_fetch': random.choice([True, False]), - 'external_description': helpers.random_string(100), - 'serialization': random.choice(['forbidden', 'required', 'optional']), - 'version': 0, - - 'bag_info-INITIAL_FORMS': 0, - 'bag_info-TOTAL_FORMS': 1, - 'bag_info-0-required': random.choice([True, False]), - 'bag_info-0-field': random.choice(BAGINFO_FIELD_CHOICES)[0], - 'bag_info-0-repeatable': random.choice([True, False]), - 'nested_bag_info-0_bagitprofilebaginfovalues_set-0-name': helpers.random_string(20), - 'nested_bag_info-0_bagitprofilebaginfovalues_set-TOTAL_FORMS': 1, - 'nested_bag_info-0_bagitprofilebaginfovalues_set-INITIAL_FORMS': 0, - - 'serialization-INITIAL_FORMS': 0, - 'serialization-TOTAL_FORMS': 1, - 'serialization-0-name': random.choice(['application/zip', 'application/x-tar', 'application/x-gzip']), - - 'tag_files-TOTAL_FORMS': 1, - 'tag_files-INITIAL_FORMS': 0, - 'tag_files-0-name': helpers.random_string(20), - - 'tag_manifests-TOTAL_FORMS': 1, - 'tag_manifests-INITIAL_FORMS': 0, - 'tag_manifests-0-name': random.choice(['sha256', 'md5']), - - 'version-TOTAL_FORMS': 1, - 'version-INITIAL_FORMS': 0, - 'version-0-name': random.choice(['0.96', 0.97]), - - 'manifests-TOTAL_FORMS': 1, - 'manifests-INITIAL_FORMS': 0, - 'manifests-0-name': random.choice(['sha256', 'md5']), - }) - self.assertEqual( - new_request.status_code, 302, "Request was not redirected") + reverse("orgs:bagit-profiles-add", kwargs={"pk": organization.pk}), + { + "contact_email": "archive@rockarch.org", + "source_organization": self.user.org.pk, + "applies_to_organization": organization.pk, + "allow_fetch": random.choice([True, False]), + "external_description": helpers.random_string(100), + "serialization": random.choice(["forbidden", "required", "optional"]), + "version": 0, + "bag_info-INITIAL_FORMS": 0, + "bag_info-TOTAL_FORMS": 1, + "bag_info-0-required": random.choice([True, False]), + "bag_info-0-field": random.choice(BAGINFO_FIELD_CHOICES)[0], + "bag_info-0-repeatable": random.choice([True, False]), + "nested_bag_info-0_bagitprofilebaginfovalues_set-0-name": helpers.random_string( + 20 + ), + "nested_bag_info-0_bagitprofilebaginfovalues_set-TOTAL_FORMS": 1, + "nested_bag_info-0_bagitprofilebaginfovalues_set-INITIAL_FORMS": 0, + "serialization-INITIAL_FORMS": 0, + "serialization-TOTAL_FORMS": 1, + "serialization-0-name": random.choice( + ["application/zip", "application/x-tar", "application/x-gzip"] + ), + "tag_files-TOTAL_FORMS": 1, + "tag_files-INITIAL_FORMS": 0, + "tag_files-0-name": helpers.random_string(20), + "tag_manifests-TOTAL_FORMS": 1, + "tag_manifests-INITIAL_FORMS": 0, + "tag_manifests-0-name": random.choice(["sha256", "sha512"]), + "version-TOTAL_FORMS": 1, + "version-INITIAL_FORMS": 0, + "version-0-name": random.choice(["0.96", 0.97]), + "manifests-TOTAL_FORMS": 1, + "manifests-INITIAL_FORMS": 0, + "manifests-0-name": random.choice(["sha256", "sha512"]), + "manifests_allowed-TOTAL_FORMS": 1, + "manifests_allowed-INITIAL_FORMS": 0, + "manifests_allowed-0-name": random.choice(["sha256", "sha512"]), + }, + ) + self.assertEqual(new_request.status_code, 302, "Request was not redirected") # Updating BagItProfile profile = BagItProfile.objects.last() update_request = self.client.post( - reverse('orgs:bagit-profiles-edit', kwargs={'pk': organization.pk, 'profile_pk': profile.pk}), { - 'contact_email': 'archive@rockarch.org', - 'source_organization': self.user.org.pk, - 'applies_to_organization': organization.pk, - 'allow_fetch': random.choice([True, False]), - 'external_description': helpers.random_string(100), - 'serialization': 'optional', - 'version': 1, - - 'bag_info-INITIAL_FORMS': 1, - 'bag_info-TOTAL_FORMS': 1, - 'bag_info-0-id': 1, - 'bag_info-0-required': True, - 'bag_info-0-field': 'source_organization', - 'bag_info-0-repeatable': False, - 'nested_bag_info-0_bagitprofilebaginfovalues_set-0-name': 'Ford Foundation', - 'nested_bag_info-0_bagitprofilebaginfovalues_set-0-id': 1, - 'nested_bag_info-0_bagitprofilebaginfovalues_set-TOTAL_FORMS': 1, - 'nested_bag_info-0_bagitprofilebaginfovalues_set-INITIAL_FORMS': 1, - - 'serialization-INITIAL_FORMS': 1, - 'serialization-TOTAL_FORMS': 3, - 'serialization-0-id': 1, - 'serialization-0-name': 'application/zip', - 'serialization-1-name': 'application/x-tar', - 'serialization-2-name': 'application/x-gzip', - - 'tag_files-TOTAL_FORMS': 1, - 'tag_files-INITIAL_FORMS': 1, - 'tag_files-0-id': 1, - 'tag_files-0-DELETE': True, - - 'tag_manifests-TOTAL_FORMS': 1, - 'tag_manifests-INITIAL_FORMS': 1, - 'tag_manifests-0-id': 1, - 'tag_manifests-0-DELETE': True, - - 'version-TOTAL_FORMS': 2, - 'version-INITIAL_FORMS': 1, - 'version-0-id': 1, - 'version-0-name': '0.96', - 'version-1-name': 0.97, - - 'manifests-TOTAL_FORMS': 0, - 'manifests-INITIAL_FORMS': 1, - 'manifests-0-id': 1, - 'manifests-0-DELETE': True, - }) - self.assertEqual( - update_request.status_code, 302, "Request was not redirected") + reverse( + "orgs:bagit-profiles-edit", + kwargs={"pk": organization.pk, "profile_pk": profile.pk}, + ), + { + "contact_email": "archive@rockarch.org", + "source_organization": self.user.org.pk, + "applies_to_organization": organization.pk, + "allow_fetch": random.choice([True, False]), + "external_description": helpers.random_string(100), + "serialization": "optional", + "version": 1, + "bag_info-INITIAL_FORMS": 1, + "bag_info-TOTAL_FORMS": 1, + "bag_info-0-id": 1, + "bag_info-0-required": True, + "bag_info-0-field": "source_organization", + "bag_info-0-repeatable": False, + "nested_bag_info-0_bagitprofilebaginfovalues_set-0-name": "Ford Foundation", + "nested_bag_info-0_bagitprofilebaginfovalues_set-0-id": 1, + "nested_bag_info-0_bagitprofilebaginfovalues_set-TOTAL_FORMS": 1, + "nested_bag_info-0_bagitprofilebaginfovalues_set-INITIAL_FORMS": 1, + "serialization-INITIAL_FORMS": 1, + "serialization-TOTAL_FORMS": 3, + "serialization-0-id": 1, + "serialization-0-name": "application/zip", + "serialization-1-name": "application/x-tar", + "serialization-2-name": "application/x-gzip", + "tag_files-TOTAL_FORMS": 1, + "tag_files-INITIAL_FORMS": 1, + "tag_files-0-id": 1, + "tag_files-0-DELETE": True, + "tag_manifests-TOTAL_FORMS": 1, + "tag_manifests-INITIAL_FORMS": 1, + "tag_manifests-0-id": 1, + "tag_manifests-0-DELETE": True, + "version-TOTAL_FORMS": 2, + "version-INITIAL_FORMS": 1, + "version-0-id": 1, + "version-0-name": "0.96", + "version-1-name": 0.97, + "manifests-TOTAL_FORMS": 0, + "manifests-INITIAL_FORMS": 1, + "manifests-0-id": 1, + "manifests-0-DELETE": True, + "manifests_allowed-TOTAL_FORMS": 0, + "manifests_allowed-INITIAL_FORMS": 1, + "manifests_allowed-0-id": 1, + "manifests_allowed-0-DELETE": True, + }, + ) + self.assertEqual(update_request.status_code, 302, "Request was not redirected") # Ensure bags are validated - bag_paths = helpers.create_target_bags('valid_bag', settings.TEST_BAGS_DIR, self.orgs[0]) + helpers.create_target_bags("valid_bag", settings.TEST_BAGS_DIR, self.orgs[0]) tr = helpers.run_transfer_routine() for transfer in tr.transfers: archive = helpers.create_test_archive(transfer, self.orgs[0]) @@ -194,13 +222,30 @@ def test_bagitprofiles(self): # Delete bagit profile delete_request = self.client.get( - reverse('orgs:bagit-profiles-api', kwargs={'pk': organization.pk, 'profile_pk': profile.pk, 'action': 'delete'}), - {}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + reverse( + "orgs:bagit-profiles-api", + kwargs={ + "pk": organization.pk, + "profile_pk": profile.pk, + "action": "delete", + }, + ), + {}, + HTTP_X_REQUESTED_WITH="XMLHttpRequest", + ) self.assertEqual(delete_request.status_code, 200) - resp = ast.literal_eval(delete_request.content) - self.assertEqual(resp['success'], 1) + resp = delete_request.json() + self.assertEqual(resp["success"], 1) non_ajax_request = self.client.get( - reverse('orgs:bagit-profiles-api', kwargs={'pk': organization.pk, 'profile_pk': profile.pk, 'action': 'delete'})) + reverse( + "orgs:bagit-profiles-api", + kwargs={ + "pk": organization.pk, + "profile_pk": profile.pk, + "action": "delete", + }, + ) + ) self.assertEqual(non_ajax_request.status_code, 404) def tearDown(self): diff --git a/aurora/bag_transfer/test/test_bags.py b/aurora/bag_transfer/test/test_bags.py index 29ed42b8..0454419e 100644 --- a/aurora/bag_transfer/test/test_bags.py +++ b/aurora/bag_transfer/test/test_bags.py @@ -1,7 +1,4 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals import os -import pwd import random from django.test import TransactionTestCase, Client @@ -9,32 +6,34 @@ from django.urls import reverse from bag_transfer.test import helpers -from bag_transfer.test.setup import * -from bag_transfer.lib.transfer_routine import * -from bag_transfer.lib.files_helper import * +from bag_transfer.test.setup import TEST_ORG_COUNT, BAGS_REF +from bag_transfer.lib.transfer_routine import TransferRoutine +from bag_transfer.lib.files_helper import remove_file_or_dir from bag_transfer.lib.bag_checker import bagChecker -from bag_transfer.models import Archives, User +from bag_transfer.models import Archives, BAGLog, Organization, User class BagTestCase(TransactionTestCase): def setUp(self): self.orgs = helpers.create_test_orgs(org_count=TEST_ORG_COUNT) self.baglogcodes = helpers.create_test_baglogcodes() - self.groups = helpers.create_test_groups(['managing_archivists']) - self.user = helpers.create_test_user(username=settings.TEST_USER['USERNAME'], org=random.choice(self.orgs)) + self.groups = helpers.create_test_groups(["managing_archivists"]) + self.user = helpers.create_test_user( + username=settings.TEST_USER["USERNAME"], org=random.choice(self.orgs) + ) for group in self.groups: self.user.groups.add(group) self.user.is_staff = True - self.user.set_password(settings.TEST_USER['PASSWORD']) + self.user.set_password(settings.TEST_USER["PASSWORD"]) self.user.save() self.client = Client() def test_bags(self): - test_on_bagchecker = [r[0] for r in bags_ref if len(r) > 2 and r[2]] - test_on_transfer_routine = [r[0] for r in bags_ref if len(r) > 3 and r[3]] + test_on_bagchecker = [r[0] for r in BAGS_REF if len(r) > 2 and r[2]] + test_on_transfer_routine = [r[0] for r in BAGS_REF if len(r) > 3 and r[3]] - for ref in bags_ref: + for ref in BAGS_REF: # creates test bags helpers.create_target_bags(ref[0], settings.TEST_BAGS_DIR, self.orgs[0]) @@ -50,7 +49,7 @@ def test_bags(self): # testing valid bag still valid up until this point for trans in tr.transfers: - if not trans['file_name'].startswith(ref[0]): + if not trans["file_name"].startswith(ref[0]): continue ############### @@ -58,14 +57,13 @@ def test_bags(self): ############### # a valid bag should be valid until this point so test - if ref[0] == 'valid_bag': - self.assertFalse(trans['auto_fail']) + if ref[0] == "valid_bag": + self.assertFalse(trans["auto_fail"]) else: - - if r[0] in test_on_transfer_routine: - print ref - self.assertTrue(trans['auto_fail']) - self.assertEquals(ref[1], trans['auto_fail_code']) + if ref[0] in test_on_transfer_routine: + print(ref) + self.assertTrue(trans["auto_fail"]) + self.assertEqual(ref[1], trans["auto_fail_code"]) ############### # END -- TEST RESULTS OF RUN ROUTINE @@ -77,22 +75,23 @@ def test_bags(self): self.assertIsNot(False, archive.machine_file_identifier) # okay to stop here since archive saved - if trans['auto_fail']: + if trans["auto_fail"]: continue bag = bagChecker(archive) passed_all_results = bag.bag_passed_all() # deleting path in processing and tmp dir - remove_file_or_dir(os.path.join(settings.TRANSFER_EXTRACT_TMP, archive.bag_it_name)) + remove_file_or_dir( + os.path.join(settings.TRANSFER_EXTRACT_TMP, archive.bag_it_name) + ) remove_file_or_dir(archive.machine_file_path) - ############### # START -- TEST RESULTS OF Bag Checker ############### - if ref[0] in ['valid_bag', 'no_metadata_file']: + if ref[0] in ["valid_bag", "no_metadata_file"]: self.assertTrue(passed_all_results) else: @@ -100,8 +99,8 @@ def test_bags(self): self.assertFalse(passed_all_results) if ref[0] in test_on_bagchecker: - print ref - self.assertEquals(ref[1],bag.ecode) + print(ref) + self.assertEqual(ref[1], bag.ecode) ############### # END -- TEST RESULTS OF Bag Checker @@ -111,23 +110,50 @@ def test_bags(self): # START -- TEST Views ############### - self.client.login(username=self.user.username, password=settings.TEST_USER['PASSWORD']) - for view in ['organization-list', 'archives-list', 'baglog-list', 'user-list', 'user-current']: + self.client.login( + username=self.user.username, password=settings.TEST_USER["PASSWORD"] + ) + for view in [ + "organization-list", + "archives-list", + "baglog-list", + "user-list", + "user-current", + ]: resp = self.client.get(reverse(view)) self.assertEqual(resp.status_code, 200) - resp = self.client.get(reverse('organization-detail', kwargs={'pk': random.choice(Organization.objects.all()).pk})) + resp = self.client.get( + reverse( + "organization-detail", + kwargs={"pk": random.choice(Organization.objects.all()).pk}, + ) + ) self.assertEqual(resp.status_code, 200) - resp = self.client.get(reverse('archives-detail', kwargs={'pk': random.choice(Archives.objects.all()).pk})) + resp = self.client.get( + reverse( + "archives-detail", + kwargs={"pk": random.choice(Archives.objects.all()).pk}, + ) + ) self.assertEqual(resp.status_code, 200) - resp = self.client.get(reverse('baglog-detail', kwargs={'pk': random.choice(BAGLog.objects.all()).pk})) + resp = self.client.get( + reverse( + "baglog-detail", + kwargs={"pk": random.choice(BAGLog.objects.all()).pk}, + ) + ) self.assertEqual(resp.status_code, 200) - resp = self.client.get(reverse('user-detail', kwargs={'pk': random.choice(User.objects.all()).pk})) + resp = self.client.get( + reverse( + "user-detail", + kwargs={"pk": random.choice(User.objects.all()).pk}, + ) + ) self.assertEqual(resp.status_code, 200) - def tearDown(self): helpers.delete_test_orgs(self.orgs) diff --git a/aurora/bag_transfer/test/test_cron.py b/aurora/bag_transfer/test/test_cron.py new file mode 100644 index 00000000..d73c0bb4 --- /dev/null +++ b/aurora/bag_transfer/test/test_cron.py @@ -0,0 +1,49 @@ +import os +import pwd +import random + +import bagit +from django.test import TransactionTestCase, Client +from django.conf import settings + +from bag_transfer.lib.cron import DiscoverTransfers, DeliverTransfers +from bag_transfer.test import helpers +from bag_transfer.test.setup import BAGS_REF, TEST_ORG_COUNT +from bag_transfer.models import Archives, User + + +class CronTestCase(TransactionTestCase): + def setUp(self): + self.orgs = helpers.create_test_orgs(org_count=1) + self.baglogcodes = helpers.create_test_baglogcodes() + self.groups = helpers.create_test_groups(['managing_archivists']) + self.user = helpers.create_test_user(username=settings.TEST_USER['USERNAME'], org=random.choice(self.orgs)) + for group in self.groups: + self.user.groups.add(group) + self.user.is_staff = True + self.user.set_password(settings.TEST_USER['PASSWORD']) + self.user.save() + self.client = Client() + + def test_cron(self): + for ref in BAGS_REF: + helpers.create_target_bags(ref[0], settings.TEST_BAGS_DIR, self.orgs[0], username=self.user.username) + discovered = DiscoverTransfers().do() + self.assertIsNot(False, discovered) + + for archive in Archives.objects.filter(process_status=Archives.VALIDATED): + archive.process_status = Archives.ACCESSIONING_STARTED + archive.save() + delivered = DeliverTransfers().do() + self.assertIsNot(False, delivered) + self.assertEqual(len(Archives.objects.filter(process_status=Archives.ACCESSIONING_STARTED)), 0) + self.assertEqual( + len(Archives.objects.filter(process_status=Archives.DELIVERED)), + len(os.listdir(settings.DELIVERY_QUEUE_DIR)) + ) + for bag_path in os.listdir(settings.DELIVERY_QUEUE_DIR): + bag = bagit.Bag(os.path.join(settings.DELIVERY_QUEUE_DIR, bag_path)) + self.assertTrue('Origin' in bag.bag_info) + + def tearDown(self): + helpers.delete_test_orgs(self.orgs) diff --git a/aurora/bag_transfer/test/test_rights.py b/aurora/bag_transfer/test/test_rights.py index 9da9ee8d..6220e1e1 100644 --- a/aurora/bag_transfer/test/test_rights.py +++ b/aurora/bag_transfer/test/test_rights.py @@ -1,19 +1,11 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import ast -from os.path import join import random -from urlparse import urljoin from django.test import TestCase, Client from django.conf import settings from django.urls import reverse from bag_transfer.test import helpers, setup -from bag_transfer.rights.forms import * -from bag_transfer.rights.models import * -from bag_transfer.rights.views import * +from bag_transfer.rights.models import RightsStatement from bag_transfer.lib.bag_checker import bagChecker @@ -23,25 +15,31 @@ def setUp(self): self.record_types = helpers.create_test_record_types(setup.record_types) self.baglogcodes = helpers.create_test_baglogcodes() self.orgs = helpers.create_test_orgs(org_count=1) - self.bags = helpers.create_target_bags('valid_bag', settings.TEST_BAGS_DIR, self.orgs[0]) + self.bags = helpers.create_target_bags( + "valid_bag", settings.TEST_BAGS_DIR, self.orgs[0] + ) tr = helpers.run_transfer_routine() self.archives = [] for transfer in tr.transfers: archive = helpers.create_test_archive(transfer, self.orgs[0]) self.archives.append(archive) - self.groups = helpers.create_test_groups(['managing_archivists']) - self.user = helpers.create_test_user(username=settings.TEST_USER['USERNAME'], org=random.choice(self.orgs)) + self.groups = helpers.create_test_groups(["managing_archivists"]) + self.user = helpers.create_test_user( + username=settings.TEST_USER["USERNAME"], org=random.choice(self.orgs) + ) for group in self.groups: self.user.groups.add(group) self.user.is_staff = True - self.user.set_password(settings.TEST_USER['PASSWORD']) + self.user.set_password(settings.TEST_USER["PASSWORD"]) self.user.save() def test_rights(self): for record_type in self.record_types: helpers.create_rights_statement( - record_type=record_type, org=random.choice(self.orgs), - rights_basis=random.choice(setup.rights_bases)) + record_type=record_type, + org=random.choice(self.orgs), + rights_basis=random.choice(setup.rights_bases), + ) self.assertEqual(len(RightsStatement.objects.all()), len(self.record_types)) for rights_statement in RightsStatement.objects.all(): @@ -56,7 +54,7 @@ def test_rights(self): # Rights statements are cloned when assigned, so we should have more of them now assigned_length = len(RightsStatement.objects.all()) - self.assertEqual(assigned_length, len(setup.record_types)+len(self.archives)) + self.assertEqual(assigned_length, len(setup.record_types) + len(self.archives)) # Test GET views self.get_requests() @@ -70,7 +68,7 @@ def test_rights(self): # Delete rights statement to_delete = random.choice(RightsStatement.objects.all()) self.assertTrue(to_delete.delete()) - self.assertEqual(len(RightsStatement.objects.all()), assigned_length-1) + self.assertEqual(len(RightsStatement.objects.all()), assigned_length - 1) ############################################# # Functions used in Rights Statements tests # @@ -79,11 +77,14 @@ def test_rights(self): def assemble_rights_statement(self, rights_statement): helpers.create_rights_info(rights_statement=rights_statement) helpers.create_rights_granted( - rights_statement=rights_statement, granted_count=random.randint(1, 2)) + rights_statement=rights_statement, granted_count=random.randint(1, 2) + ) # Make sure correct rights info objects were assigned rights_basis_type = setup.get_rights_basis_type(rights_statement) - self.assertIsInstance(rights_statement.get_rights_info_object(), rights_basis_type) + self.assertIsInstance( + rights_statement.get_rights_info_object(), rights_basis_type + ) # Make sure RightsGranted objects were created self.assertIsNot(False, rights_statement.get_rights_granted_objects()) @@ -95,66 +96,92 @@ def assemble_rights_statement(self, rights_statement): self.assertTrue(org.rights_statements) def get_requests(self): - self.client.login(username=self.user.username, password=settings.TEST_USER['PASSWORD']) - for view in ['rights:edit', 'rights:detail']: + self.client.login( + username=self.user.username, password=settings.TEST_USER["PASSWORD"] + ) + for view in ["rights:edit", "rights:detail"]: rights_statement = random.choice(RightsStatement.objects.all()) - response = self.client.get(reverse(view, kwargs={'pk': rights_statement.pk})) + response = self.client.get( + reverse(view, kwargs={"pk": rights_statement.pk}) + ) self.assertEqual(response.status_code, 200) - add_response = self.client.get(reverse('rights:add'), {'org': self.orgs[0].pk}) + add_response = self.client.get(reverse("rights:add"), {"org": self.orgs[0].pk}) self.assertEqual(add_response.status_code, 200) - resp = self.client.get(reverse('organization-rights-statements', kwargs={'pk': self.orgs[0].pk})) + resp = self.client.get( + reverse("organization-rights-statements", kwargs={"pk": self.orgs[0].pk}) + ) self.assertEqual(resp.status_code, 200) def post_requests(self): # Creating new RightsStatements post_organization = random.choice(self.orgs) new_basis_data = random.choice(setup.basis_data) - new_basis_data['organization'] = post_organization.pk + new_basis_data["organization"] = post_organization.pk new_basis_data.update(setup.grant_data) previous_length = len(RightsStatement.objects.all()) new_request = self.client.post( - urljoin(reverse('rights:add'), '?org={}'.format(post_organization.pk)), new_basis_data) - self.assertEqual( - new_request.status_code, 302, "Request was not successful") + "{}{}".format( + reverse("rights:add"), "?org={}".format(post_organization.pk) + ), + new_basis_data, + ) + self.assertEqual(new_request.status_code, 302, "Request was not successful") self.assertEqual( - len(RightsStatement.objects.all()), previous_length+1, - "{} Rights Statements were created, correct number is 1".format(len(RightsStatement.objects.all())-previous_length)) + len(RightsStatement.objects.all()), + previous_length + 1, + "{} Rights Statements were created, correct number is 1".format( + len(RightsStatement.objects.all()) - previous_length + ), + ) self.assertEqual( - RightsStatement.objects.last().rights_basis, new_basis_data['rights_basis'], - "Rights bases do not match") + RightsStatement.objects.last().rights_basis, + new_basis_data["rights_basis"], + "Rights bases do not match", + ) # Updating RightsStatements rights_statement = RightsStatement.objects.last() updated_basis_data = new_basis_data - if updated_basis_data['rights_basis'] == 'Other': - basis_set = 'rightsstatementother_set' - note_key = 'other_rights_note' + if updated_basis_data["rights_basis"] == "Other": + basis_set = "rightsstatementother_set" + note_key = "other_rights_note" else: - basis_set = 'rightsstatement{}_set'.format(updated_basis_data['rights_basis'].lower()) - note_key = '{}_note'.format(updated_basis_data['rights_basis'].lower()) - updated_basis_data[basis_set+'-0-'+note_key] = 'Revised test note' + basis_set = "rightsstatement{}_set".format( + updated_basis_data["rights_basis"].lower() + ) + note_key = "{}_note".format(updated_basis_data["rights_basis"].lower()) + updated_basis_data[basis_set + "-0-" + note_key] = "Revised test note" basis_objects = getattr(rights_statement, basis_set).all() - updated_basis_data[basis_set+'-0-id'] = basis_objects[0].pk + updated_basis_data[basis_set + "-0-id"] = basis_objects[0].pk update_request = self.client.post( - reverse('rights:edit', kwargs={'pk': rights_statement.pk}), - updated_basis_data) - self.assertEqual( - update_request.status_code, 302, "Request was not redirected") + reverse("rights:edit", kwargs={"pk": rights_statement.pk}), + updated_basis_data, + ) + self.assertEqual(update_request.status_code, 302, "Request was not redirected") self.assertEqual( - len(RightsStatement.objects.all()), previous_length+1, - "Another rights statement was mistakenly created") + len(RightsStatement.objects.all()), + previous_length + 1, + "Another rights statement was mistakenly created", + ) def ajax_requests(self): rights_statement = RightsStatement.objects.last() delete_request = self.client.get( - reverse('rights:api', kwargs={'pk': rights_statement.pk, 'action': 'delete'}), - {}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + reverse( + "rights:api", kwargs={"pk": rights_statement.pk, "action": "delete"} + ), + {}, + HTTP_X_REQUESTED_WITH="XMLHttpRequest", + ) self.assertEqual(delete_request.status_code, 200) - resp = ast.literal_eval(delete_request.content) - self.assertEqual(resp['success'], 1) + resp = delete_request.json() + self.assertEqual(resp["success"], 1) non_ajax_request = self.client.get( - reverse('rights:api', kwargs={'pk': rights_statement.pk, 'action': 'delete'})) + reverse( + "rights:api", kwargs={"pk": rights_statement.pk, "action": "delete"} + ) + ) self.assertEqual(non_ajax_request.status_code, 404) def tearDown(self): diff --git a/aurora/bag_transfer/test/test_transfer_routine.py b/aurora/bag_transfer/test/test_transfer_routine.py index cb17092a..22a2a57f 100644 --- a/aurora/bag_transfer/test/test_transfer_routine.py +++ b/aurora/bag_transfer/test/test_transfer_routine.py @@ -3,8 +3,8 @@ from django.test import TransactionTestCase from bag_transfer.test import helpers -from bag_transfer.lib.transfer_routine import * -from bag_transfer.lib.files_helper import * +from bag_transfer.lib.transfer_routine import TransferRoutine +from bag_transfer.lib.files_helper import remove_file_or_dir class TransferRoutineTestCase(TransactionTestCase): @@ -31,23 +31,25 @@ def tearDown(self): helpers.delete_test_orgs(self.orgs) def sub_test_db_has_active_orgs(self): - self.change_all_orgs_in_list_status(self.orgs, False) # turns all test orgs inactive - self.assertFalse(self.TR.setup_routine()) # test setup catches inactives - self.assertTrue(self.TR.has_setup_err) # 2nd check that it was an error - self.change_all_orgs_in_list_status(self.orgs, True) #reverts back to True + self.change_all_orgs_in_list_status( + self.orgs, False + ) # turns all test orgs inactive + self.assertFalse(self.TR.setup_routine()) # test setup catches inactives + self.assertTrue(self.TR.has_setup_err) # 2nd check that it was an error + self.change_all_orgs_in_list_status(self.orgs, True) # reverts back to True def sub_test_verify_organizations_paths(self): """removes directory from an org and check to see if item removed from active orgs""" - self.TR.has_active_organizations() #resets the active orgs + self.TR.has_active_organizations() # resets the active orgs original_active_count = len(self.TR.active_organizations) last_org = self.TR.active_organizations[0] last_org_upload_paths = last_org.org_machine_upload_paths() - random_index = random.randrange(0,len(last_org_upload_paths)) + random_index = random.randrange(0, len(last_org_upload_paths)) remove_file_or_dir(last_org_upload_paths[random_index]) self.TR.verify_organizations_paths() - self.assertNotEqual(original_active_count,len(self.TR.active_organizations)) + self.assertNotEqual(original_active_count, len(self.TR.active_organizations)) - def change_all_orgs_in_list_status(self, orgs ={}, Status=False): + def change_all_orgs_in_list_status(self, orgs={}, Status=False): for org in orgs: org.is_active = Status org.save() diff --git a/aurora/bag_transfer/test/test_users_orgs.py b/aurora/bag_transfer/test/test_users_orgs.py index 3bee0d94..fedbc964 100644 --- a/aurora/bag_transfer/test/test_users_orgs.py +++ b/aurora/bag_transfer/test/test_users_orgs.py @@ -1,21 +1,12 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import ast -import json -from os.path import join import random -from urlparse import urljoin from django.test import TestCase, Client from django.conf import settings from django.urls import reverse from bag_transfer.test import helpers -from bag_transfer.models import Archives, User, Organization +from bag_transfer.models import User, Organization from bag_transfer.test import setup -from bag_transfer.appraise.views import AppraiseView -from bag_transfer.lib.bag_checker import bagChecker org_count = 1 @@ -24,7 +15,9 @@ class UserOrgTestCase(TestCase): def setUp(self): self.client = Client() self.orgs = helpers.create_test_orgs(org_count=org_count) - self.bags = helpers.create_target_bags('valid_bag', settings.TEST_BAGS_DIR, self.orgs[0]) + self.bags = helpers.create_target_bags( + "valid_bag", settings.TEST_BAGS_DIR, self.orgs[0] + ) tr = helpers.run_transfer_routine() self.archives = [] for transfer in tr.transfers: @@ -32,29 +25,58 @@ def setUp(self): self.archives.append(archive) def test_users(self): - for user in (('donor', 'donor'), ('managing_archivists', 'manager'), ('appraisal_archivists', 'appraiser'), ('accessioning_archivists', 'accessioner')): + for user in ( + ("donor", "donor"), + ("managing_archivists", "manager"), + ("appraisal_archivists", "appraiser"), + ("accessioning_archivists", "accessioner"), + ): groups = helpers.create_test_groups([user[0]]) - user = helpers.create_test_user(username=user[1], org=random.choice(self.orgs)) + user = helpers.create_test_user( + username=user[1], org=random.choice(self.orgs) + ) for group in groups: user.groups.add(group) - if group.name in ['managing_archivists', 'appraisal_archivists', 'accessioning_archivists']: + if group.name in [ + "managing_archivists", + "appraisal_archivists", + "accessioning_archivists", + ]: user.is_staff = True - user.set_password(settings.TEST_USER['PASSWORD']) + user.set_password(settings.TEST_USER["PASSWORD"]) user.save() # Username, assertTrue methods, assertFalse methods user_list = ( - ('donor', [], ['is_archivist', 'can_appraise', 'is_manager'], ''), - ('manager', ['is_archivist', 'can_appraise', 'is_manager'], [], 'MANAGING'), - ('accessioner', ['is_archivist'], ['can_appraise', 'is_manager'], 'ACCESSIONER'), - ('appraiser', ['is_archivist', 'can_appraise'], ['is_manager'], 'APPRAISER'), + ("donor", [], ["is_archivist", "can_appraise", "is_manager"], ""), + ("manager", ["is_archivist", "can_appraise", "is_manager"], [], "MANAGING"), + ( + "accessioner", + ["is_archivist"], + ["can_appraise", "is_manager"], + "ACCESSIONER", + ), + ( + "appraiser", + ["is_archivist", "can_appraise"], + ["is_manager"], + "APPRAISER", + ), ) for u in user_list: user = User.objects.get(username=u[0]) for meth in u[1]: - self.assertTrue(getattr(user, meth)(), "User {} is unable to perform function {}".format(user, meth)) + self.assertTrue( + getattr(user, meth)(), + "User {} is unable to perform function {}".format(user, meth), + ) for meth in u[2]: - self.assertFalse(getattr(user, meth)(), "User {} should not be able to perform function {}".format(user, meth)) + self.assertFalse( + getattr(user, meth)(), + "User {} should not be able to perform function {}".format( + user, meth + ), + ) if len(u[3]) > 1: self.assertTrue(user.has_privs(u[3])) @@ -62,14 +84,18 @@ def test_users(self): self.user_views() def test_orgs(self): - groups = helpers.create_test_groups(['managing_archivists']) - user = helpers.create_test_user(username=settings.TEST_USER['USERNAME'], org=random.choice(self.orgs)) + groups = helpers.create_test_groups(["managing_archivists"]) + user = helpers.create_test_user( + username=settings.TEST_USER["USERNAME"], org=random.choice(self.orgs) + ) for group in groups: user.groups.add(group) user.is_staff = True - user.set_password(settings.TEST_USER['PASSWORD']) + user.set_password(settings.TEST_USER["PASSWORD"]) user.save() - self.client.login(username=user.username, password=settings.TEST_USER['PASSWORD']) + self.client.login( + username=user.username, password=settings.TEST_USER["PASSWORD"] + ) # Test Org views self.org_views() @@ -81,39 +107,50 @@ def tearDown(self): helpers.delete_test_orgs(self.orgs) def user_views(self): - user = User.objects.get(groups__name='managing_archivists') - self.client.login(username=user.username, password=settings.TEST_USER['PASSWORD']) + user = User.objects.get(groups__name="managing_archivists") + self.client.login( + username=user.username, password=settings.TEST_USER["PASSWORD"] + ) - for view in ['users:detail', 'users:edit']: - response = self.client.get(reverse(view, kwargs={'pk': random.choice(User.objects.all()).pk})) + for view in ["users:detail", "users:edit"]: + response = self.client.get( + reverse(view, kwargs={"pk": random.choice(User.objects.all()).pk}) + ) self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('users:add')) + response = self.client.get(reverse("users:add")) self.assertEqual(response.status_code, 200) user_data = setup.user_data - user_data['organization'] = random.choice(self.orgs) - response = self.client.post(reverse('users:add'), user_data) + user_data["organization"] = random.choice(self.orgs) + response = self.client.post(reverse("users:add"), user_data) self.assertTrue(response.status_code, 200) # make user inactive - user_data['active'] = False - response = self.client.post(reverse('users:edit', kwargs={'pk': random.choice(User.objects.all()).pk}), user_data) + user_data["active"] = False + response = self.client.post( + reverse("users:edit", kwargs={"pk": random.choice(User.objects.all()).pk}), + user_data, + ) self.assertTrue(response.status_code, 200) def org_views(self): - response = self.client.get(reverse('orgs:list')) + response = self.client.get(reverse("orgs:list")) self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['object_list']), org_count) - for view in ['orgs:detail', 'orgs:edit']: - response = self.client.get(reverse(view, kwargs={'pk': random.choice(self.orgs).pk})) + self.assertEqual(len(response.context["object_list"]), org_count) + for view in ["orgs:detail", "orgs:edit"]: + response = self.client.get( + reverse(view, kwargs={"pk": random.choice(self.orgs).pk}) + ) self.assertEqual(response.status_code, 200) org_data = setup.org_data - response = self.client.post(reverse('orgs:add'), org_data) + response = self.client.post(reverse("orgs:add"), org_data) self.assertTrue(response.status_code, 200) # make org inactive - org_data['active'] = False - response = self.client.post(reverse('orgs:edit', kwargs={'pk': random.choice(self.orgs).pk}), org_data) + org_data["active"] = False + response = self.client.post( + reverse("orgs:edit", kwargs={"pk": random.choice(self.orgs).pk}), org_data + ) self.assertTrue(response.status_code, 200) diff --git a/aurora/bag_transfer/transfers/urls.py b/aurora/bag_transfer/transfers/urls.py index a4a93a88..b46aa1dc 100644 --- a/aurora/bag_transfer/transfers/urls.py +++ b/aurora/bag_transfer/transfers/urls.py @@ -1,9 +1,16 @@ from django.conf.urls import url -from bag_transfer.transfers.views import * +from bag_transfer.transfers.views import ( + TransfersView, + TransferDataView, + TransferDataTableView, + TransferDetailView, +) + +app_name = "transfers" urlpatterns = [ - url(r'^$', TransfersView.as_view(), name='list'), - url(r'^csv/$', TransferDataView.as_view(), name='data'), - url(r'^datatable/$', TransferDataTableView.as_view(), name='datatable'), - url(r'^(?P\d+)$', TransferDetailView.as_view(), name='detail'), + url(r"^$", TransfersView.as_view(), name="list"), + url(r"^csv/$", TransferDataView.as_view(), name="data"), + url(r"^datatable/$", TransferDataTableView.as_view(), name="datatable"), + url(r"^(?P\d+)$", TransferDetailView.as_view(), name="detail"), ] diff --git a/aurora/bag_transfer/transfers/views.py b/aurora/bag_transfer/transfers/views.py index 06c7f2b1..09c08b21 100644 --- a/aurora/bag_transfer/transfers/views.py +++ b/aurora/bag_transfer/transfers/views.py @@ -1,20 +1,24 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals, division from django_datatables_view.base_datatable_view import BaseDatatableView from datetime import date from dateutil import tz from dateutil.relativedelta import relativedelta from django.views.generic import TemplateView, View, DetailView -from django.db.models import Sum from django.db.models.functions import Concat -from django.shortcuts import render -from django.utils.html import escape +from django.shortcuts import render, get_object_or_404 from bag_transfer.lib.view_helpers import file_size, label_class -from bag_transfer.models import Archives, Organization, User, BagInfoMetadata, DashboardMonthData, DashboardRecordTypeData -from bag_transfer.rights.models import RightsStatement -from bag_transfer.mixins.authmixins import LoggedInMixinDefaults, OrgReadViewMixin, ArchivistMixin +from bag_transfer.models import ( + Archives, + Organization, + User, + DashboardMonthData, + DashboardRecordTypeData, +) +from bag_transfer.mixins.authmixins import ( + LoggedInMixinDefaults, + OrgReadViewMixin, +) from bag_transfer.mixins.formatmixins import CSVResponseMixin @@ -23,118 +27,176 @@ class MainView(LoggedInMixinDefaults, TemplateView): def get_org_data(self, org, org_name, users): data = {} - data['name'] = org_name - data['users'] = [] - data['user_uploads'] = [] + data["name"] = org_name + data["users"] = [] + data["user_uploads"] = [] for user in users: user.uploads = Archives.objects.filter( - user_uploaded=user, - process_status__gte=Archives.TRANSFER_COMPLETED).count() - data['users'].append(user) - data['uploads'] = Archives.objects.filter( - process_status__gte=Archives.TRANSFER_COMPLETED, - organization__in=org).order_by('-created_time')[:15] - data['uploads_count'] = Archives.objects.filter( - process_status__gte=Archives.TRANSFER_COMPLETED, - organization__in=org).count() - data['validated_count'] = Archives.objects.filter( - process_status__gte=Archives.VALIDATED, - organization__in=org).count() - data['accepted_count'] = Archives.objects.filter( - process_status__gte=Archives.ACCEPTED, - organization__in=org).count() - data['accessioned_count'] = Archives.objects.filter( - process_status__gte=Archives.ACCESSIONING_COMPLETE, - organization__in=org).count() - data['month_labels'] = [] - data['upload_count_by_month'] = [] - data['upload_count_by_year'] = 0 - data['upload_size_by_month'] = [] - data['upload_size_by_year'] = 0 - data['record_types_by_year'] = [] + user_uploaded=user, process_status__gte=Archives.TRANSFER_COMPLETED + ).count() + data["users"].append(user) + data["uploads"] = Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, organization__in=org + ).order_by("-created_time")[:15] + data["uploads_count"] = Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, organization__in=org + ).count() + data["validated_count"] = Archives.objects.filter( + process_status__gte=Archives.VALIDATED, organization__in=org + ).count() + data["accepted_count"] = Archives.objects.filter( + process_status__gte=Archives.ACCEPTED, organization__in=org + ).count() + data["accessioned_count"] = Archives.objects.filter( + process_status__gte=Archives.ACCESSIONING_COMPLETE, organization__in=org + ).count() + data["month_labels"] = [] + data["upload_count_by_month"] = [] + data["upload_count_by_year"] = 0 + data["upload_size_by_month"] = [] + data["upload_size_by_year"] = 0 + data["record_types_by_year"] = [] today = date.today() current = today - relativedelta(years=1) - colors = ['#f56954', '#00a65a', '#f39c12', '#00c0ef', '#3c8dbc', '#d2d6de', - '#f56954', '#00a65a', '#f39c12', '#00c0ef', '#3c8dbc', '#d2d6de', - '#f56954', '#00a65a', '#f39c12', '#00c0ef', '#3c8dbc', '#d2d6de'] + colors = [ + "#f56954", + "#00a65a", + "#f39c12", + "#00c0ef", + "#3c8dbc", + "#d2d6de", + "#f56954", + "#00a65a", + "#f39c12", + "#00c0ef", + "#3c8dbc", + "#d2d6de", + "#f56954", + "#00a65a", + "#f39c12", + "#00c0ef", + "#3c8dbc", + "#d2d6de", + ] while current <= today: - sort_date = int(str(current.year)+str(current.month)) - if DashboardMonthData.objects.filter(organization__in=org, sort_date=sort_date).exists(): + sort_date = int(str(current.year) + str(current.month)) + if DashboardMonthData.objects.filter( + organization__in=org, sort_date=sort_date + ).exists(): upload_count = 0 upload_size = 0 - for month_data in DashboardMonthData.objects.filter(organization__in=org, sort_date=sort_date): + for month_data in DashboardMonthData.objects.filter( + organization__in=org, sort_date=sort_date + ): upload_count += month_data.upload_count upload_size += month_data.upload_size - data['month_labels'].append(str(month_data.month_label)) - data['upload_count_by_month'].append(upload_count) - data['upload_count_by_year'] += upload_count - data['upload_size_by_month'].append(upload_size) - data['upload_size_by_year'] += upload_size + data["month_labels"].append(str(month_data.month_label)) + data["upload_count_by_month"].append(upload_count) + data["upload_count_by_year"] += upload_count + data["upload_size_by_month"].append(upload_size) + data["upload_size_by_year"] += upload_size else: - data['month_labels'].append(current.strftime("%B")) - data['upload_count_by_month'].append(0) - data['upload_size_by_month'].append(0) + data["month_labels"].append(current.strftime("%B")) + data["upload_count_by_month"].append(0) + data["upload_size_by_month"].append(0) current += relativedelta(months=1) - for (n, label) in enumerate(set(DashboardRecordTypeData.objects.all().values_list('label', flat=True))): + for (n, label) in enumerate( + set(DashboardRecordTypeData.objects.all().values_list("label", flat=True)) + ): record_type_count = 0 - for count in DashboardRecordTypeData.objects.filter(label=label, organization__in=org).values_list('count', flat=True): + for count in DashboardRecordTypeData.objects.filter( + label=label, organization__in=org + ).values_list("count", flat=True): record_type_count += count - data['record_types_by_year'].append({"label": label, "value": record_type_count, "color": colors[n]}) - - data['size_trend'] = round((data['upload_size_by_month'][-1] - (data['upload_size_by_year']/12))/100, 2) - data['count_trend'] = round((data['upload_count_by_month'][-1] - (data['upload_count_by_year']/12))/100, 2) + data["record_types_by_year"].append( + {"label": label, "value": record_type_count, "color": colors[n]} + ) + + data["size_trend"] = round( + (data["upload_size_by_month"][-1] - (data["upload_size_by_year"] / 12)) + / 100, + 2, + ) + data["count_trend"] = round( + (data["upload_count_by_month"][-1] - (data["upload_count_by_year"] / 12)) + / 100, + 2, + ) return data def get_context_data(self, **kwargs): context = super(MainView, self).get_context_data(**kwargs) - context['data'] = {} - context['meta_page_title'] = "Dashboard" - context['sorted_org_list'] = [] + context["data"] = {} + context["meta_page_title"] = "Dashboard" + context["sorted_org_list"] = [] - organizations = Organization.objects.all() if (self.request.user.is_archivist()) else Organization.objects.filter(id=self.request.user.organization.pk) + organizations = ( + Organization.objects.all() + if (self.request.user.is_archivist()) + else Organization.objects.filter(id=self.request.user.organization.pk) + ) if self.request.user.is_archivist(): - all_orgs_data = self.get_org_data(organizations, 'All Organizations', User.objects.all()) - context['data']['all_orgs'] = {} - context['data']['all_orgs'].update(all_orgs_data) - context['sorted_org_list'].append(['all_orgs', 'All Organizations']) - - user_data = self.get_org_data(Organization.objects.filter( - id=self.request.user.organization.pk), 'My Transfers', - User.objects.filter(id=self.request.user.pk)) - context['data'][self.request.user] = {} - context['data'][self.request.user].update(user_data) - context['sorted_org_list'].append([self.request.user.username, 'My Transfers']) + all_orgs_data = self.get_org_data( + organizations, "All Organizations", User.objects.all() + ) + context["data"]["all_orgs"] = {} + context["data"]["all_orgs"].update(all_orgs_data) + context["sorted_org_list"].append(["all_orgs", "All Organizations"]) + + user_data = self.get_org_data( + Organization.objects.filter(id=self.request.user.organization.pk), + "My Transfers", + User.objects.filter(id=self.request.user.pk), + ) + context["data"][self.request.user] = {} + context["data"][self.request.user].update(user_data) + context["sorted_org_list"].append([self.request.user.username, "My Transfers"]) for organization in organizations: - org_data = self.get_org_data(Organization.objects.filter( - id=organization.pk), organization.name, - User.objects.filter(organization=organization)) - context['data'][organization.machine_name] = {} - context['data'][organization.machine_name].update(org_data) - context['sorted_org_list'].append([organization.machine_name, organization.name]) + org_data = self.get_org_data( + Organization.objects.filter(id=organization.pk), + organization.name, + User.objects.filter(organization=organization), + ) + context["data"][organization.machine_name] = {} + context["data"][organization.machine_name].update(org_data) + context["sorted_org_list"].append( + [organization.machine_name, organization.name] + ) return context class TransfersView(LoggedInMixinDefaults, View): - template_name = 'orgs/transfers.html' + template_name = "orgs/transfers.html" def get(self, request, *args, **kwargs): - organization = Organization.objects.all() if (self.request.user.is_archivist()) else Organization.objects.filter(id=self.request.user.organization.pk) - return render(request, self.template_name, { - 'meta_page_title': 'Transfers', - 'org_uploads_count': Archives.objects.filter( - process_status__gte=Archives.TRANSFER_COMPLETED, - organization__in=organization).count(), - 'user_uploads_count': Archives.objects.filter( - process_status__gte=Archives.TRANSFER_COMPLETED, - organization__in=organization, user_uploaded=request.user).count(), - }) + organization = ( + Organization.objects.all() + if (self.request.user.is_archivist()) + else Organization.objects.filter(id=self.request.user.organization.pk) + ) + return render( + request, + self.template_name, + { + "meta_page_title": "Transfers", + "org_uploads_count": Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, + organization__in=organization, + ).count(), + "user_uploads_count": Archives.objects.filter( + process_status__gte=Archives.TRANSFER_COMPLETED, + organization__in=organization, + user_uploaded=request.user, + ).count(), + }, + ) class TransferDataView(CSVResponseMixin, OrgReadViewMixin, View): @@ -146,50 +208,88 @@ def process_status_display(self, status): return s[1] def get(self, request, *args, **kwargs): - data = [('Bag Name', 'Identifier', 'Status', 'Dates', 'Organization', 'Record Creators', 'Record Type', 'Size', 'Upload Time')] + data = [ + ( + "Bag Name", + "Identifier", + "Status", + "Dates", + "Organization", + "Record Creators", + "Record Type", + "Size", + "Upload Time", + ) + ] if self.request.user.is_archivist: transfers = Archives.objects.filter( - process_status__gte=Archives.TRANSFER_COMPLETED).order_by('-created_time') + process_status__gte=Archives.TRANSFER_COMPLETED + ).order_by("-created_time") else: - self.organization = get_object_or_404(Organization, pk=self.kwargs['pk']) + self.organization = get_object_or_404(Organization, pk=self.kwargs["pk"]) transfers = Archives.objects.filter( process_status__gte=Archives.TRANSFER_COMPLETED, - organization=self.organization).order_by('-created_time') + organization=self.organization, + ).order_by("-created_time") for transfer in transfers: - dates = '' - creators = '' - upload_time = transfer.machine_file_upload_time.astimezone(tz.tzlocal()).strftime('%b %e, %Y %I:%M:%S %p') + dates = "" + creators = "" + upload_time = transfer.machine_file_upload_time.astimezone( + tz.tzlocal() + ).strftime("%b %e, %Y %I:%M:%S %p") bag_info_data = transfer.get_bag_data() if bag_info_data: dates = "{} - {}".format( - bag_info_data.get('date_start').strftime('%b %e, %Y'), - bag_info_data.get('date_end').strftime('%b %e, %Y')) - creators = (', ').join(bag_info_data.get('record_creators')) - - data.append(( - transfer.bag_or_failed_name(), - transfer.machine_file_identifier, - self.process_status_display(transfer.process_status), - dates, - transfer.organization.name, - creators, - bag_info_data.get('record_type'), - file_size(int(transfer.machine_file_size)), - upload_time)) + bag_info_data.get("date_start").strftime("%b %e, %Y"), + bag_info_data.get("date_end").strftime("%b %e, %Y"), + ) + creators = (", ").join(bag_info_data.get("record_creators")) + + data.append( + ( + transfer.bag_or_failed_name(), + transfer.machine_file_identifier, + self.process_status_display(transfer.process_status), + dates, + transfer.organization.name, + creators, + bag_info_data.get("record_type"), + file_size(int(transfer.machine_file_size)), + upload_time, + ) + ) return self.render_to_csv(data) class TransferDataTableView(LoggedInMixinDefaults, BaseDatatableView): model = Archives - columns = ['metadata__external_identifier', 'title', 'machine_file_identifier', 'process_status', 'metadata__date_start', - 'organization__name', 'metadata__record_creators__name', - 'metadata__record_type', 'machine_file_size', 'machine_file_upload_time',] - order_columns = ['title', 'machine_file_identifier', 'process_status', 'metadata__date_start', - 'organization__name', 'metadata__record_creators__name', - 'metadata__record_type', 'machine_file_size', 'machine_file_upload_time'] + columns = [ + "metadata__external_identifier", + "title", + "machine_file_identifier", + "process_status", + "metadata__date_start", + "organization__name", + "metadata__record_creators__name", + "metadata__record_type", + "machine_file_size", + "machine_file_upload_time", + ] + order_columns = [ + "title", + "machine_file_identifier", + "process_status", + "metadata__date_start", + "organization__name", + "metadata__record_creators__name", + "metadata__record_type", + "machine_file_size", + "machine_file_upload_time", + ] max_display_length = 500 - def get_filter_method(self): return self.FILTER_ICONTAINS + def get_filter_method(self): + return self.FILTER_ICONTAINS def process_status_display(self, status): for s in Archives.processing_statuses: @@ -197,70 +297,85 @@ def process_status_display(self, status): return s[1] def process_status_tag(self, status): - percentage = int(round(status/Archives.ACCESSIONING_COMPLETE * 100)) + percentage = int(round(status / Archives.ACCESSIONING_COMPLETE * 100)) return "{label}
    \
    \ -
    ".format(label=self.process_status_display(status), label_class=label_class(status), percentage=percentage) + ".format( + label=self.process_status_display(status), + label_class=label_class(status), + percentage=percentage, + ) def get_initial_queryset(self): - organization = Organization.objects.all() if (self.request.user.is_archivist()) else Organization.objects.filter(id=self.request.user.organization.pk) - if self.request.GET.get('q', None) == 'user': + organization = ( + Organization.objects.all() + if (self.request.user.is_archivist()) + else Organization.objects.filter(id=self.request.user.organization.pk) + ) + if self.request.GET.get("q", None) == "user": return Archives.objects.filter( process_status__gte=Archives.TRANSFER_COMPLETED, organization__in=organization, - user_uploaded=self.request.user - ).annotate(title=Concat('metadata__title', 'bag_it_name')) + user_uploaded=self.request.user, + ).annotate(title=Concat("metadata__title", "bag_it_name")) return Archives.objects.filter( process_status__gte=Archives.TRANSFER_COMPLETED, - organization__in=organization - ).annotate(title=Concat('metadata__title', 'bag_it_name')) + organization__in=organization, + ).annotate(title=Concat("metadata__title", "bag_it_name")) def prepare_results(self, qs): json_data = [] for transfer in qs: - dates = '' - creators = '' - upload_time = transfer.machine_file_upload_time.astimezone(tz.tzlocal()).strftime('%b %e, %Y %I:%M:%S %p') + dates = "" + creators = "" + upload_time = transfer.machine_file_upload_time.astimezone( + tz.tzlocal() + ).strftime("%b %e, %Y %I:%M:%S %p") bag_info_data = transfer.get_bag_data() if bag_info_data: dates = "{} - {}".format( - bag_info_data.get('date_start').strftime('%b %e, %Y'), - bag_info_data.get('date_end').strftime('%b %e, %Y')) - creators = ('
    ').join(bag_info_data.get('record_creators')) + bag_info_data.get("date_start").strftime("%b %e, %Y"), + bag_info_data.get("date_end").strftime("%b %e, %Y"), + ) + creators = ("
    ").join(bag_info_data.get("record_creators")) if self.request.user.is_archivist(): - json_data.append([ - transfer.bag_or_failed_name(), - transfer.machine_file_identifier, - self.process_status_tag(transfer.process_status), - dates, - transfer.organization.name, - creators, - bag_info_data.get('record_type'), - file_size(int(transfer.machine_file_size)), - upload_time, - "/app/transfers/{}".format(transfer.pk) - ]) + json_data.append( + [ + transfer.bag_or_failed_name(), + transfer.machine_file_identifier, + self.process_status_tag(transfer.process_status), + dates, + transfer.organization.name, + creators, + bag_info_data.get("record_type"), + file_size(int(transfer.machine_file_size)), + upload_time, + "/app/transfers/{}".format(transfer.pk), + ] + ) else: - json_data.append([ - transfer.bag_or_failed_name(), - transfer.machine_file_identifier, - self.process_status_tag(transfer.process_status), - dates, - creators, - bag_info_data.get('record_type'), - file_size(int(transfer.machine_file_size)), - upload_time, - "/app/transfers/{}".format(transfer.pk) - ]) + json_data.append( + [ + transfer.bag_or_failed_name(), + transfer.machine_file_identifier, + self.process_status_tag(transfer.process_status), + dates, + creators, + bag_info_data.get("record_type"), + file_size(int(transfer.machine_file_size)), + upload_time, + "/app/transfers/{}".format(transfer.pk), + ] + ) return json_data class TransferDetailView(OrgReadViewMixin, DetailView): - template_name = 'transfers/detail.html' + template_name = "transfers/detail.html" model = Archives def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) - context['meta_page_title'] = self.object.bag_or_failed_name - context['metadata'] = sorted(self.object.get_bag_data().iteritems()) + context["meta_page_title"] = self.object.bag_or_failed_name + context["metadata"] = sorted(self.object.get_bag_data().items()) return context diff --git a/aurora/bag_transfer/users/form.py b/aurora/bag_transfer/users/form.py index 46311632..bd4cce1e 100644 --- a/aurora/bag_transfer/users/form.py +++ b/aurora/bag_transfer/users/form.py @@ -1,6 +1,10 @@ from django import forms -from django.contrib.auth.forms import PasswordChangeForm, PasswordResetForm, SetPasswordForm +from django.contrib.auth.forms import ( + PasswordChangeForm, + PasswordResetForm, + SetPasswordForm, +) from django.utils.translation import ugettext, ugettext_lazy as _ from bag_transfer.models import User @@ -9,82 +13,108 @@ class OrgUserCreateForm(forms.ModelForm): class Meta: model = User - fields = ['is_active', 'username', 'first_name', 'last_name', 'email', 'organization', 'groups'] + fields = [ + "is_active", + "username", + "first_name", + "last_name", + "email", + "organization", + "groups", + ] widgets = { - 'username': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'first_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'last_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'email': forms.widgets.EmailInput(attrs={'class': 'form-control'}), - 'organization': forms.widgets.Select(attrs={'class': 'form-control'}), + "username": forms.widgets.TextInput(attrs={"class": "form-control"}), + "first_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "last_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "email": forms.widgets.EmailInput(attrs={"class": "form-control"}), + "organization": forms.widgets.Select(attrs={"class": "form-control"}), } class OrgUserUpdateForm(forms.ModelForm): class Meta: model = User - fields = ['is_active', 'username', 'first_name', 'last_name', 'email', 'organization', 'groups'] + fields = [ + "is_active", + "username", + "first_name", + "last_name", + "email", + "organization", + "groups", + ] widgets = { - 'username': forms.widgets.TextInput(attrs={'class': 'form-control', 'readonly': 'readonly'}), - 'first_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'last_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'email': forms.widgets.EmailInput(attrs={'class': 'form-control'}), - 'organization': forms.widgets.Select(attrs={'class': 'form-control'}), + "username": forms.widgets.TextInput( + attrs={"class": "form-control", "readonly": "readonly"} + ), + "first_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "last_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "email": forms.widgets.EmailInput(attrs={"class": "form-control"}), + "organization": forms.widgets.Select(attrs={"class": "form-control"}), } class RACSuperUserUpdateForm(forms.ModelForm): class Meta: model = User - fields = ['is_active', 'username', 'first_name', 'last_name', 'email', 'groups'] + fields = ["is_active", "username", "first_name", "last_name", "email", "groups"] widgets = { - 'username': forms.widgets.TextInput(attrs={'class': 'form-control', 'readonly': 'readonly'}), - 'first_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'last_name': forms.widgets.TextInput(attrs={'class': 'form-control'}), - 'email': forms.widgets.EmailInput(attrs={'class': 'form-control'}), + "username": forms.widgets.TextInput( + attrs={"class": "form-control", "readonly": "readonly"} + ), + "first_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "last_name": forms.widgets.TextInput(attrs={"class": "form-control"}), + "email": forms.widgets.EmailInput(attrs={"class": "form-control"}), } class UserPasswordChangeForm(PasswordChangeForm): - error_css_class = 'has-error' + error_css_class = "has-error" - error_messages = dict(PasswordChangeForm.error_messages, **{ - 'password_incorrect': _("You entered your current password incorrectly"), - }) + error_messages = dict( + PasswordChangeForm.error_messages, + **{"password_incorrect": _("You entered your current password incorrectly")} + ) old_password = forms.CharField( required=True, - label='Current Password', - widget=forms.PasswordInput(attrs={'class': 'form-control'}), - error_messages={'required': 'Please enter your current password'} - ) + label="Current Password", + widget=forms.PasswordInput(attrs={"class": "form-control"}), + error_messages={"required": "Please enter your current password"}, + ) new_password1 = forms.CharField( required=True, - label='New Password', - widget=forms.PasswordInput(attrs={'class': 'form-control'}), - error_messages={'required': 'Please enter your new password'} - ) + label="New Password", + widget=forms.PasswordInput(attrs={"class": "form-control"}), + error_messages={"required": "Please enter your new password"}, + ) new_password2 = forms.CharField( required=True, - label='New Password (repeat)', - widget=forms.PasswordInput(attrs={'class': 'form-control'}), - error_messages={'required': 'Please confirm your new password'} - ) + label="New Password (repeat)", + widget=forms.PasswordInput(attrs={"class": "form-control"}), + error_messages={"required": "Please confirm your new password"}, + ) class UserPasswordResetForm(PasswordResetForm): email = forms.EmailField( - required=True, - widget=forms.EmailInput(attrs={'class': 'form-control has-feedback'}), - error_messages={'required': 'Please enter your email'}) + required=True, + widget=forms.EmailInput(attrs={"class": "form-control has-feedback"}), + error_messages={"required": "Please enter your email"}, + ) class UserSetPasswordForm(SetPasswordForm): new_password1 = forms.CharField( - required=True, label='New Password', - widget=forms.PasswordInput(attrs={'class': 'form-control'}), - error_messages={'required': 'Please enter your new password'}) + required=True, + label="New Password", + widget=forms.PasswordInput(attrs={"class": "form-control"}), + error_messages={"required": "Please enter your new password"}, + ) new_password2 = forms.CharField( - required=True, label='New Password (repeat)', - widget=forms.PasswordInput(attrs={'class': 'form-control'}), - error_messages={'required': 'Please confirm your new password'}) + required=True, + label="New Password (repeat)", + widget=forms.PasswordInput(attrs={"class": "form-control"}), + error_messages={"required": "Please confirm your new password"}, + ) diff --git a/aurora/bag_transfer/users/urls.py b/aurora/bag_transfer/users/urls.py index 1bb541d8..9adb170c 100644 --- a/aurora/bag_transfer/users/urls.py +++ b/aurora/bag_transfer/users/urls.py @@ -1,11 +1,14 @@ from django.conf.urls import url -from bag_transfer.users.views import * +from bag_transfer.users.views import UsersCreateView, UsersDetailView, UsersEditView, UsersListView, UserPasswordChangeView +app_name = "users" urlpatterns = [ - url(r'^$', UsersListView.as_view(), name='list'), - url(r'^(?P\d+)/$', UsersDetailView.as_view(), name='detail'), - url(r'^add/$', UsersCreateView.as_view(), name='add'), - url(r'^(?P\d+)/edit/$', UsersEditView.as_view(), name='edit'), - url(r'^change-password/$', UserPasswordChangeView.as_view(), name='password-change'), + url(r"^$", UsersListView.as_view(), name="list"), + url(r"^(?P\d+)/$", UsersDetailView.as_view(), name="detail"), + url(r"^add/$", UsersCreateView.as_view(), name="add"), + url(r"^(?P\d+)/edit/$", UsersEditView.as_view(), name="edit"), + url( + r"^change-password/$", UserPasswordChangeView.as_view(), name="password-change" + ), ] diff --git a/aurora/bag_transfer/users/views.py b/aurora/bag_transfer/users/views.py index 33dc6096..2381bbec 100644 --- a/aurora/bag_transfer/users/views.py +++ b/aurora/bag_transfer/users/views.py @@ -1,143 +1,170 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django import forms -from django.views.generic import TemplateView, ListView, CreateView, DetailView, UpdateView -from django.contrib import messages +from django.views.generic import ( + TemplateView, + ListView, + CreateView, + DetailView, + UpdateView, +) from django.contrib.auth.forms import PasswordResetForm -from django.contrib.auth.views import PasswordChangeView, PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView +from django.contrib.auth.views import ( + PasswordChangeView, + PasswordResetView, + PasswordResetDoneView, + PasswordResetConfirmView, + PasswordResetCompleteView, +) from django.contrib.messages.views import SuccessMessageMixin -from django.core.urlresolvers import reverse_lazy from django.shortcuts import render, redirect - +from django.urls import reverse from braces.views import AnonymousRequiredMixin -from bag_transfer.mixins.authmixins import * -from bag_transfer.users.form import * +from bag_transfer.models import Archives, Organization, User +from bag_transfer.mixins.authmixins import ( + ArchivistMixin, + ManagingArchivistMixin, + OrgReadViewMixin, +) +from bag_transfer.users.form import ( + OrgUserCreateForm, + OrgUserUpdateForm, + RACSuperUserUpdateForm, + UserPasswordChangeForm, + UserPasswordResetForm, + UserSetPasswordForm, +) from bag_transfer.lib.RAC_CMD import set_server_password -class SplashView(AnonymousRequiredMixin, TemplateView): +class SplashView(AnonymousRequiredMixin, TemplateView): def get(self, request): - return redirect('login') + return redirect("login") class UsersListView(ArchivistMixin, SuccessMessageMixin, ListView): - template_name = 'users/list.html' + template_name = "users/list.html" model = User def get(self, request, *args, **kwargs): - users_list = [{'org': {}, 'users': []}] - users_list[0]['org'] = {'pass': 'pass'} - users_list[0]['users'] = User.objects.all().order_by('username') - org_users_list = [{'org': {}, 'users': []}] + users_list = [{"org": {}, "users": []}] + users_list[0]["org"] = {"pass": "pass"} + users_list[0]["users"] = User.objects.all().order_by("username") + org_users_list = [{"org": {}, "users": []}] org_users_list = Organization.users_by_org() - return render(request, self.template_name, { - 'meta_page_title': 'Users', - 'users_list': users_list, - 'org_users_list': org_users_list, - }) + return render( + request, + self.template_name, + { + "meta_page_title": "Users", + "users_list": users_list, + "org_users_list": org_users_list, + }, + ) class UsersCreateView(ManagingArchivistMixin, SuccessMessageMixin, CreateView): - template_name = 'users/update.html' + template_name = "users/update.html" model = User success_message = "New User Saved!" def get_form_class(self): - return (OrgUserCreateForm) + return OrgUserCreateForm def get_success_url(self): - return reverse('users:detail', kwargs={'pk': self.object.pk}) + return reverse("users:detail", kwargs={"pk": self.object.pk}) def post(self, request, *args, **kwargs): + """Send password reset email so user changes automatically-generated + random password.""" post = super(UsersCreateView, self).post(request, *args, **kwargs) - # send password reset email (should be different email template) - form = PasswordResetForm({"email": request.POST.get('email')}) + form = PasswordResetForm({"email": request.POST.get("email")}) form.is_valid() - form.save(request=self.request, - subject_template_name='users/password_initial_set_subject.txt', - email_template_name='users/password_initial_set_email.html',) + form.save( + request=self.request, + subject_template_name="users/password_initial_set_subject.txt", + email_template_name="users/password_initial_set_email.html", + ) return post class UsersDetailView(OrgReadViewMixin, DetailView): - template_name = 'users/detail.html' + template_name = "users/detail.html" model = User def get_context_data(self, **kwargs): context = super(UsersDetailView, self).get_context_data(**kwargs) - context['meta_page_title'] = self.object.username - context['uploads'] = [] + context["meta_page_title"] = self.object.username + context["uploads"] = [] archives = Archives.objects.filter( process_status__gte=Archives.TRANSFER_COMPLETED, - user_uploaded=context['object']).order_by('-created_time')[:9] + user_uploaded=context["object"], + ).order_by("-created_time")[:9] for archive in archives: archive.bag_info_data = archive.get_bag_data() - context['uploads'].append(archive) - context['uploads_count'] = Archives.objects.filter( + context["uploads"].append(archive) + context["uploads_count"] = Archives.objects.filter( process_status__gte=Archives.TRANSFER_COMPLETED, - user_uploaded=context['object']).count() + user_uploaded=context["object"], + ).count() return context class UsersEditView(ManagingArchivistMixin, SuccessMessageMixin, UpdateView): - template_name = 'users/update.html' + template_name = "users/update.html" model = User success_message = "Your changes have been saved!" def get_form_class(self): - return (RACSuperUserUpdateForm if self.object.is_staff else OrgUserUpdateForm) + return RACSuperUserUpdateForm if self.object.is_staff else OrgUserUpdateForm def get_context_data(self, **kwargs): context = super(UsersEditView, self).get_context_data(**kwargs) - context['page_title'] = "Edit {}".format(self.object.username) - context['meta_page_title'] = "Edit {}".format(self.object.username) + context["page_title"] = "Edit {}".format(self.object.username) + context["meta_page_title"] = "Edit {}".format(self.object.username) return context def get_success_url(self): - return reverse('users:detail', kwargs={'pk': self.object.pk}) + return reverse("users:detail", kwargs={"pk": self.object.pk}) class UserPasswordChangeView(SuccessMessageMixin, PasswordChangeView): - template_name = 'users/password_change.html' + template_name = "users/password_change.html" model = User success_message = "New password saved." form_class = UserPasswordChangeForm def get_context_data(self, **kwargs): context = super(UserPasswordChangeView, self).get_context_data(**kwargs) - context['meta_page_title'] = 'Change Password' + context["meta_page_title"] = "Change Password" return context def get_success_url(self): - return reverse('users:detail', kwargs={'pk': self.request.user.pk}) + return reverse("users:detail", kwargs={"pk": self.request.user.pk}) def form_valid(self, form): result = super(UserPasswordChangeView, self).form_valid(form) - set_server_password(form.user.username, form.cleaned_data['new_password1']) + set_server_password(form.user.username, form.cleaned_data["new_password1"]) return result class UserPasswordResetView(AnonymousRequiredMixin, PasswordResetView): - template_name = 'users/password_reset_form.html' + template_name = "users/password_reset_form.html" form_class = UserPasswordResetForm class UserPasswordResetDoneView(AnonymousRequiredMixin, PasswordResetDoneView): - template_name = 'users/password_reset_done.html' + template_name = "users/password_reset_done.html" class UserPasswordResetConfirmView(AnonymousRequiredMixin, PasswordResetConfirmView): - template_name = 'users/password_reset_confirm.html' + template_name = "users/password_reset_confirm.html" form_class = UserSetPasswordForm def form_valid(self, form): results = super(UserPasswordResetConfirmView, self).form_valid(form) - set_server_password(form.user.username, form.cleaned_data['new_password1']) + set_server_password(form.user.username, form.cleaned_data["new_password1"]) return results class UserPasswordResetCompleteView(AnonymousRequiredMixin, PasswordResetCompleteView): - template_name = 'users/password_reset_complete.html' + template_name = "users/password_reset_complete.html" diff --git a/requirements.txt b/requirements.txt index a3fa624b..51bb996f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,47 +1,40 @@ -bagit==1.5.4 -bagit-profile==1.3.0 -certifi==2017.7.27.1 +attrs==19.3.0 +bagit==1.7.0 +bagit-profile==1.3.1 +certifi==2019.9.11 chardet==3.0.4 -click==6.7 -coreapi==2.3.3 -coreschema==0.0.4 -coverage==4.5 -Django==1.11.23 -django-braces==1.11.0 -django-common-helpers==0.9.1 -django-cron==0.5.0 -django-datatables-view==1.17.0 -djangorestframework==3.9.1 +Click==7.0 +Django==2.2.10 +django-braces==1.13.0 +django-common-helpers==0.9.2 +django-cron==0.5.1 +django-datatables-view==1.19.1 +djangorestframework==3.10.3 djangorestframework-jwt==1.11.0 -drf-yasg==1.11.0 -flex==6.14.0 -functools32==3.2.3.post2 -future==0.16.0 +health-check==3.4.1 idna==2.8 +importlib-metadata==0.23 inflection==0.3.1 iso-639==0.4.5 iso8601==0.1.12 -itypes==1.1.0 -Jinja2==2.10.1 -jsonpointer==1.14 -jsonschema==2.6.0 -MarkupSafe==1.0 -mysqlclient==1.4.2.post1 -openapi-codec==1.3.2 -psutil==5.3.1 +jsonpointer==2.0 +jsonschema==3.2.0 +MarkupSafe==1.1.1 +more-itertools==7.2.0 +mysqlclient==1.4.6 +psutil==5.6.7 pyClamd==0.4.0 -PyJWT==1.6.1 -python-dateutil==2.6.1 +PyJWT==1.7.1 +pyparsing==2.4.5 +pyrsistent==0.15.6 +python-dateutil==2.8.1 pytz==2019.3 -PyYAML==4.2b4 +PyYAML==5.1.2 requests==2.22.0 -rfc3987==1.3.7 -ruamel.ordereddict==0.4.13 -ruamel.yaml==0.15.71 -six==1.11.0 +rfc3987==1.3.8 +six==1.13.0 +sqlparse==0.3.0 strict-rfc3339==0.7 -swagger-spec-validator==2.1.0 uritemplate==3.0.0 -urllib3==1.24.2 -validate-email==1.3 -virtualenv==16.0.0 +urllib3==1.25.7 +zipp==0.6.0 diff --git a/sample_bags/admin/manifest-md5.txt b/sample_bags/admin/manifest-md5.txt deleted file mode 100644 index f3a5ec95..00000000 --- a/sample_bags/admin/manifest-md5.txt +++ /dev/null @@ -1,2 +0,0 @@ -0cb77f9495310cc9256fa4d3c02c2a9a data/For Good Measure.pptx -f9f7ebbbfe71471a6ab1a8662186a90f data/LICENSE.txt diff --git a/sample_bags/admin/manifest-sha256.txt b/sample_bags/admin/manifest-sha256.txt new file mode 100644 index 00000000..ed18d16d --- /dev/null +++ b/sample_bags/admin/manifest-sha256.txt @@ -0,0 +1,2 @@ +03594d4bb653013a6dda7549dd626d2908a889d9673473eb15835e04f2fff801 data/For Good Measure.pptx +71e6f4bff39549691332af9bcc953267e80684888d04d411c91a357d6f023a64 data/LICENSE.txt diff --git a/sample_bags/admin/manifest-sha512.txt b/sample_bags/admin/manifest-sha512.txt new file mode 100644 index 00000000..5da744c6 --- /dev/null +++ b/sample_bags/admin/manifest-sha512.txt @@ -0,0 +1,2 @@ +5474f85af93dcfc6832d83b54efc934e4d43047a7a1f6bb0febf16c22d3a257842fd2a087f5f7e25bb62bb3010417d84770911d976b1a3d5b6b0d572077edbfc data/For Good Measure.pptx +985507d372a55e86719de77b3d32ce236d7bb128265b13baf4cc2b73c9e56ccea13b5b9b7513d46d85ae18c11b7e964c78ee17b3f8251a7718fc68fc81691670 data/LICENSE.txt diff --git a/sample_bags/admin/tagmanifest-md5.txt b/sample_bags/admin/tagmanifest-md5.txt deleted file mode 100644 index 2d70ca1c..00000000 --- a/sample_bags/admin/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -69cba30683d11078501e65f7c2099bad bag-info.txt -2b99b18ca0f056227a99ebd4452f53f3 manifest-md5.txt diff --git a/sample_bags/admin/tagmanifest-sha256.txt b/sample_bags/admin/tagmanifest-sha256.txt new file mode 100644 index 00000000..2b08e5cf --- /dev/null +++ b/sample_bags/admin/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +b4f4c009ac785a1ef1d59557f176359a38bf97abf5d56a39eb25580120c3b399 bag-info.txt +b96c74e310a7510f3db9df36c25aacf44bd443e5daa5a6a422910d3b3759e442 manifest-sha512.txt +48129ef927a83274e2ded3c46c2858b5f546b9dd67d1c01c400f1c494692726b manifest-sha256.txt diff --git a/sample_bags/admin/tagmanifest-sha512.txt b/sample_bags/admin/tagmanifest-sha512.txt new file mode 100644 index 00000000..e97fa197 --- /dev/null +++ b/sample_bags/admin/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +5a0ecc3a544115b6f517649c8219c1e7afb30eeea30a2b7cd3ce0bfe24e25f2142b4f6e2906f417fd20d41a869ea516d96ce766aa6639eb6f1c140915eaa9973 bag-info.txt +3de8eb99c2914678d06da0a6409e332c08d84df98af231d150d2a8b170daceb4eb4e718facd4ebdf90ac93ae7729dcdb7102bc831c3948dd004778ceff00dbd8 manifest-sha512.txt +533fdb0a787174f8dc0b7165e0f83d4a9c5be0dccf62ca395501a98e5d281527dff473487d079ffaf84c5977cba0d925d363feafb552f03132fa9b0d7592085e manifest-sha256.txt diff --git a/sample_bags/admin2.tar b/sample_bags/admin2.tar index 8f6357a1..7f41c266 100644 Binary files a/sample_bags/admin2.tar and b/sample_bags/admin2.tar differ diff --git a/sample_bags/admin3.tar.gz b/sample_bags/admin3.tar.gz index e1d69c4e..1b310107 100644 Binary files a/sample_bags/admin3.tar.gz and b/sample_bags/admin3.tar.gz differ diff --git a/sample_bags/admin4.zip b/sample_bags/admin4.zip index 8586961d..b9ba6e30 100644 Binary files a/sample_bags/admin4.zip and b/sample_bags/admin4.zip differ diff --git a/sample_bags/annual/manifest-md5.txt b/sample_bags/annual/manifest-md5.txt deleted file mode 100644 index 0f58869d..00000000 --- a/sample_bags/annual/manifest-md5.txt +++ /dev/null @@ -1,6 +0,0 @@ -af296662fe5909749c983f98746bd4f8 data/Project Electron Milestones.png -0b492d1e3a586f363c3f24302b9a525f data/Project Electron Year Two Gantt.png -d68b445ceb1befbcb6bdc357e6896edc data/demo.docx -8eb7307b41ae27e400ffd3db47be3f09 data/hGrant_Spec.pdf -cfc62f46dcbaf505b60140ea5051db77 data/idealware_gms_trends_4.21.16.pdf -94b6e2e66323c5ce3273ef6af9a66126 data/metadata.json diff --git a/sample_bags/annual/manifest-sha256.txt b/sample_bags/annual/manifest-sha256.txt new file mode 100644 index 00000000..4daccf2e --- /dev/null +++ b/sample_bags/annual/manifest-sha256.txt @@ -0,0 +1,6 @@ +1770ef8af984ca96b37d2d19da74aa8924abe97dbe68558f7f565ab41ca3d793 data/Project Electron Milestones.png +50b17b0cb820625a3f0caaba8e95ecbd401631b943c72d6c8e00bf45bc61c302 data/Project Electron Year Two Gantt.png +269329fc7ae54b3f289b3ac52efde387edc2e566ef9a48d637e841022c7e0eab data/demo.docx +c1cc91fe83aae24ab0aa0703fee87919bd8cc6baf0e581c48c8204b5d3a5a170 data/hGrant_Spec.pdf +2e01adf8d272c5954b7cba592dc5458dbce684324eaa4960bbc6044e32394676 data/idealware_gms_trends_4.21.16.pdf +93efae05e86d7c43e323239b17e9fb3fff7cff0f6cb3a7bb3f9606b2b8e1a71b data/metadata.json diff --git a/sample_bags/annual/manifest-sha512.txt b/sample_bags/annual/manifest-sha512.txt new file mode 100644 index 00000000..3da956c8 --- /dev/null +++ b/sample_bags/annual/manifest-sha512.txt @@ -0,0 +1,6 @@ +366e30fa1cf10b260801c733318f0b3e25ad5fa07340a9186c50bb9536c2b69cc0938dc53e7859f5236ce9a325513b029bb7ef44a0fb61c58d39e2684d7fdb1c data/Project Electron Milestones.png +8a28b4386d21655ac71767a1eada85584326687af7808fe7b174ed831f70fbf6b97ba2973b8a48b7d50ed60190db0d611c0a2569cccf31b1658241d76bfba914 data/Project Electron Year Two Gantt.png +d635c5c57f8a56666967a866c1681f62e3362cdf8961e15123ead1af567532a2cd3a235758e6fb6d1d2b4c667b3907cc2b27a338a6c24c81a8b565060cb8d93b data/demo.docx +b9f0fc8a546bae4a0c4c77d4977a6dd2b2733a0efe1d40dba48db6d8b61700817ca0a610a137c1ffc1a9b04bed0f5678e83467e4f1421173f3f3b9559ff66299 data/hGrant_Spec.pdf +30c8370356b6d3721ffb02db069e9e3e58ecdd7cda75a4dd9d8db79482562595cd4f1f633821d00aa158056f0e531e7747443db37a59faca11f00c6e5028c226 data/idealware_gms_trends_4.21.16.pdf +bddd225316b5fe71afbae00bc1bd5102125f993c2042c06fc4ab572b79f07c286517e563343fcf3ee4fc210a6dc9cb79eed1a600208004427038e66b94440581 data/metadata.json diff --git a/sample_bags/annual/tagmanifest-md5.txt b/sample_bags/annual/tagmanifest-md5.txt deleted file mode 100644 index d1a1a479..00000000 --- a/sample_bags/annual/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -37ab29453aa5408de36bfa79084ce2ce bag-info.txt -bb17d2dfc8f6c5e366efeb8395b811f7 manifest-md5.txt diff --git a/sample_bags/annual/tagmanifest-sha256.txt b/sample_bags/annual/tagmanifest-sha256.txt new file mode 100644 index 00000000..0b5c9c21 --- /dev/null +++ b/sample_bags/annual/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +cc577c45c9b08fa01417fb8afd0a8973f622e00501591f8d052b181769143904 bag-info.txt +3f6e9c2a4c29d1f33c7e01aefedf9963f6c7335144f1a4ae06245c5ac1490d0d manifest-sha512.txt +706bf16a1b922d4dbb6b61c2cef56e7c7c06a36c2641047a5a2ff49c0be5e233 manifest-sha256.txt diff --git a/sample_bags/annual/tagmanifest-sha512.txt b/sample_bags/annual/tagmanifest-sha512.txt new file mode 100644 index 00000000..24849a9d --- /dev/null +++ b/sample_bags/annual/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +04d5edd841ecf1f2925453a8de90ebdca45db599600dd6404f1a82cbac9e875b1f3db778650fa26ce0d468169e3bfc38601d45753d3386ab3f4ef1433fee5547 bag-info.txt +2cce68e970e908fe2d7bcf6c8edbe0064408f6f67b5d4623168a46618bb2c1b819e44647483a6f8d8c1f6686b238670c19b764f07ff61db74098f1dea0aff701 manifest-sha512.txt +f5986d0dafcb5f0787e73179f8b515f0ef72fbc92ed245375bdae95cf336f72678d5ec9926abf1ef8c868cd984f96fe20d0ef49ff6ae4b2c3a6df234acfb7c74 manifest-sha256.txt diff --git a/sample_bags/annual2.tar b/sample_bags/annual2.tar index 4007a881..6f76cc91 100644 Binary files a/sample_bags/annual2.tar and b/sample_bags/annual2.tar differ diff --git a/sample_bags/annual3.tar.gz b/sample_bags/annual3.tar.gz index 7f92b641..8f421a04 100644 Binary files a/sample_bags/annual3.tar.gz and b/sample_bags/annual3.tar.gz differ diff --git a/sample_bags/annual4.zip b/sample_bags/annual4.zip index 2b242f6a..64fa3265 100644 Binary files a/sample_bags/annual4.zip and b/sample_bags/annual4.zip differ diff --git a/sample_bags/board/manifest-md5.txt b/sample_bags/board/manifest-md5.txt deleted file mode 100644 index 0f58869d..00000000 --- a/sample_bags/board/manifest-md5.txt +++ /dev/null @@ -1,6 +0,0 @@ -af296662fe5909749c983f98746bd4f8 data/Project Electron Milestones.png -0b492d1e3a586f363c3f24302b9a525f data/Project Electron Year Two Gantt.png -d68b445ceb1befbcb6bdc357e6896edc data/demo.docx -8eb7307b41ae27e400ffd3db47be3f09 data/hGrant_Spec.pdf -cfc62f46dcbaf505b60140ea5051db77 data/idealware_gms_trends_4.21.16.pdf -94b6e2e66323c5ce3273ef6af9a66126 data/metadata.json diff --git a/sample_bags/board/manifest-sha256.txt b/sample_bags/board/manifest-sha256.txt new file mode 100644 index 00000000..4daccf2e --- /dev/null +++ b/sample_bags/board/manifest-sha256.txt @@ -0,0 +1,6 @@ +1770ef8af984ca96b37d2d19da74aa8924abe97dbe68558f7f565ab41ca3d793 data/Project Electron Milestones.png +50b17b0cb820625a3f0caaba8e95ecbd401631b943c72d6c8e00bf45bc61c302 data/Project Electron Year Two Gantt.png +269329fc7ae54b3f289b3ac52efde387edc2e566ef9a48d637e841022c7e0eab data/demo.docx +c1cc91fe83aae24ab0aa0703fee87919bd8cc6baf0e581c48c8204b5d3a5a170 data/hGrant_Spec.pdf +2e01adf8d272c5954b7cba592dc5458dbce684324eaa4960bbc6044e32394676 data/idealware_gms_trends_4.21.16.pdf +93efae05e86d7c43e323239b17e9fb3fff7cff0f6cb3a7bb3f9606b2b8e1a71b data/metadata.json diff --git a/sample_bags/board/manifest-sha512.txt b/sample_bags/board/manifest-sha512.txt new file mode 100644 index 00000000..3da956c8 --- /dev/null +++ b/sample_bags/board/manifest-sha512.txt @@ -0,0 +1,6 @@ +366e30fa1cf10b260801c733318f0b3e25ad5fa07340a9186c50bb9536c2b69cc0938dc53e7859f5236ce9a325513b029bb7ef44a0fb61c58d39e2684d7fdb1c data/Project Electron Milestones.png +8a28b4386d21655ac71767a1eada85584326687af7808fe7b174ed831f70fbf6b97ba2973b8a48b7d50ed60190db0d611c0a2569cccf31b1658241d76bfba914 data/Project Electron Year Two Gantt.png +d635c5c57f8a56666967a866c1681f62e3362cdf8961e15123ead1af567532a2cd3a235758e6fb6d1d2b4c667b3907cc2b27a338a6c24c81a8b565060cb8d93b data/demo.docx +b9f0fc8a546bae4a0c4c77d4977a6dd2b2733a0efe1d40dba48db6d8b61700817ca0a610a137c1ffc1a9b04bed0f5678e83467e4f1421173f3f3b9559ff66299 data/hGrant_Spec.pdf +30c8370356b6d3721ffb02db069e9e3e58ecdd7cda75a4dd9d8db79482562595cd4f1f633821d00aa158056f0e531e7747443db37a59faca11f00c6e5028c226 data/idealware_gms_trends_4.21.16.pdf +bddd225316b5fe71afbae00bc1bd5102125f993c2042c06fc4ab572b79f07c286517e563343fcf3ee4fc210a6dc9cb79eed1a600208004427038e66b94440581 data/metadata.json diff --git a/sample_bags/board/tagmanifest-md5.txt b/sample_bags/board/tagmanifest-md5.txt deleted file mode 100644 index 0034abd1..00000000 --- a/sample_bags/board/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -9ceddc812bd9f9855bf60669279c6d72 bag-info.txt -bb17d2dfc8f6c5e366efeb8395b811f7 manifest-md5.txt diff --git a/sample_bags/board/tagmanifest-sha256.txt b/sample_bags/board/tagmanifest-sha256.txt new file mode 100644 index 00000000..e49e5693 --- /dev/null +++ b/sample_bags/board/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +4346fb07e5aed8737cedafdd6f94f60f6fcd7365164d1af78e377da676725569 bag-info.txt +3f6e9c2a4c29d1f33c7e01aefedf9963f6c7335144f1a4ae06245c5ac1490d0d manifest-sha512.txt +706bf16a1b922d4dbb6b61c2cef56e7c7c06a36c2641047a5a2ff49c0be5e233 manifest-sha256.txt diff --git a/sample_bags/board/tagmanifest-sha512.txt b/sample_bags/board/tagmanifest-sha512.txt new file mode 100644 index 00000000..d6f06b84 --- /dev/null +++ b/sample_bags/board/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +696dadee0f387d282d8cfee3211eef62c859ef337f22b853c1f9184b92f89c09103bc12214804902856f6fdd362bc0fb6c9fd9e2db668c46c08d5a8d209b8f25 bag-info.txt +2cce68e970e908fe2d7bcf6c8edbe0064408f6f67b5d4623168a46618bb2c1b819e44647483a6f8d8c1f6686b238670c19b764f07ff61db74098f1dea0aff701 manifest-sha512.txt +f5986d0dafcb5f0787e73179f8b515f0ef72fbc92ed245375bdae95cf336f72678d5ec9926abf1ef8c868cd984f96fe20d0ef49ff6ae4b2c3a6df234acfb7c74 manifest-sha256.txt diff --git a/sample_bags/board2.tar b/sample_bags/board2.tar index c7f718f6..60b80022 100644 Binary files a/sample_bags/board2.tar and b/sample_bags/board2.tar differ diff --git a/sample_bags/board3.tar.gz b/sample_bags/board3.tar.gz index 9fe847cf..aa975655 100644 Binary files a/sample_bags/board3.tar.gz and b/sample_bags/board3.tar.gz differ diff --git a/sample_bags/board4.zip b/sample_bags/board4.zip index e98c7369..f93c814d 100644 Binary files a/sample_bags/board4.zip and b/sample_bags/board4.zip differ diff --git a/sample_bags/comms/manifest-md5.txt b/sample_bags/comms/manifest-md5.txt deleted file mode 100644 index aed2a982..00000000 --- a/sample_bags/comms/manifest-md5.txt +++ /dev/null @@ -1,5 +0,0 @@ -9705c6398426e57b113ca3152fc03753 data/Important Document.docx -b261276b5db34ee905a2b1f98cbe6618 data/hinted vs unhinted.txt -6ac18e876125b7d84a9f8e959b43bfeb data/install-mac.txt -9a559708f214c357a6dbd568ed6d2b48 data/install-win.txt -87290540b91697d73adc589b1fca1f1e data/metadata.json diff --git a/sample_bags/comms/manifest-sha256.txt b/sample_bags/comms/manifest-sha256.txt new file mode 100644 index 00000000..1e1e76c3 --- /dev/null +++ b/sample_bags/comms/manifest-sha256.txt @@ -0,0 +1,5 @@ +d659a1be5b30b983d2c0f41e90c4cbbe43ee6a21bcf8191f0aeb328957a5dc78 data/Important Document.docx +499e56f9b9f4c31eb0f141143febdfad5fcd27218f4c56bca9bbb220ff7dd3f1 data/hinted vs unhinted.txt +c37d2cfba99c396b93f8a4c83dadc64bf54e365bd5378af0aa6f8e29c33dea9e data/install-mac.txt +5d2864aacdf05c7f54244db918befb60183852d687785ba13a18b75b6e8c248e data/install-win.txt +facde7bee8f375e3f8142fc01baa5e6e32b18c1fd4599533f171817eb30f5069 data/metadata.json diff --git a/sample_bags/comms/manifest-sha512.txt b/sample_bags/comms/manifest-sha512.txt new file mode 100644 index 00000000..14501616 --- /dev/null +++ b/sample_bags/comms/manifest-sha512.txt @@ -0,0 +1,5 @@ +0dfb9addd743e4e930d0d4af7f87c88b80d98b45ce9676f5560105b632293eb73323e7c0ecc3f72beb381aec78bebcf6bc646e8cecabbe34dfbb4900a9f9636c data/Important Document.docx +7f894d50e0b3535fbf1a5e6aabd1f0b0de9258c109b2f4e3e6732468c1ff6d2a7a0a0d57fdf76fb2c86557c9e81d3a8189be80213186381e408cf1ddd3ffc34a data/hinted vs unhinted.txt +f8ba6afb947631706d4c906d1156e86c056c21387c3acca23925a7594793247bd158d86e670caea7bcef4616626fbd20d213bb866248559528401cb27a5d732e data/install-mac.txt +dc99515176869171531f6c0982aeb946f0120cb22baac5f7fd23f834513ee00155916fc9da334f009fd4d44e1a86a3258dd03a8dc1669d4ed5f84d5c4b3fbb4d data/install-win.txt +e906b8f4366103592ea476f35c43f26ffc7e438bdcb58bcdf6fe13fda1c479405f6549fee9b00e2787fedc4f8cd8d965b83477a4899297540144f263dd680aa4 data/metadata.json diff --git a/sample_bags/comms/tagmanifest-md5.txt b/sample_bags/comms/tagmanifest-md5.txt deleted file mode 100644 index 059fa838..00000000 --- a/sample_bags/comms/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -44fafe65211cb3c9c1a23f6c999f1c09 bag-info.txt -5cc1d852bb884f54b282a7553a264072 manifest-md5.txt diff --git a/sample_bags/comms/tagmanifest-sha256.txt b/sample_bags/comms/tagmanifest-sha256.txt new file mode 100644 index 00000000..dc3893e1 --- /dev/null +++ b/sample_bags/comms/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +469202344ac748029315d2f95a655304ee59105775001c858789ccd23ca98cd9 bag-info.txt +b54f16014428b7f39fd39d65c7aa75d96cdb4d77573db966a84bd47c6e9900b5 manifest-sha512.txt +80a9154c74b758714490614cf5bd1d53d8f1893c520240211baa76158700a750 manifest-sha256.txt diff --git a/sample_bags/comms/tagmanifest-sha512.txt b/sample_bags/comms/tagmanifest-sha512.txt new file mode 100644 index 00000000..79ea0642 --- /dev/null +++ b/sample_bags/comms/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +dae5ea7d0d606cc788a48470971d81372770a9fb9fb4d5da9c45852d6e5dcbe8cbbad1590f88dfc6cf04fc4592e9589b7e9efc9af2a7906bc808e0ac15c8f7fc bag-info.txt +02f72498bfc99011f3ac891cfbc8788be024685db0dc7abbff74acc06e99f9c2a7fc2d5652807123df864b83afc3daac963cf4c918cd3ff644a806faa755d7c4 manifest-sha512.txt +c75d0c162af1d4df8290fda294bca94010a49d7414d5255391c10d0fbbd49e7c20521054961cfdb213b97ecedbfe1d20a12356f18a567eb8b928484f8cf4fdd5 manifest-sha256.txt diff --git a/sample_bags/comms2.tar b/sample_bags/comms2.tar index ab896677..e86bc39e 100644 Binary files a/sample_bags/comms2.tar and b/sample_bags/comms2.tar differ diff --git a/sample_bags/comms3.tar.gz b/sample_bags/comms3.tar.gz index c54a2479..c4b6bf34 100644 Binary files a/sample_bags/comms3.tar.gz and b/sample_bags/comms3.tar.gz differ diff --git a/sample_bags/comms4.zip b/sample_bags/comms4.zip index 6e7eba2f..ec013ef6 100644 Binary files a/sample_bags/comms4.zip and b/sample_bags/comms4.zip differ diff --git a/sample_bags/grants/manifest-md5.txt b/sample_bags/grants/manifest-md5.txt deleted file mode 100644 index 0f58869d..00000000 --- a/sample_bags/grants/manifest-md5.txt +++ /dev/null @@ -1,6 +0,0 @@ -af296662fe5909749c983f98746bd4f8 data/Project Electron Milestones.png -0b492d1e3a586f363c3f24302b9a525f data/Project Electron Year Two Gantt.png -d68b445ceb1befbcb6bdc357e6896edc data/demo.docx -8eb7307b41ae27e400ffd3db47be3f09 data/hGrant_Spec.pdf -cfc62f46dcbaf505b60140ea5051db77 data/idealware_gms_trends_4.21.16.pdf -94b6e2e66323c5ce3273ef6af9a66126 data/metadata.json diff --git a/sample_bags/grants/manifest-sha256.txt b/sample_bags/grants/manifest-sha256.txt new file mode 100644 index 00000000..4daccf2e --- /dev/null +++ b/sample_bags/grants/manifest-sha256.txt @@ -0,0 +1,6 @@ +1770ef8af984ca96b37d2d19da74aa8924abe97dbe68558f7f565ab41ca3d793 data/Project Electron Milestones.png +50b17b0cb820625a3f0caaba8e95ecbd401631b943c72d6c8e00bf45bc61c302 data/Project Electron Year Two Gantt.png +269329fc7ae54b3f289b3ac52efde387edc2e566ef9a48d637e841022c7e0eab data/demo.docx +c1cc91fe83aae24ab0aa0703fee87919bd8cc6baf0e581c48c8204b5d3a5a170 data/hGrant_Spec.pdf +2e01adf8d272c5954b7cba592dc5458dbce684324eaa4960bbc6044e32394676 data/idealware_gms_trends_4.21.16.pdf +93efae05e86d7c43e323239b17e9fb3fff7cff0f6cb3a7bb3f9606b2b8e1a71b data/metadata.json diff --git a/sample_bags/grants/manifest-sha512.txt b/sample_bags/grants/manifest-sha512.txt new file mode 100644 index 00000000..3da956c8 --- /dev/null +++ b/sample_bags/grants/manifest-sha512.txt @@ -0,0 +1,6 @@ +366e30fa1cf10b260801c733318f0b3e25ad5fa07340a9186c50bb9536c2b69cc0938dc53e7859f5236ce9a325513b029bb7ef44a0fb61c58d39e2684d7fdb1c data/Project Electron Milestones.png +8a28b4386d21655ac71767a1eada85584326687af7808fe7b174ed831f70fbf6b97ba2973b8a48b7d50ed60190db0d611c0a2569cccf31b1658241d76bfba914 data/Project Electron Year Two Gantt.png +d635c5c57f8a56666967a866c1681f62e3362cdf8961e15123ead1af567532a2cd3a235758e6fb6d1d2b4c667b3907cc2b27a338a6c24c81a8b565060cb8d93b data/demo.docx +b9f0fc8a546bae4a0c4c77d4977a6dd2b2733a0efe1d40dba48db6d8b61700817ca0a610a137c1ffc1a9b04bed0f5678e83467e4f1421173f3f3b9559ff66299 data/hGrant_Spec.pdf +30c8370356b6d3721ffb02db069e9e3e58ecdd7cda75a4dd9d8db79482562595cd4f1f633821d00aa158056f0e531e7747443db37a59faca11f00c6e5028c226 data/idealware_gms_trends_4.21.16.pdf +bddd225316b5fe71afbae00bc1bd5102125f993c2042c06fc4ab572b79f07c286517e563343fcf3ee4fc210a6dc9cb79eed1a600208004427038e66b94440581 data/metadata.json diff --git a/sample_bags/grants/tagmanifest-md5.txt b/sample_bags/grants/tagmanifest-md5.txt deleted file mode 100644 index 1409af44..00000000 --- a/sample_bags/grants/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -29551a30e182b601e293dff47a4eb881 bag-info.txt -bb17d2dfc8f6c5e366efeb8395b811f7 manifest-md5.txt diff --git a/sample_bags/grants/tagmanifest-sha256.txt b/sample_bags/grants/tagmanifest-sha256.txt new file mode 100644 index 00000000..92a4fb69 --- /dev/null +++ b/sample_bags/grants/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +8683a40e48c3c4441fe16ad2d3b499b82f897e9d5ebbd64cb1399c82e718aa2e bag-info.txt +3f6e9c2a4c29d1f33c7e01aefedf9963f6c7335144f1a4ae06245c5ac1490d0d manifest-sha512.txt +706bf16a1b922d4dbb6b61c2cef56e7c7c06a36c2641047a5a2ff49c0be5e233 manifest-sha256.txt diff --git a/sample_bags/grants/tagmanifest-sha512.txt b/sample_bags/grants/tagmanifest-sha512.txt new file mode 100644 index 00000000..0431cf7c --- /dev/null +++ b/sample_bags/grants/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +fc7890aeba7e08843a65e3ce8268cb152acd8eff2b79c98556b0659dee2d4c7769c9101597f18e8042a2a4c21249500ea1f59b09319a3f809fd6f10e866458b2 bag-info.txt +2cce68e970e908fe2d7bcf6c8edbe0064408f6f67b5d4623168a46618bb2c1b819e44647483a6f8d8c1f6686b238670c19b764f07ff61db74098f1dea0aff701 manifest-sha512.txt +f5986d0dafcb5f0787e73179f8b515f0ef72fbc92ed245375bdae95cf336f72678d5ec9926abf1ef8c868cd984f96fe20d0ef49ff6ae4b2c3a6df234acfb7c74 manifest-sha256.txt diff --git a/sample_bags/grants2.tar b/sample_bags/grants2.tar index f3823d8e..2d38cb7e 100644 Binary files a/sample_bags/grants2.tar and b/sample_bags/grants2.tar differ diff --git a/sample_bags/grants3.tar.gz b/sample_bags/grants3.tar.gz index 0e521b03..4266114f 100644 Binary files a/sample_bags/grants3.tar.gz and b/sample_bags/grants3.tar.gz differ diff --git a/sample_bags/grants4.zip b/sample_bags/grants4.zip index de819b01..ecef111a 100644 Binary files a/sample_bags/grants4.zip and b/sample_bags/grants4.zip differ diff --git a/sample_bags/invalid_datatype_date/bag-info.txt b/sample_bags/invalid_datatype_date/bag-info.txt deleted file mode 100755 index 971029bb..00000000 --- a/sample_bags/invalid_datatype_date/bag-info.txt +++ /dev/null @@ -1,15 +0,0 @@ -Bag-Software-Agent: bagit.py -BagIt-Profile-Identifier: http://localhost:8000/api/bagit_profiles/2/ -Bagging-Date: 2017-11-04T14:57:10.324823 -Date-End: June 22, 2002 -Date-Start: 2000-05-14 -External-Identifier: records-2017-11-04T14:57:10.324823 -Internal-Sender-Description: Grant awarded to the Village Green Preservation Society for the purpose of "preserving the old ways from being abused, protecting the new ways for me and for you" -Language: eng -Payload-Oxum: 435255.8 -Record-Creators: Custard Pie Appreciation Consortium -Record-Creators: Desperate Dan Appreciation Society -Record-Type: grant records -Restrictions: Records open only to Mrs. Mopp and good old Mother Riley -Source-Organization: Donor Organization -Title: Grant to the Village Green Preservation Society diff --git a/sample_bags/invalid_datatype_date/bagit.txt b/sample_bags/invalid_datatype_date/bagit.txt deleted file mode 100755 index c4aebb43..00000000 --- a/sample_bags/invalid_datatype_date/bagit.txt +++ /dev/null @@ -1,2 +0,0 @@ -BagIt-Version: 0.97 -Tag-File-Character-Encoding: UTF-8 diff --git a/sample_bags/invalid_datatype_date/data/Lorem ipsum dolor sit amet.docx b/sample_bags/invalid_datatype_date/data/Lorem ipsum dolor sit amet.docx deleted file mode 100755 index e9b27c83..00000000 Binary files a/sample_bags/invalid_datatype_date/data/Lorem ipsum dolor sit amet.docx and /dev/null differ diff --git a/sample_bags/invalid_datatype_date/data/Lorem ipsum.odt b/sample_bags/invalid_datatype_date/data/Lorem ipsum.odt deleted file mode 100755 index 4d63bef0..00000000 Binary files a/sample_bags/invalid_datatype_date/data/Lorem ipsum.odt and /dev/null differ diff --git a/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.pdf b/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.pdf deleted file mode 100755 index a5ff1e24..00000000 Binary files a/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.pdf and /dev/null differ diff --git a/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.rtf b/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.rtf deleted file mode 100755 index 57faf807..00000000 --- a/sample_bags/invalid_datatype_date/data/consectetur adipiscing elit.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg10000\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\fdbmajor\f31501\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f38\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\f39\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\f41\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\f42\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\f43\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\f44\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\f45\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\f46\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f48\fbidi \fnil\fcharset238\fprq2 Arial CE;}{\f49\fbidi \fnil\fcharset204\fprq2 Arial Cyr;} {\f51\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\f52\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\f53\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);}{\f54\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\f55\fbidi \fnil\fcharset186\fprq2 Arial Baltic;} {\f56\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);}{\f398\fbidi \fnil\fcharset238\fprq2 Calibri CE;}{\f399\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\f401\fbidi \fnil\fcharset161\fprq2 Calibri Greek;} {\f402\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\f405\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;}{\f406\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \fnil\fcharset238\fprq2 Arial CE;} {\flomajor\f31509\fbidi \fnil\fcharset204\fprq2 Arial Cyr;}{\flomajor\f31511\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\flomajor\f31512\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\flomajor\f31513\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);} {\flomajor\f31514\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\flomajor\f31515\fbidi \fnil\fcharset186\fprq2 Arial Baltic;}{\flomajor\f31516\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);} {\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbmajor\f31522\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbmajor\f31525\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fnil\fcharset238\fprq2 Calibri Light CE;} {\fhimajor\f31529\fbidi \fnil\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fnil\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fnil\fcharset162\fprq2 Calibri Light Tur;} {\fhimajor\f31535\fbidi \fnil\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fnil\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbimajor\f31545\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\flominor\f31555\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbminor\f31565\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fnil\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fnil\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbiminor\f31585\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0; \red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128; \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{ \s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \sunhideused \styrsid6382479 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid5859285\rsid6104307\rsid6382479\rsid7956859\rsid10444034}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1 \mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Hillel Arnold}{\operator Hillel Arnold}{\creatim\yr2017\mo8\dy14\hr16\min27}{\revtim\yr2017\mo8\dy14\hr16\min27}{\version2}{\edmins1}{\nofpages2}{\nofwords1318}{\nofchars7515} {\nofcharsws8816}{\vern61059}{\*\saveprevpict}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1 \jexpand\viewkind1\viewscale190\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel \wrppunct\asianbrkrule\rsidroot6382479\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal\outdisponlyhtml \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5859285\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6382479 \cbpat8 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ultrices tellus ac congue pretium. Quisque consectetur nunc erat. Maecenas nec mauris ut nisl posuere molestie ut ut eros. Duis a lacus nec est scelerisque consequat vel sed lectus. Donec non ali q uam ex. Ut non urna tristique, euismod nulla eu, venenatis tellus. Nullam in semper magna. Praesent auctor feugiat mauris, vitae elementum nisi sagittis ut. Quisque ultrices lectus ac egestas rutrum. Cras convallis vitae nisl eu lobortis. Sed ullamcorper felis eget laoreet maximus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi in ante ac purus ullamcorper pulvinar. Aenean rhoncus in odio vel sollicitudin. Donec a imperdiet elit.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Cras vitae eros non turpis maxi mus consequat laoreet ac enim. Suspendisse elit dui, convallis ac dui in, gravida vehicula nulla. Pellentesque lorem arcu, imperdiet sed blandit vehicula, consectetur ut sem. Nullam sit amet ipsum viverra, consequat elit ut, mollis diam. Aenean varius tel l us vitae urna rhoncus, a sodales nulla rhoncus. Fusce posuere orci sit amet sem convallis, vitae hendrerit lacus suscipit. Sed accumsan ligula eu sem cursus, ut maximus justo varius. In volutpat felis eget eleifend fringilla. Donec nec suscipit diam, vel c ongue dolor. Etiam non lectus placerat, venenatis ex sit amet, rutrum urna. Morbi mi tortor, dignissim ut mi vitae, auctor pellentesque nisl. Vestibulum eu nibh vitae neque viverra pulvinar non nec sapien. Donec tincidunt dui sit amet erat commodo, ut con sectetur odio porttitor. Nulla eu risus placerat neque congue venenatis. Etiam bibendum mi nibh, eget dignissim eros ullamcorper eget. Maecenas mollis lectus aliquet ante pharetra vulputate.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus sit amet risus justo. Nam varius metus at elementum tinc idunt. Sed sed mauris libero. Cras tincidunt sagittis turpis, eget faucibus metus bibendum ut. Quisque euismod libero elit. Nunc placerat gravida augue a egestas. Quisque eu mattis velit. Suspendisse id efficitur ante, non aliquam eros. Donec luctus, augu e egestas egestas ultrices, arcu quam pellentesque elit, et molestie justo leo ullamcorper tellus. In dignissim mollis nulla, nec lobortis dolor. Etiam ac arcu cursus, ullamcorper dui eu, hendrerit ex. Fusce congue ante interdum nunc porttitor pulvinar. Su s pendisse ligula sapien, tincidunt quis est sit amet, sodales tincidunt nibh. Etiam vitae aliquet lorem, sit amet accumsan velit. Sed fermentum arcu nec massa gravida, sit amet aliquet purus suscipit. Cras eget ligula hendrerit, scelerisque tellus id, ulla mcorper ipsum.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut tellus velit, faucibus semper mi in, elementum vestibulum turpis. Proin consequat tempus quam, ut sollicitudin diam elementum sed. Nam tellus dolor, porta ac congue sit amet, ornare sed nunc. Phasellus velit sapien, eleifend at imperdiet n on, tristique non nibh. Aliquam erat volutpat. Vivamus in est nunc. Etiam hendrerit, erat vitae elementum aliquet, felis ipsum maximus dui, quis gravida velit orci sit amet erat. Curabitur massa nibh, efficitur quis dolor id, malesuada elementum felis. In tristique mattis nibh, sed porta justo aliquam euismod. Mauris et fermentum erat. Integer pretium velit non neque condimentum, at varius augue blandit. Quisque a faucibus dolor. Aliquam in neque ut ipsum blandit auctor. Mauris dignissim augue non ultricie s rhoncus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 In maximus id felis vel porta. Morbi venenatis nisi nec lacinia vulputate. Nunc hendrerit risus non arcu pulvinar malesuada. Nunc viverra turpis justo, vitae efficitur ex pellentesque facilisis. Duis sit amet dolor nunc. Maecenas luctus justo a v ulputate maximus. Nulla felis arcu, euismod et magna eget, bibendum condimentum enim. Cras sodales ultrices orci vulputate rhoncus. Donec ac ipsum scelerisque, fermentum justo at, pulvinar leo. Sed tincidunt ligula mi, non ultricies nunc laoreet quis. Mau ris pharetra ut massa vel egestas.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Sed massa augue, aliquet et rutrum quis, accumsan iaculis magna. Donec hendrerit orci vitae nulla euismod, rhoncus pellentesque felis luctus. Etiam augue lorem, molestie in neque sed, mattis mattis eros. Nulla id sapien pu lvinar, tincidunt diam ut, aliquam orci. Pellentesque sit amet massa et tellus ultricies euismod non sed urna. Ut congue imperdiet purus, scelerisque eleifend neque hendrerit sed. Vivamus ultrices faucibus lacus, sit amet porttitor sem fermentum ac. Sed i aculis erat quis venenatis tincidunt. Pellentesque mattis bibendum urna vel faucibus. Nulla facilisi. Praesent quis nulla rutrum, dignissim dui eu, interdum arcu. Proin pharetra egestas dui et tempus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Vestibulum turpis nisl, posuere vitae ante ut, rhoncus h endrerit magna. Proin finibus massa ipsum. Nullam porttitor, neque at laoreet tincidunt, massa metus iaculis turpis, et sodales erat velit vitae orci. Morbi congue, dui lobortis egestas commodo, ipsum felis pretium leo, vitae aliquet felis massa faucibus e ros. Nullam a erat quis tellus euismod convallis. Donec mi turpis, faucibus at aliquet pharetra, fringilla eget arcu. Proin ac lectus ipsum. Nulla at lacinia sapien. Aenean tortor velit, feugiat quis ultrices ac, dapibus id enim. Mauris sollicitudin ut ma uris nec aliquam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nam ornare porttitor erat, nec semper nisl sagittis eget. Morbi pretium lorem magna. Donec ultrices bibendum ex, quis efficitur tellus. Proin id cursus purus, vel luctus justo. Nam in lacus sit amet urna facilisis facilisis vel a sem. Cura bitur ut commodo odio, in maximus lectus. Mauris pretium vehicula elit, et sodales diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus consectetur tristique lectus et rhoncus. Aenean vel vehicula nisl, id vestibulum quam. Duis hendrerit, metus sed blandit tempus, tortor purus posuere turpis, et mollis enim velit id nisl. Suspendisse ullamcorper efficitur dui vitae commodo. Aenean posuere justo sit amet tincidunt pulvinar. In molestie eu est et aliquam. Curabitur velit erat, malesuada eu sodales non, eleifend sagittis sapien. Ut faucibus eges t as elementum. Nulla quis pharetra erat. Maecenas pretium ornare quam fringilla sodales. Nunc ut volutpat ante, egestas vestibulum diam. Nam ultricies tellus convallis convallis molestie. Donec venenatis quis justo quis tristique. Proin commodo blandit urn a vitae gravida.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nulla id lacus ornare, egestas nulla ut, sagittis magna. Etiam dui dolor, gravida ac nulla sed, efficitur elementum massa. Etiam sem est, hendrerit ut viverra eu, commodo id ligula. Donec non metus blandit, iaculis ipsum eu, egestas est. Ae nean eget aliquet justo. Ut bibendum mi ac tellus luctus, at gravida libero placerat. Maecenas eu mi consectetur, mollis urna a, imperdiet tellus. Pellentesque nec dolor tortor. Cras tellus tellus, scelerisque vitae aliquam ut, tristique eu dui. Ut nec ma gna turpis. Donec efficitur luctus ultricies. Vivamus et sapien blandit, euismod metus ac, mollis ligula. Sed vestibulum a ante quis semper.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Praesent mi tellus, hendrerit eu aliquam quis, pharetra sit amet risus. Nulla nec consequat tortor. Etiam mollis ali quet porttitor. Donec metus purus, viverra in risus at, rhoncus luctus leo. Proin venenatis, lectus non vestibulum suscipit, nisi magna dignissim nulla, ut dignissim eros sem at nulla. Suspendisse tincidunt lobortis accumsan. Integer id dictum diam. Pelle ntesque commodo facilisis nisi et congue. Duis lobortis scelerisque ex, non pharetra odio blandit at. Maecenas facilisis commodo mollis. Donec convallis venenatis dolor id porta. Nunc nec nisi diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut ultricies, est in rutrum vestibulum, dui lorem condimen tum ipsum, id maximus lorem turpis et quam. Nunc ultricies augue at velit aliquam iaculis. Praesent eget felis egestas, placerat arcu vel, tempor risus. Nunc neque quam, vulputate quis tellus quis, venenatis gravida arcu. In suscipit at massa eu porta. Mo r bi vitae tempus urna, a vestibulum nunc. Etiam efficitur pharetra laoreet. Duis at risus eget dolor molestie vulputate non in diam. Nunc diam magna, accumsan ac euismod eu, gravida at eros. Cras in tellus eu velit consectetur vehicula ac non velit. Mauris volutpat neque et euismod congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur non mauris at nisl condimentum viverra quis lacinia nisl.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }\pard \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6104307 \cbpat8 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Morbi fermentum nibh in lorem bibendum dictum. Class aptent taciti sociosqu ad litora torque nt per conubia nostra, per inceptos himenaeos. Nam condimentum odio felis, et porta diam laoreet sit amet. Nulla consectetur urna sem, placerat pretium nunc lobortis aliquam. Etiam non eros ut elit placerat scelerisque sed at purus. Morbi vitae auctor ex, lacinia tempus magna. Suspendisse quis euismod nunc. Morbi eu posuere ante. Suspendisse sed ultrices urna, eu cursus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer nisi mauris, vehicula ut ultr ices vel, molestie et risus. Nullam ac libero id purus ultricies posuere. Nunc sed pulvinar sapien. Pellentesque sed commodo leo.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid7956859\charrsid6104307 \par }{\*\themedata 504b0304140006000800000021009be8704ffc0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 72ba28a5d8cea28f5d1f8bf40306796c8bd823214d42f2f71d3b2e941202856e04d2ccbdf7cca85c1fc641ed3126e7a9d2abbcd00ac9fac65157e9cfcd4b76af 5562a006064f58e92326bdaeafafcacd316052a2a654e99e393c18936c8f23a4dc0724a9b43e8ec0728d9d0960b7d0a1b92d8a3b633d3112673c79e8ba7cc216 7603abe7833c9f4844aed5e3a96f8aaa348430380b2ca066aa9ab3ba8843ba20dc53f38b2e5bc87251cee6a97721dd2c09efb29ae81a541f10f90d46e1302c43 e2cff31548468bf965e633d1be6d9dc5c6dbdd28ebc867e3c5ec4f00abff89fece34f3dfd65f000000ffff0300504b030414000600080000002100a5d6a7e7c0 000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060a bb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d9 4fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82f e353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f 7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d59 2c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8 d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100fb07ec41b50600008d1a0000160000007468656d652f7468656d652f746865 6d65312e786d6cec59cd8edb3610be17e83b08ba3bfe93fcb38837b0657bb7cd6e12c44eda1cb9322d314b898648efc60802f4090a14488b5e0af4d6432f01da 674ad1a60fd12125cba44d677fb00582a26b602151df0c3fce8cbea1a4fb0f5e25d4b9c019272cedb9f57b35d7c169c866248d7aeeb3e9b8d2711d2e503a4394 a5b8e7ae30771f1c7efed97d7420629c6007ec537e807a6e2cc4e2a05ae5210c237e8f2d700ad7e62c4b9080d32caace3274097e135a6dd46aad6a8248ea3a29 4ac0ede3f99c84d8994a97eee1daf988c2692ab81c08693691aeb161a1b0b3f3ba44f0150f68e65c20da73619e19bb9ce257c27528e2022ef4dc9afa73ab87f7 abe8a030a2628fad6637567f855d61303b6fa839b3e8ac9cd4f37cafd52ffd2b0015bbb8517bd41ab54a7f0a80c210569a73317db61b81576035507e68f13d6c 0f9b7503aff96fee70eefbf267e01528f7efede0c7e300a268e01528c7fb3b787fd01d0c4dff0a94e35b3bf876ad3ff4da867f058a2949cf77d035bfd50cd6ab 2d2173468fadf0aeef8ddb8dc2f90605d55056979c62ce52b1afd612f49265630048204582a48e582df01c8550c501a2e42c23ce09896228bc054a1987e15aa3 36ae35e1bffc79ea4865141d60a4594b5ec084ef0c493e0e0f33b2103df74bf0ea6a90174be788899884c5acca8961718cd248b7f8f0cb777ffff48df3d76f3f 7f78fb7d3ee9369eebf8214ea3af094a3f3601ac761386f73fbcfbe3f777ef7ffcf6cf5fdf5afcf73374a6c3a724c1dc79842f9da72c81c5595680cfb29b594c 6344748b7e1a719422398bc5ff08e2a7a31fad104516dc0022a1e39e67203336e0d1f2a5417812674b412c1e1fc689013c658c0e58668dc243399716e6e9328d ec93674b1df714a10bdbdc014a8d3c8f960bd057627319c4d8a0f984a254a008a75838f21a3bc7d8b2ba178418713d2561c6389b0be705710688584332256746 356d8c8e49027959d90842be8dd89c3e77068cda563dc4172612ee0e442de4a7981a613c424b81129bcb294aa81ef01324621bc9c92a0b75dc880bc874842973 4633ccb9cde67106ebd592fe1024c69ef653ba4a4c6426c8b9cde709624c470ed97910a36461c34e481aebd82ff8399428729e3061839f32f30e91e79007108f 7de97e4eb091eeabd5e019a8ab4e695320f2ca32b3e4f20833a37e272b3a4758490d88bfa1e90949af14f82d69f7ff3d693f25691833cb8aee4ad4edae8d8cdc 50cefb19b1de4fc75b22be0fb72ddd01cb66e4d357ee215aa64f30dc2cbbedeb7fe1fe5fb8ddffbc70efbb9fef5eae370a0de22db7aef9665d6ddd93bd3bf739 a1742256149f70b579e7d0976663189476eaa915974f728b180ee59d0c1318b82843cac6c998f88a887812a305ecf0ebae7412f1c275c49d05e3b0f157c356df 124f97c9299be50facf5ba7c38cdc58323b119aff9e5383c6c881cdd6a6f1ec24af78a6da41e96d704a4ed4d48689399249a1612edf5a00c927a3487a05948a8 95dd098bae854547ba5fa76a8705502bb3021b2707b65b3dd7f7c0048ce0990a513c9379ca53bdceae4ae65d667a5f308d0a805dc4ba023699ee4aae7b972757 9797da35326d90d0cacd24a122a37a188fd10c17d52947af43e3a6b9ee6e526ad093a150f341696d68b43b1f6371db5c83ddb636d054570a9a3a973db7d5f4a1 6442b4e8b97378f087c36401b5c3e58617d108de9e8522cb6ff8db28cb22e36288789c075c894eae060911387328497aae5c7e99069a2a0d51dcea0d10844f96 5c1764e55323074937938ce7731c0a3dedda888c747e0a0a9f6b85f5aa32bf3d585ab225a47b12cf2e9d33bacc9e222831bf5d97019c110eef7fea793467045e 689642b6a9bfadc654c8aefe4651d5503e8ee822464547d1c53c872b292fe9a8b33206da59b16608a81692a2119e45b2c1ea4135ba69d935720e7bbbeed54632 729a686e7aa6a12ab26bda55cc9861dd06b66279bb26afb15a8718344deff0b9746f4b6e77ad755bfb84b24b40c0cbf859baee351a82466d3399414d32de9561 a9d9c5a8d93bd60bbc82da759a84a6faadb5dbadb8953dc23a1d0cdeaaf383dd76d5c2d07cbdaf5491565f3ef48f13ecec2588c7105e032fa9e02a95f0e92143 b0219aa83d492e1b708bbc12c5ad0147ce32233df775cdef7b41c30f2ab58e3faa784daf56e9f8fd66a5effbcdfac8afd78683c61b682c224eea7efed5650c2f a2e8aaf8f6a2c677bebf24eb776df742965499fabe5255c4d5f7977a63fff7178780e8bc6e35c6dd6677d0aa749bfd71c51b0e3a956ed01a5486ada03d1c0f03 bfd31dbf719d0b05f6facdc06b8d3a95563d082a5eab26e977ba95b6d768f4bd76bf33f2fa6f8a6d0cac3c978f2216105ec5ebf01f000000ffff0300504b0304 140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c 73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a c16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b 017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d00140006 000800000021009be8704ffc0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d001400 0600080000002100a5d6a7e7c0000000360100000b000000000000000000000000002d0100005f72656c732f2e72656c73504b01022d00140006000800000021 006b799616830000008a0000001c00000000000000000000000000160200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d 0014000600080000002100fb07ec41b50600008d1a00001600000000000000000000000000d30200007468656d652f7468656d652f7468656d65312e786d6c50 4b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000bc0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000b70a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax382\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 8; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 9;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; \lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;}}{\*\datastore }} \ No newline at end of file diff --git a/sample_bags/invalid_datatype_date/data/metadata.json b/sample_bags/invalid_datatype_date/data/metadata.json deleted file mode 100755 index 4a33170c..00000000 --- a/sample_bags/invalid_datatype_date/data/metadata.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "5992098ae5be0ee2b3a53230", - "index": 0, - "guid": "42038759-10f6-4d07-80bd-d22a3d15c2a7", - "isActive": false, - "balance": "$2,972.29", - "picture": "http://placehold.it/32x32", - "age": 40, - "eyeColor": "blue", - "name": "Ofelia Cantrell", - "gender": "female", - "company": "REMOTION", - "email": "ofeliacantrell@remotion.com", - "phone": "+1 (933) 409-2769", - "address": "703 Perry Terrace, Yonah, Ohio, 2288", - "about": "Et do amet ex do quis duis. Esse cillum dolor minim qui irure ad ut. Do adipisicing sint esse sint culpa est minim commodo reprehenderit pariatur veniam quis consectetur qui. Cupidatat veniam aute laboris deserunt sint aliqua non sit non. Non minim voluptate velit dolor quis consequat exercitation. Sint et ea magna ex incididunt ea laborum.\r\n", - "registered": "2015-06-06T02:44:14 +04:00", - "latitude": -15.53943, - "longitude": -161.829515, - "tags": [ - "duis", - "reprehenderit", - "tempor", - "exercitation", - "fugiat", - "ex", - "aliquip" - ], - "friends": [ - { - "id": 0, - "name": "Moran Donovan" - }, - { - "id": 1, - "name": "Cross Leonard" - }, - { - "id": 2, - "name": "Young Macdonald" - } - ], - "greeting": "Hello, Ofelia Cantrell! You have 2 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098a2d0e698c435ef3c4", - "index": 1, - "guid": "1602e45f-9ed8-4e8c-a464-cc921a8f5687", - "isActive": true, - "balance": "$1,819.74", - "picture": "http://placehold.it/32x32", - "age": 36, - "eyeColor": "green", - "name": "Payne Carter", - "gender": "male", - "company": "SPRINGBEE", - "email": "paynecarter@springbee.com", - "phone": "+1 (821) 446-3230", - "address": "649 Bush Street, Edgar, Missouri, 2760", - "about": "Laborum culpa dolor id quis incididunt mollit veniam. Incididunt consectetur tempor occaecat eiusmod sunt aute amet aliqua deserunt do Lorem aliquip in. Nostrud tempor irure eu ex sint magna cupidatat consequat quis pariatur elit proident. Reprehenderit consequat qui incididunt laboris esse esse incididunt quis culpa nisi. Aliqua aliqua anim aliquip irure occaecat mollit mollit nostrud ut sit qui. Amet enim ullamco qui mollit nisi irure labore ad. Velit enim aliqua laborum eu eu minim id enim deserunt.\r\n", - "registered": "2014-09-04T03:38:13 +04:00", - "latitude": 48.091037, - "longitude": -178.775433, - "tags": [ - "excepteur", - "qui", - "magna", - "exercitation", - "sit", - "labore", - "laboris" - ], - "friends": [ - { - "id": 0, - "name": "Willa Moon" - }, - { - "id": 1, - "name": "Jodie Briggs" - }, - { - "id": 2, - "name": "Katina Ramirez" - } - ], - "greeting": "Hello, Payne Carter! You have 10 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ad752f1c7ae3020a7", - "index": 2, - "guid": "051ecc3d-3e33-45ae-93c1-c1f48c892f87", - "isActive": false, - "balance": "$1,895.69", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Kristi Young", - "gender": "female", - "company": "DATACATOR", - "email": "kristiyoung@datacator.com", - "phone": "+1 (991) 418-3593", - "address": "822 Reeve Place, Swartzville, Iowa, 1295", - "about": "Amet do in laboris commodo ut aute ullamco voluptate mollit proident labore qui anim in. Ipsum occaecat incididunt sit culpa eu et ad dolore proident et tempor nostrud minim. Deserunt reprehenderit adipisicing laborum velit labore eiusmod amet consectetur aute do amet non labore exercitation.\r\n", - "registered": "2014-02-22T11:35:14 +05:00", - "latitude": -33.068243, - "longitude": -135.989542, - "tags": [ - "in", - "elit", - "consequat", - "incididunt", - "magna", - "id", - "aliqua" - ], - "friends": [ - { - "id": 0, - "name": "Mclean Merrill" - }, - { - "id": 1, - "name": "Donna Moss" - }, - { - "id": 2, - "name": "Eva Donaldson" - } - ], - "greeting": "Hello, Kristi Young! You have 4 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a3c3d2bd8f4e680b5", - "index": 3, - "guid": "434e2f6c-8896-4267-95c8-4443da518937", - "isActive": true, - "balance": "$1,226.19", - "picture": "http://placehold.it/32x32", - "age": 25, - "eyeColor": "green", - "name": "Cassie Wells", - "gender": "female", - "company": "DRAGBOT", - "email": "cassiewells@dragbot.com", - "phone": "+1 (962) 455-2900", - "address": "467 Conselyea Street, Fresno, Utah, 5198", - "about": "Nisi enim irure velit cillum et ut eu. Ullamco esse cupidatat est proident amet anim voluptate. Eiusmod aute occaecat aliquip laboris et. Elit velit minim nostrud consectetur cillum ipsum. Nostrud enim nisi proident excepteur ex aliquip exercitation. Dolore cillum laborum ut cupidatat officia exercitation aliquip eiusmod eiusmod cupidatat elit mollit esse. Aute excepteur cupidatat do aliqua magna commodo magna esse eiusmod sint et cupidatat labore elit.\r\n", - "registered": "2017-02-15T08:33:56 +05:00", - "latitude": 15.310112, - "longitude": -18.42037, - "tags": [ - "commodo", - "aliqua", - "aute", - "tempor", - "enim", - "excepteur", - "labore" - ], - "friends": [ - { - "id": 0, - "name": "Loretta Gates" - }, - { - "id": 1, - "name": "Moreno Mathis" - }, - { - "id": 2, - "name": "Lisa Sloan" - } - ], - "greeting": "Hello, Cassie Wells! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ac51d569909f3f924", - "index": 4, - "guid": "c55f4203-3136-427e-a9b1-cd4f447a7e66", - "isActive": true, - "balance": "$2,813.15", - "picture": "http://placehold.it/32x32", - "age": 23, - "eyeColor": "blue", - "name": "Leigh Levy", - "gender": "female", - "company": "IMAGINART", - "email": "leighlevy@imaginart.com", - "phone": "+1 (976) 465-3476", - "address": "390 Furman Street, Albrightsville, Wisconsin, 2324", - "about": "Excepteur commodo minim veniam aute et dolore ea voluptate magna eu laboris. Laboris cupidatat est mollit proident consectetur eiusmod officia aute aliqua culpa. In fugiat qui enim sunt.\r\n", - "registered": "2014-05-03T01:12:53 +04:00", - "latitude": 35.087356, - "longitude": -5.142767, - "tags": [ - "mollit", - "duis", - "veniam", - "laboris", - "magna", - "et", - "exercitation" - ], - "friends": [ - { - "id": 0, - "name": "Middleton Walker" - }, - { - "id": 1, - "name": "Fitzgerald Dickerson" - }, - { - "id": 2, - "name": "Teresa Cherry" - } - ], - "greeting": "Hello, Leigh Levy! You have 6 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a01c1b5dc6b527746", - "index": 5, - "guid": "21cb7015-229a-48d2-89bd-ed664c493001", - "isActive": false, - "balance": "$2,106.23", - "picture": "http://placehold.it/32x32", - "age": 31, - "eyeColor": "brown", - "name": "Santiago Valencia", - "gender": "male", - "company": "TERRAGO", - "email": "santiagovalencia@terrago.com", - "phone": "+1 (887) 540-3439", - "address": "241 Quentin Road, Strong, Nevada, 9629", - "about": "Qui elit do veniam tempor do nisi in tempor anim magna. Laborum ex sint do elit reprehenderit tempor. Mollit labore ut amet in anim. Proident cillum sint elit aute reprehenderit exercitation duis fugiat ad velit pariatur non excepteur. Minim consequat anim dolore proident.\r\n", - "registered": "2015-01-27T04:21:17 +05:00", - "latitude": 31.602384, - "longitude": 78.941588, - "tags": [ - "eu", - "voluptate", - "eu", - "ad", - "excepteur", - "sit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "Ellen Mccarty" - }, - { - "id": 1, - "name": "Deloris French" - }, - { - "id": 2, - "name": "Brandie Porter" - } - ], - "greeting": "Hello, Santiago Valencia! You have 4 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098ad8b6931921cd3539", - "index": 6, - "guid": "42e83426-f488-4077-9d8a-0df690e26d77", - "isActive": false, - "balance": "$3,769.50", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Ursula Lester", - "gender": "female", - "company": "LIQUICOM", - "email": "ursulalester@liquicom.com", - "phone": "+1 (916) 549-2548", - "address": "548 Coleman Street, Elbert, Vermont, 1941", - "about": "Lorem qui pariatur officia proident ullamco occaecat velit aute ex adipisicing velit commodo proident dolor. Sit consectetur culpa commodo aliquip commodo reprehenderit labore ea dolore ex enim enim. Laboris proident fugiat ea enim sunt eiusmod enim sint non enim proident aliqua deserunt. Eiusmod qui do eiusmod irure ad. Elit magna enim in excepteur occaecat esse excepteur commodo ut. Ea aute veniam qui ea adipisicing quis id consequat esse laboris ea consectetur amet minim.\r\n", - "registered": "2017-06-24T10:28:26 +04:00", - "latitude": -72.032682, - "longitude": -58.19158, - "tags": [ - "nulla", - "nostrud", - "anim", - "exercitation", - "ullamco", - "ipsum", - "cupidatat" - ], - "friends": [ - { - "id": 0, - "name": "Maddox Weeks" - }, - { - "id": 1, - "name": "Paul Peterson" - }, - { - "id": 2, - "name": "Powers Quinn" - } - ], - "greeting": "Hello, Ursula Lester! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file diff --git a/sample_bags/invalid_datatype_date/data/more_data.xlsx b/sample_bags/invalid_datatype_date/data/more_data.xlsx deleted file mode 100755 index 7f9d7ff9..00000000 Binary files a/sample_bags/invalid_datatype_date/data/more_data.xlsx and /dev/null differ diff --git a/sample_bags/invalid_datatype_date/data/sample_data.xlsx b/sample_bags/invalid_datatype_date/data/sample_data.xlsx deleted file mode 100755 index f049f345..00000000 Binary files a/sample_bags/invalid_datatype_date/data/sample_data.xlsx and /dev/null differ diff --git a/sample_bags/invalid_datatype_date/manifest-md5.txt b/sample_bags/invalid_datatype_date/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/sample_bags/invalid_datatype_date/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/sample_bags/invalid_datatype_date/tagmanifest-md5.txt b/sample_bags/invalid_datatype_date/tagmanifest-md5.txt deleted file mode 100755 index e7ff5652..00000000 --- a/sample_bags/invalid_datatype_date/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -cfff4a5d2b194a8efa6f3b5bd0dfe3be bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/sample_bags/invalid_datatype_language.tar b/sample_bags/invalid_datatype_language.tar deleted file mode 100644 index 7052a2e0..00000000 Binary files a/sample_bags/invalid_datatype_language.tar and /dev/null differ diff --git a/sample_bags/invalid_metadata_file.tar.gz b/sample_bags/invalid_metadata_file.tar.gz deleted file mode 100644 index 73d2b858..00000000 Binary files a/sample_bags/invalid_metadata_file.tar.gz and /dev/null differ diff --git a/sample_bags/missing_bag_declaration.zip b/sample_bags/missing_bag_declaration.zip deleted file mode 100644 index 8ce15ed8..00000000 Binary files a/sample_bags/missing_bag_declaration.zip and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/bag-info.txt b/sample_bags/missing_bag_manifest/bag-info.txt deleted file mode 100644 index 035179ac..00000000 --- a/sample_bags/missing_bag_manifest/bag-info.txt +++ /dev/null @@ -1,3 +0,0 @@ -BagIt-Profile-Identifier: http://localhost:8000/api/bagit_profiles/2/ -Payload-Oxum: 435255.8 -Source-Organization: Donor Organization diff --git a/sample_bags/missing_bag_manifest/bagit.txt b/sample_bags/missing_bag_manifest/bagit.txt deleted file mode 100755 index c4aebb43..00000000 --- a/sample_bags/missing_bag_manifest/bagit.txt +++ /dev/null @@ -1,2 +0,0 @@ -BagIt-Version: 0.97 -Tag-File-Character-Encoding: UTF-8 diff --git a/sample_bags/missing_bag_manifest/data/Lorem ipsum dolor sit amet.docx b/sample_bags/missing_bag_manifest/data/Lorem ipsum dolor sit amet.docx deleted file mode 100755 index e9b27c83..00000000 Binary files a/sample_bags/missing_bag_manifest/data/Lorem ipsum dolor sit amet.docx and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/data/Lorem ipsum.odt b/sample_bags/missing_bag_manifest/data/Lorem ipsum.odt deleted file mode 100755 index 4d63bef0..00000000 Binary files a/sample_bags/missing_bag_manifest/data/Lorem ipsum.odt and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.pdf b/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.pdf deleted file mode 100755 index a5ff1e24..00000000 Binary files a/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.pdf and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.rtf b/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.rtf deleted file mode 100755 index 57faf807..00000000 --- a/sample_bags/missing_bag_manifest/data/consectetur adipiscing elit.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg10000\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\fdbmajor\f31501\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f38\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\f39\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\f41\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\f42\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\f43\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\f44\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\f45\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\f46\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f48\fbidi \fnil\fcharset238\fprq2 Arial CE;}{\f49\fbidi \fnil\fcharset204\fprq2 Arial Cyr;} {\f51\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\f52\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\f53\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);}{\f54\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\f55\fbidi \fnil\fcharset186\fprq2 Arial Baltic;} {\f56\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);}{\f398\fbidi \fnil\fcharset238\fprq2 Calibri CE;}{\f399\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\f401\fbidi \fnil\fcharset161\fprq2 Calibri Greek;} {\f402\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\f405\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;}{\f406\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \fnil\fcharset238\fprq2 Arial CE;} {\flomajor\f31509\fbidi \fnil\fcharset204\fprq2 Arial Cyr;}{\flomajor\f31511\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\flomajor\f31512\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\flomajor\f31513\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);} {\flomajor\f31514\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\flomajor\f31515\fbidi \fnil\fcharset186\fprq2 Arial Baltic;}{\flomajor\f31516\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);} {\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbmajor\f31522\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbmajor\f31525\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fnil\fcharset238\fprq2 Calibri Light CE;} {\fhimajor\f31529\fbidi \fnil\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fnil\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fnil\fcharset162\fprq2 Calibri Light Tur;} {\fhimajor\f31535\fbidi \fnil\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fnil\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbimajor\f31545\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\flominor\f31555\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbminor\f31565\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fnil\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fnil\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbiminor\f31585\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0; \red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128; \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{ \s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \sunhideused \styrsid6382479 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid5859285\rsid6104307\rsid6382479\rsid7956859\rsid10444034}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1 \mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Hillel Arnold}{\operator Hillel Arnold}{\creatim\yr2017\mo8\dy14\hr16\min27}{\revtim\yr2017\mo8\dy14\hr16\min27}{\version2}{\edmins1}{\nofpages2}{\nofwords1318}{\nofchars7515} {\nofcharsws8816}{\vern61059}{\*\saveprevpict}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1 \jexpand\viewkind1\viewscale190\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel \wrppunct\asianbrkrule\rsidroot6382479\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal\outdisponlyhtml \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5859285\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6382479 \cbpat8 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ultrices tellus ac congue pretium. Quisque consectetur nunc erat. Maecenas nec mauris ut nisl posuere molestie ut ut eros. Duis a lacus nec est scelerisque consequat vel sed lectus. Donec non ali q uam ex. Ut non urna tristique, euismod nulla eu, venenatis tellus. Nullam in semper magna. Praesent auctor feugiat mauris, vitae elementum nisi sagittis ut. Quisque ultrices lectus ac egestas rutrum. Cras convallis vitae nisl eu lobortis. Sed ullamcorper felis eget laoreet maximus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi in ante ac purus ullamcorper pulvinar. Aenean rhoncus in odio vel sollicitudin. Donec a imperdiet elit.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Cras vitae eros non turpis maxi mus consequat laoreet ac enim. Suspendisse elit dui, convallis ac dui in, gravida vehicula nulla. Pellentesque lorem arcu, imperdiet sed blandit vehicula, consectetur ut sem. Nullam sit amet ipsum viverra, consequat elit ut, mollis diam. Aenean varius tel l us vitae urna rhoncus, a sodales nulla rhoncus. Fusce posuere orci sit amet sem convallis, vitae hendrerit lacus suscipit. Sed accumsan ligula eu sem cursus, ut maximus justo varius. In volutpat felis eget eleifend fringilla. Donec nec suscipit diam, vel c ongue dolor. Etiam non lectus placerat, venenatis ex sit amet, rutrum urna. Morbi mi tortor, dignissim ut mi vitae, auctor pellentesque nisl. Vestibulum eu nibh vitae neque viverra pulvinar non nec sapien. Donec tincidunt dui sit amet erat commodo, ut con sectetur odio porttitor. Nulla eu risus placerat neque congue venenatis. Etiam bibendum mi nibh, eget dignissim eros ullamcorper eget. Maecenas mollis lectus aliquet ante pharetra vulputate.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus sit amet risus justo. Nam varius metus at elementum tinc idunt. Sed sed mauris libero. Cras tincidunt sagittis turpis, eget faucibus metus bibendum ut. Quisque euismod libero elit. Nunc placerat gravida augue a egestas. Quisque eu mattis velit. Suspendisse id efficitur ante, non aliquam eros. Donec luctus, augu e egestas egestas ultrices, arcu quam pellentesque elit, et molestie justo leo ullamcorper tellus. In dignissim mollis nulla, nec lobortis dolor. Etiam ac arcu cursus, ullamcorper dui eu, hendrerit ex. Fusce congue ante interdum nunc porttitor pulvinar. Su s pendisse ligula sapien, tincidunt quis est sit amet, sodales tincidunt nibh. Etiam vitae aliquet lorem, sit amet accumsan velit. Sed fermentum arcu nec massa gravida, sit amet aliquet purus suscipit. Cras eget ligula hendrerit, scelerisque tellus id, ulla mcorper ipsum.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut tellus velit, faucibus semper mi in, elementum vestibulum turpis. Proin consequat tempus quam, ut sollicitudin diam elementum sed. Nam tellus dolor, porta ac congue sit amet, ornare sed nunc. Phasellus velit sapien, eleifend at imperdiet n on, tristique non nibh. Aliquam erat volutpat. Vivamus in est nunc. Etiam hendrerit, erat vitae elementum aliquet, felis ipsum maximus dui, quis gravida velit orci sit amet erat. Curabitur massa nibh, efficitur quis dolor id, malesuada elementum felis. In tristique mattis nibh, sed porta justo aliquam euismod. Mauris et fermentum erat. Integer pretium velit non neque condimentum, at varius augue blandit. Quisque a faucibus dolor. Aliquam in neque ut ipsum blandit auctor. Mauris dignissim augue non ultricie s rhoncus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 In maximus id felis vel porta. Morbi venenatis nisi nec lacinia vulputate. Nunc hendrerit risus non arcu pulvinar malesuada. Nunc viverra turpis justo, vitae efficitur ex pellentesque facilisis. Duis sit amet dolor nunc. Maecenas luctus justo a v ulputate maximus. Nulla felis arcu, euismod et magna eget, bibendum condimentum enim. Cras sodales ultrices orci vulputate rhoncus. Donec ac ipsum scelerisque, fermentum justo at, pulvinar leo. Sed tincidunt ligula mi, non ultricies nunc laoreet quis. Mau ris pharetra ut massa vel egestas.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Sed massa augue, aliquet et rutrum quis, accumsan iaculis magna. Donec hendrerit orci vitae nulla euismod, rhoncus pellentesque felis luctus. Etiam augue lorem, molestie in neque sed, mattis mattis eros. Nulla id sapien pu lvinar, tincidunt diam ut, aliquam orci. Pellentesque sit amet massa et tellus ultricies euismod non sed urna. Ut congue imperdiet purus, scelerisque eleifend neque hendrerit sed. Vivamus ultrices faucibus lacus, sit amet porttitor sem fermentum ac. Sed i aculis erat quis venenatis tincidunt. Pellentesque mattis bibendum urna vel faucibus. Nulla facilisi. Praesent quis nulla rutrum, dignissim dui eu, interdum arcu. Proin pharetra egestas dui et tempus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Vestibulum turpis nisl, posuere vitae ante ut, rhoncus h endrerit magna. Proin finibus massa ipsum. Nullam porttitor, neque at laoreet tincidunt, massa metus iaculis turpis, et sodales erat velit vitae orci. Morbi congue, dui lobortis egestas commodo, ipsum felis pretium leo, vitae aliquet felis massa faucibus e ros. Nullam a erat quis tellus euismod convallis. Donec mi turpis, faucibus at aliquet pharetra, fringilla eget arcu. Proin ac lectus ipsum. Nulla at lacinia sapien. Aenean tortor velit, feugiat quis ultrices ac, dapibus id enim. Mauris sollicitudin ut ma uris nec aliquam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nam ornare porttitor erat, nec semper nisl sagittis eget. Morbi pretium lorem magna. Donec ultrices bibendum ex, quis efficitur tellus. Proin id cursus purus, vel luctus justo. Nam in lacus sit amet urna facilisis facilisis vel a sem. Cura bitur ut commodo odio, in maximus lectus. Mauris pretium vehicula elit, et sodales diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus consectetur tristique lectus et rhoncus. Aenean vel vehicula nisl, id vestibulum quam. Duis hendrerit, metus sed blandit tempus, tortor purus posuere turpis, et mollis enim velit id nisl. Suspendisse ullamcorper efficitur dui vitae commodo. Aenean posuere justo sit amet tincidunt pulvinar. In molestie eu est et aliquam. Curabitur velit erat, malesuada eu sodales non, eleifend sagittis sapien. Ut faucibus eges t as elementum. Nulla quis pharetra erat. Maecenas pretium ornare quam fringilla sodales. Nunc ut volutpat ante, egestas vestibulum diam. Nam ultricies tellus convallis convallis molestie. Donec venenatis quis justo quis tristique. Proin commodo blandit urn a vitae gravida.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nulla id lacus ornare, egestas nulla ut, sagittis magna. Etiam dui dolor, gravida ac nulla sed, efficitur elementum massa. Etiam sem est, hendrerit ut viverra eu, commodo id ligula. Donec non metus blandit, iaculis ipsum eu, egestas est. Ae nean eget aliquet justo. Ut bibendum mi ac tellus luctus, at gravida libero placerat. Maecenas eu mi consectetur, mollis urna a, imperdiet tellus. Pellentesque nec dolor tortor. Cras tellus tellus, scelerisque vitae aliquam ut, tristique eu dui. Ut nec ma gna turpis. Donec efficitur luctus ultricies. Vivamus et sapien blandit, euismod metus ac, mollis ligula. Sed vestibulum a ante quis semper.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Praesent mi tellus, hendrerit eu aliquam quis, pharetra sit amet risus. Nulla nec consequat tortor. Etiam mollis ali quet porttitor. Donec metus purus, viverra in risus at, rhoncus luctus leo. Proin venenatis, lectus non vestibulum suscipit, nisi magna dignissim nulla, ut dignissim eros sem at nulla. Suspendisse tincidunt lobortis accumsan. Integer id dictum diam. Pelle ntesque commodo facilisis nisi et congue. Duis lobortis scelerisque ex, non pharetra odio blandit at. Maecenas facilisis commodo mollis. Donec convallis venenatis dolor id porta. Nunc nec nisi diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut ultricies, est in rutrum vestibulum, dui lorem condimen tum ipsum, id maximus lorem turpis et quam. Nunc ultricies augue at velit aliquam iaculis. Praesent eget felis egestas, placerat arcu vel, tempor risus. Nunc neque quam, vulputate quis tellus quis, venenatis gravida arcu. In suscipit at massa eu porta. Mo r bi vitae tempus urna, a vestibulum nunc. Etiam efficitur pharetra laoreet. Duis at risus eget dolor molestie vulputate non in diam. Nunc diam magna, accumsan ac euismod eu, gravida at eros. Cras in tellus eu velit consectetur vehicula ac non velit. Mauris volutpat neque et euismod congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur non mauris at nisl condimentum viverra quis lacinia nisl.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }\pard \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6104307 \cbpat8 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Morbi fermentum nibh in lorem bibendum dictum. Class aptent taciti sociosqu ad litora torque nt per conubia nostra, per inceptos himenaeos. Nam condimentum odio felis, et porta diam laoreet sit amet. Nulla consectetur urna sem, placerat pretium nunc lobortis aliquam. Etiam non eros ut elit placerat scelerisque sed at purus. Morbi vitae auctor ex, lacinia tempus magna. Suspendisse quis euismod nunc. Morbi eu posuere ante. Suspendisse sed ultrices urna, eu cursus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer nisi mauris, vehicula ut ultr ices vel, molestie et risus. Nullam ac libero id purus ultricies posuere. Nunc sed pulvinar sapien. Pellentesque sed commodo leo.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid7956859\charrsid6104307 \par }{\*\themedata 504b0304140006000800000021009be8704ffc0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 72ba28a5d8cea28f5d1f8bf40306796c8bd823214d42f2f71d3b2e941202856e04d2ccbdf7cca85c1fc641ed3126e7a9d2abbcd00ac9fac65157e9cfcd4b76af 5562a006064f58e92326bdaeafafcacd316052a2a654e99e393c18936c8f23a4dc0724a9b43e8ec0728d9d0960b7d0a1b92d8a3b633d3112673c79e8ba7cc216 7603abe7833c9f4844aed5e3a96f8aaa348430380b2ca066aa9ab3ba8843ba20dc53f38b2e5bc87251cee6a97721dd2c09efb29ae81a541f10f90d46e1302c43 e2cff31548468bf965e633d1be6d9dc5c6dbdd28ebc867e3c5ec4f00abff89fece34f3dfd65f000000ffff0300504b030414000600080000002100a5d6a7e7c0 000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060a bb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d9 4fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82f e353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f 7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d59 2c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8 d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100fb07ec41b50600008d1a0000160000007468656d652f7468656d652f746865 6d65312e786d6cec59cd8edb3610be17e83b08ba3bfe93fcb38837b0657bb7cd6e12c44eda1cb9322d314b898648efc60802f4090a14488b5e0af4d6432f01da 674ad1a60fd12125cba44d677fb00582a26b602151df0c3fce8cbea1a4fb0f5e25d4b9c019272cedb9f57b35d7c169c866248d7aeeb3e9b8d2711d2e503a4394 a5b8e7ae30771f1c7efed97d7420629c6007ec537e807a6e2cc4e2a05ae5210c237e8f2d700ad7e62c4b9080d32caace3274097e135a6dd46aad6a8248ea3a29 4ac0ede3f99c84d8994a97eee1daf988c2692ab81c08693691aeb161a1b0b3f3ba44f0150f68e65c20da73619e19bb9ce257c27528e2022ef4dc9afa73ab87f7 abe8a030a2628fad6637567f855d61303b6fa839b3e8ac9cd4f37cafd52ffd2b0015bbb8517bd41ab54a7f0a80c210569a73317db61b81576035507e68f13d6c 0f9b7503aff96fee70eefbf267e01528f7efede0c7e300a268e01528c7fb3b787fd01d0c4dff0a94e35b3bf876ad3ff4da867f058a2949cf77d035bfd50cd6ab 2d2173468fadf0aeef8ddb8dc2f90605d55056979c62ce52b1afd612f49265630048204582a48e582df01c8550c501a2e42c23ce09896228bc054a1987e15aa3 36ae35e1bffc79ea4865141d60a4594b5ec084ef0c493e0e0f33b2103df74bf0ea6a90174be788899884c5acca8961718cd248b7f8f0cb777ffff48df3d76f3f 7f78fb7d3ee9369eebf8214ea3af094a3f3601ac761386f73fbcfbe3f777ef7ffcf6cf5fdf5afcf73374a6c3a724c1dc79842f9da72c81c5595680cfb29b594c 6344748b7e1a719422398bc5ff08e2a7a31fad104516dc0022a1e39e67203336e0d1f2a5417812674b412c1e1fc689013c658c0e58668dc243399716e6e9328d ec93674b1df714a10bdbdc014a8d3c8f960bd057627319c4d8a0f984a254a008a75838f21a3bc7d8b2ba178418713d2561c6389b0be705710688584332256746 356d8c8e49027959d90842be8dd89c3e77068cda563dc4172612ee0e442de4a7981a613c424b81129bcb294aa81ef01324621bc9c92a0b75dc880bc874842973 4633ccb9cde67106ebd592fe1024c69ef653ba4a4c6426c8b9cde709624c470ed97910a36461c34e481aebd82ff8399428729e3061839f32f30e91e79007108f 7de97e4eb091eeabd5e019a8ab4e695320f2ca32b3e4f20833a37e272b3a4758490d88bfa1e90949af14f82d69f7ff3d693f25691833cb8aee4ad4edae8d8cdc 50cefb19b1de4fc75b22be0fb72ddd01cb66e4d357ee215aa64f30dc2cbbedeb7fe1fe5fb8ddffbc70efbb9fef5eae370a0de22db7aef9665d6ddd93bd3bf739 a1742256149f70b579e7d0976663189476eaa915974f728b180ee59d0c1318b82843cac6c998f88a887812a305ecf0ebae7412f1c275c49d05e3b0f157c356df 124f97c9299be50facf5ba7c38cdc58323b119aff9e5383c6c881cdd6a6f1ec24af78a6da41e96d704a4ed4d48689399249a1612edf5a00c927a3487a05948a8 95dd098bae854547ba5fa76a8705502bb3021b2707b65b3dd7f7c0048ce0990a513c9379ca53bdceae4ae65d667a5f308d0a805dc4ba023699ee4aae7b972757 9797da35326d90d0cacd24a122a37a188fd10c17d52947af43e3a6b9ee6e526ad093a150f341696d68b43b1f6371db5c83ddb636d054570a9a3a973db7d5f4a1 6442b4e8b97378f087c36401b5c3e58617d108de9e8522cb6ff8db28cb22e36288789c075c894eae060911387328497aae5c7e99069a2a0d51dcea0d10844f96 5c1764e55323074937938ce7731c0a3dedda888c747e0a0a9f6b85f5aa32bf3d585ab225a47b12cf2e9d33bacc9e222831bf5d97019c110eef7fea793467045e 689642b6a9bfadc654c8aefe4651d5503e8ee822464547d1c53c872b292fe9a8b33206da59b16608a81692a2119e45b2c1ea4135ba69d935720e7bbbeed54632 729a686e7aa6a12ab26bda55cc9861dd06b66279bb26afb15a8718344deff0b9746f4b6e77ad755bfb84b24b40c0cbf859baee351a82466d3399414d32de9561 a9d9c5a8d93bd60bbc82da759a84a6faadb5dbadb8953dc23a1d0cdeaaf383dd76d5c2d07cbdaf5491565f3ef48f13ecec2588c7105e032fa9e02a95f0e92143 b0219aa83d492e1b708bbc12c5ad0147ce32233df775cdef7b41c30f2ab58e3faa784daf56e9f8fd66a5effbcdfac8afd78683c61b682c224eea7efed5650c2f a2e8aaf8f6a2c677bebf24eb776df742965499fabe5255c4d5f7977a63fff7178780e8bc6e35c6dd6677d0aa749bfd71c51b0e3a956ed01a5486ada03d1c0f03 bfd31dbf719d0b05f6facdc06b8d3a95563d082a5eab26e977ba95b6d768f4bd76bf33f2fa6f8a6d0cac3c978f2216105ec5ebf01f000000ffff0300504b0304 140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c 73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a c16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b 017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d00140006 000800000021009be8704ffc0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d001400 0600080000002100a5d6a7e7c0000000360100000b000000000000000000000000002d0100005f72656c732f2e72656c73504b01022d00140006000800000021 006b799616830000008a0000001c00000000000000000000000000160200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d 0014000600080000002100fb07ec41b50600008d1a00001600000000000000000000000000d30200007468656d652f7468656d652f7468656d65312e786d6c50 4b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000bc0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000b70a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax382\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 8; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 9;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; \lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;}}{\*\datastore }} \ No newline at end of file diff --git a/sample_bags/missing_bag_manifest/data/metadata.json b/sample_bags/missing_bag_manifest/data/metadata.json deleted file mode 100755 index 4a33170c..00000000 --- a/sample_bags/missing_bag_manifest/data/metadata.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "5992098ae5be0ee2b3a53230", - "index": 0, - "guid": "42038759-10f6-4d07-80bd-d22a3d15c2a7", - "isActive": false, - "balance": "$2,972.29", - "picture": "http://placehold.it/32x32", - "age": 40, - "eyeColor": "blue", - "name": "Ofelia Cantrell", - "gender": "female", - "company": "REMOTION", - "email": "ofeliacantrell@remotion.com", - "phone": "+1 (933) 409-2769", - "address": "703 Perry Terrace, Yonah, Ohio, 2288", - "about": "Et do amet ex do quis duis. Esse cillum dolor minim qui irure ad ut. Do adipisicing sint esse sint culpa est minim commodo reprehenderit pariatur veniam quis consectetur qui. Cupidatat veniam aute laboris deserunt sint aliqua non sit non. Non minim voluptate velit dolor quis consequat exercitation. Sint et ea magna ex incididunt ea laborum.\r\n", - "registered": "2015-06-06T02:44:14 +04:00", - "latitude": -15.53943, - "longitude": -161.829515, - "tags": [ - "duis", - "reprehenderit", - "tempor", - "exercitation", - "fugiat", - "ex", - "aliquip" - ], - "friends": [ - { - "id": 0, - "name": "Moran Donovan" - }, - { - "id": 1, - "name": "Cross Leonard" - }, - { - "id": 2, - "name": "Young Macdonald" - } - ], - "greeting": "Hello, Ofelia Cantrell! You have 2 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098a2d0e698c435ef3c4", - "index": 1, - "guid": "1602e45f-9ed8-4e8c-a464-cc921a8f5687", - "isActive": true, - "balance": "$1,819.74", - "picture": "http://placehold.it/32x32", - "age": 36, - "eyeColor": "green", - "name": "Payne Carter", - "gender": "male", - "company": "SPRINGBEE", - "email": "paynecarter@springbee.com", - "phone": "+1 (821) 446-3230", - "address": "649 Bush Street, Edgar, Missouri, 2760", - "about": "Laborum culpa dolor id quis incididunt mollit veniam. Incididunt consectetur tempor occaecat eiusmod sunt aute amet aliqua deserunt do Lorem aliquip in. Nostrud tempor irure eu ex sint magna cupidatat consequat quis pariatur elit proident. Reprehenderit consequat qui incididunt laboris esse esse incididunt quis culpa nisi. Aliqua aliqua anim aliquip irure occaecat mollit mollit nostrud ut sit qui. Amet enim ullamco qui mollit nisi irure labore ad. Velit enim aliqua laborum eu eu minim id enim deserunt.\r\n", - "registered": "2014-09-04T03:38:13 +04:00", - "latitude": 48.091037, - "longitude": -178.775433, - "tags": [ - "excepteur", - "qui", - "magna", - "exercitation", - "sit", - "labore", - "laboris" - ], - "friends": [ - { - "id": 0, - "name": "Willa Moon" - }, - { - "id": 1, - "name": "Jodie Briggs" - }, - { - "id": 2, - "name": "Katina Ramirez" - } - ], - "greeting": "Hello, Payne Carter! You have 10 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ad752f1c7ae3020a7", - "index": 2, - "guid": "051ecc3d-3e33-45ae-93c1-c1f48c892f87", - "isActive": false, - "balance": "$1,895.69", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Kristi Young", - "gender": "female", - "company": "DATACATOR", - "email": "kristiyoung@datacator.com", - "phone": "+1 (991) 418-3593", - "address": "822 Reeve Place, Swartzville, Iowa, 1295", - "about": "Amet do in laboris commodo ut aute ullamco voluptate mollit proident labore qui anim in. Ipsum occaecat incididunt sit culpa eu et ad dolore proident et tempor nostrud minim. Deserunt reprehenderit adipisicing laborum velit labore eiusmod amet consectetur aute do amet non labore exercitation.\r\n", - "registered": "2014-02-22T11:35:14 +05:00", - "latitude": -33.068243, - "longitude": -135.989542, - "tags": [ - "in", - "elit", - "consequat", - "incididunt", - "magna", - "id", - "aliqua" - ], - "friends": [ - { - "id": 0, - "name": "Mclean Merrill" - }, - { - "id": 1, - "name": "Donna Moss" - }, - { - "id": 2, - "name": "Eva Donaldson" - } - ], - "greeting": "Hello, Kristi Young! You have 4 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a3c3d2bd8f4e680b5", - "index": 3, - "guid": "434e2f6c-8896-4267-95c8-4443da518937", - "isActive": true, - "balance": "$1,226.19", - "picture": "http://placehold.it/32x32", - "age": 25, - "eyeColor": "green", - "name": "Cassie Wells", - "gender": "female", - "company": "DRAGBOT", - "email": "cassiewells@dragbot.com", - "phone": "+1 (962) 455-2900", - "address": "467 Conselyea Street, Fresno, Utah, 5198", - "about": "Nisi enim irure velit cillum et ut eu. Ullamco esse cupidatat est proident amet anim voluptate. Eiusmod aute occaecat aliquip laboris et. Elit velit minim nostrud consectetur cillum ipsum. Nostrud enim nisi proident excepteur ex aliquip exercitation. Dolore cillum laborum ut cupidatat officia exercitation aliquip eiusmod eiusmod cupidatat elit mollit esse. Aute excepteur cupidatat do aliqua magna commodo magna esse eiusmod sint et cupidatat labore elit.\r\n", - "registered": "2017-02-15T08:33:56 +05:00", - "latitude": 15.310112, - "longitude": -18.42037, - "tags": [ - "commodo", - "aliqua", - "aute", - "tempor", - "enim", - "excepteur", - "labore" - ], - "friends": [ - { - "id": 0, - "name": "Loretta Gates" - }, - { - "id": 1, - "name": "Moreno Mathis" - }, - { - "id": 2, - "name": "Lisa Sloan" - } - ], - "greeting": "Hello, Cassie Wells! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ac51d569909f3f924", - "index": 4, - "guid": "c55f4203-3136-427e-a9b1-cd4f447a7e66", - "isActive": true, - "balance": "$2,813.15", - "picture": "http://placehold.it/32x32", - "age": 23, - "eyeColor": "blue", - "name": "Leigh Levy", - "gender": "female", - "company": "IMAGINART", - "email": "leighlevy@imaginart.com", - "phone": "+1 (976) 465-3476", - "address": "390 Furman Street, Albrightsville, Wisconsin, 2324", - "about": "Excepteur commodo minim veniam aute et dolore ea voluptate magna eu laboris. Laboris cupidatat est mollit proident consectetur eiusmod officia aute aliqua culpa. In fugiat qui enim sunt.\r\n", - "registered": "2014-05-03T01:12:53 +04:00", - "latitude": 35.087356, - "longitude": -5.142767, - "tags": [ - "mollit", - "duis", - "veniam", - "laboris", - "magna", - "et", - "exercitation" - ], - "friends": [ - { - "id": 0, - "name": "Middleton Walker" - }, - { - "id": 1, - "name": "Fitzgerald Dickerson" - }, - { - "id": 2, - "name": "Teresa Cherry" - } - ], - "greeting": "Hello, Leigh Levy! You have 6 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a01c1b5dc6b527746", - "index": 5, - "guid": "21cb7015-229a-48d2-89bd-ed664c493001", - "isActive": false, - "balance": "$2,106.23", - "picture": "http://placehold.it/32x32", - "age": 31, - "eyeColor": "brown", - "name": "Santiago Valencia", - "gender": "male", - "company": "TERRAGO", - "email": "santiagovalencia@terrago.com", - "phone": "+1 (887) 540-3439", - "address": "241 Quentin Road, Strong, Nevada, 9629", - "about": "Qui elit do veniam tempor do nisi in tempor anim magna. Laborum ex sint do elit reprehenderit tempor. Mollit labore ut amet in anim. Proident cillum sint elit aute reprehenderit exercitation duis fugiat ad velit pariatur non excepteur. Minim consequat anim dolore proident.\r\n", - "registered": "2015-01-27T04:21:17 +05:00", - "latitude": 31.602384, - "longitude": 78.941588, - "tags": [ - "eu", - "voluptate", - "eu", - "ad", - "excepteur", - "sit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "Ellen Mccarty" - }, - { - "id": 1, - "name": "Deloris French" - }, - { - "id": 2, - "name": "Brandie Porter" - } - ], - "greeting": "Hello, Santiago Valencia! You have 4 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098ad8b6931921cd3539", - "index": 6, - "guid": "42e83426-f488-4077-9d8a-0df690e26d77", - "isActive": false, - "balance": "$3,769.50", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Ursula Lester", - "gender": "female", - "company": "LIQUICOM", - "email": "ursulalester@liquicom.com", - "phone": "+1 (916) 549-2548", - "address": "548 Coleman Street, Elbert, Vermont, 1941", - "about": "Lorem qui pariatur officia proident ullamco occaecat velit aute ex adipisicing velit commodo proident dolor. Sit consectetur culpa commodo aliquip commodo reprehenderit labore ea dolore ex enim enim. Laboris proident fugiat ea enim sunt eiusmod enim sint non enim proident aliqua deserunt. Eiusmod qui do eiusmod irure ad. Elit magna enim in excepteur occaecat esse excepteur commodo ut. Ea aute veniam qui ea adipisicing quis id consequat esse laboris ea consectetur amet minim.\r\n", - "registered": "2017-06-24T10:28:26 +04:00", - "latitude": -72.032682, - "longitude": -58.19158, - "tags": [ - "nulla", - "nostrud", - "anim", - "exercitation", - "ullamco", - "ipsum", - "cupidatat" - ], - "friends": [ - { - "id": 0, - "name": "Maddox Weeks" - }, - { - "id": 1, - "name": "Paul Peterson" - }, - { - "id": 2, - "name": "Powers Quinn" - } - ], - "greeting": "Hello, Ursula Lester! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file diff --git a/sample_bags/missing_bag_manifest/data/more_data.xlsx b/sample_bags/missing_bag_manifest/data/more_data.xlsx deleted file mode 100755 index 7f9d7ff9..00000000 Binary files a/sample_bags/missing_bag_manifest/data/more_data.xlsx and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/data/sample_data.xlsx b/sample_bags/missing_bag_manifest/data/sample_data.xlsx deleted file mode 100755 index f049f345..00000000 Binary files a/sample_bags/missing_bag_manifest/data/sample_data.xlsx and /dev/null differ diff --git a/sample_bags/missing_bag_manifest/manifest-md5.txt b/sample_bags/missing_bag_manifest/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/sample_bags/missing_bag_manifest/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/sample_bags/missing_bag_manifest/tagmanifest-md5.txt b/sample_bags/missing_bag_manifest/tagmanifest-md5.txt deleted file mode 100755 index 576b0f6b..00000000 --- a/sample_bags/missing_bag_manifest/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -de8f75f428bb939cea0c94e312c22a3e bag-info.txt -194577a7e20bdcc7afbb718f502c134c .DS_Store -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/sample_bags/missing_description.tar b/sample_bags/missing_description.tar deleted file mode 100644 index 07a83842..00000000 Binary files a/sample_bags/missing_description.tar and /dev/null differ diff --git a/sample_bags/missing_payload_directory.tar.gz b/sample_bags/missing_payload_directory.tar.gz deleted file mode 100644 index 3645d34d..00000000 Binary files a/sample_bags/missing_payload_directory.tar.gz and /dev/null differ diff --git a/sample_bags/missing_payload_manifest.zip b/sample_bags/missing_payload_manifest.zip deleted file mode 100644 index 6152c42b..00000000 Binary files a/sample_bags/missing_payload_manifest.zip and /dev/null differ diff --git a/sample_bags/missing_record_type/bag-info.txt b/sample_bags/missing_record_type/bag-info.txt deleted file mode 100755 index 7779af58..00000000 --- a/sample_bags/missing_record_type/bag-info.txt +++ /dev/null @@ -1,14 +0,0 @@ -Bag-Software-Agent: bagit.py -BagIt-Profile-Identifier: http://localhost:8000/api/bagit_profiles/2/ -Bagging-Date: 2017-11-04T14:51:41.554126 -Date-End: 2002-06-22 -Date-Start: 2000-05-14 -External-Identifier: records-2017-11-04T14:51:41.554126 -Internal-Sender-Description: Grant awarded to the Village Green Preservation Society for the purpose of "preserving the old ways from being abused, protecting the new ways for me and for you" -Language: eng -Payload-Oxum: 435255.8 -Record-Creators: Custard Pie Appreciation Consortium -Record-Creators: Desperate Dan Appreciation Society -Restrictions: Records open only to Mrs. Mopp and good old Mother Riley -Source-Organization: Donor Organization -Title: Grant to the Village Green Preservation Society diff --git a/sample_bags/missing_record_type/bagit.txt b/sample_bags/missing_record_type/bagit.txt deleted file mode 100755 index c4aebb43..00000000 --- a/sample_bags/missing_record_type/bagit.txt +++ /dev/null @@ -1,2 +0,0 @@ -BagIt-Version: 0.97 -Tag-File-Character-Encoding: UTF-8 diff --git a/sample_bags/missing_record_type/data/Lorem ipsum dolor sit amet.docx b/sample_bags/missing_record_type/data/Lorem ipsum dolor sit amet.docx deleted file mode 100755 index e9b27c83..00000000 Binary files a/sample_bags/missing_record_type/data/Lorem ipsum dolor sit amet.docx and /dev/null differ diff --git a/sample_bags/missing_record_type/data/Lorem ipsum.odt b/sample_bags/missing_record_type/data/Lorem ipsum.odt deleted file mode 100755 index 4d63bef0..00000000 Binary files a/sample_bags/missing_record_type/data/Lorem ipsum.odt and /dev/null differ diff --git a/sample_bags/missing_record_type/data/consectetur adipiscing elit.pdf b/sample_bags/missing_record_type/data/consectetur adipiscing elit.pdf deleted file mode 100755 index a5ff1e24..00000000 Binary files a/sample_bags/missing_record_type/data/consectetur adipiscing elit.pdf and /dev/null differ diff --git a/sample_bags/missing_record_type/data/consectetur adipiscing elit.rtf b/sample_bags/missing_record_type/data/consectetur adipiscing elit.rtf deleted file mode 100755 index 57faf807..00000000 --- a/sample_bags/missing_record_type/data/consectetur adipiscing elit.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg10000\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\fdbmajor\f31501\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f38\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\f39\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\f41\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\f42\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\f43\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\f44\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\f45\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\f46\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f48\fbidi \fnil\fcharset238\fprq2 Arial CE;}{\f49\fbidi \fnil\fcharset204\fprq2 Arial Cyr;} {\f51\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\f52\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\f53\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);}{\f54\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\f55\fbidi \fnil\fcharset186\fprq2 Arial Baltic;} {\f56\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);}{\f398\fbidi \fnil\fcharset238\fprq2 Calibri CE;}{\f399\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\f401\fbidi \fnil\fcharset161\fprq2 Calibri Greek;} {\f402\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\f405\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;}{\f406\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \fnil\fcharset238\fprq2 Arial CE;} {\flomajor\f31509\fbidi \fnil\fcharset204\fprq2 Arial Cyr;}{\flomajor\f31511\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\flomajor\f31512\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\flomajor\f31513\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);} {\flomajor\f31514\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\flomajor\f31515\fbidi \fnil\fcharset186\fprq2 Arial Baltic;}{\flomajor\f31516\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);} {\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbmajor\f31522\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbmajor\f31525\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fnil\fcharset238\fprq2 Calibri Light CE;} {\fhimajor\f31529\fbidi \fnil\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fnil\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fnil\fcharset162\fprq2 Calibri Light Tur;} {\fhimajor\f31535\fbidi \fnil\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fnil\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbimajor\f31545\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\flominor\f31555\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbminor\f31565\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fnil\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fnil\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbiminor\f31585\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0; \red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128; \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{ \s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \sunhideused \styrsid6382479 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid5859285\rsid6104307\rsid6382479\rsid7956859\rsid10444034}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1 \mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Hillel Arnold}{\operator Hillel Arnold}{\creatim\yr2017\mo8\dy14\hr16\min27}{\revtim\yr2017\mo8\dy14\hr16\min27}{\version2}{\edmins1}{\nofpages2}{\nofwords1318}{\nofchars7515} {\nofcharsws8816}{\vern61059}{\*\saveprevpict}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1 \jexpand\viewkind1\viewscale190\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel \wrppunct\asianbrkrule\rsidroot6382479\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal\outdisponlyhtml \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5859285\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6382479 \cbpat8 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ultrices tellus ac congue pretium. Quisque consectetur nunc erat. Maecenas nec mauris ut nisl posuere molestie ut ut eros. Duis a lacus nec est scelerisque consequat vel sed lectus. Donec non ali q uam ex. Ut non urna tristique, euismod nulla eu, venenatis tellus. Nullam in semper magna. Praesent auctor feugiat mauris, vitae elementum nisi sagittis ut. Quisque ultrices lectus ac egestas rutrum. Cras convallis vitae nisl eu lobortis. Sed ullamcorper felis eget laoreet maximus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi in ante ac purus ullamcorper pulvinar. Aenean rhoncus in odio vel sollicitudin. Donec a imperdiet elit.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Cras vitae eros non turpis maxi mus consequat laoreet ac enim. Suspendisse elit dui, convallis ac dui in, gravida vehicula nulla. Pellentesque lorem arcu, imperdiet sed blandit vehicula, consectetur ut sem. Nullam sit amet ipsum viverra, consequat elit ut, mollis diam. Aenean varius tel l us vitae urna rhoncus, a sodales nulla rhoncus. Fusce posuere orci sit amet sem convallis, vitae hendrerit lacus suscipit. Sed accumsan ligula eu sem cursus, ut maximus justo varius. In volutpat felis eget eleifend fringilla. Donec nec suscipit diam, vel c ongue dolor. Etiam non lectus placerat, venenatis ex sit amet, rutrum urna. Morbi mi tortor, dignissim ut mi vitae, auctor pellentesque nisl. Vestibulum eu nibh vitae neque viverra pulvinar non nec sapien. Donec tincidunt dui sit amet erat commodo, ut con sectetur odio porttitor. Nulla eu risus placerat neque congue venenatis. Etiam bibendum mi nibh, eget dignissim eros ullamcorper eget. Maecenas mollis lectus aliquet ante pharetra vulputate.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus sit amet risus justo. Nam varius metus at elementum tinc idunt. Sed sed mauris libero. Cras tincidunt sagittis turpis, eget faucibus metus bibendum ut. Quisque euismod libero elit. Nunc placerat gravida augue a egestas. Quisque eu mattis velit. Suspendisse id efficitur ante, non aliquam eros. Donec luctus, augu e egestas egestas ultrices, arcu quam pellentesque elit, et molestie justo leo ullamcorper tellus. In dignissim mollis nulla, nec lobortis dolor. Etiam ac arcu cursus, ullamcorper dui eu, hendrerit ex. Fusce congue ante interdum nunc porttitor pulvinar. Su s pendisse ligula sapien, tincidunt quis est sit amet, sodales tincidunt nibh. Etiam vitae aliquet lorem, sit amet accumsan velit. Sed fermentum arcu nec massa gravida, sit amet aliquet purus suscipit. Cras eget ligula hendrerit, scelerisque tellus id, ulla mcorper ipsum.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut tellus velit, faucibus semper mi in, elementum vestibulum turpis. Proin consequat tempus quam, ut sollicitudin diam elementum sed. Nam tellus dolor, porta ac congue sit amet, ornare sed nunc. Phasellus velit sapien, eleifend at imperdiet n on, tristique non nibh. Aliquam erat volutpat. Vivamus in est nunc. Etiam hendrerit, erat vitae elementum aliquet, felis ipsum maximus dui, quis gravida velit orci sit amet erat. Curabitur massa nibh, efficitur quis dolor id, malesuada elementum felis. In tristique mattis nibh, sed porta justo aliquam euismod. Mauris et fermentum erat. Integer pretium velit non neque condimentum, at varius augue blandit. Quisque a faucibus dolor. Aliquam in neque ut ipsum blandit auctor. Mauris dignissim augue non ultricie s rhoncus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 In maximus id felis vel porta. Morbi venenatis nisi nec lacinia vulputate. Nunc hendrerit risus non arcu pulvinar malesuada. Nunc viverra turpis justo, vitae efficitur ex pellentesque facilisis. Duis sit amet dolor nunc. Maecenas luctus justo a v ulputate maximus. Nulla felis arcu, euismod et magna eget, bibendum condimentum enim. Cras sodales ultrices orci vulputate rhoncus. Donec ac ipsum scelerisque, fermentum justo at, pulvinar leo. Sed tincidunt ligula mi, non ultricies nunc laoreet quis. Mau ris pharetra ut massa vel egestas.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Sed massa augue, aliquet et rutrum quis, accumsan iaculis magna. Donec hendrerit orci vitae nulla euismod, rhoncus pellentesque felis luctus. Etiam augue lorem, molestie in neque sed, mattis mattis eros. Nulla id sapien pu lvinar, tincidunt diam ut, aliquam orci. Pellentesque sit amet massa et tellus ultricies euismod non sed urna. Ut congue imperdiet purus, scelerisque eleifend neque hendrerit sed. Vivamus ultrices faucibus lacus, sit amet porttitor sem fermentum ac. Sed i aculis erat quis venenatis tincidunt. Pellentesque mattis bibendum urna vel faucibus. Nulla facilisi. Praesent quis nulla rutrum, dignissim dui eu, interdum arcu. Proin pharetra egestas dui et tempus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Vestibulum turpis nisl, posuere vitae ante ut, rhoncus h endrerit magna. Proin finibus massa ipsum. Nullam porttitor, neque at laoreet tincidunt, massa metus iaculis turpis, et sodales erat velit vitae orci. Morbi congue, dui lobortis egestas commodo, ipsum felis pretium leo, vitae aliquet felis massa faucibus e ros. Nullam a erat quis tellus euismod convallis. Donec mi turpis, faucibus at aliquet pharetra, fringilla eget arcu. Proin ac lectus ipsum. Nulla at lacinia sapien. Aenean tortor velit, feugiat quis ultrices ac, dapibus id enim. Mauris sollicitudin ut ma uris nec aliquam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nam ornare porttitor erat, nec semper nisl sagittis eget. Morbi pretium lorem magna. Donec ultrices bibendum ex, quis efficitur tellus. Proin id cursus purus, vel luctus justo. Nam in lacus sit amet urna facilisis facilisis vel a sem. Cura bitur ut commodo odio, in maximus lectus. Mauris pretium vehicula elit, et sodales diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus consectetur tristique lectus et rhoncus. Aenean vel vehicula nisl, id vestibulum quam. Duis hendrerit, metus sed blandit tempus, tortor purus posuere turpis, et mollis enim velit id nisl. Suspendisse ullamcorper efficitur dui vitae commodo. Aenean posuere justo sit amet tincidunt pulvinar. In molestie eu est et aliquam. Curabitur velit erat, malesuada eu sodales non, eleifend sagittis sapien. Ut faucibus eges t as elementum. Nulla quis pharetra erat. Maecenas pretium ornare quam fringilla sodales. Nunc ut volutpat ante, egestas vestibulum diam. Nam ultricies tellus convallis convallis molestie. Donec venenatis quis justo quis tristique. Proin commodo blandit urn a vitae gravida.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nulla id lacus ornare, egestas nulla ut, sagittis magna. Etiam dui dolor, gravida ac nulla sed, efficitur elementum massa. Etiam sem est, hendrerit ut viverra eu, commodo id ligula. Donec non metus blandit, iaculis ipsum eu, egestas est. Ae nean eget aliquet justo. Ut bibendum mi ac tellus luctus, at gravida libero placerat. Maecenas eu mi consectetur, mollis urna a, imperdiet tellus. Pellentesque nec dolor tortor. Cras tellus tellus, scelerisque vitae aliquam ut, tristique eu dui. Ut nec ma gna turpis. Donec efficitur luctus ultricies. Vivamus et sapien blandit, euismod metus ac, mollis ligula. Sed vestibulum a ante quis semper.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Praesent mi tellus, hendrerit eu aliquam quis, pharetra sit amet risus. Nulla nec consequat tortor. Etiam mollis ali quet porttitor. Donec metus purus, viverra in risus at, rhoncus luctus leo. Proin venenatis, lectus non vestibulum suscipit, nisi magna dignissim nulla, ut dignissim eros sem at nulla. Suspendisse tincidunt lobortis accumsan. Integer id dictum diam. Pelle ntesque commodo facilisis nisi et congue. Duis lobortis scelerisque ex, non pharetra odio blandit at. Maecenas facilisis commodo mollis. Donec convallis venenatis dolor id porta. Nunc nec nisi diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut ultricies, est in rutrum vestibulum, dui lorem condimen tum ipsum, id maximus lorem turpis et quam. Nunc ultricies augue at velit aliquam iaculis. Praesent eget felis egestas, placerat arcu vel, tempor risus. Nunc neque quam, vulputate quis tellus quis, venenatis gravida arcu. In suscipit at massa eu porta. Mo r bi vitae tempus urna, a vestibulum nunc. Etiam efficitur pharetra laoreet. Duis at risus eget dolor molestie vulputate non in diam. Nunc diam magna, accumsan ac euismod eu, gravida at eros. Cras in tellus eu velit consectetur vehicula ac non velit. Mauris volutpat neque et euismod congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur non mauris at nisl condimentum viverra quis lacinia nisl.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }\pard \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6104307 \cbpat8 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Morbi fermentum nibh in lorem bibendum dictum. Class aptent taciti sociosqu ad litora torque nt per conubia nostra, per inceptos himenaeos. Nam condimentum odio felis, et porta diam laoreet sit amet. Nulla consectetur urna sem, placerat pretium nunc lobortis aliquam. Etiam non eros ut elit placerat scelerisque sed at purus. Morbi vitae auctor ex, lacinia tempus magna. Suspendisse quis euismod nunc. Morbi eu posuere ante. Suspendisse sed ultrices urna, eu cursus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer nisi mauris, vehicula ut ultr ices vel, molestie et risus. Nullam ac libero id purus ultricies posuere. Nunc sed pulvinar sapien. Pellentesque sed commodo leo.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid7956859\charrsid6104307 \par }{\*\themedata 504b0304140006000800000021009be8704ffc0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 72ba28a5d8cea28f5d1f8bf40306796c8bd823214d42f2f71d3b2e941202856e04d2ccbdf7cca85c1fc641ed3126e7a9d2abbcd00ac9fac65157e9cfcd4b76af 5562a006064f58e92326bdaeafafcacd316052a2a654e99e393c18936c8f23a4dc0724a9b43e8ec0728d9d0960b7d0a1b92d8a3b633d3112673c79e8ba7cc216 7603abe7833c9f4844aed5e3a96f8aaa348430380b2ca066aa9ab3ba8843ba20dc53f38b2e5bc87251cee6a97721dd2c09efb29ae81a541f10f90d46e1302c43 e2cff31548468bf965e633d1be6d9dc5c6dbdd28ebc867e3c5ec4f00abff89fece34f3dfd65f000000ffff0300504b030414000600080000002100a5d6a7e7c0 000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060a bb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d9 4fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82f e353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f 7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d59 2c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8 d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100fb07ec41b50600008d1a0000160000007468656d652f7468656d652f746865 6d65312e786d6cec59cd8edb3610be17e83b08ba3bfe93fcb38837b0657bb7cd6e12c44eda1cb9322d314b898648efc60802f4090a14488b5e0af4d6432f01da 674ad1a60fd12125cba44d677fb00582a26b602151df0c3fce8cbea1a4fb0f5e25d4b9c019272cedb9f57b35d7c169c866248d7aeeb3e9b8d2711d2e503a4394 a5b8e7ae30771f1c7efed97d7420629c6007ec537e807a6e2cc4e2a05ae5210c237e8f2d700ad7e62c4b9080d32caace3274097e135a6dd46aad6a8248ea3a29 4ac0ede3f99c84d8994a97eee1daf988c2692ab81c08693691aeb161a1b0b3f3ba44f0150f68e65c20da73619e19bb9ce257c27528e2022ef4dc9afa73ab87f7 abe8a030a2628fad6637567f855d61303b6fa839b3e8ac9cd4f37cafd52ffd2b0015bbb8517bd41ab54a7f0a80c210569a73317db61b81576035507e68f13d6c 0f9b7503aff96fee70eefbf267e01528f7efede0c7e300a268e01528c7fb3b787fd01d0c4dff0a94e35b3bf876ad3ff4da867f058a2949cf77d035bfd50cd6ab 2d2173468fadf0aeef8ddb8dc2f90605d55056979c62ce52b1afd612f49265630048204582a48e582df01c8550c501a2e42c23ce09896228bc054a1987e15aa3 36ae35e1bffc79ea4865141d60a4594b5ec084ef0c493e0e0f33b2103df74bf0ea6a90174be788899884c5acca8961718cd248b7f8f0cb777ffff48df3d76f3f 7f78fb7d3ee9369eebf8214ea3af094a3f3601ac761386f73fbcfbe3f777ef7ffcf6cf5fdf5afcf73374a6c3a724c1dc79842f9da72c81c5595680cfb29b594c 6344748b7e1a719422398bc5ff08e2a7a31fad104516dc0022a1e39e67203336e0d1f2a5417812674b412c1e1fc689013c658c0e58668dc243399716e6e9328d ec93674b1df714a10bdbdc014a8d3c8f960bd057627319c4d8a0f984a254a008a75838f21a3bc7d8b2ba178418713d2561c6389b0be705710688584332256746 356d8c8e49027959d90842be8dd89c3e77068cda563dc4172612ee0e442de4a7981a613c424b81129bcb294aa81ef01324621bc9c92a0b75dc880bc874842973 4633ccb9cde67106ebd592fe1024c69ef653ba4a4c6426c8b9cde709624c470ed97910a36461c34e481aebd82ff8399428729e3061839f32f30e91e79007108f 7de97e4eb091eeabd5e019a8ab4e695320f2ca32b3e4f20833a37e272b3a4758490d88bfa1e90949af14f82d69f7ff3d693f25691833cb8aee4ad4edae8d8cdc 50cefb19b1de4fc75b22be0fb72ddd01cb66e4d357ee215aa64f30dc2cbbedeb7fe1fe5fb8ddffbc70efbb9fef5eae370a0de22db7aef9665d6ddd93bd3bf739 a1742256149f70b579e7d0976663189476eaa915974f728b180ee59d0c1318b82843cac6c998f88a887812a305ecf0ebae7412f1c275c49d05e3b0f157c356df 124f97c9299be50facf5ba7c38cdc58323b119aff9e5383c6c881cdd6a6f1ec24af78a6da41e96d704a4ed4d48689399249a1612edf5a00c927a3487a05948a8 95dd098bae854547ba5fa76a8705502bb3021b2707b65b3dd7f7c0048ce0990a513c9379ca53bdceae4ae65d667a5f308d0a805dc4ba023699ee4aae7b972757 9797da35326d90d0cacd24a122a37a188fd10c17d52947af43e3a6b9ee6e526ad093a150f341696d68b43b1f6371db5c83ddb636d054570a9a3a973db7d5f4a1 6442b4e8b97378f087c36401b5c3e58617d108de9e8522cb6ff8db28cb22e36288789c075c894eae060911387328497aae5c7e99069a2a0d51dcea0d10844f96 5c1764e55323074937938ce7731c0a3dedda888c747e0a0a9f6b85f5aa32bf3d585ab225a47b12cf2e9d33bacc9e222831bf5d97019c110eef7fea793467045e 689642b6a9bfadc654c8aefe4651d5503e8ee822464547d1c53c872b292fe9a8b33206da59b16608a81692a2119e45b2c1ea4135ba69d935720e7bbbeed54632 729a686e7aa6a12ab26bda55cc9861dd06b66279bb26afb15a8718344deff0b9746f4b6e77ad755bfb84b24b40c0cbf859baee351a82466d3399414d32de9561 a9d9c5a8d93bd60bbc82da759a84a6faadb5dbadb8953dc23a1d0cdeaaf383dd76d5c2d07cbdaf5491565f3ef48f13ecec2588c7105e032fa9e02a95f0e92143 b0219aa83d492e1b708bbc12c5ad0147ce32233df775cdef7b41c30f2ab58e3faa784daf56e9f8fd66a5effbcdfac8afd78683c61b682c224eea7efed5650c2f a2e8aaf8f6a2c677bebf24eb776df742965499fabe5255c4d5f7977a63fff7178780e8bc6e35c6dd6677d0aa749bfd71c51b0e3a956ed01a5486ada03d1c0f03 bfd31dbf719d0b05f6facdc06b8d3a95563d082a5eab26e977ba95b6d768f4bd76bf33f2fa6f8a6d0cac3c978f2216105ec5ebf01f000000ffff0300504b0304 140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c 73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a c16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b 017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d00140006 000800000021009be8704ffc0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d001400 0600080000002100a5d6a7e7c0000000360100000b000000000000000000000000002d0100005f72656c732f2e72656c73504b01022d00140006000800000021 006b799616830000008a0000001c00000000000000000000000000160200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d 0014000600080000002100fb07ec41b50600008d1a00001600000000000000000000000000d30200007468656d652f7468656d652f7468656d65312e786d6c50 4b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000bc0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000b70a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax382\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 8; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 9;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; \lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;}}{\*\datastore }} \ No newline at end of file diff --git a/sample_bags/missing_record_type/data/metadata.json b/sample_bags/missing_record_type/data/metadata.json deleted file mode 100755 index 4a33170c..00000000 --- a/sample_bags/missing_record_type/data/metadata.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "5992098ae5be0ee2b3a53230", - "index": 0, - "guid": "42038759-10f6-4d07-80bd-d22a3d15c2a7", - "isActive": false, - "balance": "$2,972.29", - "picture": "http://placehold.it/32x32", - "age": 40, - "eyeColor": "blue", - "name": "Ofelia Cantrell", - "gender": "female", - "company": "REMOTION", - "email": "ofeliacantrell@remotion.com", - "phone": "+1 (933) 409-2769", - "address": "703 Perry Terrace, Yonah, Ohio, 2288", - "about": "Et do amet ex do quis duis. Esse cillum dolor minim qui irure ad ut. Do adipisicing sint esse sint culpa est minim commodo reprehenderit pariatur veniam quis consectetur qui. Cupidatat veniam aute laboris deserunt sint aliqua non sit non. Non minim voluptate velit dolor quis consequat exercitation. Sint et ea magna ex incididunt ea laborum.\r\n", - "registered": "2015-06-06T02:44:14 +04:00", - "latitude": -15.53943, - "longitude": -161.829515, - "tags": [ - "duis", - "reprehenderit", - "tempor", - "exercitation", - "fugiat", - "ex", - "aliquip" - ], - "friends": [ - { - "id": 0, - "name": "Moran Donovan" - }, - { - "id": 1, - "name": "Cross Leonard" - }, - { - "id": 2, - "name": "Young Macdonald" - } - ], - "greeting": "Hello, Ofelia Cantrell! You have 2 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098a2d0e698c435ef3c4", - "index": 1, - "guid": "1602e45f-9ed8-4e8c-a464-cc921a8f5687", - "isActive": true, - "balance": "$1,819.74", - "picture": "http://placehold.it/32x32", - "age": 36, - "eyeColor": "green", - "name": "Payne Carter", - "gender": "male", - "company": "SPRINGBEE", - "email": "paynecarter@springbee.com", - "phone": "+1 (821) 446-3230", - "address": "649 Bush Street, Edgar, Missouri, 2760", - "about": "Laborum culpa dolor id quis incididunt mollit veniam. Incididunt consectetur tempor occaecat eiusmod sunt aute amet aliqua deserunt do Lorem aliquip in. Nostrud tempor irure eu ex sint magna cupidatat consequat quis pariatur elit proident. Reprehenderit consequat qui incididunt laboris esse esse incididunt quis culpa nisi. Aliqua aliqua anim aliquip irure occaecat mollit mollit nostrud ut sit qui. Amet enim ullamco qui mollit nisi irure labore ad. Velit enim aliqua laborum eu eu minim id enim deserunt.\r\n", - "registered": "2014-09-04T03:38:13 +04:00", - "latitude": 48.091037, - "longitude": -178.775433, - "tags": [ - "excepteur", - "qui", - "magna", - "exercitation", - "sit", - "labore", - "laboris" - ], - "friends": [ - { - "id": 0, - "name": "Willa Moon" - }, - { - "id": 1, - "name": "Jodie Briggs" - }, - { - "id": 2, - "name": "Katina Ramirez" - } - ], - "greeting": "Hello, Payne Carter! You have 10 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ad752f1c7ae3020a7", - "index": 2, - "guid": "051ecc3d-3e33-45ae-93c1-c1f48c892f87", - "isActive": false, - "balance": "$1,895.69", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Kristi Young", - "gender": "female", - "company": "DATACATOR", - "email": "kristiyoung@datacator.com", - "phone": "+1 (991) 418-3593", - "address": "822 Reeve Place, Swartzville, Iowa, 1295", - "about": "Amet do in laboris commodo ut aute ullamco voluptate mollit proident labore qui anim in. Ipsum occaecat incididunt sit culpa eu et ad dolore proident et tempor nostrud minim. Deserunt reprehenderit adipisicing laborum velit labore eiusmod amet consectetur aute do amet non labore exercitation.\r\n", - "registered": "2014-02-22T11:35:14 +05:00", - "latitude": -33.068243, - "longitude": -135.989542, - "tags": [ - "in", - "elit", - "consequat", - "incididunt", - "magna", - "id", - "aliqua" - ], - "friends": [ - { - "id": 0, - "name": "Mclean Merrill" - }, - { - "id": 1, - "name": "Donna Moss" - }, - { - "id": 2, - "name": "Eva Donaldson" - } - ], - "greeting": "Hello, Kristi Young! You have 4 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a3c3d2bd8f4e680b5", - "index": 3, - "guid": "434e2f6c-8896-4267-95c8-4443da518937", - "isActive": true, - "balance": "$1,226.19", - "picture": "http://placehold.it/32x32", - "age": 25, - "eyeColor": "green", - "name": "Cassie Wells", - "gender": "female", - "company": "DRAGBOT", - "email": "cassiewells@dragbot.com", - "phone": "+1 (962) 455-2900", - "address": "467 Conselyea Street, Fresno, Utah, 5198", - "about": "Nisi enim irure velit cillum et ut eu. Ullamco esse cupidatat est proident amet anim voluptate. Eiusmod aute occaecat aliquip laboris et. Elit velit minim nostrud consectetur cillum ipsum. Nostrud enim nisi proident excepteur ex aliquip exercitation. Dolore cillum laborum ut cupidatat officia exercitation aliquip eiusmod eiusmod cupidatat elit mollit esse. Aute excepteur cupidatat do aliqua magna commodo magna esse eiusmod sint et cupidatat labore elit.\r\n", - "registered": "2017-02-15T08:33:56 +05:00", - "latitude": 15.310112, - "longitude": -18.42037, - "tags": [ - "commodo", - "aliqua", - "aute", - "tempor", - "enim", - "excepteur", - "labore" - ], - "friends": [ - { - "id": 0, - "name": "Loretta Gates" - }, - { - "id": 1, - "name": "Moreno Mathis" - }, - { - "id": 2, - "name": "Lisa Sloan" - } - ], - "greeting": "Hello, Cassie Wells! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ac51d569909f3f924", - "index": 4, - "guid": "c55f4203-3136-427e-a9b1-cd4f447a7e66", - "isActive": true, - "balance": "$2,813.15", - "picture": "http://placehold.it/32x32", - "age": 23, - "eyeColor": "blue", - "name": "Leigh Levy", - "gender": "female", - "company": "IMAGINART", - "email": "leighlevy@imaginart.com", - "phone": "+1 (976) 465-3476", - "address": "390 Furman Street, Albrightsville, Wisconsin, 2324", - "about": "Excepteur commodo minim veniam aute et dolore ea voluptate magna eu laboris. Laboris cupidatat est mollit proident consectetur eiusmod officia aute aliqua culpa. In fugiat qui enim sunt.\r\n", - "registered": "2014-05-03T01:12:53 +04:00", - "latitude": 35.087356, - "longitude": -5.142767, - "tags": [ - "mollit", - "duis", - "veniam", - "laboris", - "magna", - "et", - "exercitation" - ], - "friends": [ - { - "id": 0, - "name": "Middleton Walker" - }, - { - "id": 1, - "name": "Fitzgerald Dickerson" - }, - { - "id": 2, - "name": "Teresa Cherry" - } - ], - "greeting": "Hello, Leigh Levy! You have 6 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a01c1b5dc6b527746", - "index": 5, - "guid": "21cb7015-229a-48d2-89bd-ed664c493001", - "isActive": false, - "balance": "$2,106.23", - "picture": "http://placehold.it/32x32", - "age": 31, - "eyeColor": "brown", - "name": "Santiago Valencia", - "gender": "male", - "company": "TERRAGO", - "email": "santiagovalencia@terrago.com", - "phone": "+1 (887) 540-3439", - "address": "241 Quentin Road, Strong, Nevada, 9629", - "about": "Qui elit do veniam tempor do nisi in tempor anim magna. Laborum ex sint do elit reprehenderit tempor. Mollit labore ut amet in anim. Proident cillum sint elit aute reprehenderit exercitation duis fugiat ad velit pariatur non excepteur. Minim consequat anim dolore proident.\r\n", - "registered": "2015-01-27T04:21:17 +05:00", - "latitude": 31.602384, - "longitude": 78.941588, - "tags": [ - "eu", - "voluptate", - "eu", - "ad", - "excepteur", - "sit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "Ellen Mccarty" - }, - { - "id": 1, - "name": "Deloris French" - }, - { - "id": 2, - "name": "Brandie Porter" - } - ], - "greeting": "Hello, Santiago Valencia! You have 4 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098ad8b6931921cd3539", - "index": 6, - "guid": "42e83426-f488-4077-9d8a-0df690e26d77", - "isActive": false, - "balance": "$3,769.50", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Ursula Lester", - "gender": "female", - "company": "LIQUICOM", - "email": "ursulalester@liquicom.com", - "phone": "+1 (916) 549-2548", - "address": "548 Coleman Street, Elbert, Vermont, 1941", - "about": "Lorem qui pariatur officia proident ullamco occaecat velit aute ex adipisicing velit commodo proident dolor. Sit consectetur culpa commodo aliquip commodo reprehenderit labore ea dolore ex enim enim. Laboris proident fugiat ea enim sunt eiusmod enim sint non enim proident aliqua deserunt. Eiusmod qui do eiusmod irure ad. Elit magna enim in excepteur occaecat esse excepteur commodo ut. Ea aute veniam qui ea adipisicing quis id consequat esse laboris ea consectetur amet minim.\r\n", - "registered": "2017-06-24T10:28:26 +04:00", - "latitude": -72.032682, - "longitude": -58.19158, - "tags": [ - "nulla", - "nostrud", - "anim", - "exercitation", - "ullamco", - "ipsum", - "cupidatat" - ], - "friends": [ - { - "id": 0, - "name": "Maddox Weeks" - }, - { - "id": 1, - "name": "Paul Peterson" - }, - { - "id": 2, - "name": "Powers Quinn" - } - ], - "greeting": "Hello, Ursula Lester! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file diff --git a/sample_bags/missing_record_type/data/more_data.xlsx b/sample_bags/missing_record_type/data/more_data.xlsx deleted file mode 100755 index 7f9d7ff9..00000000 Binary files a/sample_bags/missing_record_type/data/more_data.xlsx and /dev/null differ diff --git a/sample_bags/missing_record_type/data/sample_data.xlsx b/sample_bags/missing_record_type/data/sample_data.xlsx deleted file mode 100755 index f049f345..00000000 Binary files a/sample_bags/missing_record_type/data/sample_data.xlsx and /dev/null differ diff --git a/sample_bags/missing_record_type/manifest-md5.txt b/sample_bags/missing_record_type/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/sample_bags/missing_record_type/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/sample_bags/missing_record_type/tagmanifest-md5.txt b/sample_bags/missing_record_type/tagmanifest-md5.txt deleted file mode 100755 index dddf49a6..00000000 --- a/sample_bags/missing_record_type/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -ea0bb51cb1dfc3219d1be416ef545c7b bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/sample_bags/missing_source_organization.tar b/sample_bags/missing_source_organization.tar deleted file mode 100644 index e14af6cd..00000000 Binary files a/sample_bags/missing_source_organization.tar and /dev/null differ diff --git a/sample_bags/missing_title.tar.gz b/sample_bags/missing_title.tar.gz deleted file mode 100644 index c5753ce0..00000000 Binary files a/sample_bags/missing_title.tar.gz and /dev/null differ diff --git a/sample_bags/repeating_record_type.zip b/sample_bags/repeating_record_type.zip deleted file mode 100644 index 7f277e62..00000000 Binary files a/sample_bags/repeating_record_type.zip and /dev/null differ diff --git a/sample_bags/repeating_source_organization/bag-info.txt b/sample_bags/repeating_source_organization/bag-info.txt deleted file mode 100755 index a88c68a0..00000000 --- a/sample_bags/repeating_source_organization/bag-info.txt +++ /dev/null @@ -1,16 +0,0 @@ -Bag-Software-Agent: bagit.py -BagIt-Profile-Identifier: http://localhost:8000/api/bagit_profiles/2/ -Bagging-Date: 2017-11-04T14:47:20.787717 -Date-End: 2002-06-22 -Date-Start: 2000-05-14 -External-Identifier: records-2017-11-04T14:47:20.787717 -Internal-Sender-Description: Grant awarded to the Village Green Preservation Society for the purpose of "preserving the old ways from being abused, protecting the new ways for me and for you" -Language: eng -Payload-Oxum: 435255.8 -Record-Creators: Custard Pie Appreciation Consortium -Record-Creators: Desperate Dan Appreciation Society -Record-Type: grant records -Restrictions: Records open only to Mrs. Mopp and good old Mother Riley -Source-Organization: Ford Foundation -Source-Organization: Rockefeller Foundation -Title: Grant to the Village Green Preservation Society diff --git a/sample_bags/repeating_source_organization/bagit.txt b/sample_bags/repeating_source_organization/bagit.txt deleted file mode 100755 index c4aebb43..00000000 --- a/sample_bags/repeating_source_organization/bagit.txt +++ /dev/null @@ -1,2 +0,0 @@ -BagIt-Version: 0.97 -Tag-File-Character-Encoding: UTF-8 diff --git a/sample_bags/repeating_source_organization/data/Lorem ipsum dolor sit amet.docx b/sample_bags/repeating_source_organization/data/Lorem ipsum dolor sit amet.docx deleted file mode 100755 index e9b27c83..00000000 Binary files a/sample_bags/repeating_source_organization/data/Lorem ipsum dolor sit amet.docx and /dev/null differ diff --git a/sample_bags/repeating_source_organization/data/Lorem ipsum.odt b/sample_bags/repeating_source_organization/data/Lorem ipsum.odt deleted file mode 100755 index 4d63bef0..00000000 Binary files a/sample_bags/repeating_source_organization/data/Lorem ipsum.odt and /dev/null differ diff --git a/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.pdf b/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.pdf deleted file mode 100755 index a5ff1e24..00000000 Binary files a/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.pdf and /dev/null differ diff --git a/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.rtf b/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.rtf deleted file mode 100755 index 57faf807..00000000 --- a/sample_bags/repeating_source_organization/data/consectetur adipiscing elit.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg10000\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\fdbmajor\f31501\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f38\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\f39\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\f41\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\f42\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\f43\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\f44\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\f45\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\f46\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f48\fbidi \fnil\fcharset238\fprq2 Arial CE;}{\f49\fbidi \fnil\fcharset204\fprq2 Arial Cyr;} {\f51\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\f52\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\f53\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);}{\f54\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\f55\fbidi \fnil\fcharset186\fprq2 Arial Baltic;} {\f56\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);}{\f398\fbidi \fnil\fcharset238\fprq2 Calibri CE;}{\f399\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\f401\fbidi \fnil\fcharset161\fprq2 Calibri Greek;} {\f402\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\f405\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;}{\f406\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \fnil\fcharset238\fprq2 Arial CE;} {\flomajor\f31509\fbidi \fnil\fcharset204\fprq2 Arial Cyr;}{\flomajor\f31511\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\flomajor\f31512\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\flomajor\f31513\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);} {\flomajor\f31514\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\flomajor\f31515\fbidi \fnil\fcharset186\fprq2 Arial Baltic;}{\flomajor\f31516\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);} {\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbmajor\f31522\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbmajor\f31525\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fnil\fcharset238\fprq2 Calibri Light CE;} {\fhimajor\f31529\fbidi \fnil\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fnil\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fnil\fcharset162\fprq2 Calibri Light Tur;} {\fhimajor\f31535\fbidi \fnil\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fnil\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbimajor\f31545\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\flominor\f31555\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbminor\f31565\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fnil\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fnil\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbiminor\f31585\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0; \red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128; \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{ \s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \sunhideused \styrsid6382479 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid5859285\rsid6104307\rsid6382479\rsid7956859\rsid10444034}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1 \mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Hillel Arnold}{\operator Hillel Arnold}{\creatim\yr2017\mo8\dy14\hr16\min27}{\revtim\yr2017\mo8\dy14\hr16\min27}{\version2}{\edmins1}{\nofpages2}{\nofwords1318}{\nofchars7515} {\nofcharsws8816}{\vern61059}{\*\saveprevpict}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1 \jexpand\viewkind1\viewscale190\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel \wrppunct\asianbrkrule\rsidroot6382479\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal\outdisponlyhtml \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5859285\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6382479 \cbpat8 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ultrices tellus ac congue pretium. Quisque consectetur nunc erat. Maecenas nec mauris ut nisl posuere molestie ut ut eros. Duis a lacus nec est scelerisque consequat vel sed lectus. Donec non ali q uam ex. Ut non urna tristique, euismod nulla eu, venenatis tellus. Nullam in semper magna. Praesent auctor feugiat mauris, vitae elementum nisi sagittis ut. Quisque ultrices lectus ac egestas rutrum. Cras convallis vitae nisl eu lobortis. Sed ullamcorper felis eget laoreet maximus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi in ante ac purus ullamcorper pulvinar. Aenean rhoncus in odio vel sollicitudin. Donec a imperdiet elit.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Cras vitae eros non turpis maxi mus consequat laoreet ac enim. Suspendisse elit dui, convallis ac dui in, gravida vehicula nulla. Pellentesque lorem arcu, imperdiet sed blandit vehicula, consectetur ut sem. Nullam sit amet ipsum viverra, consequat elit ut, mollis diam. Aenean varius tel l us vitae urna rhoncus, a sodales nulla rhoncus. Fusce posuere orci sit amet sem convallis, vitae hendrerit lacus suscipit. Sed accumsan ligula eu sem cursus, ut maximus justo varius. In volutpat felis eget eleifend fringilla. Donec nec suscipit diam, vel c ongue dolor. Etiam non lectus placerat, venenatis ex sit amet, rutrum urna. Morbi mi tortor, dignissim ut mi vitae, auctor pellentesque nisl. Vestibulum eu nibh vitae neque viverra pulvinar non nec sapien. Donec tincidunt dui sit amet erat commodo, ut con sectetur odio porttitor. Nulla eu risus placerat neque congue venenatis. Etiam bibendum mi nibh, eget dignissim eros ullamcorper eget. Maecenas mollis lectus aliquet ante pharetra vulputate.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus sit amet risus justo. Nam varius metus at elementum tinc idunt. Sed sed mauris libero. Cras tincidunt sagittis turpis, eget faucibus metus bibendum ut. Quisque euismod libero elit. Nunc placerat gravida augue a egestas. Quisque eu mattis velit. Suspendisse id efficitur ante, non aliquam eros. Donec luctus, augu e egestas egestas ultrices, arcu quam pellentesque elit, et molestie justo leo ullamcorper tellus. In dignissim mollis nulla, nec lobortis dolor. Etiam ac arcu cursus, ullamcorper dui eu, hendrerit ex. Fusce congue ante interdum nunc porttitor pulvinar. Su s pendisse ligula sapien, tincidunt quis est sit amet, sodales tincidunt nibh. Etiam vitae aliquet lorem, sit amet accumsan velit. Sed fermentum arcu nec massa gravida, sit amet aliquet purus suscipit. Cras eget ligula hendrerit, scelerisque tellus id, ulla mcorper ipsum.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut tellus velit, faucibus semper mi in, elementum vestibulum turpis. Proin consequat tempus quam, ut sollicitudin diam elementum sed. Nam tellus dolor, porta ac congue sit amet, ornare sed nunc. Phasellus velit sapien, eleifend at imperdiet n on, tristique non nibh. Aliquam erat volutpat. Vivamus in est nunc. Etiam hendrerit, erat vitae elementum aliquet, felis ipsum maximus dui, quis gravida velit orci sit amet erat. Curabitur massa nibh, efficitur quis dolor id, malesuada elementum felis. In tristique mattis nibh, sed porta justo aliquam euismod. Mauris et fermentum erat. Integer pretium velit non neque condimentum, at varius augue blandit. Quisque a faucibus dolor. Aliquam in neque ut ipsum blandit auctor. Mauris dignissim augue non ultricie s rhoncus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 In maximus id felis vel porta. Morbi venenatis nisi nec lacinia vulputate. Nunc hendrerit risus non arcu pulvinar malesuada. Nunc viverra turpis justo, vitae efficitur ex pellentesque facilisis. Duis sit amet dolor nunc. Maecenas luctus justo a v ulputate maximus. Nulla felis arcu, euismod et magna eget, bibendum condimentum enim. Cras sodales ultrices orci vulputate rhoncus. Donec ac ipsum scelerisque, fermentum justo at, pulvinar leo. Sed tincidunt ligula mi, non ultricies nunc laoreet quis. Mau ris pharetra ut massa vel egestas.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Sed massa augue, aliquet et rutrum quis, accumsan iaculis magna. Donec hendrerit orci vitae nulla euismod, rhoncus pellentesque felis luctus. Etiam augue lorem, molestie in neque sed, mattis mattis eros. Nulla id sapien pu lvinar, tincidunt diam ut, aliquam orci. Pellentesque sit amet massa et tellus ultricies euismod non sed urna. Ut congue imperdiet purus, scelerisque eleifend neque hendrerit sed. Vivamus ultrices faucibus lacus, sit amet porttitor sem fermentum ac. Sed i aculis erat quis venenatis tincidunt. Pellentesque mattis bibendum urna vel faucibus. Nulla facilisi. Praesent quis nulla rutrum, dignissim dui eu, interdum arcu. Proin pharetra egestas dui et tempus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Vestibulum turpis nisl, posuere vitae ante ut, rhoncus h endrerit magna. Proin finibus massa ipsum. Nullam porttitor, neque at laoreet tincidunt, massa metus iaculis turpis, et sodales erat velit vitae orci. Morbi congue, dui lobortis egestas commodo, ipsum felis pretium leo, vitae aliquet felis massa faucibus e ros. Nullam a erat quis tellus euismod convallis. Donec mi turpis, faucibus at aliquet pharetra, fringilla eget arcu. Proin ac lectus ipsum. Nulla at lacinia sapien. Aenean tortor velit, feugiat quis ultrices ac, dapibus id enim. Mauris sollicitudin ut ma uris nec aliquam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nam ornare porttitor erat, nec semper nisl sagittis eget. Morbi pretium lorem magna. Donec ultrices bibendum ex, quis efficitur tellus. Proin id cursus purus, vel luctus justo. Nam in lacus sit amet urna facilisis facilisis vel a sem. Cura bitur ut commodo odio, in maximus lectus. Mauris pretium vehicula elit, et sodales diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus consectetur tristique lectus et rhoncus. Aenean vel vehicula nisl, id vestibulum quam. Duis hendrerit, metus sed blandit tempus, tortor purus posuere turpis, et mollis enim velit id nisl. Suspendisse ullamcorper efficitur dui vitae commodo. Aenean posuere justo sit amet tincidunt pulvinar. In molestie eu est et aliquam. Curabitur velit erat, malesuada eu sodales non, eleifend sagittis sapien. Ut faucibus eges t as elementum. Nulla quis pharetra erat. Maecenas pretium ornare quam fringilla sodales. Nunc ut volutpat ante, egestas vestibulum diam. Nam ultricies tellus convallis convallis molestie. Donec venenatis quis justo quis tristique. Proin commodo blandit urn a vitae gravida.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nulla id lacus ornare, egestas nulla ut, sagittis magna. Etiam dui dolor, gravida ac nulla sed, efficitur elementum massa. Etiam sem est, hendrerit ut viverra eu, commodo id ligula. Donec non metus blandit, iaculis ipsum eu, egestas est. Ae nean eget aliquet justo. Ut bibendum mi ac tellus luctus, at gravida libero placerat. Maecenas eu mi consectetur, mollis urna a, imperdiet tellus. Pellentesque nec dolor tortor. Cras tellus tellus, scelerisque vitae aliquam ut, tristique eu dui. Ut nec ma gna turpis. Donec efficitur luctus ultricies. Vivamus et sapien blandit, euismod metus ac, mollis ligula. Sed vestibulum a ante quis semper.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Praesent mi tellus, hendrerit eu aliquam quis, pharetra sit amet risus. Nulla nec consequat tortor. Etiam mollis ali quet porttitor. Donec metus purus, viverra in risus at, rhoncus luctus leo. Proin venenatis, lectus non vestibulum suscipit, nisi magna dignissim nulla, ut dignissim eros sem at nulla. Suspendisse tincidunt lobortis accumsan. Integer id dictum diam. Pelle ntesque commodo facilisis nisi et congue. Duis lobortis scelerisque ex, non pharetra odio blandit at. Maecenas facilisis commodo mollis. Donec convallis venenatis dolor id porta. Nunc nec nisi diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut ultricies, est in rutrum vestibulum, dui lorem condimen tum ipsum, id maximus lorem turpis et quam. Nunc ultricies augue at velit aliquam iaculis. Praesent eget felis egestas, placerat arcu vel, tempor risus. Nunc neque quam, vulputate quis tellus quis, venenatis gravida arcu. In suscipit at massa eu porta. Mo r bi vitae tempus urna, a vestibulum nunc. Etiam efficitur pharetra laoreet. Duis at risus eget dolor molestie vulputate non in diam. Nunc diam magna, accumsan ac euismod eu, gravida at eros. Cras in tellus eu velit consectetur vehicula ac non velit. Mauris volutpat neque et euismod congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur non mauris at nisl condimentum viverra quis lacinia nisl.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }\pard \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6104307 \cbpat8 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Morbi fermentum nibh in lorem bibendum dictum. Class aptent taciti sociosqu ad litora torque nt per conubia nostra, per inceptos himenaeos. Nam condimentum odio felis, et porta diam laoreet sit amet. Nulla consectetur urna sem, placerat pretium nunc lobortis aliquam. Etiam non eros ut elit placerat scelerisque sed at purus. Morbi vitae auctor ex, lacinia tempus magna. Suspendisse quis euismod nunc. Morbi eu posuere ante. Suspendisse sed ultrices urna, eu cursus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer nisi mauris, vehicula ut ultr ices vel, molestie et risus. Nullam ac libero id purus ultricies posuere. Nunc sed pulvinar sapien. Pellentesque sed commodo leo.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid7956859\charrsid6104307 \par }{\*\themedata 504b0304140006000800000021009be8704ffc0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 72ba28a5d8cea28f5d1f8bf40306796c8bd823214d42f2f71d3b2e941202856e04d2ccbdf7cca85c1fc641ed3126e7a9d2abbcd00ac9fac65157e9cfcd4b76af 5562a006064f58e92326bdaeafafcacd316052a2a654e99e393c18936c8f23a4dc0724a9b43e8ec0728d9d0960b7d0a1b92d8a3b633d3112673c79e8ba7cc216 7603abe7833c9f4844aed5e3a96f8aaa348430380b2ca066aa9ab3ba8843ba20dc53f38b2e5bc87251cee6a97721dd2c09efb29ae81a541f10f90d46e1302c43 e2cff31548468bf965e633d1be6d9dc5c6dbdd28ebc867e3c5ec4f00abff89fece34f3dfd65f000000ffff0300504b030414000600080000002100a5d6a7e7c0 000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060a bb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d9 4fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82f e353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f 7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d59 2c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8 d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100fb07ec41b50600008d1a0000160000007468656d652f7468656d652f746865 6d65312e786d6cec59cd8edb3610be17e83b08ba3bfe93fcb38837b0657bb7cd6e12c44eda1cb9322d314b898648efc60802f4090a14488b5e0af4d6432f01da 674ad1a60fd12125cba44d677fb00582a26b602151df0c3fce8cbea1a4fb0f5e25d4b9c019272cedb9f57b35d7c169c866248d7aeeb3e9b8d2711d2e503a4394 a5b8e7ae30771f1c7efed97d7420629c6007ec537e807a6e2cc4e2a05ae5210c237e8f2d700ad7e62c4b9080d32caace3274097e135a6dd46aad6a8248ea3a29 4ac0ede3f99c84d8994a97eee1daf988c2692ab81c08693691aeb161a1b0b3f3ba44f0150f68e65c20da73619e19bb9ce257c27528e2022ef4dc9afa73ab87f7 abe8a030a2628fad6637567f855d61303b6fa839b3e8ac9cd4f37cafd52ffd2b0015bbb8517bd41ab54a7f0a80c210569a73317db61b81576035507e68f13d6c 0f9b7503aff96fee70eefbf267e01528f7efede0c7e300a268e01528c7fb3b787fd01d0c4dff0a94e35b3bf876ad3ff4da867f058a2949cf77d035bfd50cd6ab 2d2173468fadf0aeef8ddb8dc2f90605d55056979c62ce52b1afd612f49265630048204582a48e582df01c8550c501a2e42c23ce09896228bc054a1987e15aa3 36ae35e1bffc79ea4865141d60a4594b5ec084ef0c493e0e0f33b2103df74bf0ea6a90174be788899884c5acca8961718cd248b7f8f0cb777ffff48df3d76f3f 7f78fb7d3ee9369eebf8214ea3af094a3f3601ac761386f73fbcfbe3f777ef7ffcf6cf5fdf5afcf73374a6c3a724c1dc79842f9da72c81c5595680cfb29b594c 6344748b7e1a719422398bc5ff08e2a7a31fad104516dc0022a1e39e67203336e0d1f2a5417812674b412c1e1fc689013c658c0e58668dc243399716e6e9328d ec93674b1df714a10bdbdc014a8d3c8f960bd057627319c4d8a0f984a254a008a75838f21a3bc7d8b2ba178418713d2561c6389b0be705710688584332256746 356d8c8e49027959d90842be8dd89c3e77068cda563dc4172612ee0e442de4a7981a613c424b81129bcb294aa81ef01324621bc9c92a0b75dc880bc874842973 4633ccb9cde67106ebd592fe1024c69ef653ba4a4c6426c8b9cde709624c470ed97910a36461c34e481aebd82ff8399428729e3061839f32f30e91e79007108f 7de97e4eb091eeabd5e019a8ab4e695320f2ca32b3e4f20833a37e272b3a4758490d88bfa1e90949af14f82d69f7ff3d693f25691833cb8aee4ad4edae8d8cdc 50cefb19b1de4fc75b22be0fb72ddd01cb66e4d357ee215aa64f30dc2cbbedeb7fe1fe5fb8ddffbc70efbb9fef5eae370a0de22db7aef9665d6ddd93bd3bf739 a1742256149f70b579e7d0976663189476eaa915974f728b180ee59d0c1318b82843cac6c998f88a887812a305ecf0ebae7412f1c275c49d05e3b0f157c356df 124f97c9299be50facf5ba7c38cdc58323b119aff9e5383c6c881cdd6a6f1ec24af78a6da41e96d704a4ed4d48689399249a1612edf5a00c927a3487a05948a8 95dd098bae854547ba5fa76a8705502bb3021b2707b65b3dd7f7c0048ce0990a513c9379ca53bdceae4ae65d667a5f308d0a805dc4ba023699ee4aae7b972757 9797da35326d90d0cacd24a122a37a188fd10c17d52947af43e3a6b9ee6e526ad093a150f341696d68b43b1f6371db5c83ddb636d054570a9a3a973db7d5f4a1 6442b4e8b97378f087c36401b5c3e58617d108de9e8522cb6ff8db28cb22e36288789c075c894eae060911387328497aae5c7e99069a2a0d51dcea0d10844f96 5c1764e55323074937938ce7731c0a3dedda888c747e0a0a9f6b85f5aa32bf3d585ab225a47b12cf2e9d33bacc9e222831bf5d97019c110eef7fea793467045e 689642b6a9bfadc654c8aefe4651d5503e8ee822464547d1c53c872b292fe9a8b33206da59b16608a81692a2119e45b2c1ea4135ba69d935720e7bbbeed54632 729a686e7aa6a12ab26bda55cc9861dd06b66279bb26afb15a8718344deff0b9746f4b6e77ad755bfb84b24b40c0cbf859baee351a82466d3399414d32de9561 a9d9c5a8d93bd60bbc82da759a84a6faadb5dbadb8953dc23a1d0cdeaaf383dd76d5c2d07cbdaf5491565f3ef48f13ecec2588c7105e032fa9e02a95f0e92143 b0219aa83d492e1b708bbc12c5ad0147ce32233df775cdef7b41c30f2ab58e3faa784daf56e9f8fd66a5effbcdfac8afd78683c61b682c224eea7efed5650c2f a2e8aaf8f6a2c677bebf24eb776df742965499fabe5255c4d5f7977a63fff7178780e8bc6e35c6dd6677d0aa749bfd71c51b0e3a956ed01a5486ada03d1c0f03 bfd31dbf719d0b05f6facdc06b8d3a95563d082a5eab26e977ba95b6d768f4bd76bf33f2fa6f8a6d0cac3c978f2216105ec5ebf01f000000ffff0300504b0304 140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c 73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a c16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b 017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d00140006 000800000021009be8704ffc0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d001400 0600080000002100a5d6a7e7c0000000360100000b000000000000000000000000002d0100005f72656c732f2e72656c73504b01022d00140006000800000021 006b799616830000008a0000001c00000000000000000000000000160200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d 0014000600080000002100fb07ec41b50600008d1a00001600000000000000000000000000d30200007468656d652f7468656d652f7468656d65312e786d6c50 4b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000bc0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000b70a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax382\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 8; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 9;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; \lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;}}{\*\datastore }} \ No newline at end of file diff --git a/sample_bags/repeating_source_organization/data/metadata.json b/sample_bags/repeating_source_organization/data/metadata.json deleted file mode 100755 index 4a33170c..00000000 --- a/sample_bags/repeating_source_organization/data/metadata.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "5992098ae5be0ee2b3a53230", - "index": 0, - "guid": "42038759-10f6-4d07-80bd-d22a3d15c2a7", - "isActive": false, - "balance": "$2,972.29", - "picture": "http://placehold.it/32x32", - "age": 40, - "eyeColor": "blue", - "name": "Ofelia Cantrell", - "gender": "female", - "company": "REMOTION", - "email": "ofeliacantrell@remotion.com", - "phone": "+1 (933) 409-2769", - "address": "703 Perry Terrace, Yonah, Ohio, 2288", - "about": "Et do amet ex do quis duis. Esse cillum dolor minim qui irure ad ut. Do adipisicing sint esse sint culpa est minim commodo reprehenderit pariatur veniam quis consectetur qui. Cupidatat veniam aute laboris deserunt sint aliqua non sit non. Non minim voluptate velit dolor quis consequat exercitation. Sint et ea magna ex incididunt ea laborum.\r\n", - "registered": "2015-06-06T02:44:14 +04:00", - "latitude": -15.53943, - "longitude": -161.829515, - "tags": [ - "duis", - "reprehenderit", - "tempor", - "exercitation", - "fugiat", - "ex", - "aliquip" - ], - "friends": [ - { - "id": 0, - "name": "Moran Donovan" - }, - { - "id": 1, - "name": "Cross Leonard" - }, - { - "id": 2, - "name": "Young Macdonald" - } - ], - "greeting": "Hello, Ofelia Cantrell! You have 2 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098a2d0e698c435ef3c4", - "index": 1, - "guid": "1602e45f-9ed8-4e8c-a464-cc921a8f5687", - "isActive": true, - "balance": "$1,819.74", - "picture": "http://placehold.it/32x32", - "age": 36, - "eyeColor": "green", - "name": "Payne Carter", - "gender": "male", - "company": "SPRINGBEE", - "email": "paynecarter@springbee.com", - "phone": "+1 (821) 446-3230", - "address": "649 Bush Street, Edgar, Missouri, 2760", - "about": "Laborum culpa dolor id quis incididunt mollit veniam. Incididunt consectetur tempor occaecat eiusmod sunt aute amet aliqua deserunt do Lorem aliquip in. Nostrud tempor irure eu ex sint magna cupidatat consequat quis pariatur elit proident. Reprehenderit consequat qui incididunt laboris esse esse incididunt quis culpa nisi. Aliqua aliqua anim aliquip irure occaecat mollit mollit nostrud ut sit qui. Amet enim ullamco qui mollit nisi irure labore ad. Velit enim aliqua laborum eu eu minim id enim deserunt.\r\n", - "registered": "2014-09-04T03:38:13 +04:00", - "latitude": 48.091037, - "longitude": -178.775433, - "tags": [ - "excepteur", - "qui", - "magna", - "exercitation", - "sit", - "labore", - "laboris" - ], - "friends": [ - { - "id": 0, - "name": "Willa Moon" - }, - { - "id": 1, - "name": "Jodie Briggs" - }, - { - "id": 2, - "name": "Katina Ramirez" - } - ], - "greeting": "Hello, Payne Carter! You have 10 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ad752f1c7ae3020a7", - "index": 2, - "guid": "051ecc3d-3e33-45ae-93c1-c1f48c892f87", - "isActive": false, - "balance": "$1,895.69", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Kristi Young", - "gender": "female", - "company": "DATACATOR", - "email": "kristiyoung@datacator.com", - "phone": "+1 (991) 418-3593", - "address": "822 Reeve Place, Swartzville, Iowa, 1295", - "about": "Amet do in laboris commodo ut aute ullamco voluptate mollit proident labore qui anim in. Ipsum occaecat incididunt sit culpa eu et ad dolore proident et tempor nostrud minim. Deserunt reprehenderit adipisicing laborum velit labore eiusmod amet consectetur aute do amet non labore exercitation.\r\n", - "registered": "2014-02-22T11:35:14 +05:00", - "latitude": -33.068243, - "longitude": -135.989542, - "tags": [ - "in", - "elit", - "consequat", - "incididunt", - "magna", - "id", - "aliqua" - ], - "friends": [ - { - "id": 0, - "name": "Mclean Merrill" - }, - { - "id": 1, - "name": "Donna Moss" - }, - { - "id": 2, - "name": "Eva Donaldson" - } - ], - "greeting": "Hello, Kristi Young! You have 4 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a3c3d2bd8f4e680b5", - "index": 3, - "guid": "434e2f6c-8896-4267-95c8-4443da518937", - "isActive": true, - "balance": "$1,226.19", - "picture": "http://placehold.it/32x32", - "age": 25, - "eyeColor": "green", - "name": "Cassie Wells", - "gender": "female", - "company": "DRAGBOT", - "email": "cassiewells@dragbot.com", - "phone": "+1 (962) 455-2900", - "address": "467 Conselyea Street, Fresno, Utah, 5198", - "about": "Nisi enim irure velit cillum et ut eu. Ullamco esse cupidatat est proident amet anim voluptate. Eiusmod aute occaecat aliquip laboris et. Elit velit minim nostrud consectetur cillum ipsum. Nostrud enim nisi proident excepteur ex aliquip exercitation. Dolore cillum laborum ut cupidatat officia exercitation aliquip eiusmod eiusmod cupidatat elit mollit esse. Aute excepteur cupidatat do aliqua magna commodo magna esse eiusmod sint et cupidatat labore elit.\r\n", - "registered": "2017-02-15T08:33:56 +05:00", - "latitude": 15.310112, - "longitude": -18.42037, - "tags": [ - "commodo", - "aliqua", - "aute", - "tempor", - "enim", - "excepteur", - "labore" - ], - "friends": [ - { - "id": 0, - "name": "Loretta Gates" - }, - { - "id": 1, - "name": "Moreno Mathis" - }, - { - "id": 2, - "name": "Lisa Sloan" - } - ], - "greeting": "Hello, Cassie Wells! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ac51d569909f3f924", - "index": 4, - "guid": "c55f4203-3136-427e-a9b1-cd4f447a7e66", - "isActive": true, - "balance": "$2,813.15", - "picture": "http://placehold.it/32x32", - "age": 23, - "eyeColor": "blue", - "name": "Leigh Levy", - "gender": "female", - "company": "IMAGINART", - "email": "leighlevy@imaginart.com", - "phone": "+1 (976) 465-3476", - "address": "390 Furman Street, Albrightsville, Wisconsin, 2324", - "about": "Excepteur commodo minim veniam aute et dolore ea voluptate magna eu laboris. Laboris cupidatat est mollit proident consectetur eiusmod officia aute aliqua culpa. In fugiat qui enim sunt.\r\n", - "registered": "2014-05-03T01:12:53 +04:00", - "latitude": 35.087356, - "longitude": -5.142767, - "tags": [ - "mollit", - "duis", - "veniam", - "laboris", - "magna", - "et", - "exercitation" - ], - "friends": [ - { - "id": 0, - "name": "Middleton Walker" - }, - { - "id": 1, - "name": "Fitzgerald Dickerson" - }, - { - "id": 2, - "name": "Teresa Cherry" - } - ], - "greeting": "Hello, Leigh Levy! You have 6 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a01c1b5dc6b527746", - "index": 5, - "guid": "21cb7015-229a-48d2-89bd-ed664c493001", - "isActive": false, - "balance": "$2,106.23", - "picture": "http://placehold.it/32x32", - "age": 31, - "eyeColor": "brown", - "name": "Santiago Valencia", - "gender": "male", - "company": "TERRAGO", - "email": "santiagovalencia@terrago.com", - "phone": "+1 (887) 540-3439", - "address": "241 Quentin Road, Strong, Nevada, 9629", - "about": "Qui elit do veniam tempor do nisi in tempor anim magna. Laborum ex sint do elit reprehenderit tempor. Mollit labore ut amet in anim. Proident cillum sint elit aute reprehenderit exercitation duis fugiat ad velit pariatur non excepteur. Minim consequat anim dolore proident.\r\n", - "registered": "2015-01-27T04:21:17 +05:00", - "latitude": 31.602384, - "longitude": 78.941588, - "tags": [ - "eu", - "voluptate", - "eu", - "ad", - "excepteur", - "sit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "Ellen Mccarty" - }, - { - "id": 1, - "name": "Deloris French" - }, - { - "id": 2, - "name": "Brandie Porter" - } - ], - "greeting": "Hello, Santiago Valencia! You have 4 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098ad8b6931921cd3539", - "index": 6, - "guid": "42e83426-f488-4077-9d8a-0df690e26d77", - "isActive": false, - "balance": "$3,769.50", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Ursula Lester", - "gender": "female", - "company": "LIQUICOM", - "email": "ursulalester@liquicom.com", - "phone": "+1 (916) 549-2548", - "address": "548 Coleman Street, Elbert, Vermont, 1941", - "about": "Lorem qui pariatur officia proident ullamco occaecat velit aute ex adipisicing velit commodo proident dolor. Sit consectetur culpa commodo aliquip commodo reprehenderit labore ea dolore ex enim enim. Laboris proident fugiat ea enim sunt eiusmod enim sint non enim proident aliqua deserunt. Eiusmod qui do eiusmod irure ad. Elit magna enim in excepteur occaecat esse excepteur commodo ut. Ea aute veniam qui ea adipisicing quis id consequat esse laboris ea consectetur amet minim.\r\n", - "registered": "2017-06-24T10:28:26 +04:00", - "latitude": -72.032682, - "longitude": -58.19158, - "tags": [ - "nulla", - "nostrud", - "anim", - "exercitation", - "ullamco", - "ipsum", - "cupidatat" - ], - "friends": [ - { - "id": 0, - "name": "Maddox Weeks" - }, - { - "id": 1, - "name": "Paul Peterson" - }, - { - "id": 2, - "name": "Powers Quinn" - } - ], - "greeting": "Hello, Ursula Lester! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file diff --git a/sample_bags/repeating_source_organization/data/more_data.xlsx b/sample_bags/repeating_source_organization/data/more_data.xlsx deleted file mode 100755 index 7f9d7ff9..00000000 Binary files a/sample_bags/repeating_source_organization/data/more_data.xlsx and /dev/null differ diff --git a/sample_bags/repeating_source_organization/data/sample_data.xlsx b/sample_bags/repeating_source_organization/data/sample_data.xlsx deleted file mode 100755 index f049f345..00000000 Binary files a/sample_bags/repeating_source_organization/data/sample_data.xlsx and /dev/null differ diff --git a/sample_bags/repeating_source_organization/manifest-md5.txt b/sample_bags/repeating_source_organization/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/sample_bags/repeating_source_organization/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/sample_bags/repeating_source_organization/tagmanifest-md5.txt b/sample_bags/repeating_source_organization/tagmanifest-md5.txt deleted file mode 100755 index 435a7ec9..00000000 --- a/sample_bags/repeating_source_organization/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -606bb996f1654fbabaae6d6983dd246b bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/sample_bags/repeating_title.tar b/sample_bags/repeating_title.tar deleted file mode 100644 index 7e2291c9..00000000 Binary files a/sample_bags/repeating_title.tar and /dev/null differ diff --git a/sample_bags/unauthorized_record_type.tar.gz b/sample_bags/unauthorized_record_type.tar.gz deleted file mode 100644 index 7a8c32a1..00000000 Binary files a/sample_bags/unauthorized_record_type.tar.gz and /dev/null differ diff --git a/sample_bags/unauthorized_source_organization.zip b/sample_bags/unauthorized_source_organization.zip deleted file mode 100644 index b5690666..00000000 Binary files a/sample_bags/unauthorized_source_organization.zip and /dev/null differ diff --git a/sample_bags/valid_bag/bag-info.txt b/sample_bags/valid_bag/bag-info.txt deleted file mode 100755 index 74c796f9..00000000 --- a/sample_bags/valid_bag/bag-info.txt +++ /dev/null @@ -1,15 +0,0 @@ -Bag-Software-Agent: bagit.py -BagIt-Profile-Identifier: http://localhost:8000/api/bagit_profiles/2/ -Bagging-Date: 2017-11-04T14:40:17.118401 -Date-End: 2002-06-22 -Date-Start: 2000-05-14 -External-Identifier: records-2017-11-04T14:40:17.118401 -Internal-Sender-Description: Grant awarded to the Village Green Preservation Society for the purpose of "preserving the old ways from being abused, protecting the new ways for me and for you" -Language: eng -Payload-Oxum: 435255.8 -Record-Creators: Custard Pie Appreciation Consortium -Record-Creators: Desperate Dan Appreciation Society -Record-Type: grant records -Restrictions: Records open only to Mrs. Mopp and good old Mother Riley -Source-Organization: Donor Organization -Title: Grant to the Village Green Preservation Society diff --git a/sample_bags/valid_bag/bagit.txt b/sample_bags/valid_bag/bagit.txt deleted file mode 100755 index c4aebb43..00000000 --- a/sample_bags/valid_bag/bagit.txt +++ /dev/null @@ -1,2 +0,0 @@ -BagIt-Version: 0.97 -Tag-File-Character-Encoding: UTF-8 diff --git a/sample_bags/valid_bag/data/Lorem ipsum dolor sit amet.docx b/sample_bags/valid_bag/data/Lorem ipsum dolor sit amet.docx deleted file mode 100755 index e9b27c83..00000000 Binary files a/sample_bags/valid_bag/data/Lorem ipsum dolor sit amet.docx and /dev/null differ diff --git a/sample_bags/valid_bag/data/Lorem ipsum.odt b/sample_bags/valid_bag/data/Lorem ipsum.odt deleted file mode 100755 index 4d63bef0..00000000 Binary files a/sample_bags/valid_bag/data/Lorem ipsum.odt and /dev/null differ diff --git a/sample_bags/valid_bag/data/consectetur adipiscing elit.pdf b/sample_bags/valid_bag/data/consectetur adipiscing elit.pdf deleted file mode 100755 index a5ff1e24..00000000 Binary files a/sample_bags/valid_bag/data/consectetur adipiscing elit.pdf and /dev/null differ diff --git a/sample_bags/valid_bag/data/consectetur adipiscing elit.rtf b/sample_bags/valid_bag/data/consectetur adipiscing elit.rtf deleted file mode 100755 index 57faf807..00000000 --- a/sample_bags/valid_bag/data/consectetur adipiscing elit.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg10000\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \fnil\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\fdbmajor\f31501\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fnil\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \fnil\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f38\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\f39\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\f41\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\f42\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\f43\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\f44\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\f45\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\f46\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f48\fbidi \fnil\fcharset238\fprq2 Arial CE;}{\f49\fbidi \fnil\fcharset204\fprq2 Arial Cyr;} {\f51\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\f52\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\f53\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);}{\f54\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\f55\fbidi \fnil\fcharset186\fprq2 Arial Baltic;} {\f56\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);}{\f398\fbidi \fnil\fcharset238\fprq2 Calibri CE;}{\f399\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\f401\fbidi \fnil\fcharset161\fprq2 Calibri Greek;} {\f402\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\f405\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;}{\f406\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \fnil\fcharset238\fprq2 Arial CE;} {\flomajor\f31509\fbidi \fnil\fcharset204\fprq2 Arial Cyr;}{\flomajor\f31511\fbidi \fnil\fcharset161\fprq2 Arial Greek;}{\flomajor\f31512\fbidi \fnil\fcharset162\fprq2 Arial Tur;}{\flomajor\f31513\fbidi \fnil\fcharset177\fprq2 Arial (Hebrew);} {\flomajor\f31514\fbidi \fnil\fcharset178\fprq2 Arial (Arabid);}{\flomajor\f31515\fbidi \fnil\fcharset186\fprq2 Arial Baltic;}{\flomajor\f31516\fbidi \fnil\fcharset163\fprq2 Arial (Vietnamese);} {\fdbmajor\f31518\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbmajor\f31522\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbmajor\f31525\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fnil\fcharset238\fprq2 Calibri Light CE;} {\fhimajor\f31529\fbidi \fnil\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fnil\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fnil\fcharset162\fprq2 Calibri Light Tur;} {\fhimajor\f31535\fbidi \fnil\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fnil\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbimajor\f31545\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\flominor\f31555\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);} {\fdbminor\f31565\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fnil\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fnil\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fnil\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fnil\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fnil\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fnil\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \fnil\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \fnil\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \fnil\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \fnil\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \fnil\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \fnil\fcharset178\fprq2 Times New Roman (Arabid);}{\fbiminor\f31585\fbidi \fnil\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \fnil\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0; \red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128; \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs24 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs24\alang1025 \ltrch\fcs0 \f31506\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{ \s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \sunhideused \styrsid6382479 Normal (Web);}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid5859285\rsid6104307\rsid6382479\rsid7956859\rsid10444034}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1 \mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Hillel Arnold}{\operator Hillel Arnold}{\creatim\yr2017\mo8\dy14\hr16\min27}{\revtim\yr2017\mo8\dy14\hr16\min27}{\version2}{\edmins1}{\nofpages2}{\nofwords1318}{\nofchars7515} {\nofcharsws8816}{\vern61059}{\*\saveprevpict}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1 \jexpand\viewkind1\viewscale190\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel \wrppunct\asianbrkrule\rsidroot6382479\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal\outdisponlyhtml \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid5859285\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6382479 \cbpat8 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ultrices tellus ac congue pretium. Quisque consectetur nunc erat. Maecenas nec mauris ut nisl posuere molestie ut ut eros. Duis a lacus nec est scelerisque consequat vel sed lectus. Donec non ali q uam ex. Ut non urna tristique, euismod nulla eu, venenatis tellus. Nullam in semper magna. Praesent auctor feugiat mauris, vitae elementum nisi sagittis ut. Quisque ultrices lectus ac egestas rutrum. Cras convallis vitae nisl eu lobortis. Sed ullamcorper felis eget laoreet maximus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi in ante ac purus ullamcorper pulvinar. Aenean rhoncus in odio vel sollicitudin. Donec a imperdiet elit.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Cras vitae eros non turpis maxi mus consequat laoreet ac enim. Suspendisse elit dui, convallis ac dui in, gravida vehicula nulla. Pellentesque lorem arcu, imperdiet sed blandit vehicula, consectetur ut sem. Nullam sit amet ipsum viverra, consequat elit ut, mollis diam. Aenean varius tel l us vitae urna rhoncus, a sodales nulla rhoncus. Fusce posuere orci sit amet sem convallis, vitae hendrerit lacus suscipit. Sed accumsan ligula eu sem cursus, ut maximus justo varius. In volutpat felis eget eleifend fringilla. Donec nec suscipit diam, vel c ongue dolor. Etiam non lectus placerat, venenatis ex sit amet, rutrum urna. Morbi mi tortor, dignissim ut mi vitae, auctor pellentesque nisl. Vestibulum eu nibh vitae neque viverra pulvinar non nec sapien. Donec tincidunt dui sit amet erat commodo, ut con sectetur odio porttitor. Nulla eu risus placerat neque congue venenatis. Etiam bibendum mi nibh, eget dignissim eros ullamcorper eget. Maecenas mollis lectus aliquet ante pharetra vulputate.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus sit amet risus justo. Nam varius metus at elementum tinc idunt. Sed sed mauris libero. Cras tincidunt sagittis turpis, eget faucibus metus bibendum ut. Quisque euismod libero elit. Nunc placerat gravida augue a egestas. Quisque eu mattis velit. Suspendisse id efficitur ante, non aliquam eros. Donec luctus, augu e egestas egestas ultrices, arcu quam pellentesque elit, et molestie justo leo ullamcorper tellus. In dignissim mollis nulla, nec lobortis dolor. Etiam ac arcu cursus, ullamcorper dui eu, hendrerit ex. Fusce congue ante interdum nunc porttitor pulvinar. Su s pendisse ligula sapien, tincidunt quis est sit amet, sodales tincidunt nibh. Etiam vitae aliquet lorem, sit amet accumsan velit. Sed fermentum arcu nec massa gravida, sit amet aliquet purus suscipit. Cras eget ligula hendrerit, scelerisque tellus id, ulla mcorper ipsum.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut tellus velit, faucibus semper mi in, elementum vestibulum turpis. Proin consequat tempus quam, ut sollicitudin diam elementum sed. Nam tellus dolor, porta ac congue sit amet, ornare sed nunc. Phasellus velit sapien, eleifend at imperdiet n on, tristique non nibh. Aliquam erat volutpat. Vivamus in est nunc. Etiam hendrerit, erat vitae elementum aliquet, felis ipsum maximus dui, quis gravida velit orci sit amet erat. Curabitur massa nibh, efficitur quis dolor id, malesuada elementum felis. In tristique mattis nibh, sed porta justo aliquam euismod. Mauris et fermentum erat. Integer pretium velit non neque condimentum, at varius augue blandit. Quisque a faucibus dolor. Aliquam in neque ut ipsum blandit auctor. Mauris dignissim augue non ultricie s rhoncus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 In maximus id felis vel porta. Morbi venenatis nisi nec lacinia vulputate. Nunc hendrerit risus non arcu pulvinar malesuada. Nunc viverra turpis justo, vitae efficitur ex pellentesque facilisis. Duis sit amet dolor nunc. Maecenas luctus justo a v ulputate maximus. Nulla felis arcu, euismod et magna eget, bibendum condimentum enim. Cras sodales ultrices orci vulputate rhoncus. Donec ac ipsum scelerisque, fermentum justo at, pulvinar leo. Sed tincidunt ligula mi, non ultricies nunc laoreet quis. Mau ris pharetra ut massa vel egestas.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Sed massa augue, aliquet et rutrum quis, accumsan iaculis magna. Donec hendrerit orci vitae nulla euismod, rhoncus pellentesque felis luctus. Etiam augue lorem, molestie in neque sed, mattis mattis eros. Nulla id sapien pu lvinar, tincidunt diam ut, aliquam orci. Pellentesque sit amet massa et tellus ultricies euismod non sed urna. Ut congue imperdiet purus, scelerisque eleifend neque hendrerit sed. Vivamus ultrices faucibus lacus, sit amet porttitor sem fermentum ac. Sed i aculis erat quis venenatis tincidunt. Pellentesque mattis bibendum urna vel faucibus. Nulla facilisi. Praesent quis nulla rutrum, dignissim dui eu, interdum arcu. Proin pharetra egestas dui et tempus.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Vestibulum turpis nisl, posuere vitae ante ut, rhoncus h endrerit magna. Proin finibus massa ipsum. Nullam porttitor, neque at laoreet tincidunt, massa metus iaculis turpis, et sodales erat velit vitae orci. Morbi congue, dui lobortis egestas commodo, ipsum felis pretium leo, vitae aliquet felis massa faucibus e ros. Nullam a erat quis tellus euismod convallis. Donec mi turpis, faucibus at aliquet pharetra, fringilla eget arcu. Proin ac lectus ipsum. Nulla at lacinia sapien. Aenean tortor velit, feugiat quis ultrices ac, dapibus id enim. Mauris sollicitudin ut ma uris nec aliquam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nam ornare porttitor erat, nec semper nisl sagittis eget. Morbi pretium lorem magna. Donec ultrices bibendum ex, quis efficitur tellus. Proin id cursus purus, vel luctus justo. Nam in lacus sit amet urna facilisis facilisis vel a sem. Cura bitur ut commodo odio, in maximus lectus. Mauris pretium vehicula elit, et sodales diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Phasellus consectetur tristique lectus et rhoncus. Aenean vel vehicula nisl, id vestibulum quam. Duis hendrerit, metus sed blandit tempus, tortor purus posuere turpis, et mollis enim velit id nisl. Suspendisse ullamcorper efficitur dui vitae commodo. Aenean posuere justo sit amet tincidunt pulvinar. In molestie eu est et aliquam. Curabitur velit erat, malesuada eu sodales non, eleifend sagittis sapien. Ut faucibus eges t as elementum. Nulla quis pharetra erat. Maecenas pretium ornare quam fringilla sodales. Nunc ut volutpat ante, egestas vestibulum diam. Nam ultricies tellus convallis convallis molestie. Donec venenatis quis justo quis tristique. Proin commodo blandit urn a vitae gravida.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Nulla id lacus ornare, egestas nulla ut, sagittis magna. Etiam dui dolor, gravida ac nulla sed, efficitur elementum massa. Etiam sem est, hendrerit ut viverra eu, commodo id ligula. Donec non metus blandit, iaculis ipsum eu, egestas est. Ae nean eget aliquet justo. Ut bibendum mi ac tellus luctus, at gravida libero placerat. Maecenas eu mi consectetur, mollis urna a, imperdiet tellus. Pellentesque nec dolor tortor. Cras tellus tellus, scelerisque vitae aliquam ut, tristique eu dui. Ut nec ma gna turpis. Donec efficitur luctus ultricies. Vivamus et sapien blandit, euismod metus ac, mollis ligula. Sed vestibulum a ante quis semper.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Praesent mi tellus, hendrerit eu aliquam quis, pharetra sit amet risus. Nulla nec consequat tortor. Etiam mollis ali quet porttitor. Donec metus purus, viverra in risus at, rhoncus luctus leo. Proin venenatis, lectus non vestibulum suscipit, nisi magna dignissim nulla, ut dignissim eros sem at nulla. Suspendisse tincidunt lobortis accumsan. Integer id dictum diam. Pelle ntesque commodo facilisis nisi et congue. Duis lobortis scelerisque ex, non pharetra odio blandit at. Maecenas facilisis commodo mollis. Donec convallis venenatis dolor id porta. Nunc nec nisi diam.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Ut ultricies, est in rutrum vestibulum, dui lorem condimen tum ipsum, id maximus lorem turpis et quam. Nunc ultricies augue at velit aliquam iaculis. Praesent eget felis egestas, placerat arcu vel, tempor risus. Nunc neque quam, vulputate quis tellus quis, venenatis gravida arcu. In suscipit at massa eu porta. Mo r bi vitae tempus urna, a vestibulum nunc. Etiam efficitur pharetra laoreet. Duis at risus eget dolor molestie vulputate non in diam. Nunc diam magna, accumsan ac euismod eu, gravida at eros. Cras in tellus eu velit consectetur vehicula ac non velit. Mauris volutpat neque et euismod congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur non mauris at nisl condimentum viverra quis lacinia nisl.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 \par }\pard \ltrpar\s15\qj \li0\ri0\sa225\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6104307 \cbpat8 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid6382479 Morbi fermentum nibh in lorem bibendum dictum. Class aptent taciti sociosqu ad litora torque nt per conubia nostra, per inceptos himenaeos. Nam condimentum odio felis, et porta diam laoreet sit amet. Nulla consectetur urna sem, placerat pretium nunc lobortis aliquam. Etiam non eros ut elit placerat scelerisque sed at purus. Morbi vitae auctor ex, lacinia tempus magna. Suspendisse quis euismod nunc. Morbi eu posuere ante. Suspendisse sed ultrices urna, eu cursus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer nisi mauris, vehicula ut ultr ices vel, molestie et risus. Nullam ac libero id purus ultricies posuere. Nunc sed pulvinar sapien. Pellentesque sed commodo leo.}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf1\insrsid7956859\charrsid6104307 \par }{\*\themedata 504b0304140006000800000021009be8704ffc0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 72ba28a5d8cea28f5d1f8bf40306796c8bd823214d42f2f71d3b2e941202856e04d2ccbdf7cca85c1fc641ed3126e7a9d2abbcd00ac9fac65157e9cfcd4b76af 5562a006064f58e92326bdaeafafcacd316052a2a654e99e393c18936c8f23a4dc0724a9b43e8ec0728d9d0960b7d0a1b92d8a3b633d3112673c79e8ba7cc216 7603abe7833c9f4844aed5e3a96f8aaa348430380b2ca066aa9ab3ba8843ba20dc53f38b2e5bc87251cee6a97721dd2c09efb29ae81a541f10f90d46e1302c43 e2cff31548468bf965e633d1be6d9dc5c6dbdd28ebc867e3c5ec4f00abff89fece34f3dfd65f000000ffff0300504b030414000600080000002100a5d6a7e7c0 000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060a bb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d9 4fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82f e353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f 7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d59 2c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8 d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100fb07ec41b50600008d1a0000160000007468656d652f7468656d652f746865 6d65312e786d6cec59cd8edb3610be17e83b08ba3bfe93fcb38837b0657bb7cd6e12c44eda1cb9322d314b898648efc60802f4090a14488b5e0af4d6432f01da 674ad1a60fd12125cba44d677fb00582a26b602151df0c3fce8cbea1a4fb0f5e25d4b9c019272cedb9f57b35d7c169c866248d7aeeb3e9b8d2711d2e503a4394 a5b8e7ae30771f1c7efed97d7420629c6007ec537e807a6e2cc4e2a05ae5210c237e8f2d700ad7e62c4b9080d32caace3274097e135a6dd46aad6a8248ea3a29 4ac0ede3f99c84d8994a97eee1daf988c2692ab81c08693691aeb161a1b0b3f3ba44f0150f68e65c20da73619e19bb9ce257c27528e2022ef4dc9afa73ab87f7 abe8a030a2628fad6637567f855d61303b6fa839b3e8ac9cd4f37cafd52ffd2b0015bbb8517bd41ab54a7f0a80c210569a73317db61b81576035507e68f13d6c 0f9b7503aff96fee70eefbf267e01528f7efede0c7e300a268e01528c7fb3b787fd01d0c4dff0a94e35b3bf876ad3ff4da867f058a2949cf77d035bfd50cd6ab 2d2173468fadf0aeef8ddb8dc2f90605d55056979c62ce52b1afd612f49265630048204582a48e582df01c8550c501a2e42c23ce09896228bc054a1987e15aa3 36ae35e1bffc79ea4865141d60a4594b5ec084ef0c493e0e0f33b2103df74bf0ea6a90174be788899884c5acca8961718cd248b7f8f0cb777ffff48df3d76f3f 7f78fb7d3ee9369eebf8214ea3af094a3f3601ac761386f73fbcfbe3f777ef7ffcf6cf5fdf5afcf73374a6c3a724c1dc79842f9da72c81c5595680cfb29b594c 6344748b7e1a719422398bc5ff08e2a7a31fad104516dc0022a1e39e67203336e0d1f2a5417812674b412c1e1fc689013c658c0e58668dc243399716e6e9328d ec93674b1df714a10bdbdc014a8d3c8f960bd057627319c4d8a0f984a254a008a75838f21a3bc7d8b2ba178418713d2561c6389b0be705710688584332256746 356d8c8e49027959d90842be8dd89c3e77068cda563dc4172612ee0e442de4a7981a613c424b81129bcb294aa81ef01324621bc9c92a0b75dc880bc874842973 4633ccb9cde67106ebd592fe1024c69ef653ba4a4c6426c8b9cde709624c470ed97910a36461c34e481aebd82ff8399428729e3061839f32f30e91e79007108f 7de97e4eb091eeabd5e019a8ab4e695320f2ca32b3e4f20833a37e272b3a4758490d88bfa1e90949af14f82d69f7ff3d693f25691833cb8aee4ad4edae8d8cdc 50cefb19b1de4fc75b22be0fb72ddd01cb66e4d357ee215aa64f30dc2cbbedeb7fe1fe5fb8ddffbc70efbb9fef5eae370a0de22db7aef9665d6ddd93bd3bf739 a1742256149f70b579e7d0976663189476eaa915974f728b180ee59d0c1318b82843cac6c998f88a887812a305ecf0ebae7412f1c275c49d05e3b0f157c356df 124f97c9299be50facf5ba7c38cdc58323b119aff9e5383c6c881cdd6a6f1ec24af78a6da41e96d704a4ed4d48689399249a1612edf5a00c927a3487a05948a8 95dd098bae854547ba5fa76a8705502bb3021b2707b65b3dd7f7c0048ce0990a513c9379ca53bdceae4ae65d667a5f308d0a805dc4ba023699ee4aae7b972757 9797da35326d90d0cacd24a122a37a188fd10c17d52947af43e3a6b9ee6e526ad093a150f341696d68b43b1f6371db5c83ddb636d054570a9a3a973db7d5f4a1 6442b4e8b97378f087c36401b5c3e58617d108de9e8522cb6ff8db28cb22e36288789c075c894eae060911387328497aae5c7e99069a2a0d51dcea0d10844f96 5c1764e55323074937938ce7731c0a3dedda888c747e0a0a9f6b85f5aa32bf3d585ab225a47b12cf2e9d33bacc9e222831bf5d97019c110eef7fea793467045e 689642b6a9bfadc654c8aefe4651d5503e8ee822464547d1c53c872b292fe9a8b33206da59b16608a81692a2119e45b2c1ea4135ba69d935720e7bbbeed54632 729a686e7aa6a12ab26bda55cc9861dd06b66279bb26afb15a8718344deff0b9746f4b6e77ad755bfb84b24b40c0cbf859baee351a82466d3399414d32de9561 a9d9c5a8d93bd60bbc82da759a84a6faadb5dbadb8953dc23a1d0cdeaaf383dd76d5c2d07cbdaf5491565f3ef48f13ecec2588c7105e032fa9e02a95f0e92143 b0219aa83d492e1b708bbc12c5ad0147ce32233df775cdef7b41c30f2ab58e3faa784daf56e9f8fd66a5effbcdfac8afd78683c61b682c224eea7efed5650c2f a2e8aaf8f6a2c677bebf24eb776df742965499fabe5255c4d5f7977a63fff7178780e8bc6e35c6dd6677d0aa749bfd71c51b0e3a956ed01a5486ada03d1c0f03 bfd31dbf719d0b05f6facdc06b8d3a95563d082a5eab26e977ba95b6d768f4bd76bf33f2fa6f8a6d0cac3c978f2216105ec5ebf01f000000ffff0300504b0304 140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c 73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a c16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b 017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d00140006 000800000021009be8704ffc0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d001400 0600080000002100a5d6a7e7c0000000360100000b000000000000000000000000002d0100005f72656c732f2e72656c73504b01022d00140006000800000021 006b799616830000008a0000001c00000000000000000000000000160200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d 0014000600080000002100fb07ec41b50600008d1a00001600000000000000000000000000d30200007468656d652f7468656d652f7468656d65312e786d6c50 4b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000bc0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000b70a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax382\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 8; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Level 9;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; \lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;}}{\*\datastore }} \ No newline at end of file diff --git a/sample_bags/valid_bag/data/metadata.json b/sample_bags/valid_bag/data/metadata.json deleted file mode 100755 index 4a33170c..00000000 --- a/sample_bags/valid_bag/data/metadata.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "5992098ae5be0ee2b3a53230", - "index": 0, - "guid": "42038759-10f6-4d07-80bd-d22a3d15c2a7", - "isActive": false, - "balance": "$2,972.29", - "picture": "http://placehold.it/32x32", - "age": 40, - "eyeColor": "blue", - "name": "Ofelia Cantrell", - "gender": "female", - "company": "REMOTION", - "email": "ofeliacantrell@remotion.com", - "phone": "+1 (933) 409-2769", - "address": "703 Perry Terrace, Yonah, Ohio, 2288", - "about": "Et do amet ex do quis duis. Esse cillum dolor minim qui irure ad ut. Do adipisicing sint esse sint culpa est minim commodo reprehenderit pariatur veniam quis consectetur qui. Cupidatat veniam aute laboris deserunt sint aliqua non sit non. Non minim voluptate velit dolor quis consequat exercitation. Sint et ea magna ex incididunt ea laborum.\r\n", - "registered": "2015-06-06T02:44:14 +04:00", - "latitude": -15.53943, - "longitude": -161.829515, - "tags": [ - "duis", - "reprehenderit", - "tempor", - "exercitation", - "fugiat", - "ex", - "aliquip" - ], - "friends": [ - { - "id": 0, - "name": "Moran Donovan" - }, - { - "id": 1, - "name": "Cross Leonard" - }, - { - "id": 2, - "name": "Young Macdonald" - } - ], - "greeting": "Hello, Ofelia Cantrell! You have 2 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098a2d0e698c435ef3c4", - "index": 1, - "guid": "1602e45f-9ed8-4e8c-a464-cc921a8f5687", - "isActive": true, - "balance": "$1,819.74", - "picture": "http://placehold.it/32x32", - "age": 36, - "eyeColor": "green", - "name": "Payne Carter", - "gender": "male", - "company": "SPRINGBEE", - "email": "paynecarter@springbee.com", - "phone": "+1 (821) 446-3230", - "address": "649 Bush Street, Edgar, Missouri, 2760", - "about": "Laborum culpa dolor id quis incididunt mollit veniam. Incididunt consectetur tempor occaecat eiusmod sunt aute amet aliqua deserunt do Lorem aliquip in. Nostrud tempor irure eu ex sint magna cupidatat consequat quis pariatur elit proident. Reprehenderit consequat qui incididunt laboris esse esse incididunt quis culpa nisi. Aliqua aliqua anim aliquip irure occaecat mollit mollit nostrud ut sit qui. Amet enim ullamco qui mollit nisi irure labore ad. Velit enim aliqua laborum eu eu minim id enim deserunt.\r\n", - "registered": "2014-09-04T03:38:13 +04:00", - "latitude": 48.091037, - "longitude": -178.775433, - "tags": [ - "excepteur", - "qui", - "magna", - "exercitation", - "sit", - "labore", - "laboris" - ], - "friends": [ - { - "id": 0, - "name": "Willa Moon" - }, - { - "id": 1, - "name": "Jodie Briggs" - }, - { - "id": 2, - "name": "Katina Ramirez" - } - ], - "greeting": "Hello, Payne Carter! You have 10 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ad752f1c7ae3020a7", - "index": 2, - "guid": "051ecc3d-3e33-45ae-93c1-c1f48c892f87", - "isActive": false, - "balance": "$1,895.69", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Kristi Young", - "gender": "female", - "company": "DATACATOR", - "email": "kristiyoung@datacator.com", - "phone": "+1 (991) 418-3593", - "address": "822 Reeve Place, Swartzville, Iowa, 1295", - "about": "Amet do in laboris commodo ut aute ullamco voluptate mollit proident labore qui anim in. Ipsum occaecat incididunt sit culpa eu et ad dolore proident et tempor nostrud minim. Deserunt reprehenderit adipisicing laborum velit labore eiusmod amet consectetur aute do amet non labore exercitation.\r\n", - "registered": "2014-02-22T11:35:14 +05:00", - "latitude": -33.068243, - "longitude": -135.989542, - "tags": [ - "in", - "elit", - "consequat", - "incididunt", - "magna", - "id", - "aliqua" - ], - "friends": [ - { - "id": 0, - "name": "Mclean Merrill" - }, - { - "id": 1, - "name": "Donna Moss" - }, - { - "id": 2, - "name": "Eva Donaldson" - } - ], - "greeting": "Hello, Kristi Young! You have 4 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a3c3d2bd8f4e680b5", - "index": 3, - "guid": "434e2f6c-8896-4267-95c8-4443da518937", - "isActive": true, - "balance": "$1,226.19", - "picture": "http://placehold.it/32x32", - "age": 25, - "eyeColor": "green", - "name": "Cassie Wells", - "gender": "female", - "company": "DRAGBOT", - "email": "cassiewells@dragbot.com", - "phone": "+1 (962) 455-2900", - "address": "467 Conselyea Street, Fresno, Utah, 5198", - "about": "Nisi enim irure velit cillum et ut eu. Ullamco esse cupidatat est proident amet anim voluptate. Eiusmod aute occaecat aliquip laboris et. Elit velit minim nostrud consectetur cillum ipsum. Nostrud enim nisi proident excepteur ex aliquip exercitation. Dolore cillum laborum ut cupidatat officia exercitation aliquip eiusmod eiusmod cupidatat elit mollit esse. Aute excepteur cupidatat do aliqua magna commodo magna esse eiusmod sint et cupidatat labore elit.\r\n", - "registered": "2017-02-15T08:33:56 +05:00", - "latitude": 15.310112, - "longitude": -18.42037, - "tags": [ - "commodo", - "aliqua", - "aute", - "tempor", - "enim", - "excepteur", - "labore" - ], - "friends": [ - { - "id": 0, - "name": "Loretta Gates" - }, - { - "id": 1, - "name": "Moreno Mathis" - }, - { - "id": 2, - "name": "Lisa Sloan" - } - ], - "greeting": "Hello, Cassie Wells! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098ac51d569909f3f924", - "index": 4, - "guid": "c55f4203-3136-427e-a9b1-cd4f447a7e66", - "isActive": true, - "balance": "$2,813.15", - "picture": "http://placehold.it/32x32", - "age": 23, - "eyeColor": "blue", - "name": "Leigh Levy", - "gender": "female", - "company": "IMAGINART", - "email": "leighlevy@imaginart.com", - "phone": "+1 (976) 465-3476", - "address": "390 Furman Street, Albrightsville, Wisconsin, 2324", - "about": "Excepteur commodo minim veniam aute et dolore ea voluptate magna eu laboris. Laboris cupidatat est mollit proident consectetur eiusmod officia aute aliqua culpa. In fugiat qui enim sunt.\r\n", - "registered": "2014-05-03T01:12:53 +04:00", - "latitude": 35.087356, - "longitude": -5.142767, - "tags": [ - "mollit", - "duis", - "veniam", - "laboris", - "magna", - "et", - "exercitation" - ], - "friends": [ - { - "id": 0, - "name": "Middleton Walker" - }, - { - "id": 1, - "name": "Fitzgerald Dickerson" - }, - { - "id": 2, - "name": "Teresa Cherry" - } - ], - "greeting": "Hello, Leigh Levy! You have 6 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "5992098a01c1b5dc6b527746", - "index": 5, - "guid": "21cb7015-229a-48d2-89bd-ed664c493001", - "isActive": false, - "balance": "$2,106.23", - "picture": "http://placehold.it/32x32", - "age": 31, - "eyeColor": "brown", - "name": "Santiago Valencia", - "gender": "male", - "company": "TERRAGO", - "email": "santiagovalencia@terrago.com", - "phone": "+1 (887) 540-3439", - "address": "241 Quentin Road, Strong, Nevada, 9629", - "about": "Qui elit do veniam tempor do nisi in tempor anim magna. Laborum ex sint do elit reprehenderit tempor. Mollit labore ut amet in anim. Proident cillum sint elit aute reprehenderit exercitation duis fugiat ad velit pariatur non excepteur. Minim consequat anim dolore proident.\r\n", - "registered": "2015-01-27T04:21:17 +05:00", - "latitude": 31.602384, - "longitude": 78.941588, - "tags": [ - "eu", - "voluptate", - "eu", - "ad", - "excepteur", - "sit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "Ellen Mccarty" - }, - { - "id": 1, - "name": "Deloris French" - }, - { - "id": 2, - "name": "Brandie Porter" - } - ], - "greeting": "Hello, Santiago Valencia! You have 4 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "5992098ad8b6931921cd3539", - "index": 6, - "guid": "42e83426-f488-4077-9d8a-0df690e26d77", - "isActive": false, - "balance": "$3,769.50", - "picture": "http://placehold.it/32x32", - "age": 28, - "eyeColor": "brown", - "name": "Ursula Lester", - "gender": "female", - "company": "LIQUICOM", - "email": "ursulalester@liquicom.com", - "phone": "+1 (916) 549-2548", - "address": "548 Coleman Street, Elbert, Vermont, 1941", - "about": "Lorem qui pariatur officia proident ullamco occaecat velit aute ex adipisicing velit commodo proident dolor. Sit consectetur culpa commodo aliquip commodo reprehenderit labore ea dolore ex enim enim. Laboris proident fugiat ea enim sunt eiusmod enim sint non enim proident aliqua deserunt. Eiusmod qui do eiusmod irure ad. Elit magna enim in excepteur occaecat esse excepteur commodo ut. Ea aute veniam qui ea adipisicing quis id consequat esse laboris ea consectetur amet minim.\r\n", - "registered": "2017-06-24T10:28:26 +04:00", - "latitude": -72.032682, - "longitude": -58.19158, - "tags": [ - "nulla", - "nostrud", - "anim", - "exercitation", - "ullamco", - "ipsum", - "cupidatat" - ], - "friends": [ - { - "id": 0, - "name": "Maddox Weeks" - }, - { - "id": 1, - "name": "Paul Peterson" - }, - { - "id": 2, - "name": "Powers Quinn" - } - ], - "greeting": "Hello, Ursula Lester! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file diff --git a/sample_bags/valid_bag/data/more_data.xlsx b/sample_bags/valid_bag/data/more_data.xlsx deleted file mode 100755 index 7f9d7ff9..00000000 Binary files a/sample_bags/valid_bag/data/more_data.xlsx and /dev/null differ diff --git a/sample_bags/valid_bag/data/sample_data.xlsx b/sample_bags/valid_bag/data/sample_data.xlsx deleted file mode 100755 index f049f345..00000000 Binary files a/sample_bags/valid_bag/data/sample_data.xlsx and /dev/null differ diff --git a/sample_bags/valid_bag/manifest-md5.txt b/sample_bags/valid_bag/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/sample_bags/valid_bag/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/sample_bags/valid_bag/tagmanifest-md5.txt b/sample_bags/valid_bag/tagmanifest-md5.txt deleted file mode 100755 index 6d274492..00000000 --- a/sample_bags/valid_bag/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -5a76dc93d44df3f169a94c2f3405e51e bag-info.txt -dd7a1449ac7e9ef79093ce133e1b593a .DS_Store -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/setup_objects.py b/setup_objects.py index 0736ce80..5c0adb4d 100644 --- a/setup_objects.py +++ b/setup_objects.py @@ -1,23 +1,30 @@ from django.contrib.auth.models import Group import psutil -from subprocess import * -from bag_transfer.models import Organization, User, BagItProfile, BagItProfileBagInfo, BagItProfileBagInfoValues, ManifestsRequired, AcceptSerialization, AcceptBagItVersion, TagManifestsRequired, TagFilesRequired -from bag_transfer.rights.models import RightsStatement, RightsStatementCopyright, RightsStatementOther, RightsStatementRightsGranted, RecordType +from bag_transfer.models import ( + ManifestsAllowed, + Organization, + User, + BagItProfile, + BagItProfileBagInfo, + BagItProfileBagInfoValues, + AcceptSerialization, + AcceptBagItVersion, +) +from bag_transfer.rights.models import ( + RightsStatement, + RightsStatementCopyright, + RightsStatementOther, + RightsStatementRightsGranted, + RecordType, +) from bag_transfer.lib.RAC_CMD import add_org, add_user, add2grp -from aurora import settings orgs = Organization.objects.all() org_ids = [] DEFAULT_ORGS = [ - { - "name": "Archival Repository", - "acquisition_type": "donation" - }, - { - "name": "Donor Organization", - "acquisition_type": "deposit" - } + {"name": "Archival Repository", "acquisition_type": "donation"}, + {"name": "Donor Organization", "acquisition_type": "deposit"}, ] DEFAULT_USERS = [ { @@ -27,7 +34,7 @@ "last_name": "Administrator", "superuser": True, "staff": True, - "org": "Archival Repository" + "org": "Archival Repository", }, { "username": "donor", @@ -36,7 +43,7 @@ "last_name": "Representative", "superuser": False, "staff": False, - "org": "Donor Organization" + "org": "Donor Organization", }, { "username": "manager", @@ -46,7 +53,7 @@ "superuser": False, "staff": True, "groups": ["managing_archivists"], - "org": "Archival Repository" + "org": "Archival Repository", }, { "username": "appraiser", @@ -56,7 +63,7 @@ "superuser": False, "staff": True, "groups": ["appraisal_archivists"], - "org": "Archival Repository" + "org": "Archival Repository", }, { "username": "accessioner", @@ -66,22 +73,29 @@ "superuser": False, "staff": True, "groups": ["accessioning_archivists"], - "org": "Archival Repository" - } + "org": "Archival Repository", + }, ] -print "Creating record types" -for type in ['administrative records', 'board materials', 'grant records', - 'communications and publications', 'annual reports']: +print("Creating record types") +for type in [ + "administrative records", + "board materials", + "grant records", + "communications and publications", + "annual reports", +]: RecordType.objects.get_or_create(name=type) -print "Creating organizations" +print("Creating organizations") if len(orgs) == 0: for org in DEFAULT_ORGS: - new_org = Organization.objects.create(name=org['name'], acquisition_type=org['acquisition_type']) + new_org = Organization.objects.create( + name=org["name"], acquisition_type=org["acquisition_type"] + ) archive_org = Organization.objects.get(name="Archival Repository") - print "Creating BagIt Profile for {}".format(new_org) + print("Creating BagIt Profile for {}".format(new_org)) profile = BagItProfile.objects.create( applies_to_organization=new_org, source_organization=archive_org, @@ -89,123 +103,124 @@ contact_email="archive@example.org", ) AcceptSerialization.objects.create( - name='application/zip', - bagit_profile=profile + name="application/zip", bagit_profile=profile ) AcceptSerialization.objects.create( - name='application/x-tar', - bagit_profile=profile + name="application/x-tar", bagit_profile=profile ) AcceptSerialization.objects.create( - name='application/x-gzip', - bagit_profile=profile + name="application/x-gzip", bagit_profile=profile ) - AcceptBagItVersion.objects.create( - name='0.97', - bagit_profile=profile - ) - for field in ['external_identifier', 'internal_sender_description', 'title', - 'date_start', 'date_end', 'bagging_date', 'payload_oxum', - 'source_organization', 'record_type']: + ManifestsAllowed.objects.create(name="sha256", bagit_profile=profile) + ManifestsAllowed.objects.create(name="sha512", bagit_profile=profile) + AcceptBagItVersion.objects.create(name="0.97", bagit_profile=profile) + for field in [ + "external_identifier", + "internal_sender_description", + "title", + "date_start", + "date_end", + "bagging_date", + "payload_oxum", + "source_organization", + "record_type", + ]: BagItProfileBagInfo.objects.create( - bagit_profile=profile, - field=field, - required=True, - repeatable=False + bagit_profile=profile, field=field, required=True, repeatable=False ) - for field in ['record_creators', 'language']: + for field in ["record_creators", "language"]: BagItProfileBagInfo.objects.create( - bagit_profile=profile, - field=field, - required=True, - repeatable=True + bagit_profile=profile, field=field, required=True, repeatable=True ) - for field in ['bag_count', 'bag_group_identifier']: + for field in ["bag_count", "bag_group_identifier"]: BagItProfileBagInfo.objects.create( - bagit_profile=profile, - field=field, - required=False, - repeatable=False + bagit_profile=profile, field=field, required=False, repeatable=False ) - source_organization = BagItProfileBagInfo.objects.get(field='source_organization', bagit_profile=profile) + source_organization = BagItProfileBagInfo.objects.get( + field="source_organization", bagit_profile=profile + ) BagItProfileBagInfoValues.objects.create( - bagit_profile_baginfo=source_organization, - name=new_org.name + bagit_profile_baginfo=source_organization, name=new_org.name + ) + record_type = BagItProfileBagInfo.objects.get( + field="record_type", bagit_profile=profile ) - record_type = BagItProfileBagInfo.objects.get(field='record_type', bagit_profile=profile) - for name in ['administrative records', 'board materials', 'grant records', - 'communications and publications', 'annual reports']: + for name in [ + "administrative records", + "board materials", + "grant records", + "communications and publications", + "annual reports", + ]: BagItProfileBagInfoValues.objects.create( - bagit_profile_baginfo=record_type, - name=name + bagit_profile_baginfo=record_type, name=name ) - print "Creating Rights Statements for {}".format(new_org) + print("Creating Rights Statements for {}".format(new_org)) copyright_statement = RightsStatement.objects.create( - organization=new_org, - rights_basis="Copyright", + organization=new_org, rights_basis="Copyright", ) for record_type in RecordType.objects.all(): copyright_statement.applies_to_type.add(record_type) donor_statement = RightsStatement.objects.create( - organization=new_org, - rights_basis="Other", + organization=new_org, rights_basis="Other", ) for record_type in RecordType.objects.all(): donor_statement.applies_to_type.add(record_type) RightsStatementCopyright.objects.create( rights_statement=copyright_statement, - copyright_status='copyrighted', + copyright_status="copyrighted", copyright_end_date_period=40, - copyright_note='Work for hire, under copyright until 40 years after creation.', + copyright_note="Work for hire, under copyright until 40 years after creation.", ) RightsStatementOther.objects.create( rights_statement=donor_statement, - other_rights_basis='Donor', + other_rights_basis="Donor", other_rights_end_date_period=10, - other_rights_note='Records embargoed for 10 years after date of creation.', + other_rights_note="Records embargoed for 10 years after date of creation.", ) RightsStatementRightsGranted.objects.create( rights_statement=copyright_statement, - act='publish', + act="publish", end_date_period=40, - rights_granted_note='Records under copyright may not be republished without permission from the copyright holder.', - restriction='disallow', + rights_granted_note="Records under copyright may not be republished without permission from the copyright holder.", + restriction="disallow", ) RightsStatementRightsGranted.objects.create( rights_statement=donor_statement, - act='disseminate', + act="disseminate", start_date_period=10, - rights_granted_note='Records are open for research after expiration of embargo period.', - restriction='allow', + rights_granted_note="Records are open for research after expiration of embargo period.", + restriction="allow", ) RightsStatementRightsGranted.objects.create( rights_statement=donor_statement, - act='disseminate', + act="disseminate", end_date_period=10, - rights_granted_note='Records are open for research after expiration of embargo period.', - restriction='disallow', + rights_granted_note="Records are open for research after expiration of embargo period.", + restriction="disallow", ) else: for org in Organization.objects.all(): add_org(org.machine_name) if len(User.objects.all()) == 0: - print "Creating users" + print("Creating users") for user in DEFAULT_USERS: new_user = User.objects.create_user( - user['username'], - first_name=user['first_name'], - last_name=user['last_name'], - email="{}@example.org".format(user['username']), - is_superuser=user['superuser'], - is_staff=user['staff'], - organization=Organization.objects.get(name=user['org'])) - new_user.set_password(user['password']) - if 'groups' in user: - for group in user['groups']: + user["username"], + first_name=user["first_name"], + last_name=user["last_name"], + email="{}@example.org".format(user["username"]), + is_superuser=user["superuser"], + is_staff=user["staff"], + organization=Organization.objects.get(name=user["org"]), + ) + new_user.set_password(user["password"]) + if "groups" in user: + for group in user["groups"]: g = Group.objects.get_or_create(name=group)[0] new_user.groups.add(g) new_user.save() @@ -215,11 +230,15 @@ add2grp(user.organization.machine_name, user.username) # Terminate any idle processes, which cause problems later. -open = [p for p in psutil.process_iter(attrs=['pid', 'name']) if p.info['name'] in ['add_org', 'add_user', 'add2grp']] +open = [ + p + for p in psutil.process_iter(attrs=["pid", "name"]) + if p.info["name"] in ["add_org", "add_user", "add2grp"] +] for p in open: - print "terminating", p + print("terminating", p) p.terminate() gone, alive = psutil.wait_procs(open, timeout=3) for p in alive: - print "killing", p + print("killing", p) p.kill() diff --git a/test_bags/changed_file.tar b/test_bags/changed_file.tar old mode 100755 new mode 100644 index 73ef6ecf..b79483cb Binary files a/test_bags/changed_file.tar and b/test_bags/changed_file.tar differ diff --git a/test_bags/changed_file.tar.gz b/test_bags/changed_file.tar.gz index 79f1574f..670dda25 100644 Binary files a/test_bags/changed_file.tar.gz and b/test_bags/changed_file.tar.gz differ diff --git a/test_bags/changed_file.zip b/test_bags/changed_file.zip index f0aebc5b..dd32a6c7 100644 Binary files a/test_bags/changed_file.zip and b/test_bags/changed_file.zip differ diff --git a/test_bags/changed_file/data/metadata.json b/test_bags/changed_file/data/metadata.json index 4a33170c..d07a5c7e 100755 --- a/test_bags/changed_file/data/metadata.json +++ b/test_bags/changed_file/data/metadata.json @@ -308,10 +308,10 @@ }, { "id": 2, - "name": "Powers Quinn" + "name": "Power's Quinn" } ], "greeting": "Hello, Ursula Lester! You have 6 unread messages.", "favoriteFruit": "apple" } -] \ No newline at end of file +] diff --git a/test_bags/changed_file/manifest-md5.txt b/test_bags/changed_file/manifest-md5.txt deleted file mode 100755 index 6bfe1677..00000000 --- a/test_bags/changed_file/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -b0394158651330831ee6312a03f824d0 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -fbfa377798b44ef995418ddc2b37609e data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -5eb577ecc185cd744220f4b19757c326 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/changed_file/manifest-sha256.txt b/test_bags/changed_file/manifest-sha256.txt new file mode 100644 index 00000000..ece571f8 --- /dev/null +++ b/test_bags/changed_file/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +83565c91031eba2331b34897476fa3ea91d2364121c625d1ef8db8b7f52850c5 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +ded1b709ec07d4ce9eefe0b9e5c6a5d8f5e1d5ead4c0dc0022b079b75d14d100 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +e2888cef95448aec8f39d8cdf114956c25bbadb74e31bb56f61911491ba3fda2 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/changed_file/manifest-sha512.txt b/test_bags/changed_file/manifest-sha512.txt new file mode 100644 index 00000000..510d690b --- /dev/null +++ b/test_bags/changed_file/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +8a9b5c913dd4af76d18f847adbde0fcb6bf43662c3fa0fe3020bcfd4ca86d25a2dfd85dd712e34ebdaf1687d6f9286cedf43ba7dc46da126df725a0584338aa5 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +34800ebb39c2e588bb5900ba4e0c989e068532c898f774ac2a15474e946acb63b3eeff9133e6ca3f03177ee2db8e43c9a4712bea1d03b49587adee502fecddbc data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +7736fe0ecc696441b68bde7527119e3e27a570a6003f6f988d2704b8bb7fdd620b8a79963f32b69a50a1393336c869a57faa7a0b7c13228d26f5e0892227e969 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/changed_file/tagmanifest-md5.txt b/test_bags/changed_file/tagmanifest-md5.txt deleted file mode 100755 index c76c7419..00000000 --- a/test_bags/changed_file/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -cff7bffd959f8cbd1ac8837e907e72c0 bag-info.txt -dd7a1449ac7e9ef79093ce133e1b593a .DS_Store -3899d4658985cc417626ba9cada3860c manifest-md5.txt diff --git a/test_bags/changed_file/tagmanifest-sha256.txt b/test_bags/changed_file/tagmanifest-sha256.txt new file mode 100644 index 00000000..662e5211 --- /dev/null +++ b/test_bags/changed_file/tagmanifest-sha256.txt @@ -0,0 +1,5 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +dd3c56dba8fb0cf32030daef791e2086752985c236eb4ca4d7587d540c4ad7c8 bag-info.txt +e85b766c4dc68758411961ecf500baa06c5b67863938fbbcd070912148314b2c .DS_Store +7240d4cfa5a706f7d3940e46e167b00f740677a0136308e7a403e3d9b2df779f manifest-sha512.txt +e094c966348980ff812c623ff369ad2f715055f8568fe0b97650ce2f2991bfa7 manifest-sha256.txt diff --git a/test_bags/changed_file/tagmanifest-sha512.txt b/test_bags/changed_file/tagmanifest-sha512.txt new file mode 100644 index 00000000..42dbbccb --- /dev/null +++ b/test_bags/changed_file/tagmanifest-sha512.txt @@ -0,0 +1,5 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +e9ab17808b92ca3c32f0cb6e152b5e2b10acf48ec094807f5df7806a2c96f1a50e8d3bfbfca913db3156c041d004c79a79fbf8b4a0e3c3368f33e11950742d06 bag-info.txt +f1cec1598469dcca2122e9ad7928cc7bb3c5c424412024ff813bb831c001e3d28aaa146ef152777425286fb44a4d69ea96e945ea88874bd3e762fe7ebc1a2a15 .DS_Store +9f470afb50666543e0f21efa87430b9bb2fbefe841aae47b649d8fdd5a009b45ac23257badd00637de8ca37b95bbb260847dd8646540eac3be147f5311ebeb1c manifest-sha512.txt +5b843ecb66ac384d487bfc946f54a3e0907c36717e5d8b4d4ea8e183ce25ddd69d453a546b1769f020a7520d4cfbd29125fa5f7ee4205bb8be1806ce9a62aaa1 manifest-sha256.txt diff --git a/test_bags/empty_payload_directory.tar b/test_bags/empty_payload_directory.tar old mode 100755 new mode 100644 index 1a29bc40..1a6e9452 Binary files a/test_bags/empty_payload_directory.tar and b/test_bags/empty_payload_directory.tar differ diff --git a/test_bags/empty_payload_directory.tar.gz b/test_bags/empty_payload_directory.tar.gz index 2496078e..61d66d96 100644 Binary files a/test_bags/empty_payload_directory.tar.gz and b/test_bags/empty_payload_directory.tar.gz differ diff --git a/test_bags/empty_payload_directory.zip b/test_bags/empty_payload_directory.zip index 23d04907..a7e35c22 100644 Binary files a/test_bags/empty_payload_directory.zip and b/test_bags/empty_payload_directory.zip differ diff --git a/test_bags/empty_payload_directory/manifest-md5.txt b/test_bags/empty_payload_directory/manifest-md5.txt deleted file mode 100755 index 95366966..00000000 --- a/test_bags/empty_payload_directory/manifest-md5.txt +++ /dev/null @@ -1 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store diff --git a/test_bags/empty_payload_directory/manifest-sha256.txt b/test_bags/empty_payload_directory/manifest-sha256.txt new file mode 100644 index 00000000..c719da56 --- /dev/null +++ b/test_bags/empty_payload_directory/manifest-sha256.txt @@ -0,0 +1 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store diff --git a/test_bags/empty_payload_directory/manifest-sha512.txt b/test_bags/empty_payload_directory/manifest-sha512.txt new file mode 100644 index 00000000..ad5f2cc5 --- /dev/null +++ b/test_bags/empty_payload_directory/manifest-sha512.txt @@ -0,0 +1 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store diff --git a/test_bags/empty_payload_directory/tagmanifest-md5.txt b/test_bags/empty_payload_directory/tagmanifest-md5.txt deleted file mode 100755 index c6c52387..00000000 --- a/test_bags/empty_payload_directory/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -fdbe78e9d420671bcd27be59fb03a054 bag-info.txt -dd7a1449ac7e9ef79093ce133e1b593a .DS_Store -0211a08d0e3b68d77d04fb39a7c22c67 manifest-md5.txt diff --git a/test_bags/empty_payload_directory/tagmanifest-sha256.txt b/test_bags/empty_payload_directory/tagmanifest-sha256.txt new file mode 100644 index 00000000..d66d29a7 --- /dev/null +++ b/test_bags/empty_payload_directory/tagmanifest-sha256.txt @@ -0,0 +1,5 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +47a71a752233b3dd56953ad71646716c61162ce1eaf5391904f48e7add9ad70d bag-info.txt +e85b766c4dc68758411961ecf500baa06c5b67863938fbbcd070912148314b2c .DS_Store +3532e694a6e6de808be4038d02e8b5a8798db814b1bb8eae288e8a54ca8c4c5b manifest-sha512.txt +0006b4606e33479f0cdcfda7406ff48849f557a6ba506ba5cd62c528fdf1539d manifest-sha256.txt diff --git a/test_bags/empty_payload_directory/tagmanifest-sha512.txt b/test_bags/empty_payload_directory/tagmanifest-sha512.txt new file mode 100644 index 00000000..29c9793f --- /dev/null +++ b/test_bags/empty_payload_directory/tagmanifest-sha512.txt @@ -0,0 +1,5 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +b981abbd0d5b6c78deb590d4e5d83ab319ee4170544bba397f9eb88e5e33a23ad53e31bd778ba6e49cbc32e2eb892ae947e0342322158d639a5d895b17ac484b bag-info.txt +f1cec1598469dcca2122e9ad7928cc7bb3c5c424412024ff813bb831c001e3d28aaa146ef152777425286fb44a4d69ea96e945ea88874bd3e762fe7ebc1a2a15 .DS_Store +92d6d2faaa559be8e90fc1a83e369a7c7774ed555f6b7829cd5c837a35a580ed541b19504d2cc12fce5bf94e2e6e443dcc804d2cb57c6ae73000dcbef3a18822 manifest-sha512.txt +1b403eb1f70f543d7714186813d58af19bece219c40fc908a17d23933918de9b5b1e6fb66ed619a9579ef4ca61d108a319bb8418585a9aad478f4ade1b03e0ab manifest-sha256.txt diff --git a/test_bags/invalid_datatype_date.tar b/test_bags/invalid_datatype_date.tar old mode 100755 new mode 100644 index 28040206..8446e94d Binary files a/test_bags/invalid_datatype_date.tar and b/test_bags/invalid_datatype_date.tar differ diff --git a/test_bags/invalid_datatype_date.tar.gz b/test_bags/invalid_datatype_date.tar.gz index 05b00978..cbb7890d 100644 Binary files a/test_bags/invalid_datatype_date.tar.gz and b/test_bags/invalid_datatype_date.tar.gz differ diff --git a/test_bags/invalid_datatype_date.zip b/test_bags/invalid_datatype_date.zip index dbfcc09a..3eea05b4 100644 Binary files a/test_bags/invalid_datatype_date.zip and b/test_bags/invalid_datatype_date.zip differ diff --git a/test_bags/invalid_datatype_date/manifest-md5.txt b/test_bags/invalid_datatype_date/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/invalid_datatype_date/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_date/manifest-sha256.txt b/test_bags/invalid_datatype_date/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/invalid_datatype_date/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_date/manifest-sha512.txt b/test_bags/invalid_datatype_date/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/invalid_datatype_date/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_date/tagmanifest-md5.txt b/test_bags/invalid_datatype_date/tagmanifest-md5.txt deleted file mode 100755 index bc4ac3fb..00000000 --- a/test_bags/invalid_datatype_date/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -ca7aef69f199cd6d39251f7694459172 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/invalid_datatype_date/tagmanifest-sha256.txt b/test_bags/invalid_datatype_date/tagmanifest-sha256.txt new file mode 100644 index 00000000..b0705cea --- /dev/null +++ b/test_bags/invalid_datatype_date/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +eb100a939794360d60bbdbaac6b47d0c94579edd51aa55ebf81f82bfbcf6abf2 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/invalid_datatype_date/tagmanifest-sha512.txt b/test_bags/invalid_datatype_date/tagmanifest-sha512.txt new file mode 100644 index 00000000..0150ec32 --- /dev/null +++ b/test_bags/invalid_datatype_date/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +3dc79fec54d14ccd1b680b8d7fbd1a6ae6cce626143b73912a9e207cedae7366a674088f6bb85c644629257bb6d1fed1c17e02a4a243afb8d84c3940634d3904 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/invalid_datatype_language.tar b/test_bags/invalid_datatype_language.tar old mode 100755 new mode 100644 index 127a4f33..e0a7dea6 Binary files a/test_bags/invalid_datatype_language.tar and b/test_bags/invalid_datatype_language.tar differ diff --git a/test_bags/invalid_datatype_language.tar.gz b/test_bags/invalid_datatype_language.tar.gz index 44aac158..c58181a2 100644 Binary files a/test_bags/invalid_datatype_language.tar.gz and b/test_bags/invalid_datatype_language.tar.gz differ diff --git a/test_bags/invalid_datatype_language.zip b/test_bags/invalid_datatype_language.zip index afc62eac..7aa462fc 100644 Binary files a/test_bags/invalid_datatype_language.zip and b/test_bags/invalid_datatype_language.zip differ diff --git a/test_bags/invalid_datatype_language/manifest-md5.txt b/test_bags/invalid_datatype_language/manifest-md5.txt deleted file mode 100755 index 9126298a..00000000 --- a/test_bags/invalid_datatype_language/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -dd7a1449ac7e9ef79093ce133e1b593a data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_language/manifest-sha256.txt b/test_bags/invalid_datatype_language/manifest-sha256.txt new file mode 100644 index 00000000..e963bd7d --- /dev/null +++ b/test_bags/invalid_datatype_language/manifest-sha256.txt @@ -0,0 +1,8 @@ +e85b766c4dc68758411961ecf500baa06c5b67863938fbbcd070912148314b2c data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_language/manifest-sha512.txt b/test_bags/invalid_datatype_language/manifest-sha512.txt new file mode 100644 index 00000000..ae168ecd --- /dev/null +++ b/test_bags/invalid_datatype_language/manifest-sha512.txt @@ -0,0 +1,8 @@ +f1cec1598469dcca2122e9ad7928cc7bb3c5c424412024ff813bb831c001e3d28aaa146ef152777425286fb44a4d69ea96e945ea88874bd3e762fe7ebc1a2a15 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/invalid_datatype_language/tagmanifest-md5.txt b/test_bags/invalid_datatype_language/tagmanifest-md5.txt deleted file mode 100755 index 5b682111..00000000 --- a/test_bags/invalid_datatype_language/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -2638e7340bc7c52e7baae1b740ec8cab bag-info.txt -194577a7e20bdcc7afbb718f502c134c .DS_Store -690286388d6a350c1c08225601f830cb manifest-md5.txt diff --git a/test_bags/invalid_datatype_language/tagmanifest-sha256.txt b/test_bags/invalid_datatype_language/tagmanifest-sha256.txt new file mode 100644 index 00000000..7c50b091 --- /dev/null +++ b/test_bags/invalid_datatype_language/tagmanifest-sha256.txt @@ -0,0 +1,5 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +7b7ab4058c2a163ad621cdd6c670430763b0ab0ceba2c554c159fc3d7a7cf818 bag-info.txt +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 .DS_Store +e514b25511f07391249f753367e1aefe5f54278f2cc4d920d808134482d7fd6f manifest-sha512.txt +26af0fa000392941e63811ef08a8a3adf300fd129ab9e69932032521b8b9a6ed manifest-sha256.txt diff --git a/test_bags/invalid_datatype_language/tagmanifest-sha512.txt b/test_bags/invalid_datatype_language/tagmanifest-sha512.txt new file mode 100644 index 00000000..b71f3e77 --- /dev/null +++ b/test_bags/invalid_datatype_language/tagmanifest-sha512.txt @@ -0,0 +1,5 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +20725f19d5dd2e20727a29a6e619cd58fea70bcffacbeffa3e61286c94d04336f5e606c5057546354e20e3d5df1f769a03b07b2a2a2a1a588eeeeadf777b97b4 bag-info.txt +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 .DS_Store +9ab5227119c8b4fb698e8cc6165bb31a66066bde5bd2f0b859fe8472095426fd89cc35552f7493211a000629a68f04fbe5eef16a512d61e27f14883742334c42 manifest-sha512.txt +e8fb6eb44eda3b740dcd062418f1947ed03b970e6c51d851ed401d2e9926bfa70351f8a366e24e3d78e6807e1757cf80728b33d2c1a47bd62002d24fe9403341 manifest-sha256.txt diff --git a/test_bags/invalid_metadata_file.tar b/test_bags/invalid_metadata_file.tar old mode 100755 new mode 100644 index 882bf290..a0aa84e0 Binary files a/test_bags/invalid_metadata_file.tar and b/test_bags/invalid_metadata_file.tar differ diff --git a/test_bags/invalid_metadata_file.tar.gz b/test_bags/invalid_metadata_file.tar.gz index 4318aafd..a9a71ca2 100644 Binary files a/test_bags/invalid_metadata_file.tar.gz and b/test_bags/invalid_metadata_file.tar.gz differ diff --git a/test_bags/invalid_metadata_file.zip b/test_bags/invalid_metadata_file.zip index 2f55c926..6ac8ad65 100644 Binary files a/test_bags/invalid_metadata_file.zip and b/test_bags/invalid_metadata_file.zip differ diff --git a/test_bags/invalid_metadata_file/manifest-md5.txt b/test_bags/invalid_metadata_file/manifest-md5.txt deleted file mode 100755 index e52b034a..00000000 --- a/test_bags/invalid_metadata_file/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -1ffbe2eb2c0741256c613184bc602116 data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/invalid_metadata_file/manifest-sha256.txt b/test_bags/invalid_metadata_file/manifest-sha256.txt new file mode 100644 index 00000000..7cc19c52 --- /dev/null +++ b/test_bags/invalid_metadata_file/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +f259443f396ad6d66d1130c314bf50e10e4b961828e1510def75e80e9de41b5b data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/invalid_metadata_file/manifest-sha512.txt b/test_bags/invalid_metadata_file/manifest-sha512.txt new file mode 100644 index 00000000..dca189a7 --- /dev/null +++ b/test_bags/invalid_metadata_file/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +95208335da9ae5782d6897832bd2839ad38805d1b5921d694db1b0da6a3584f078325f061a93d2ccee356426b2f2fddb8b7c8c619e2ec59225564fc4ac267610 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/invalid_metadata_file/tagmanifest-md5.txt b/test_bags/invalid_metadata_file/tagmanifest-md5.txt deleted file mode 100755 index eda39938..00000000 --- a/test_bags/invalid_metadata_file/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -4195c80f6aa6f00175a4dd53070631a4 bag-info.txt -72cfdf19dd41af875bec450d202e4077 manifest-md5.txt diff --git a/test_bags/invalid_metadata_file/tagmanifest-sha256.txt b/test_bags/invalid_metadata_file/tagmanifest-sha256.txt new file mode 100644 index 00000000..5d48a1e4 --- /dev/null +++ b/test_bags/invalid_metadata_file/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +e1affbc08378927031d9a165e1c942faa0ff4255152ef4e688c6252d16486861 bag-info.txt +dba6faef3a2439e364d03acdaaadcf95a0c9ba9a051dc64b810fe9786a85e606 manifest-sha512.txt +eaf9120bc37fac7b7529e3a59bde02674f1ff2a797d1a2dd788d56e548191d83 manifest-sha256.txt diff --git a/test_bags/invalid_metadata_file/tagmanifest-sha512.txt b/test_bags/invalid_metadata_file/tagmanifest-sha512.txt new file mode 100644 index 00000000..af40f715 --- /dev/null +++ b/test_bags/invalid_metadata_file/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +4c13864b5187f06ac2a5b20cde4fd664e673ad1a89c9c71189ddd77c7d6dfab38a9dc914d4b118fa633289cc22e6781df855f049a035694bfd560c40ff4d2981 bag-info.txt +850f79b163ddf57a7b1fd307e0c8b6986447f8aa269a497baffa8e32d2d82d3ef4d34f888e711525e396c3f74d428d6425af6f2f1a71c7b05444e18b46220210 manifest-sha512.txt +36653185ab6169075beaa4ab575a11acbd2b1f6a7d384443989c80d1dfbd6247e6b72cefbe13f303bd1db6935e393d63149410592e39ca73bf5f1cb457dbed15 manifest-sha256.txt diff --git a/test_bags/missing_bag_declaration.tar b/test_bags/missing_bag_declaration.tar old mode 100755 new mode 100644 index 74c481df..e1684bd0 Binary files a/test_bags/missing_bag_declaration.tar and b/test_bags/missing_bag_declaration.tar differ diff --git a/test_bags/missing_bag_declaration.tar.gz b/test_bags/missing_bag_declaration.tar.gz index 552fb5c4..1ce2822b 100644 Binary files a/test_bags/missing_bag_declaration.tar.gz and b/test_bags/missing_bag_declaration.tar.gz differ diff --git a/test_bags/missing_bag_declaration.zip b/test_bags/missing_bag_declaration.zip index 9e7323d9..0b214f20 100644 Binary files a/test_bags/missing_bag_declaration.zip and b/test_bags/missing_bag_declaration.zip differ diff --git a/test_bags/missing_bag_declaration/manifest-md5.txt b/test_bags/missing_bag_declaration/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_bag_declaration/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_bag_declaration/manifest-sha256.txt b/test_bags/missing_bag_declaration/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_bag_declaration/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_bag_declaration/manifest-sha512.txt b/test_bags/missing_bag_declaration/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_bag_declaration/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_bag_declaration/tagmanifest-md5.txt b/test_bags/missing_bag_declaration/tagmanifest-md5.txt deleted file mode 100755 index 2e50cbe6..00000000 --- a/test_bags/missing_bag_declaration/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -db863f7a191dc5efce7e8e0052ba00e7 bag-info.txt -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_bag_declaration/tagmanifest-sha256.txt b/test_bags/missing_bag_declaration/tagmanifest-sha256.txt new file mode 100644 index 00000000..4d8bf8cb --- /dev/null +++ b/test_bags/missing_bag_declaration/tagmanifest-sha256.txt @@ -0,0 +1,5 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +49c720aba153ee5d3f3c0d40c19f73f68eabd912127c86ba20807fa4bef55038 bag-info.txt +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 .DS_Store +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_bag_declaration/tagmanifest-sha512.txt b/test_bags/missing_bag_declaration/tagmanifest-sha512.txt new file mode 100644 index 00000000..f8e42049 --- /dev/null +++ b/test_bags/missing_bag_declaration/tagmanifest-sha512.txt @@ -0,0 +1,5 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +08d321e93a328e8c327c91d2e0cd69f381ffe5346780064353ab34570362de8674121c48091b52412f006ea0eaa316a363558438180ee9002a22fb2035df0092 bag-info.txt +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 .DS_Store +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_bag_manifest.tar b/test_bags/missing_bag_manifest.tar old mode 100755 new mode 100644 index c64cc28b..9c614237 Binary files a/test_bags/missing_bag_manifest.tar and b/test_bags/missing_bag_manifest.tar differ diff --git a/test_bags/missing_bag_manifest.tar.gz b/test_bags/missing_bag_manifest.tar.gz index 237be01b..e23224e4 100644 Binary files a/test_bags/missing_bag_manifest.tar.gz and b/test_bags/missing_bag_manifest.tar.gz differ diff --git a/test_bags/missing_bag_manifest.zip b/test_bags/missing_bag_manifest.zip index 108fbe70..f86851ae 100644 Binary files a/test_bags/missing_bag_manifest.zip and b/test_bags/missing_bag_manifest.zip differ diff --git a/test_bags/missing_bag_manifest/manifest-md5.txt b/test_bags/missing_bag_manifest/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_bag_manifest/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_bag_manifest/manifest-sha256.txt b/test_bags/missing_bag_manifest/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_bag_manifest/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_bag_manifest/manifest-sha512.txt b/test_bags/missing_bag_manifest/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_bag_manifest/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_bag_manifest/tagmanifest-md5.txt b/test_bags/missing_bag_manifest/tagmanifest-md5.txt deleted file mode 100755 index 496ccac8..00000000 --- a/test_bags/missing_bag_manifest/tagmanifest-md5.txt +++ /dev/null @@ -1,4 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -d042b9059f49fa4c7116883080fe16fb bag-info.txt -194577a7e20bdcc7afbb718f502c134c .DS_Store -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_bag_manifest/tagmanifest-sha256.txt b/test_bags/missing_bag_manifest/tagmanifest-sha256.txt new file mode 100644 index 00000000..cb640648 --- /dev/null +++ b/test_bags/missing_bag_manifest/tagmanifest-sha256.txt @@ -0,0 +1,5 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +b6ac2f460f71a84a33c626893d66463a0cd728349d20323d33a5ef7dcf488639 bag-info.txt +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 .DS_Store +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_bag_manifest/tagmanifest-sha512.txt b/test_bags/missing_bag_manifest/tagmanifest-sha512.txt new file mode 100644 index 00000000..31715ff9 --- /dev/null +++ b/test_bags/missing_bag_manifest/tagmanifest-sha512.txt @@ -0,0 +1,5 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +14973c57c5a0f41c3e8d8db694560126aaa063865a660954490c156b6cc212bc7d97fc9d52c03ee67bd92653e66e84eaf22fbda6b06ee352de8ea4a8cda98ae5 bag-info.txt +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 .DS_Store +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_description.tar b/test_bags/missing_description.tar old mode 100755 new mode 100644 index 8de37ba3..0e646650 Binary files a/test_bags/missing_description.tar and b/test_bags/missing_description.tar differ diff --git a/test_bags/missing_description.tar.gz b/test_bags/missing_description.tar.gz index c17991f8..82f565b6 100644 Binary files a/test_bags/missing_description.tar.gz and b/test_bags/missing_description.tar.gz differ diff --git a/test_bags/missing_description.zip b/test_bags/missing_description.zip index 5504c0c9..2ba1dac4 100644 Binary files a/test_bags/missing_description.zip and b/test_bags/missing_description.zip differ diff --git a/test_bags/missing_description/manifest-md5.txt b/test_bags/missing_description/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_description/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_description/manifest-sha256.txt b/test_bags/missing_description/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_description/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_description/manifest-sha512.txt b/test_bags/missing_description/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_description/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_description/tagmanifest-md5.txt b/test_bags/missing_description/tagmanifest-md5.txt deleted file mode 100755 index db86fbf5..00000000 --- a/test_bags/missing_description/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -e9bbb23f249767f7c686e2be8b941e44 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_description/tagmanifest-sha256.txt b/test_bags/missing_description/tagmanifest-sha256.txt new file mode 100644 index 00000000..68b83535 --- /dev/null +++ b/test_bags/missing_description/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +c0df5c8c281f8ab313dd1f329c3956af7971b156d77844e5d5b1ee05c4e2d621 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_description/tagmanifest-sha512.txt b/test_bags/missing_description/tagmanifest-sha512.txt new file mode 100644 index 00000000..0eff7d06 --- /dev/null +++ b/test_bags/missing_description/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +e4a8cb39b854bf33c5896c0d86cd237be34b8790dbab8e66195ff9e5fe78d1555c060977beb61673008e7c9d21cd29bbdf3fd92c266eef0c1750fbe108b74d37 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_payload_directory.tar b/test_bags/missing_payload_directory.tar old mode 100755 new mode 100644 index 8a9bcb14..bc350fd9 Binary files a/test_bags/missing_payload_directory.tar and b/test_bags/missing_payload_directory.tar differ diff --git a/test_bags/missing_payload_directory.tar.gz b/test_bags/missing_payload_directory.tar.gz index fa98fa80..558ebef6 100644 Binary files a/test_bags/missing_payload_directory.tar.gz and b/test_bags/missing_payload_directory.tar.gz differ diff --git a/test_bags/missing_payload_directory.zip b/test_bags/missing_payload_directory.zip index e1227ab2..aa0b0d4a 100644 Binary files a/test_bags/missing_payload_directory.zip and b/test_bags/missing_payload_directory.zip differ diff --git a/test_bags/missing_payload_directory/._.DS_Store b/test_bags/missing_payload_directory/._.DS_Store deleted file mode 100644 index 2b398a25..00000000 Binary files a/test_bags/missing_payload_directory/._.DS_Store and /dev/null differ diff --git a/test_bags/missing_payload_directory/manifest-md5.txt b/test_bags/missing_payload_directory/manifest-md5.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/test_bags/missing_payload_directory/tagmanifest-md5.txt b/test_bags/missing_payload_directory/tagmanifest-md5.txt deleted file mode 100644 index cbffd190..00000000 --- a/test_bags/missing_payload_directory/tagmanifest-md5.txt +++ /dev/null @@ -1,5 +0,0 @@ -03a0bbb4d3b206ec25238f9d4eddca63 ._.DS_Store -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -62061b822e03a55a37359332271f287a bag-info.txt -194577a7e20bdcc7afbb718f502c134c .DS_Store -d41d8cd98f00b204e9800998ecf8427e manifest-md5.txt diff --git a/test_bags/missing_payload_directory/tagmanifest-sha256.txt b/test_bags/missing_payload_directory/tagmanifest-sha256.txt new file mode 100644 index 00000000..8c0ca343 --- /dev/null +++ b/test_bags/missing_payload_directory/tagmanifest-sha256.txt @@ -0,0 +1,3 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +66a93685e3df37dc185a42e15763404d903c607b9d87506209180036984c5037 bag-info.txt +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 .DS_Store diff --git a/test_bags/missing_payload_directory/tagmanifest-sha512.txt b/test_bags/missing_payload_directory/tagmanifest-sha512.txt new file mode 100644 index 00000000..d3d15b53 --- /dev/null +++ b/test_bags/missing_payload_directory/tagmanifest-sha512.txt @@ -0,0 +1,3 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +b0c4dae6fa116eab71de284a896edb4c93b8a48e43180823c71c8ae9eca45948ee7d5c6d9492c6cfc29227be2f98e09e57206a69c413c9d1f776189166e7bc70 bag-info.txt +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 .DS_Store diff --git a/test_bags/missing_payload_manifest.tar b/test_bags/missing_payload_manifest.tar old mode 100755 new mode 100644 index 5e936761..37907c6b Binary files a/test_bags/missing_payload_manifest.tar and b/test_bags/missing_payload_manifest.tar differ diff --git a/test_bags/missing_payload_manifest.tar.gz b/test_bags/missing_payload_manifest.tar.gz index d83150d2..c7de2278 100644 Binary files a/test_bags/missing_payload_manifest.tar.gz and b/test_bags/missing_payload_manifest.tar.gz differ diff --git a/test_bags/missing_payload_manifest.zip b/test_bags/missing_payload_manifest.zip index fa5cb918..785c049a 100644 Binary files a/test_bags/missing_payload_manifest.zip and b/test_bags/missing_payload_manifest.zip differ diff --git a/test_bags/missing_payload_manifest/tagmanifest-md5.txt b/test_bags/missing_payload_manifest/tagmanifest-md5.txt deleted file mode 100755 index 12b9a0d4..00000000 --- a/test_bags/missing_payload_manifest/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -075d4e24833af6c8382649add6a2a2af bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_payload_manifest/tagmanifest-sha256.txt b/test_bags/missing_payload_manifest/tagmanifest-sha256.txt new file mode 100644 index 00000000..1fe7f419 --- /dev/null +++ b/test_bags/missing_payload_manifest/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +ad093bfd091c0b3ef96278eb80e3b223f627d6ecfd30a04b96330d8941bd23ed bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_payload_manifest/tagmanifest-sha512.txt b/test_bags/missing_payload_manifest/tagmanifest-sha512.txt new file mode 100644 index 00000000..fba2b275 --- /dev/null +++ b/test_bags/missing_payload_manifest/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +7bfe46b3a31ba480802c3f6bd346af17f9d1c9c8ff5dfa3d82ae6efa77b252c469ad7976139253840c56d5b0888acfc0b3a568334d4bd616bbda433dc888ccd8 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_record_type.tar b/test_bags/missing_record_type.tar old mode 100755 new mode 100644 index de6cc0c6..bec2de59 Binary files a/test_bags/missing_record_type.tar and b/test_bags/missing_record_type.tar differ diff --git a/test_bags/missing_record_type.tar.gz b/test_bags/missing_record_type.tar.gz index 75a2e7a1..00f7c479 100644 Binary files a/test_bags/missing_record_type.tar.gz and b/test_bags/missing_record_type.tar.gz differ diff --git a/test_bags/missing_record_type.zip b/test_bags/missing_record_type.zip index cb371212..14131c9c 100644 Binary files a/test_bags/missing_record_type.zip and b/test_bags/missing_record_type.zip differ diff --git a/test_bags/missing_record_type/manifest-md5.txt b/test_bags/missing_record_type/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_record_type/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_record_type/manifest-sha256.txt b/test_bags/missing_record_type/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_record_type/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_record_type/manifest-sha512.txt b/test_bags/missing_record_type/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_record_type/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_record_type/tagmanifest-md5.txt b/test_bags/missing_record_type/tagmanifest-md5.txt deleted file mode 100755 index ffe8709f..00000000 --- a/test_bags/missing_record_type/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -b905bcc3457dd2a47780574c8e1d889c bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_record_type/tagmanifest-sha256.txt b/test_bags/missing_record_type/tagmanifest-sha256.txt new file mode 100644 index 00000000..ea69b3c5 --- /dev/null +++ b/test_bags/missing_record_type/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +59024dfedf9a8398fe3285954562a387369107d49f461006f6c04f9b445cd167 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_record_type/tagmanifest-sha512.txt b/test_bags/missing_record_type/tagmanifest-sha512.txt new file mode 100644 index 00000000..3a2fdcde --- /dev/null +++ b/test_bags/missing_record_type/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +29f1c1d5fe0b63354f49aff23135192eeca7037acfc950d1bdfd897505f6eae5ac9760de81840566d1dca88d52f6a540492dd91c0081781f1e2caf04340c8073 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_source_organization.tar b/test_bags/missing_source_organization.tar old mode 100755 new mode 100644 index 5c9f3945..acff9fb6 Binary files a/test_bags/missing_source_organization.tar and b/test_bags/missing_source_organization.tar differ diff --git a/test_bags/missing_source_organization.tar.gz b/test_bags/missing_source_organization.tar.gz index ef760471..a90e1086 100644 Binary files a/test_bags/missing_source_organization.tar.gz and b/test_bags/missing_source_organization.tar.gz differ diff --git a/test_bags/missing_source_organization.zip b/test_bags/missing_source_organization.zip index f55b5f1f..7ad439ce 100644 Binary files a/test_bags/missing_source_organization.zip and b/test_bags/missing_source_organization.zip differ diff --git a/test_bags/missing_source_organization/manifest-md5.txt b/test_bags/missing_source_organization/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_source_organization/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_source_organization/manifest-sha256.txt b/test_bags/missing_source_organization/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_source_organization/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_source_organization/manifest-sha512.txt b/test_bags/missing_source_organization/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_source_organization/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_source_organization/tagmanifest-md5.txt b/test_bags/missing_source_organization/tagmanifest-md5.txt deleted file mode 100755 index eeba81c5..00000000 --- a/test_bags/missing_source_organization/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -c31360637acc14b96daa69bdae4af234 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_source_organization/tagmanifest-sha256.txt b/test_bags/missing_source_organization/tagmanifest-sha256.txt new file mode 100644 index 00000000..7d6de34d --- /dev/null +++ b/test_bags/missing_source_organization/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +36f8d49550693ad3cdad10f53c2e500e49311b18214f2469dbee7ab68f92508b bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_source_organization/tagmanifest-sha512.txt b/test_bags/missing_source_organization/tagmanifest-sha512.txt new file mode 100644 index 00000000..bb29bc27 --- /dev/null +++ b/test_bags/missing_source_organization/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +1157efd87edb4b538c0e5d7be284f3547d0a9d0e9d916907e1c068435551e6f7db14d534d067a17d0c5cdf60cec593f0d965bf10084ba9dc89144c87f2ea5300 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/missing_title.tar b/test_bags/missing_title.tar old mode 100755 new mode 100644 index ecc291b9..3cb0bc9e Binary files a/test_bags/missing_title.tar and b/test_bags/missing_title.tar differ diff --git a/test_bags/missing_title.tar.gz b/test_bags/missing_title.tar.gz index 8a7ee60d..1c7bb217 100644 Binary files a/test_bags/missing_title.tar.gz and b/test_bags/missing_title.tar.gz differ diff --git a/test_bags/missing_title.zip b/test_bags/missing_title.zip index 6cb8b3bc..3981b3bb 100644 Binary files a/test_bags/missing_title.zip and b/test_bags/missing_title.zip differ diff --git a/test_bags/missing_title/manifest-md5.txt b/test_bags/missing_title/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/missing_title/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/missing_title/manifest-sha256.txt b/test_bags/missing_title/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/missing_title/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/missing_title/manifest-sha512.txt b/test_bags/missing_title/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/missing_title/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/missing_title/tagmanifest-md5.txt b/test_bags/missing_title/tagmanifest-md5.txt deleted file mode 100755 index 8367d701..00000000 --- a/test_bags/missing_title/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -40fb82458c3ef7fb07c539d91fb50e66 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/missing_title/tagmanifest-sha256.txt b/test_bags/missing_title/tagmanifest-sha256.txt new file mode 100644 index 00000000..6877acb6 --- /dev/null +++ b/test_bags/missing_title/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +d5f6bb5ce9b6ae2bc93506fdb1bc523e828a7ae119b5beb10ecd3ff2f9a7fab3 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/missing_title/tagmanifest-sha512.txt b/test_bags/missing_title/tagmanifest-sha512.txt new file mode 100644 index 00000000..17dc8cbd --- /dev/null +++ b/test_bags/missing_title/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +0b7b97acc9bd42c5f034b3baf801b8b31ab55ec4b894de3ab4a3a930f4345191d0a8a2cdc4c9213ac1d1b92cb768d0dfb296693407dc6a72c1c9d3980dd959ac bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/no_bagit_profile.tar b/test_bags/no_bagit_profile.tar deleted file mode 100755 index 55329b1f..00000000 Binary files a/test_bags/no_bagit_profile.tar and /dev/null differ diff --git a/test_bags/no_bagit_profile.tar.gz b/test_bags/no_bagit_profile.tar.gz deleted file mode 100644 index a1a43883..00000000 Binary files a/test_bags/no_bagit_profile.tar.gz and /dev/null differ diff --git a/test_bags/no_bagit_profile.zip b/test_bags/no_bagit_profile.zip deleted file mode 100644 index e42211db..00000000 Binary files a/test_bags/no_bagit_profile.zip and /dev/null differ diff --git a/test_bags/repeating_record_type.tar b/test_bags/repeating_record_type.tar old mode 100755 new mode 100644 index 8a3629cd..2a0bd5b7 Binary files a/test_bags/repeating_record_type.tar and b/test_bags/repeating_record_type.tar differ diff --git a/test_bags/repeating_record_type.tar.gz b/test_bags/repeating_record_type.tar.gz index 5d1168e2..7526ea70 100644 Binary files a/test_bags/repeating_record_type.tar.gz and b/test_bags/repeating_record_type.tar.gz differ diff --git a/test_bags/repeating_record_type.zip b/test_bags/repeating_record_type.zip index 9b643a05..d6320b21 100644 Binary files a/test_bags/repeating_record_type.zip and b/test_bags/repeating_record_type.zip differ diff --git a/test_bags/repeating_record_type/manifest-md5.txt b/test_bags/repeating_record_type/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/repeating_record_type/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/repeating_record_type/manifest-sha256.txt b/test_bags/repeating_record_type/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/repeating_record_type/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/repeating_record_type/manifest-sha512.txt b/test_bags/repeating_record_type/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/repeating_record_type/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/repeating_record_type/tagmanifest-md5.txt b/test_bags/repeating_record_type/tagmanifest-md5.txt deleted file mode 100755 index a86a15a4..00000000 --- a/test_bags/repeating_record_type/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -fb0c775f529f967d2cede80b05bc8812 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/repeating_record_type/tagmanifest-sha256.txt b/test_bags/repeating_record_type/tagmanifest-sha256.txt new file mode 100644 index 00000000..2d28fa73 --- /dev/null +++ b/test_bags/repeating_record_type/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +90a40089f3c84760ab36ee70d967eb6b18bb06a7345bfe638aea1d408b7d74ad bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/repeating_record_type/tagmanifest-sha512.txt b/test_bags/repeating_record_type/tagmanifest-sha512.txt new file mode 100644 index 00000000..81c3115d --- /dev/null +++ b/test_bags/repeating_record_type/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +2498ba60b9784f512fba71aa9a80b5a85d054222b1a679327b4d72c445a67c64d190483f44a99932aa17ab32a57139547cebce3a5b14b953196691488cf3d545 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/repeating_source_organization.tar b/test_bags/repeating_source_organization.tar old mode 100755 new mode 100644 index 25f1e235..9c4608b5 Binary files a/test_bags/repeating_source_organization.tar and b/test_bags/repeating_source_organization.tar differ diff --git a/test_bags/repeating_source_organization.tar.gz b/test_bags/repeating_source_organization.tar.gz index 498cad40..e9bb3774 100644 Binary files a/test_bags/repeating_source_organization.tar.gz and b/test_bags/repeating_source_organization.tar.gz differ diff --git a/test_bags/repeating_source_organization.zip b/test_bags/repeating_source_organization.zip index e78e8a8c..1b9b52ed 100644 Binary files a/test_bags/repeating_source_organization.zip and b/test_bags/repeating_source_organization.zip differ diff --git a/test_bags/repeating_source_organization/manifest-md5.txt b/test_bags/repeating_source_organization/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/repeating_source_organization/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/repeating_source_organization/manifest-sha256.txt b/test_bags/repeating_source_organization/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/repeating_source_organization/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/repeating_source_organization/manifest-sha512.txt b/test_bags/repeating_source_organization/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/repeating_source_organization/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/repeating_source_organization/tagmanifest-md5.txt b/test_bags/repeating_source_organization/tagmanifest-md5.txt deleted file mode 100755 index 92a0debc..00000000 --- a/test_bags/repeating_source_organization/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -c6448285617b342581d6ba2b0708e838 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/repeating_source_organization/tagmanifest-sha256.txt b/test_bags/repeating_source_organization/tagmanifest-sha256.txt new file mode 100644 index 00000000..2f7bd76b --- /dev/null +++ b/test_bags/repeating_source_organization/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +7afb28767cc8fca44ec5c0571cd36b3071c4f7bf6d09a606392f38b0e0edd321 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/repeating_source_organization/tagmanifest-sha512.txt b/test_bags/repeating_source_organization/tagmanifest-sha512.txt new file mode 100644 index 00000000..dfa248b5 --- /dev/null +++ b/test_bags/repeating_source_organization/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +2c51341d80461376514a82c05d412cdeca847e34b15660dbbaa1698ebf00aa6124a8b85f14bb32cbe70d2fd7bfd78b3ac9618c753fb8fd7664ed940a154a1af1 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/repeating_title.tar b/test_bags/repeating_title.tar old mode 100755 new mode 100644 index 6df1c63d..492fda7e Binary files a/test_bags/repeating_title.tar and b/test_bags/repeating_title.tar differ diff --git a/test_bags/repeating_title.tar.gz b/test_bags/repeating_title.tar.gz index 80072504..348b690f 100644 Binary files a/test_bags/repeating_title.tar.gz and b/test_bags/repeating_title.tar.gz differ diff --git a/test_bags/repeating_title.zip b/test_bags/repeating_title.zip index fc183414..b0bb5729 100644 Binary files a/test_bags/repeating_title.zip and b/test_bags/repeating_title.zip differ diff --git a/test_bags/repeating_title/manifest-md5.txt b/test_bags/repeating_title/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/repeating_title/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/repeating_title/manifest-sha256.txt b/test_bags/repeating_title/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/repeating_title/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/repeating_title/manifest-sha512.txt b/test_bags/repeating_title/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/repeating_title/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/repeating_title/tagmanifest-md5.txt b/test_bags/repeating_title/tagmanifest-md5.txt deleted file mode 100755 index f1b94bc3..00000000 --- a/test_bags/repeating_title/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -f9d2ec02795532db851d18314b1c9ea6 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/repeating_title/tagmanifest-sha256.txt b/test_bags/repeating_title/tagmanifest-sha256.txt new file mode 100644 index 00000000..78b73f2b --- /dev/null +++ b/test_bags/repeating_title/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +dd40a7bcb02bbdcfcfc78e5c86d5b863b5e16d06ca155a5b80ec49d480a6b713 bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/repeating_title/tagmanifest-sha512.txt b/test_bags/repeating_title/tagmanifest-sha512.txt new file mode 100644 index 00000000..045b5c1f --- /dev/null +++ b/test_bags/repeating_title/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +95a50594cb2f325caf6a858471254eaa35457b739efa4a44d44c39b40e5e3fb79aca60f91ad6d9453494b49c8946ae9bbf38d0cf5f412e9b212fb9d6f1b9e136 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/test_profile.json b/test_bags/test_profile.json deleted file mode 100644 index dec703ab..00000000 --- a/test_bags/test_profile.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "BagIt-Profile-Info":{ - "BagIt-Profile-Identifier":"https://raw.githubusercontent.com/RockefellerArchiveCenter/project_electron/master/transfer/organizational-bag-profile.json", - "Source-Organization":"Rockarch.org", - "Contact-Name":"Hillel Arnold", - "Contact-Email":"harnold@rockarch.org", - "External-Description":"BagIt profile for transferring records from donors to the RAC", - "Version":"1.4" - }, - "Bag-Info":{ - "Source-Organization":{ - "required":true, - "values":[ - "Ford Foundation", - "Rockefeller Foundation", - "Rockefeller University", - "Commonwealth Fund", - "Test Organization" - ], - "repeatable":false - }, - "External-Identifier":{ - "required":true, - "repeatable":false - }, - "Internal-Sender-Description":{ - "required":true, - "repeatable":false - }, - "Title":{ - "required":true, - "repeatable":false - }, - "Date-Start":{ - "required":true, - "repeatable":false - }, - "Date-End":{ - "required":true, - "repeatable":false - }, - "Record-Creators":{ - "required":true, - "repeatable":true - }, - "Record-Type":{ - "required":true, - "values":[ - "administrative records", - "board materials", - "communications and publications", - "grant records", - "annual reports" - ], - "repeatable":false - }, - "Language":{ - "required":true, - "repeatable":true - }, - "Bagging-Date":{ - "required":true, - "repeatable":false - }, - "Payload-Oxum":{ - "required":true, - "repeatable":false - }, - "Bag-Count":{ - "required":false, - "repeatable":false - }, - "Bag-Group-Identifier":{ - "required":false, - "repeatable":false - } - }, - "Manifests-Required":[], - "Allow-Fetch.txt":false, - "Serialization":"optional", - "Accept-Serialization":[ - "application/zip", - "application/x-tar", - "application/x-gzip" - ], - "Accept-BagIt-Version":[ - "0.97" - ] -} diff --git a/test_bags/unauthorized_record_type.tar b/test_bags/unauthorized_record_type.tar old mode 100755 new mode 100644 index 19f4a122..d6850abe Binary files a/test_bags/unauthorized_record_type.tar and b/test_bags/unauthorized_record_type.tar differ diff --git a/test_bags/unauthorized_record_type.tar.gz b/test_bags/unauthorized_record_type.tar.gz index 4ee8741a..4ef41ae0 100644 Binary files a/test_bags/unauthorized_record_type.tar.gz and b/test_bags/unauthorized_record_type.tar.gz differ diff --git a/test_bags/unauthorized_record_type.zip b/test_bags/unauthorized_record_type.zip index 16c5f44c..0e44131c 100644 Binary files a/test_bags/unauthorized_record_type.zip and b/test_bags/unauthorized_record_type.zip differ diff --git a/test_bags/unauthorized_record_type/manifest-md5.txt b/test_bags/unauthorized_record_type/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/unauthorized_record_type/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/unauthorized_record_type/manifest-sha256.txt b/test_bags/unauthorized_record_type/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/unauthorized_record_type/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/unauthorized_record_type/manifest-sha512.txt b/test_bags/unauthorized_record_type/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/unauthorized_record_type/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/unauthorized_record_type/tagmanifest-md5.txt b/test_bags/unauthorized_record_type/tagmanifest-md5.txt deleted file mode 100755 index 917849d0..00000000 --- a/test_bags/unauthorized_record_type/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -db7f524f4a95583934c27392c672e3ee bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/unauthorized_record_type/tagmanifest-sha256.txt b/test_bags/unauthorized_record_type/tagmanifest-sha256.txt new file mode 100644 index 00000000..77a79cfb --- /dev/null +++ b/test_bags/unauthorized_record_type/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +59b1d65831cad4de37b048d388d1dfe4b7d556e9b3376516ab6c32dfe695de3e bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/unauthorized_record_type/tagmanifest-sha512.txt b/test_bags/unauthorized_record_type/tagmanifest-sha512.txt new file mode 100644 index 00000000..ae2eac46 --- /dev/null +++ b/test_bags/unauthorized_record_type/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +1af24a2a3a56212d940903e4c7191e8abc273e5b37c59c25e73fc946183e0492ab7974a4bf71b54ec0383614d3023cd97d2353e362ed4f7fe1f5fadc34702892 bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/unauthorized_source_organization.tar b/test_bags/unauthorized_source_organization.tar old mode 100755 new mode 100644 index 691e12e9..699ac5ff Binary files a/test_bags/unauthorized_source_organization.tar and b/test_bags/unauthorized_source_organization.tar differ diff --git a/test_bags/unauthorized_source_organization.tar.gz b/test_bags/unauthorized_source_organization.tar.gz index 2a50d15f..51b79f62 100644 Binary files a/test_bags/unauthorized_source_organization.tar.gz and b/test_bags/unauthorized_source_organization.tar.gz differ diff --git a/test_bags/unauthorized_source_organization.zip b/test_bags/unauthorized_source_organization.zip index e376e3d8..78095cfa 100644 Binary files a/test_bags/unauthorized_source_organization.zip and b/test_bags/unauthorized_source_organization.zip differ diff --git a/test_bags/unauthorized_source_organization/manifest-md5.txt b/test_bags/unauthorized_source_organization/manifest-md5.txt deleted file mode 100755 index de5626bd..00000000 --- a/test_bags/unauthorized_source_organization/manifest-md5.txt +++ /dev/null @@ -1,8 +0,0 @@ -194577a7e20bdcc7afbb718f502c134c data/.DS_Store -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/unauthorized_source_organization/manifest-sha256.txt b/test_bags/unauthorized_source_organization/manifest-sha256.txt new file mode 100644 index 00000000..fef31fd6 --- /dev/null +++ b/test_bags/unauthorized_source_organization/manifest-sha256.txt @@ -0,0 +1,8 @@ +d65165279105ca6773180500688df4bdc69a2c7b771752f0a46ef120b7fd8ec3 data/.DS_Store +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/unauthorized_source_organization/manifest-sha512.txt b/test_bags/unauthorized_source_organization/manifest-sha512.txt new file mode 100644 index 00000000..eb31b713 --- /dev/null +++ b/test_bags/unauthorized_source_organization/manifest-sha512.txt @@ -0,0 +1,8 @@ +58941214a8334331e52114aab851fc3d8d5da5dd14983f933da8735c24b0ddcac134e8f13692553199c4d9a14a4b3188b62878a30b9d696edda1204666b60837 data/.DS_Store +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/unauthorized_source_organization/tagmanifest-md5.txt b/test_bags/unauthorized_source_organization/tagmanifest-md5.txt deleted file mode 100755 index 30fb3fde..00000000 --- a/test_bags/unauthorized_source_organization/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -c4722e9564ccd09c3f7bc05537abad53 bag-info.txt -171bd937a8ae63f7309447c02c94895c manifest-md5.txt diff --git a/test_bags/unauthorized_source_organization/tagmanifest-sha256.txt b/test_bags/unauthorized_source_organization/tagmanifest-sha256.txt new file mode 100644 index 00000000..bf43196b --- /dev/null +++ b/test_bags/unauthorized_source_organization/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +1d6eacf1a4205df2348822045cd331c39656f72d9159bb94ab97da83dcf7ba8d bag-info.txt +d8c26b82626a356eb5721f560ecf5692488401c69fbbf4551ac0b7256eb2baec manifest-sha512.txt +8623d2de1e61b6814a9d3842c06349284fed39d9fa6400e570fb9eb70442317e manifest-sha256.txt diff --git a/test_bags/unauthorized_source_organization/tagmanifest-sha512.txt b/test_bags/unauthorized_source_organization/tagmanifest-sha512.txt new file mode 100644 index 00000000..3bbc9f38 --- /dev/null +++ b/test_bags/unauthorized_source_organization/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +aa1894ae01458658af091b698cd47e9d8fc9ae6698e44fc7df3532dbaecc09b34857378034cee6d8beb1e9ba45a835e477e157b84e5a8f06ba658224857d4ccb bag-info.txt +2b2ff1db77d5216386ebb1ccefbfa6581808d6637861a24c7939d1d9f02a27f3fedb009dc88620bb27fc4920841d26915b3b00c1c56d1a0c8944cab5b9e599cf manifest-sha512.txt +d9b268d9604ca6a9be31508d52048c14ca52ed1c1c1a3b342b4724710ba08a6cf78b7b62133ecac9c5f92ef9da07f6f2d842efb8e0acde59f16d6a7f5e0bdc1a manifest-sha256.txt diff --git a/test_bags/valid_bag.tar b/test_bags/valid_bag.tar old mode 100755 new mode 100644 index c01a35cb..30ee1672 Binary files a/test_bags/valid_bag.tar and b/test_bags/valid_bag.tar differ diff --git a/test_bags/valid_bag.tar.gz b/test_bags/valid_bag.tar.gz index 04162af2..c6451942 100644 Binary files a/test_bags/valid_bag.tar.gz and b/test_bags/valid_bag.tar.gz differ diff --git a/test_bags/valid_bag.zip b/test_bags/valid_bag.zip index 56a61ed1..158d609d 100644 Binary files a/test_bags/valid_bag.zip and b/test_bags/valid_bag.zip differ diff --git a/test_bags/valid_bag/manifest-md5.txt b/test_bags/valid_bag/manifest-md5.txt deleted file mode 100755 index d7e46683..00000000 --- a/test_bags/valid_bag/manifest-md5.txt +++ /dev/null @@ -1,7 +0,0 @@ -d52d759e406e40739203b494cebb0e71 data/Lorem ipsum dolor sit amet.docx -6b78065070118d9657b7dface5bf8065 data/Lorem ipsum.odt -6b417a5079c8dab04cbda2c4d0b4f40f data/consectetur adipiscing elit.pdf -22146c62a885ca2ff813e1de16bdd86a data/consectetur adipiscing elit.rtf -805541eca3750659ba97aacbb4d8a1db data/metadata.json -20e136ecba3d349c5ea2ea75d1a2a547 data/more_data.xlsx -2144cb2ec4ebbc8cd508d8cf02c04bd2 data/sample_data.xlsx diff --git a/test_bags/valid_bag/manifest-sha256.txt b/test_bags/valid_bag/manifest-sha256.txt new file mode 100644 index 00000000..ea14a18e --- /dev/null +++ b/test_bags/valid_bag/manifest-sha256.txt @@ -0,0 +1,7 @@ +1db560cc9f01f46f8410e2fe1bf6c687cd68044fb38030d8ab3db076de84def4 data/Lorem ipsum dolor sit amet.docx +d34c11879fd56a405c6b1851879200c0e14292ff8be40a2546797c582f15979b data/Lorem ipsum.odt +3b3ec6d37e8e34400fa43b6806e7cba5c6e7a823249b01ae1b6b4cbb445620cf data/consectetur adipiscing elit.pdf +bf58e6442c2155419772a78bd7c09ad29c95e9c2c679e252ad2fa0bcfa7a8442 data/consectetur adipiscing elit.rtf +a2437eff4caafe2cf496f9e2053b8ec72f15c8b54d69df03deed9bd4e77f87d3 data/metadata.json +0de7d2a3a6c54e39d1428513cdcb75ff65493546c2f77c8f831aef4efce6c737 data/more_data.xlsx +c3f17156ab7c192571ecfc742e88c16a4b7243a4d4b4a420fcb68dec44e10196 data/sample_data.xlsx diff --git a/test_bags/valid_bag/manifest-sha512.txt b/test_bags/valid_bag/manifest-sha512.txt new file mode 100644 index 00000000..20204890 --- /dev/null +++ b/test_bags/valid_bag/manifest-sha512.txt @@ -0,0 +1,7 @@ +e7ed020e21359b0973da17c72a778737b2c495f327b970be68b566cce38e6a3a5a58b97ef9763fc9320cfd52836047ad9a596d6568d21ec28e14b88733d04700 data/Lorem ipsum dolor sit amet.docx +59a0c25a3c0f8590dd627cc5bcb6631d9167b41e475a91d82015da2f463c22cc80e39912935d945bc98f4e9474f64078f5198156d7f7ab26977aba8d02c945bc data/Lorem ipsum.odt +9fd9ab23192181ec4653b28aa199470bef3d832b3442d9f6e39a027d69778894206ffe2056d1a1e27c12e3a1cea01d5c53176bd16c7b24c585f4ae9fadc02760 data/consectetur adipiscing elit.pdf +dfc424a9f6d1be757ec53bed6b1dbd6d2f6d50dbe6d64cb36933426f08474df4281ee8fa289b0a36954cc899882730c7a9dbc56df19a7e16e244a9a2599e3fad data/consectetur adipiscing elit.rtf +d855bdd413bf8f5e899ac4269af3055501475a2bb271c307a21f9a8108f6b1feeb33c144caddc5bf34bb2e901af1de0d2ff8154e72f8641098efb67dfd3317d8 data/metadata.json +bb663602c07a87d61e2cdff674b12970d4b841e79e442186a0378a673a2408eb568c22c5cb8fa6f9e77187c00faaf8c9f3e47580fdf1485aaa351f026512b458 data/more_data.xlsx +2b64e204b82e83eceb6872edcbfd872a428606faf7764542b8614dcc6fdfe014524db4e6324e7a40fc6f8e3c062c3595e0b19dc2be8da488f0b8ad070733588b data/sample_data.xlsx diff --git a/test_bags/valid_bag/tagmanifest-md5.txt b/test_bags/valid_bag/tagmanifest-md5.txt deleted file mode 100755 index 7501cd45..00000000 --- a/test_bags/valid_bag/tagmanifest-md5.txt +++ /dev/null @@ -1,3 +0,0 @@ -9e5ad981e0d29adc278f6a294b8c2aca bagit.txt -0b32850fe1887c811336e453db577168 bag-info.txt -2b2cbce8cdda7005d26f8530d259e0bb manifest-md5.txt diff --git a/test_bags/valid_bag/tagmanifest-sha256.txt b/test_bags/valid_bag/tagmanifest-sha256.txt new file mode 100644 index 00000000..017ffbe3 --- /dev/null +++ b/test_bags/valid_bag/tagmanifest-sha256.txt @@ -0,0 +1,4 @@ +e91f941be5973ff71f1dccbdd1a32d598881893a7f21be516aca743da38b1689 bagit.txt +e335ba2e6cd28f71592b6e7a59816c9a9e26de5dfdec4e94622199cb8e8f3610 bag-info.txt +aa47085d75b0102f1f2982c548f2d0c2cca64f77a480e074f1ef27435a866984 manifest-sha512.txt +dbb6ad88e354b8af4698f31d440593e0dffc135ab22dbbadf536c00b596f4ada manifest-sha256.txt diff --git a/test_bags/valid_bag/tagmanifest-sha512.txt b/test_bags/valid_bag/tagmanifest-sha512.txt new file mode 100644 index 00000000..72742c3d --- /dev/null +++ b/test_bags/valid_bag/tagmanifest-sha512.txt @@ -0,0 +1,4 @@ +418dcfbe17d5f4b454b18630be795462cf7da4ceb6313afa49451aa2568e41f7ca3d34cf0280c7d056dc5681a70c37586aa1755620520b9198eede905ba2d0f6 bagit.txt +4034ba83de75e0502cb5325b5440b6434f18e0d695d4aee6df9b97f8e8e5dd1cd94d0c158f02418fd9335c736261898699a544579238d1219e528de5b50357c0 bag-info.txt +7c101a97c384e6ac6ab3b6c5311a637fdef1d39c1ffdb05be92cc848e85d04c5c5437e0fe5e5457de584542d3cd1580ac21fec49692d7a1c37f96fe828ebf710 manifest-sha512.txt +8ea337ac5b6c6c86676c9cfcfd2fe9f98aa8d0e3fd27593b4b0d11378c14bdcdc26e614bfb4e8f33a329647ac4b7f8efefef00a38ba992865e90ecf22f2fd56d manifest-sha256.txt