Compare commits

...

41 Commits

Author SHA1 Message Date
shamoon
d0257f2a3e Always coerce 2026-01-29 10:02:52 -08:00
shamoon
b2a0ca1ef8 Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-29 09:53:06 -08:00
shamoon
dda690d8f3 Fix the warning 2026-01-29 09:52:30 -08:00
shamoon
1e52b69997 Handle on frontend 2026-01-29 09:31:52 -08:00
shamoon
6c1b9fe492 Actually simpler 2026-01-29 09:02:22 -08:00
shamoon
8cf6d9fa3c Backend to JSONField 2026-01-29 08:45:13 -08:00
GitHub Actions
a367b8ad1c Auto translate strings 2026-01-29 16:07:32 +00:00
Christoph Schober
d16d3fb618 Feature: support split documents based on tag barcodes (#11645) 2026-01-29 08:05:33 -08:00
Trenton H
5577f70c69 Chore: Enables pylance pytest integration, swaps around some test markers (#11930) 2026-01-28 23:06:11 +00:00
Philipp Defner
4d9aa2e943 Expose port to host (#11918)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-01-28 21:51:10 +00:00
shamoon
72df7fb1ee Move migration 2026-01-27 17:03:05 -08:00
shamoon
873a483843 Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-27 17:02:19 -08:00
shamoon
abc7a8a1c0 Move migration 2026-01-26 15:17:19 -08:00
shamoon
359460b3c0 Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-26 15:17:08 -08:00
shamoon
d971cdf004 Rename migration 2026-01-25 17:02:34 -08:00
shamoon
5e62aa64ed Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-25 17:01:54 -08:00
shamoon
bc406d612a Regenerate migration 2026-01-24 20:02:13 -08:00
shamoon
b12936c8c6 Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-24 20:01:32 -08:00
shamoon
f596294e1f Merge branch 'dev' into feature-pw-removal-workflow-action 2026-01-09 20:45:05 -08:00
shamoon
02e590c70c Add hint for plain text password storage 2025-12-30 12:49:02 -08:00
shamoon
3c53e4bab1 Add docstrings to workflow password removal tests 2025-12-30 12:44:01 -08:00
shamoon
880b3e6d15 Better, attempt removal later for ConsumableDocument 2025-12-30 12:44:00 -08:00
shamoon
f7a6f79c8b Update test_workflows.py 2025-12-28 21:45:01 -08:00
shamoon
87dc22fbf6 Update test_workflows.py 2025-12-28 21:41:51 -08:00
shamoon
2332b3f6ad and this 2025-12-28 21:02:02 -08:00
shamoon
5fbc985b67 simplify this 2025-12-28 21:00:06 -08:00
shamoon
7f95160a63 add api tests 2025-12-28 20:58:10 -08:00
shamoon
1aaf128bcb Enhancement: password removal workflow action 2025-12-28 20:05:46 -08:00
shamoon
10db1e6405 Change param order 2025-12-28 16:05:38 -08:00
shamoon
0e2611163b Fix docs 2025-12-28 16:05:38 -08:00
shamoon
b917db44ed Cover this last bit 2025-12-28 16:05:38 -08:00
shamoon
bca409d932 Add password removal confirm dialog, with options 2025-12-28 16:05:38 -08:00
shamoon
07d67b3299 whitespace yay 2025-12-28 16:05:38 -08:00
shamoon
5fca9bac50 Fix formatting issue in document-detail.spec.ts 2025-12-28 16:05:38 -08:00
shamoon
b21df970fd backend test coverage
Added a test for the remove_password function to ensure it deletes the original document when specified.
2025-12-28 16:05:38 -08:00
shamoon
833890d0ca fix frontend test coverage 2025-12-28 16:05:38 -08:00
shamoon
eb1708420e Just hide for non-owners 2025-12-28 16:05:38 -08:00
shamoon
3bb74772a9 Backend coverage 2025-12-28 16:05:38 -08:00
shamoon
402c9af81b Add test 2025-12-28 16:05:38 -08:00
shamoon
c1de78162b Add update_document flag to bulkEdit remove_password 2025-12-28 16:05:38 -08:00
shamoon
f888722a73 Basic remove password bulk edit action 2025-12-28 16:05:38 -08:00
32 changed files with 1429 additions and 24 deletions

View File

@@ -3,6 +3,7 @@
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
"service": "paperless-development",
"workspaceFolder": "/usr/src/paperless/paperless-ngx",
"forwardPorts": [4200, 8000],
"containerEnv": {
"UV_CACHE_DIR": "/usr/src/paperless/paperless-ngx/.uv-cache"
},

View File

@@ -33,7 +33,7 @@
"label": "Start: Frontend Angular",
"description": "Start the Frontend Angular Dev Server",
"type": "shell",
"command": "pnpm start",
"command": "pnpm exec ng serve --host 0.0.0.0",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}/src-ui"

View File

@@ -805,6 +805,27 @@ See the relevant settings [`PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE`](configuratio
and [`PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING`](configuration.md#PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING)
for more information.
#### Splitting on Tag Barcodes
By default, tag barcodes only assign tags to documents without splitting them. However,
you can enable document splitting on tag barcodes by setting
[`PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT`](configuration.md#PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT)
to `true`.
When enabled, documents will be split at pages containing tag barcodes, similar to how
ASN barcodes work. Key features:
- The page with the tag barcode is **retained** in the resulting document
- **Each split document extracts its own tags** - only tags on pages within that document are assigned
- Multiple tag barcodes can trigger multiple splits in the same document
- Works seamlessly with ASN barcodes - each split document gets its own ASN and tags
This is useful for batch scanning where you place tag barcode pages between different
documents to both separate and categorize them in a single operation.
**Example:** A 6-page scan with TAG:invoice on page 3 and TAG:receipt on page 5 will create
three documents: pages 1-2 (no tags), pages 3-4 (tagged "invoice"), and pages 5-6 (tagged "receipt").
## Automatic collation of double-sided documents {#collate}
!!! note

View File

@@ -1557,6 +1557,20 @@ assigns or creates tags if a properly formatted barcode is detected.
Please refer to the Python regex documentation for more information.
#### [`PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT=<bool>`](#PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT) {#PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT}
: Enables splitting of documents on tag barcodes, similar to how ASN barcodes work.
When enabled, documents will be split into separate PDFs at pages containing
tag barcodes that match the configured `PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING`
patterns. The page with the tag barcode will be retained in the new document.
Each split document will have the detected tags assigned to it.
This only has an effect if `PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE` is also enabled.
Defaults to false.
## Audit Trail
#### [`PAPERLESS_AUDIT_LOG_ENABLED=<bool>`](#PAPERLESS_AUDIT_LOG_ENABLED) {#PAPERLESS_AUDIT_LOG_ENABLED}

View File

@@ -33,6 +33,8 @@
"**/coverage.json": true
},
"python.defaultInterpreterPath": ".venv/bin/python3",
"python.analysis.inlayHints.pytestParameters": true,
"python.testing.pytestEnabled": true,
},
"extensions": {
"recommendations": ["ms-python.python", "charliermarsh.ruff", "editorconfig.editorconfig"],

View File

@@ -66,6 +66,7 @@
#PAPERLESS_CONSUMER_BARCODE_DPI=300
#PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE=false
#PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"}
#PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT=false
#PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED=false
#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_SUBDIR_NAME=double-sided
#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_TIFF_SUPPORT=false

View File

@@ -10412,60 +10412,67 @@
<context context-type="linenumber">269</context>
</context-group>
</trans-unit>
<trans-unit id="8880243885140172279" datatype="html">
<source>Split on Tag Barcodes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">276</context>
</context-group>
</trans-unit>
<trans-unit id="7011909364081812031" datatype="html">
<source>AI Enabled</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">276</context>
<context context-type="linenumber">283</context>
</context-group>
</trans-unit>
<trans-unit id="8028880048909383956" datatype="html">
<source>Consider privacy implications when enabling AI features, especially if using a remote model.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">287</context>
</context-group>
</trans-unit>
<trans-unit id="8131374115579345652" datatype="html">
<source>LLM Embedding Backend</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">284</context>
<context context-type="linenumber">291</context>
</context-group>
</trans-unit>
<trans-unit id="6647708571891295756" datatype="html">
<source>LLM Embedding Model</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">292</context>
<context context-type="linenumber">299</context>
</context-group>
</trans-unit>
<trans-unit id="4234495692726214397" datatype="html">
<source>LLM Backend</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">299</context>
<context context-type="linenumber">306</context>
</context-group>
</trans-unit>
<trans-unit id="7935234833834000002" datatype="html">
<source>LLM Model</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">307</context>
<context context-type="linenumber">314</context>
</context-group>
</trans-unit>
<trans-unit id="1980550530387803165" datatype="html">
<source>LLM API Key</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">314</context>
<context context-type="linenumber">321</context>
</context-group>
</trans-unit>
<trans-unit id="6126617860376156501" datatype="html">
<source>LLM Endpoint</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
<context context-type="linenumber">321</context>
<context context-type="linenumber">328</context>
</context-group>
</trans-unit>
<trans-unit id="4416413576346763682" datatype="html">

View File

@@ -430,6 +430,24 @@
</div>
</div>
}
@case (WorkflowActionType.PasswordRemoval) {
<div class="row">
<div class="col">
<p class="small" i18n>
One password per line. The workflow will try them in order until one succeeds.
</p>
<pngx-input-textarea
i18n-title
title="Passwords"
formControlName="passwords"
rows="4"
[error]="error?.actions?.[i]?.passwords"
hint="Passwords are stored in plain text. Use with caution."
i18n-hint
></pngx-input-textarea>
</div>
</div>
}
}
</div>
</ng-template>

View File

@@ -3,6 +3,7 @@ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
import { provideHttpClientTesting } from '@angular/common/http/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import {
FormArray,
FormControl,
FormGroup,
FormsModule,
@@ -994,4 +995,32 @@ describe('WorkflowEditDialogComponent', () => {
component.removeSelectedCustomField(3, formGroup)
expect(formGroup.get('assign_custom_fields').value).toEqual([])
})
it('should handle parsing of passwords from array to string and back on save', () => {
const passwordAction: WorkflowAction = {
id: 1,
type: WorkflowActionType.PasswordRemoval,
passwords: ['pass1', 'pass2'],
}
component.object = {
name: 'Workflow with Passwords',
id: 1,
order: 1,
enabled: true,
triggers: [],
actions: [passwordAction],
}
component.ngOnInit()
const formActions = component.objectForm.get('actions') as FormArray
expect(formActions.value[0].passwords).toBe('pass1\npass2')
formActions.at(0).get('passwords').setValue('pass1\npass2\npass3')
component.save()
expect(component.objectForm.get('actions').value[0].passwords).toEqual([
'pass1',
'pass2',
'pass3',
])
})
})

View File

@@ -139,6 +139,10 @@ export const WORKFLOW_ACTION_OPTIONS = [
id: WorkflowActionType.Webhook,
name: $localize`Webhook`,
},
{
id: WorkflowActionType.PasswordRemoval,
name: $localize`Password removal`,
},
]
export enum TriggerFilterType {
@@ -1202,11 +1206,25 @@ export class WorkflowEditDialogComponent
headers: new FormControl(action.webhook?.headers),
include_document: new FormControl(!!action.webhook?.include_document),
}),
passwords: new FormControl(
this.formatPasswords(action.passwords ?? [])
),
}),
{ emitEvent }
)
}
private formatPasswords(passwords: string[] = []): string {
return passwords.join('\n')
}
private parsePasswords(value: string = ''): string[] {
return value
.split(/[\n,]+/)
.map((entry) => entry.trim())
.filter((entry) => entry.length > 0)
}
private updateAllTriggerActionFields(emitEvent: boolean = false) {
this.triggerFields.clear({ emitEvent: false })
this.object?.triggers.forEach((trigger) => {
@@ -1331,6 +1349,7 @@ export class WorkflowEditDialogComponent
headers: null,
include_document: false,
},
passwords: [],
}
this.object.actions.push(action)
this.createActionField(action)
@@ -1367,6 +1386,7 @@ export class WorkflowEditDialogComponent
if (action.type !== WorkflowActionType.Email) {
action.email = null
}
action.passwords = this.parsePasswords(action.passwords as any)
})
super.save()
}

View File

@@ -271,6 +271,13 @@ export const PaperlessConfigOptions: ConfigOption[] = [
config_key: 'PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING',
category: ConfigCategory.Barcode,
},
{
key: 'barcode_tag_split',
title: $localize`Split on Tag Barcodes`,
type: ConfigOptionType.Boolean,
config_key: 'PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT',
category: ConfigCategory.Barcode,
},
{
key: 'ai_enabled',
title: $localize`AI Enabled`,
@@ -352,6 +359,7 @@ export interface PaperlessConfig extends ObjectWithId {
barcode_max_pages: number
barcode_enable_tag: boolean
barcode_tag_mapping: object
barcode_tag_split: boolean
ai_enabled: boolean
llm_embedding_backend: string
llm_embedding_model: string

View File

@@ -5,6 +5,7 @@ export enum WorkflowActionType {
Removal = 2,
Email = 3,
Webhook = 4,
PasswordRemoval = 5,
}
export interface WorkflowActionEmail extends ObjectWithId {
@@ -97,4 +98,6 @@ export interface WorkflowAction extends ObjectWithId {
email?: WorkflowActionEmail
webhook?: WorkflowActionWebhook
passwords?: string[]
}

View File

@@ -60,6 +60,20 @@ class Barcode:
"""
return self.value.startswith(self.settings.barcode_asn_prefix)
@property
def is_tag(self) -> bool:
"""
Returns True if the barcode value matches any configured tag mapping pattern,
False otherwise.
Note: This does NOT exclude ASN or separator barcodes - they can also be used
as tags if they match a tag mapping pattern (e.g., {"ASN12.*": "JOHN"}).
"""
for regex in self.settings.barcode_tag_mapping:
if re.match(regex, self.value, flags=re.IGNORECASE):
return True
return False
class BarcodePlugin(ConsumeTaskPlugin):
NAME: str = "BarcodePlugin"
@@ -126,8 +140,14 @@ class BarcodePlugin(ConsumeTaskPlugin):
self.detect()
# try reading tags from barcodes
# If tag splitting is enabled, skip this on the original document - let each split document extract its own tags
# However, if we're processing a split document (original_path is set), extract tags
if (
self.settings.barcode_enable_tag
and (
not self.settings.barcode_tag_split
or self.input_doc.original_path is not None
)
and (tags := self.tags) is not None
and len(tags) > 0
):
@@ -432,16 +452,25 @@ class BarcodePlugin(ConsumeTaskPlugin):
for bc in self.barcodes
if bc.is_separator and (not retain or (retain and bc.page > 0))
} # as below, dont include the first page if retain is enabled
if not self.settings.barcode_enable_asn:
return separator_pages
# add the page numbers of the ASN barcodes
# (except for first page, that might lead to infinite loops).
return {
if self.settings.barcode_enable_asn:
separator_pages = {
**separator_pages,
**{bc.page: True for bc in self.barcodes if bc.is_asn and bc.page != 0},
}
# add the page numbers of the TAG barcodes if splitting is enabled
# (except for first page, that might lead to infinite loops).
if self.settings.barcode_tag_split and self.settings.barcode_enable_tag:
separator_pages = {
**separator_pages,
**{bc.page: True for bc in self.barcodes if bc.is_tag and bc.page != 0},
}
return separator_pages
def separate_pages(self, pages_to_split_on: dict[int, bool]) -> list[Path]:
"""
Separate the provided pdf file on the pages_to_split_on.

View File

@@ -0,0 +1,38 @@
# Generated by Django 5.2.7 on 2025-12-29 03:56
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "0008_sharelinkbundle"),
]
operations = [
migrations.AddField(
model_name="workflowaction",
name="passwords",
field=models.JSONField(
blank=True,
help_text="Passwords to try when removing PDF protection. Separate with commas or new lines.",
null=True,
verbose_name="passwords",
),
),
migrations.AlterField(
model_name="workflowaction",
name="type",
field=models.PositiveIntegerField(
choices=[
(1, "Assignment"),
(2, "Removal"),
(3, "Email"),
(4, "Webhook"),
(5, "Password removal"),
],
default=1,
verbose_name="Workflow Action Type",
),
),
]

View File

@@ -1405,6 +1405,10 @@ class WorkflowAction(models.Model):
4,
_("Webhook"),
)
PASSWORD_REMOVAL = (
5,
_("Password removal"),
)
type = models.PositiveIntegerField(
_("Workflow Action Type"),
@@ -1634,6 +1638,15 @@ class WorkflowAction(models.Model):
verbose_name=_("webhook"),
)
passwords = models.JSONField(
_("passwords"),
null=True,
blank=True,
help_text=_(
"Passwords to try when removing PDF protection. Separate with commas or new lines.",
),
)
class Meta:
verbose_name = _("workflow action")
verbose_name_plural = _("workflow actions")

View File

@@ -2613,6 +2613,7 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
"remove_change_groups",
"email",
"webhook",
"passwords",
]
def validate(self, attrs):
@@ -2669,6 +2670,23 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
"Webhook data is required for webhook actions",
)
if (
"type" in attrs
and attrs["type"] == WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL
):
passwords = attrs.get("passwords")
# ensure passwords is a non-empty list of non-empty strings
if (
passwords is None
or not isinstance(passwords, list)
or len(passwords) == 0
or any(not isinstance(pw, str) for pw in passwords)
or any(len(pw.strip()) == 0 for pw in passwords)
):
raise serializers.ValidationError(
"Passwords are required for password removal actions",
)
return attrs

View File

@@ -48,6 +48,7 @@ from documents.permissions import get_objects_for_user_owner_aware
from documents.templating.utils import convert_format_str_to_template_format
from documents.workflows.actions import build_workflow_action_context
from documents.workflows.actions import execute_email_action
from documents.workflows.actions import execute_password_removal_action
from documents.workflows.actions import execute_webhook_action
from documents.workflows.mutations import apply_assignment_to_document
from documents.workflows.mutations import apply_assignment_to_overrides
@@ -822,6 +823,8 @@ def run_workflows(
logging_group,
original_file,
)
elif action.type == WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL:
execute_password_removal_action(action, document, logging_group)
if not use_overrides:
# limit title to 128 characters

View File

@@ -0,0 +1,191 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 4 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
5 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3461 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0bW:r$j4o4s3aL9.o/:sRKC1+V[Po_hnP="8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.EM=P;M`ictLh5:'u?=R'nd;IE]5Hh=BmqB2p^7X$0Q$9UiFPkD[m)hEDD7]3!20S(%m5Eepo,>73Ncpo[qg"0,Gt5J@p\hbEY.UOcVYbgK@oqO7DN/KYR@egT:O\Y"S^Nmne(=m!@M;\.mreAj`lssm2RjQmR*'f[]=0V/jtsN_^"C8&k'PptV(jd(Ymp-?-DiQUlg??aR5p7DE%a+(Q2+a1De[G>Bl&EKZ&,I(pUY]E@qJJG)r-?G9P(rih-1dREuNfk?>O(#o=aSKd[6HOfEV(Z'2t=fFn_3AbT-'E'3sZfj1^M@pYhQ7E1%B!q_i'CLMJZ]APP)MgR*7.Y/pg53RP?TA*/3L-50YH7,u"@RJ5[/9Q6C5NVbVGhM5l%_.?@umb=+S+0N]gQT<I'De%pX\0_kok!\7DNLBP"RS7[g'92lIB&8;Y13$pgHd09iRG2p8o0-ECM)-sFC\FmSgqH^TpYhQ7S=01ZZYsF;p79@=&(b@ObfogMI4I+_mo8Ft\0_l%B"lm`>FE$MV_[_Y246E[o=\bnb0967Q$FISai'U8mksuCAo?M*bkl?R-I0h_YM$B?F8J^DhM5l%EG"?[c+]I2gNP.=5$X;.1Gdp(p8uQo^/LHoiL3GZR2\raAeSG3ICLU;>is%i\_.+PGos32"IH[hA8X<AA_r2X1;RO>4IM[5E1-IZRS7[g)c,U.'3s[J\0_kok/NUqf`[Xe+0N]gQauWsDDo=BhM5l%_.@LHR@?oiRJ5[/9Q6C=:Zc7&>ipIE-50YH`fmsd"IFD+`\u,TrPk$]NL;edD'YO[I2buE1hPl,[ZP+_p2)p[e!QQPfLD$lgUH]`:1Im2@iJ!ODVrHt3K9FeNGTr/\U>Dmjtp]41q&NWk4WXSRF@Oke(@-QRG54@A56WH:1G57Ao?MGP<"Vj3K7l$RCR_b:ZaKGk$5CC.+u(L[aFc^qb6b_]O]p>fgaTjmPE\no9+M@B,b.F]?bTVcV*tKS8EA]mlo3K5;1^!EOO9f^ACUurOc[u`n<i5qsH8rp[aPr)eU*qn%6nfhp4shD4GHb^$e/6I6TC<[rJk(otL;sp\ha8ho=>=fDB;AhhFPj09^)KAJ38&9VV?L8MpH&M<8.ldJV05RX^_no.Ld9qHZg`b02a-m$D"%2.\6nf;,`[G2:]5WQ\V2c@4Gh=&YtOF%n^mA_13^REE`2l0OaBG;Wq]1Y8G/?Zt8UPc;l3PKnX1F]VM=136/NqdnAb9ps/J2<jIo?$A/;.Po\PZX7lf=5<1=SU;dP(A-q:-FpT?Fn1s1>L9Q0S)iGGeB)@_DF)%_Cm',a;^\2o]*8-oZUsS%9V$PXmM>H\bU0m00m3&T\6I=`1RmI^`mi+Cibh&sc>8Yj)cJ,VM7Wri3jVEGD+pLJ-LMZAlc^]d[kW$rRCHJJs-pTpHZ/#)PI^.2/_/Gu9ldRQT$2WWCT5#pBp+rKo47:$?VC&L8X%rrR4!(5rE?5)8Xe^PcTIWmmak?b:!t:GHfiH*GJBI/CQ^$TfeZFd^AG<;?^!=gc(929pYE$LqO43ODYD;<\aOu!e^l'@EjKDMb^K5$WP0]nZLJ^%HY#u61\3[enc_V2NHb$M)gp)%RGYQ;01^D,]VFZHi02I1r6C:L6.0i7*Bj-$T6+]-GAcILP+EW]kd`YIUbagAF!G%Ro\=[]cb7.BSXK;E)u5)]kJfT0mL;AEbfoP2a;6*b2r;r'Dt$>2Aq&o4^*)[NnW'2fK24Nao/eo%"\I%"GP'Z0I+"FNhmnk&i,4+8D*45U9lOt5(Y:H%gNYJ4S)E#I0<Sr*[ddmG2Slep?X1q4Cu`XmCk?Fi^UTlGfuB5df`]o]IW7MlZ]->RZO*cDrSi.cAfFP.AeSDgqSi-Obr20;bpKqYoS`%'Rr(9URn[j=kSMi,2qrR42k/aZcu)c8-TRTajWn-2h:0V>:?H.K8QTXcol?4Z\QM\UQ.esGSE+3uQBQEeG#L%A3LQAu,[ID*eB:EYk%6VF=)'\eEfuWs=\dD1g.f8NjCE.oPB<XE;_KLYR@E:`?)cZ0b=PIkAiWFaqb5fI-eXjPMG'4JbhVF=>A92cbB:e#8i1-tFRQ=g8G;/Vi_h'@1H2o><Z37\Ea<[a&ri:uh0UX]P'smD\5\=)b`2&(Pm5@E>ZY116t>@KpYJMpA7)Ji/leW#F/+)#V*VC?f+jW%d?qJl]slE4fpD#^99j27h!!U!Boq])FiC1L1hLXTfG0bKqW+XE:1[0q:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9j"6dh3D"AU^/LHoRCY]P]2P,]<+kV\Q$K"$)s"^pPrVEYk.Xc^pR/TYm^lDcP>l2_4-b)`W>jp44-_ftFlpD:RJ3,\612?`R?LT_mQ6\ZT;`dj^,qT?8Tj10;jmBJ\j>br;jihKBC7jHH(V&TjM!^@3D"AU^/LHoRCY]P]2P,]<+kV\Q$K"$)s"`VbpKshhJ;heIJ#,$L#d]nmrG`@m^r4^I;<3g8o>f_?gbP]CkDQP]k60U=20o&8FDiA/iT9X^3d':\+\@Uj;*pUjhAp_-FiO$C\FlYoddS,jF4Z.EjH)?]D%bBCL@$4DBZPtm^q7jK)=uLB&D<D^QMelm[*f'2k/a>H`u,3p=6A-(6\RV^<=bJ\F89ip8rc9/%LApI_"ofZO-'3pR6MG?i<T7+h:tJ]8a.RlgO*ANA"r%CuY<'3^MfLff,D1riT#Cpi?)Q-Eb+a'/[FnIC"drn*1%805'0Yiqg8J60$/A2k.>VY"m@=Eq[a)Y.q"N1qoK.Z\e#:l3*)"BA[ObqR\dSisd?'T6oD_R;-aleNSse-CL'A2.`f0WDraO2OS)NhURji-Dsc/e(A2o3I+\)VOF#I[81:r8`o)>9poa:.b-_B9dZ9lG;Ws3af/8:1cCb4:>XNcW@"N@mF0]uOu[eh;l6"R9!qH)P=aot>tp`%E[oU'ND1afPBSlqWl_5>q`ONacB7HTe^^)FjdQ)cmKTR7qbD9Vk'+?_^P9A:.ET;&?(LdsY0!m+DK&4Rmo3A$I[=j@CUb=RP3b9\eX>=VRf")l#,`aD:3C^AGI]'8L:b8NahC\ZSbZQoafjZ@E([G)<**^]QYZ/-\/Us$loWbJRG[+pr#4u-V^2.7F`lhj\L&UoOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>j''C?8XL9P~>endstream
endobj
6 0 obj
<<
/Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.1ec20b3a96e40a35266a0a8a0d634adb 5 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
7 0 obj
<<
/Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
8 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3500 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0s\bV$q&G/J($uOju)%+%1&)hn*)-NT`"8nzzzzzzzzzzzz!!'grT65NupmP_`]63jRce!oT8TqIFGMi(@D>9Q18%Wp<?-h,WY=WoE>BeutHu8YIA4O7SpKc+sL9F0lZs.b3omCWORUeq#Fn]1ff7pJ#G-kItht;A6pmP_`]63jRce!oT8TqIF@N3&*FmnO#.ck97`6:E%D03I(`QWUU&i9D1[aFc>'f5%G8^-ObfLFJ><m7)c-S_r'@N/VA=YXu(T>\r;M/@@JB>r)?I1e@5,du+nSeX'Eoh!BoPLr@VHWJ@\f-`;Z:LY8Kmo_Ad?D#0[5)F,u]k>=.H$p;]q^?<O]sAA.1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'f.Yl]\/XO/+Ys=-5A<mcb.qtW[m[)^*XRN1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'f.Yl]\/XO/+Ys=-5A<mcb.qtW[m[)^*XRN1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'u%mtD9P\Mk\;?)Y=XF$F&s;:;^o<38E=PaiQL$,`lqD>Xu6pgRT0&;GI9.]Q(k==7(su_^<Bl"bY4ksC*SkE8VJg=<uWqo.D"5(jD.ZPbM:XfbZ'J&2A5hS<;84m[4sJ&U8s8A^*XT/b[#)09Vprf,E]0$KeILK)`(DA]%T^9CJs-7XQ[gn40.j^hT+6D_O"EQQ.^@^iQJlpY=XF$Z_AtVn#XBmGopCW$=@C6=(^>mKeN$]^*XT/b_iRI^9\/Rk'_VO.X[X!?($+R'u%ohpmP1W1+Tpkqp$[=RJ65/WUOJ"FCk0:<VS?<j(hQObH0pMloV9;A_tJZUr&I$d?WC/<oM67:LY8MbP\bnpIT2]CRMpqmllSFHnFsAk1qDiNNZpmg:[;.[dgcL?^l83`&>>qq.oTiPM!n,14O/tI1k<0>3<$5]2)lT?d&ATH1smHj(k't2X`iUD'W$A9g"p/H/<t\qlZj@Rs6j=o=XsBpK^R_2t:^YkBZgdm^o&GDrTG<ch$SRh02"nhScaWT'+q-]C1'g]SU874jU`9GMi(XGn\LNHCf>Qm_8!9o-U&'oK;S+h0mmRk"Rt-k]u$5])/Y.baWi8dIY"AkBe/\3oGMcAUk_L);rMA#.X2i!H.gHJ/`tUi5T+.\FGmdDZ"(U:O*o%bOL")-=7^7DrE74n%8HFqc1)_qsI.l2X9/9=Xr<QpJLXbCr,l%R=&l$]nNdl^@1KblrVkln%1COg8K?+B;p:9h+-/%Z3B-0BC`H-pD2%Pq7aJ%Z<q/N^@0A.CSU;LS>Ge)G9:D2aqfB^S]TJQh-2j3jnnI0b'oU-pqAhRYDp-&E0eZ@h0kOd.U2CjG:$Z9F`64iQ1)?^./R#Qi;;q9^,G95_HAAGGP@N9hjJ)bTkmPnBP&2>q6mNRbVk[p.ML'C@j^(Kp6jTgZ9`&rR;L1/gVQ-1gJBf,9Jj)8R=&5kB4`+*#*k$W[P<ta$iA.a6eS+fdEFL\nnhg-R;F>k<$n'e`_=)ulnbsWAV8,n1Y\;=[tT6B[\7M6R:p1O1\nJ`cce;3%4W%9Cu];YgRj<\hRi@\^S#q;\'`3BG@'2DFDp_.g3E)3$iGVE:#8>Yn(i8??dQL.gM#W\4"p(2\i4mRD7k)U"b&c3-?#Z=p[5]00Bh9RD7&iiSJV&)h4)':2Vu(;!l(CTPIJrZHZrfS**lhrDLp#UDVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]dt()PtR=ZX#Ne^?[k]n7>Yqk"X@5,N$b[n+t<ZI$k_`GnY>faEOuZ]=tTY?Y5"1hF(X2o%i[0Y4&I/QW`::2c81eHoLr:lT;0:AQJTg:"6Qqhp&n(qT^R<R2*G]'6W]`GI-bM^9\/RAqb0[6sVnFh<b$An#XBm=lGi/;:ghU2uC>T40.j^<qtfOe?pOYc+`ZCc7440'u"rJJT(G.c#rLLN&!'U(Z28lDQ`kTc7&8cJ+:35jlX/Sk);&Kn/'u_;f8c8DpBd&!e9aR3p#M8s5o7q0CTe8X&Eo=qesb.o)aF3]fP9;])UoO1,&,5hlB[nY5<._..[Lin\%!Fk.:TTN&!'U(Z28lDQ`kTc7&;D]rq>1..d;(9\b4QZdNohWf>5rbj0%"E=9M)9$`?o2DU%CYHQ'd/bh(O4X[8`a;i@8^*XN&i6/4oS>^0IF"$YVRS;Lg0=0)JU8j3sU!2h<13!]9bY$3<W\uVf19[n'`%Ca>.m58[g;k8V]Y5^+\)>H2oUMjp,BG:)qO1+5JhOIYF/#[obb<8HCGKl;^<B3qM%\S,H5f%lH95tRk08_qgJBXiTC$Zs\'m6IhOH"!%41W;fe.Jp4)JKic&!(f:bk8-m;f,6dl(gpS1(WO-1g`]/pDV'D.D_QM%\Q>1-_DuEi6Cq2J1g9.'X4-oCLWfGBu>fA*2$m'&-5<5G.=`Vmk,5B&9%+Ymi#No@Ya?H95tRk08_qgJBXiTC$Zs\'m6IhOI,Nj6S(_kfW7]G@i>d]6GuK^GF1_VGb-dpCd3^o5%kcjh#ajEPF<U-Dj\TMt[kY47d8t.cn9e06+`_cR,Me^5M^upH.t_@OgKOGV='O1X@DF;SJ(`')+KZCgnmU]6GuK^GF1_VGb-dpCd5$SD?,d0=+!u_ELRn>rts0m[M:a=eTY?+/Q$@*@YXq:#sL!:q!ThdT+nZPdC66nmtiM>M)I1WbY,IfmOP01+SS@m%\[Q[3Of"^576*(!7<c;7c&HO`GX&7)$kPAIJA`?$5O*3P02R?Y5"tKmf2g\osm>h)CHLZU3?^5"\m^4&XAlS&gq!Tkn-ZV5pa>F_*aPG"-*$7)!s@;;.u'G3*prREq=mOkD[UDr,o,2X7_Vq-@@iZY!i\p.aV;G9<Z@\ntMtf9c<7fbp3+'D^eH7qn`9gQg[hANjmQ7V:OG^3THMg8NbLj`c-@c^LDeff,%3hL1VHlF(!o?!la#AnPZJ:#qdf+/Ot.D-)2<Qhd`9)4>mdq<$L'BqoS#Q/D7G5&5=2B&?"jH1t1iW7uLWGC>n*R[oSo2j&%8I1k:217u7s3aHUt;K^6R.'Y9Ko@YXqe('1+<S+m?'"_$sT=r*&?#B@7Fj6C(Yq%-lfdj/QeV5_Wf=ZqQ]2CDV]tug9D>7"Oc'p,d.jaf?/$.4ML+cQY]SR95;DOlX_E(t>pel7ZRjbNl-1fe?XOG^S03-W:M%[Eu17u7s3aHUt;K^6R.'Y9Ko@YXqe('1+<S+m?PTA#EbWE/3Y5NP"]T:Lk9Zk"(]B\*gf?O1@?-T1h40tujrH@#0O4)QPb.KOBlIp1.c2/npc(rQFZ`C8-G29flda_%6]JI1bg2GTfq^>apUs(p,X02DEh7SfseP+,u1V;r+DqE82-sb)nbWE/3Y5NP"]T:Lk9Zk"(]B\*gf?F9qzzzzzzzzzzzz5k,pqe-_`~>endstream
endobj
9 0 obj
<<
/Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.1280b7d13f0587f75dbba24117c3e12a 8 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
10 0 obj
<<
/Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
11 0 obj
<<
/Contents 20 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
12 0 obj
<<
/PageMode /UseNone /Pages 14 0 R /Type /Catalog
>>
endobj
13 0 obj
<<
/Author (anonymous) /CreationDate (D:20251216142815+00'00') /Creator (anonymous) /Keywords () /ModDate (D:20251216142815+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
14 0 obj
<<
/Count 6 /Kids [ 3 0 R 6 0 R 7 0 R 9 0 R 10 0 R 11 0 R ] /Type /Pages
>>
endobj
15 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 180
>>
stream
GarW2_$YcZ&4#]5`B.*sm?lG7-r1F@qZF9DA`.IipA]su.E!o]Gjlb!W-Y8MVLYd\SdH+*Db)WVcj08*lF:SRr1h[EQATgu\mTX&mM6\8TBJjRrY+[@;2SB>n%<o^ecds*8b94pS?3+.GJiRY?$tJ'kE;+M?S1+H*dP`*I]"P+I/q7'3Jd~>endstream
endobj
16 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 247
>>
stream
GarW49oHkR%#46B/)I%IW6)D&Ib[t)(Vt`^F7>Vna$l[3>H5Gfa')=U#ta'/k95LEWOSG3"r7^/'n\C!!F0.=g]gEL*]\ARI\tm.$t5=QeJN,a-U84$:2lt0pl4os1D+HLYKtgFoDtT3?g;TJZ"p1Ms8-mnFZu9hhtp+9>=dda($9HW?h<;`raPb)D!6nUI04P3H\NHB@T2`*R;q_bb$8O:'I:6:edBMuW3U[l<LGI>h[8WZ3d+9:~>endstream
endobj
17 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 174
>>
stream
GarW05mkIo$q9nR`F#VQ:"lUo>6R=/74qEVW"iqLlKJ$aC5XZ78-0=Y@o+._YHbl4Yh1ZiKj;Fh4GOo\Q)*Tmo(5G_$S2VM\7.0Q<EDUIL"miXU&6:llV)t3kO76]f1&V`o<RW_$L^=Zj5S/(^?3g%MR/&;IQVW!7L'9`%ko%``W~>endstream
endobj
18 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 244
>>
stream
GarW4b6l*?&4Q?hMRuh(23Tpmkt^cRET&,M[qV:g6EQRMs2I6!U^T$](X?G+!r#.NZmDs+Qu<6UTF4R17*n#s2&gSmk2Mk.09@0r[k9DgRu9WjKt]k!Ic1n'J.q+%HiE61]07.7.f1^O]tp[&Fn>&8hUMD]+;spqhR>>LX`Bap0=GTNaa\,&7Zqt_h]FP:T4bD(VQ.g\Pm&EGSuJ6sK$-Os9'08g6q!hekXZP?.6B5f2_i<IDu~>endstream
endobj
19 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 177
>>
stream
GarW05mkI_&4Q=V`F#VQSZ/`o[HbngaBTj`WC0EX,i7E\>AQT[REn!?T0[2$]@m:4_<Sts*7B@qAH=gO.+uD8j8"aV?VhBDBuOM(;)a,J%_4qBA,/pbTJI0<]mhonfJ__#oZJ*o;$A%?:)bSCqJ5Nag.!$oHGKA(4Iu=r,7iHH@ok]?~>endstream
endobj
20 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 167
>>
stream
GarWpYmu@>'Lq&PV`:G4BJ1Rt7[P0S\M$3?0c4(6nGPe/#`385LHkTp@/;7gD`sVT>qS[,<_0MjcjQ72dr'n'riIp[%YeJCl<.DN]-CUV%s0VJJ"dSm@n9+>F4SmfNcSuChM%!&%Rn8_]8SB3ren*ZdT2U-SH5HD>?EhY~>endstream
endobj
xref
0 21
0000000000 65535 f
0000000061 00000 n
0000000102 00000 n
0000000209 00000 n
0000000404 00000 n
0000000516 00000 n
0000004168 00000 n
0000004426 00000 n
0000004621 00000 n
0000008312 00000 n
0000008570 00000 n
0000008766 00000 n
0000008962 00000 n
0000009032 00000 n
0000009294 00000 n
0000009386 00000 n
0000009657 00000 n
0000009995 00000 n
0000010260 00000 n
0000010595 00000 n
0000010863 00000 n
trailer
<<
/ID
[<93a746516153ebd4bfbd42147dac7019><93a746516153ebd4bfbd42147dac7019>]
% ReportLab generated PDF document -- digest (opensource)
/Info 13 0 R
/Root 12 0 R
/Size 21
>>
startxref
11121
%%EOF

View File

@@ -0,0 +1,251 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 3 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
4 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3565 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0s\bV$q&G/J(%!d.nqi3%"dr>?4mOts8EB+zzzzzzzzzzzz!*oM+-e25^Cnl29l&b?1]i8(4Z]3i/UdM`^pJP:nc8L!XP7Hikhb/*W3nrlS:-,3JIP95Ol>35>46_jpqn5s1WO%T@mA*+\n+T^cV9UuF\!%<d^>DS+Prd[`h+g#,qgL3K<U+CqG<>&Nmea[s=/iNchX.++@iJ&&?TXb*R+\CBNRSd!GW)BQZVP'MW@t^MCeA2LT>ice?YncUPfCp2NGYK*fZ(6HNL>25gIQatNFu0.1]'#;OnrN+c_`O2p1\=fou/h\9khi<e(@.TMetSGd[8^cZ&R6LgNYWQ0scpZqhe?bhn8-AB4gkNX0g9qf;'UUff/Bqk*_Wcmj`02nhmC;AbOAq^3O=&hn)K"NI4GM;OMt)So:3gg%VYt7O)9(MH"3F]]YbsB(ip=[*ctHU`u)W2t-S)R@/Kl.W%$525s,Xp<@ruH"L[G]1O$%Hqc(gR=4[uDk<BMpTDq6,@?Xl<+b%#kF6*rp:[N6dE'q8,*gh?n+l+6R=4NRD)Cf@WUOIo8^2V6q[HopI=+a=I$mo2oA9.h_j>Wj?]th(k*4B.GJ2o'A_tJZUr&HY,rP-sml,W^p[L,?n7>?dc$S(>%:A7GHqc)<R8[#ThXu?8Q['Z[P6t[ZPgm?i^#/<jhT+6D_O!8/2=Fi>2gh%fnMR<8APPhAHe8-(?flca9e(OY;c<5DomXfFGopCWMT3kt`d*!#p[L,?B[!PkSCa*Q+((4h`ls=[H$u+TnMR:ZbcGKJf9^b)?^$Aeb_jDcI@9j"25t95XD"-UQ['Z[PD[B(MT0piRJ65/WG'MWBUm\@GopCWMT3kt`d*!#p[L,?B[!PkSCa*QT>id:gK2Uh2l/78:Lb>9k4;`pb^!,*1]'#;Tk$?Z<QpslV(o;P@iJ&&o3'&VGuGV;q_YaTA3QVcba^Vg0saYc)bT8a=iJU1;]7Ih1q')g5+bj!S2[9!ZVP'M9'5_J`QWU+)Dh7I[\74qT2j+*2l/78:Lb>9k4;`pb^!,*1]+i^b,/"tD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4RYJu^>DlOD*6S:4>5EnIDCiW$uk5["5N[p!&sm4^l?);E8rSRh"]%m2uYSJNP>nZ4+DCq2sL42I@5NP.]F?D<I3LL[A0.XIIAYb)W+P@hC#_+R@/Kl.]F?D<I3LL[A0.XIIAYb)W+P@hC#_+R@/Kl.]F?D<I3LL[A0.XIIAYb)W+P@hC#_+R@/Kl.]F?D<I3LL[A0.XIIAYb)W+P@hC#_+R@/Kl.]F?D<I3LL[A0.XIIAYb)W+P@hC#]7`QV:oW@c?\lC;T2V2]COdZWlH[=t#SSQ"pN[.2C1>#Lof[P5%gF/jYQ2SRj89<,>J(1q`4::6/2`]"iN8Tg?Q_T]1.WV03Cpgta&WQnCGR+^"MeNQSEhe])7eQHVp1V5]Gg.,l;RuOeN3_O<uAln.pq^?</Z]UPQB;mK,m-:*U+/Os82U[cR/@C2"?(Fp]j6J1;F(6\,k*Zn]Rad@F2`IW)AY(p0Y=\-&GB77D?fmairL25rHoF!]nn"CQdB?./aEM]8.UV>+'E+BLNdNcEVXe;i3RP$%mDsKm@k(jJR1oOfe;eo82l?.WSiP3%8aXTCF(6\,k*Zn]Rad@F2`IW)AY(morkEmYot@DJjn#L]gNe59mc3'j^2HC'b3)cC\+BIQh8d"^IG]e-Q-ZMfDWg]+]8pmFqn<N9/"]nVh9P>5G9>^kpO*uQ=$Eg6]:IRJmQSA`me\o,Y'aRKFuunrh0j\Jh=kb7?2;.um<2gn]DMBs]C4KN](1-sg[2YfGPCXpGMfm'FQN+o\(c1Vn*]5jn%N^-l,r0hDn#?7hJLcP6!rcB2`JI/^Lm3;l:\Y34S.^TGOa;/SmQmP\!^mch"WN$Rb@;50B"h\baTR/`EtEJIe>#BAtF9hj1G)%B$[ZpK\O^,Df0q=J'I?UeX(6EH03A2n)CO=4hph+DDTVO\a`u'27)II?c$[BR5[(=Mn`ltr9?qbbrkU[`cn]Bb\tDn[ATgh_uqm2NGlQ/0;Y,U">dfPDnc-&V4,=*1V\of^AKX\R`#=b^Q!0Gr%Fn8_uqm2NGlQ/0;Y,U">dfPDnc-&V4,=*1V\of^AKX\R`#=b^Q!0Gr%Fn8_uqm2NGlQ/0;Y,-.D:`8P^-25mE:I'Hs9-=k"U!+0/NUuD';?92q?HmbkTAjKbS+T<*/rPj"K:*;NuH*?1#go^O06V;<CSq[4a?8nnfO=R5`[H^<HAq[tPN-hGdSR1?1%F(/gBB;dJe6N5'aE85\MDFgWkYrb?8tQ[.^pk=_($qeI+^nmt#BSEe7`.WtI:1j8!(I(hVkPqQ/&m&t-ib*VpOF/g`tWmo^/e(Bp=oD.NJ=2%Y5ZbNBB.pqH1c)IjnWD[AY9k.8=bibHo?27BpcMj9PY'cY`2lF7XV+R<W22to;17rJ[Flc8]3r<\2]CKMshjiuSQR[.OfD'YmpbL1.=jd#IdUXS0P6t[ZR5ZW7hc6+]jD.ZPb<5B.7H;!PPDsra.X[XshQ1C<=)"t&Y=XF$o?<[=NUJ>k2Y&`)n7A2:Z_HtqV9)3@-5F8=1N-;N^8j*DaOd6)Q[.`<MT0k*-6)cL<;85p]NNYWY0pi*?]th(k*\.Y)W+P`CufA0YqP^m<5,]]c24;_p:WODo?:1JZc^PiUjDaJ4#?KP<5,]]c24;_p:WODo?:1JZc^PiUjDaJ4#?KP<5,]]c24;_p:WODo?:1JZc^PiUjDaJ4#?KP<5,]]c24;_p:WODo?:1JZc^PiUjDaJ4#?KP<5,]]c24;_p:WODo?:1JZc^PiUjDaJ40oCXXMU;aF`SebNYK4OWA^!I$=DrFc&I*4;YW#Fg/-'EI$mnl2tH?,iQIa+6TM4:APV(:aL<CJ06=-&jfH=c3H]Bfhi8Dbbc*LbZO1(%eBNu#4&Yi/VqOtm.X[X_2`L<p8E%a^C-t"^n7>ANgrQrLKeIMI%HX\.QT920,N"Lq^<EQ7Pd:^(k1%Y8)V[f2=6HoIGMTp%\+/:B)V\(Dqp$\JFn9Y1`cl'1CdZ>240*VXc-(AOhjpaO%4/@LXQ!ME0B[2"GG`A<Pg$kJMKdmhS@A%ER2XgV1Af?HhKAF1hSsbPC2?8ZloV7mf?MKa)rI3cYmi"cn#YMS2_X?2I!;I-2O)G"Z\it_]UZJ$h3f29:bqpn.c,=>Eo+f[B6s<K9VK]-:$6Fn]kd&]2pL]Ng6%FOml-fP:%b["45Vm$6Y]+Tb.QVRr\i<=k3dWGbRUTmq'bi`e+q`tn!^l[9f"l,G3#FBqb?6l;nZu7c8X#7OP5hX1@I/m^J4C(\NA\*ZU8It50COqFT+2K]B8O/e'&<$*Vh,TIae,I<:?9fo1_#&Uitgobkk,tDc=>bm`mc9m#]q`O#$/_S\InlY.6XO1]m^XzzzzzzzzzzzzDZ'feLL1)~>endstream
endobj
5 0 obj
<<
/Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.969a0a278dab8164403e924542d002c7 4 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/Contents 20 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
7 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3730 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M_/\Be$q&G0^ZfP<ejT+dJ>D]&P!ICnq2'o`LkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkCLkpkC#aKo*\@Q^OSZ$ER1V!=bkN^34G+uR=bi%p$SuXBnfno!;15!4-HEODUB.'_6aUIUOlaaTISXl]s-Sr:0Y35)mF`sLjS]p$[]:Q&Rf@c#GFu"]^ms;.>>\>FagW9ll^?`>@Eh/c"DC76Mql],Ib&qm%\t.&!Z&R?j^GbOE'AIa`o5!sc1U2qk1;>a94ql[q/b<cLmPD,-f.t*!mlhE>GV/N&oBnE>NRor#2X`gCgNY=AC\-sMZ&R?j^GbOE'AIa`o5!scUY@ukb,dZtkV<g_bkpUm,[?a[B*hjU6C2s>?'BplZgKB<b=q+Tn"XZ]E+RUk-$5O]?06QW9bOVQ]!I&B1SN")O02'kQ!&<sct+PGRJ5)d8[pPAc4[_4KJ)j[\g@_bB&-TVQ^Q33hFH0CiQA5`9B\,E]$1'8RNu.+F_;"dAjVi0+'k(`0!gIOhRhW_kVDV%CQd%UG&bcRfD?"_k'_>G'"Z:>Y'KJ^^S/i`O02&@QeB>8mp5B@FIDmN2+d!e]=@":lhuPjo00`4$!h-Zf=Z=@hp>rk8(T#[bO"5WpTF60]$1'8RO!!C?!R!XomT8pGop=UKJ'ThCYl\[Ds/tFUMH%>ATi(<He8-(?06QW9bP%]4ko1gb*@5o?'BpoF3cajVK-8)8(T#[bM9F`SuGt_pX(iikVDmKULu&Xk'_>G'"Z:MgZY'JQ$FHWPCtQ0cSg*HEb4)tf-I'5gp<!3WEbkcd5=MZ1A>U[B.@!FI<80r]$*=lkaBSYGop=UKJ%>l2L;6@A_q'/)nO7;hq=!\oBK#nX>@*jfCqu2S6'?4At=cq\@uUMkI`hh1[@_N_t?/+4m1@`Qs"'2)m8XtkW,il`6:7UgMhSe7*g.$->(hsfS8^=-@3t<1GQ5]`&:lX1XU8MSV`bW-FVn0Sr''1l:fF'1U.D@pIt4L=(buSS\"9g$Sq1hZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmh8e>q4YlKEZP/nmNTnOXoArC<7fK\![JXSJCAH$seFJqpW9#[j:s32]TpEGE67m[iKNeA\pj;0WLN'q"ON]k7-=$$-j4_68?%QVTfe_T5G9>H1FmfqgF3gEaf=Upi[]b%E+IRTM9Xrs8a0g?O]*-72ZY./JmQRf@leWpYk+4^LY'9V[D.!#i5r/3$R;fjOO)+X(G6sGCB?u7sh0iP_f=ah=bWU;">jq+@g:lu\Jn4<&1Z<Y(+4=]G/_kcL2orVBZar&"RJ5CdoA,aTK=n6HX)#V<H(TLJhgJ'TaLf$i\i*f]pY"0ih3W59]W4,pCVuE_T7&l[I7ZB=]=P>[2I)[Eg"5iOQZRkmX#m@t_j,M>I6HJ98N4`&]!Jt+>ab?>fCRgbFG%6,40*/7Q$K!M4l:ZZ2orVBZar&"RJ5CdoA,aTK=n6HX)#V<GotiXFRPAlY+&^0HTFs0O/o=]IGLc@h<[2Wds7[9>[:@slSb$oB%P_-c4fU*lDeT+\#EUk]?^+lSnK3I=&o./:$&t>Fge4>7/OL*WnQ'A.bDqJZTXj,g;h`De\5p"\ScS]mHHa\5-D&gp2ukIFgLCM:ZmT.EHP9hYM3$ZRpBZR3`!,DX/i7Kh555KloNnMH(o^X)nIACmca(3]&?8XH^EO#&*`Ae%A$K1Y#MuVaj'^EY$Tl@3>LLFV0eQa]FX8l[1/^+&[#*EGKJ,,OKMpEi&MP28u6m$gq40^lEq(m;\?03\p)9@qiIsegYb(,iC]qnQe]4al0>YcSl66(<4[:qc23U*?JFBu(#_c]H^EO#&*`Ae%A$K1Y#MuVaj'_TgceTc9^P6Z<$X7[40]52>oU?qkq_QOd\S.Uak;Mf\EMYnm7<RH2j#^-a\9uTCr8]nL2KMmbdrXQWCUWAG%)CC\i+XldUh!(Ue=-3PHtqWE7)(egQ=+pDB`@9P*qi2fS5<e%Gd%dR<92-;N]2am)1eeFD^5bUs#j/8=,3E->+^7iM(*T[j,0jh*ehR,VqGBYmhLT)nI'S1@$:8V';>LfnjRahf+!d4Yr:$&RTWeXR:GdAL=B#^?E:5h=n"o9N"<,d=&:2moc!FUl+rAqdO^*ZS"%*(%F`e`Tk0M?"T6Lif!5_eU>cTbTp3,(Yon.qjqqu8ZIS"\h@+Y4mOke<"WJZ?``[Ben$2-iqLN\dhA/$Fk1]AleV0Wqc%F.%l1?SXQsKM]B>[XWS0lbA7!kjf?LIBcSt;k[?3Yo]WSTDRpGKSDr.C,,CPZ!?"[G%]A>^.]MI'IqB5C@cFRn:]mIJ=T;mnC60<<\FkuD1pO)Qr<?(1Tbj.=U]%QcEq<!+*2UVhuf6,YeZg6H=c21IWU^o5al`BDaf=U48pR0Z'cYk%&p7KrJ@TU-Z6[*V-oT`aPf4ADm\o0r[F5?JR?CTPX@TU-Z6[*V-oT`aPf4ADm\o0r[F5?JR?CTPX@TU-Z6[*V-oT`aPf4ADm\o0r[F5?JR?CTPX@TU-Z6[*V-oT`aPf4ADm\o0r[F5?JR?CTPX@TU-Z6[*V-oT`aPf1":I0ekIU7CY+bk+,&p1GLU?8O^-E]B5YTf/#-91J($F1:u\>8CoXP0f)Bi\2(\YSOh?g0ekIU7CY+bk+,&p1GLU?8O^-E]B5YTf/#-91J($F1:u\>8CoXP0f)Bi\2(\YSOh?g0ekIU7CY+bk+,&p1GLU?8O^-E]B5YTf/',Dm$``@G,6D((A8nW\TUBd\gAVh?)\+8KmcKnXrWY2Y),\]="8f<@3<p_CIdHeCEeqpQ&6\gfS=S1g(?@2RYYKtV'<trp*!_PG!sWe-6ej`W<fe`I7RGB*Kd\2M+D5[.Y;JF+4?Ei8*$ae,*LWEMBH-ULNMY3&NT0GLh(\*,01Pn+^MX%7*`@j,+2`9#dT/486;r7\MCd7meJJ,V0f[!dK\C.mTj+1f?HJ9-)l"Tp-dUWqpiB\bNugNkIW")mbOI*)e?^pGBK<Z2tq]dUscs2'5<*c=8/jMZg6bFmugY]GC(NNOT"J$eR`p[h"+g79)!4!U^aV:h7L8BY+'dP92b$2m>829p8`OAQe?M&cZ_r1h7Gh42TU>in*2[?DXR<Q8YpdC-di4PYO5\%B%P9jh^,7Dn+JTC%?fCe<l^K*B,a!.m##=sS^h_VlIeX&'>#HV?"\:bWHu##e&8C[B%L0+=/qj/oJEg'P1atYa-EZ;)a-p^MI^n$eT%GNfg\aN]-<YKB6@IYHFD5M`3)XCf3'+qWh+)"1pJQofl^?9Q)\I94\b:#A9ONoEM_sR7Si3M-?@@(hQ>OFjh.acpE<i8jI2FJ>IVr$H!NAt6b;R)2(s6aDP*3c\o-A[FOcRj?Li!i4tGf=h7O9_W[HE2jP@Cq<mL$BGotI7:Teub]64"PSC_oT5,>6N>k=,&lh4IAYNt>!867sbjsBKImB^h>f?O2SY'P-59AZf*BB?e/S+e(3p#MR.]N_kkb'@8O7moa56psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psF26psEGnK3us@Di~>endstream
endobj
8 0 obj
<<
/Contents 21 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.f6e745526a61cd8416256ca62679b160 7 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
9 0 obj
<<
/Contents 22 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
10 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3461 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M5n_s,&44e"s3f#4<j$Hd!m(E/-.0*upFcLHzzzzzzzzzzzzE;=RG<*-'*MpC^#6b;aX;I--E/ipJ*%I(UQ96HL\]BJ$F2Pg460@a(fm%SP_foYY!]Mqt3Z]!,rA4*rso28kjc7V/eP7?cjcV&DG3kOV2:,\pF4tkGdlKk6d45#_`qn,m0WO%N.m:8Sqn+0F_V9U\S\!%8ZD((geFuEndZd3)"W@rGbCs$4!T>`]d?gQe*Pf:j1Mf#9(fYt0GMj\u/gIQatMe>s(1]&`3OnrN'c_`7*p/u2Vou/PT9j,^,Ze.b4Md8H7ZC'<XZ&R6L]6H5F0sf28)lYK6nSH?WAfoq('rfEkH(T$Cbj9[XBk*:/8OY,8Dr0ZH4#?cj<SCR9CJp;;m$mbFk0D2bGEk'%q3k9Y1Ag3^^:?&+mp2cL7D:)`WQ`)%T5X/Am!DfJA!*rd74PW^hWL@i1]-$/g0!EO;N],gS+la@cHO"HPr9ERRT-(<qrW=@\MLS\?)<NL^*XSobeA@pDskj9HWOokOfq>F.^O'MkF4Ohqqb?,=QF6qiQIaSReL+VDtl*Fa4I-(QT6?Ln%7H6n7B=pY=XF$F%U3(GJ1cMbBtC=P6t[ZPgmA7H@Ni!q*)M>'u%m@WHmCore<)tI=+a=I$mo2o=jPh%:A8ppmP1W18gr1IFn?8^<H?A26$(V:.`_-Y4jl&RIB0O;W5fhP+),Nmr.tVhoF?E_O!8/2=J06hsb3kO0;-o@V3U=]Y;VanMR:JbcFp:f9c:s^*XSQR2(YOqD-sKf;)k1ZXRo\?fq7\RT(hM<\2P^bBtC=PD[?'MT'jhRIB0O;R)TlYrJp?o6l!\.Mafj(?b@%^5oHh`F<Guik3"Lp[L,?=NmjKSCa,'5)X:Q[]enb2e=_McXIhck3'(.c?W>(1]&`3Tk&U9X6?'4AMLO;@N.r%kHg&kGuGJ7q^f1LA:?_CkaXSC0sf28)bT8UZ\m%R;\h1d/@M6_IQjgrS2Y"6Zd3)"9'5<CMU$KG(,Ph=[\75\5-*n;2e=_McXIhck3'(.c?W>(1]*^>b$$4b/tQA@4R[^HI@mF]]6JMHo=XfhpO/Vgn)E"hch$!@h=l3;]SgD=4jSJIFPl71o.HV?oK;SjdX@acbe&+CdIY$F8b[Y)1@O5U7F1S^-f+NBb.NXF(Hp)kT6/uR.J#0`?1^8JIF<P9Vp)btG1#oo=NC+92uYSJNP>m@j"CMipr`Xrr\D9K^C5)A0*C#)b5aL#1AlXJ?_-a^qS$TLB&C3mWl91IT'qls;.jLu]1T*BGEncgPM/lHB&C3mWl91IT'qls;.jLu]1T*BGEncgPM/lHB&C3mWl91IT'qls;.jLu]1T*BGEncgPM/lHB&C3mWl91IT'qls;.jLu]1T*BGEncgPM/lHB&C3mWl91IT'qls;.jLu]1T*BGEncgPM2/fXD_E6B349YHfs51pA)9lSb:7.kj7TiI.+`&ffibEWO'<a'qJX$S*unl458ra.Ws<$YG/A(F7[*:DJ/io?)>jCk#HMHF`+p;hX,-OYH-/Uhn4ilY0P;dcF]Y7o6$<Zl^Lu'g"!Y/hKcT:ID2j^B79A$3kIF3h`L:M[a3Q*lE"o17;#]bk'Q:IcM%(F8tGY"X6Ap8gjJS'gY(sT\'TE,nnr(ihaI8$gTRp!cC:)C4&br%_CseqPmqonXM!;Uau9o]q=^k*Yk)Jgh9K!6M=A]t?Y+k\2_4??VXdH7?bZIg)sk4?H+,SpD^,,Mm8qtKkKV/]SZ-uMiKnJtap'qG<o34;jdQOjI/?o%fQjgoDJ(HV7/5luYHl!iS!A1Z;u%cWYPWL-9(i+"8nq\i]8MoV3d^;ml;COOqVGMRFOf&ck?""5Rb.<%,,M?cSia]uPgm@[G8D]6FnXVdeYT)(ot@t.l)M)QcEAiH26ZK)77pXP4a2?t.B.T@mk.MLlKl(QX%Q%/l[*i<dT'r+SR5YpC0of0Mj1A*Hg^gs;H!,_hYe@"ccXN$^;=qMqbf#[Mc5"-:i>uT3N5u9n)>&=(6k;:?VW*$ik%1h[ftl*hj9O![J2@LnSLS&g%XU(;D#V@;g_eGDYAK=WDnfEiY:8cPad).:+FfR]/[d="m'@RQ]k%Lpb#>3D*b_cpZ82K/\[-AHs9Ebp3es#</^5)DOk.[WGfD(Y:K82r,PP\gHBpiTjQuLF6_NJiTgjL3kq1`hf]N;=6S93jdc1UHhb0=^WnLqe@48Of+n.)IQ==?m2j!Ed'*&a3V@7`n9'G6SR9[ADnCe./+i0*E__&;4a^Ne8oN`PA_pBfpLV>th\K+SGuJ#)QPmPc>=_WR9m(ScB)M4:+[qeXe^])9n]SCq'P6-#=8-:G0AdOCP^-25h3T"oHs9-=k"Tu@?Y96,D';?92q?H,RISJ0KbS+T<*/g*`\63b;NuH*?/:hb^D<=2Aa]K]I&U"V^Lj`$?fpO@;dK2sV9XP7@TU:fcSqc5ntesLrL1^.I$pUF:3GYkPree"Md?-65Mr!rb*OT#p1kGUnn!9a3RsBJ<U/r&/9^-ur-WRc.po=+frnQFb*Vr"k#>Er<2m32Ze1NroCL5+Y'd3HB>8&`.pqH%Ro<Vg;PhZfNNZuK0=,SkYBACkDC=<G'u%o+M8%P@kI[:4)cZSfq^2/C=.Sf'nnh4^bNt_^CL)(sgW?ojKeKcNU9A^iq/.S;"r4kr^59ST<TgubHlH&[1A`Ep>$%9`G4KKHiQLSWk\FIH^>$c=6%ptuDkaFXebO)1hZah0beAqJelCnFSU;AUUb_hm.Q;i/o6l!*oPJ%,XE*pa1>g-]6/NFncRLl'/b=C<)t[uUnZ6d&f.u7([mAme(=+HhIkC8?HlM]p@I^F>o@GbTa1"@l()G4G2h*FNI=*"+D.2t9Eq@m<hoE2lh\I!R.Q;i/o6l!*oPJ%,XE*pa1>g-]6/NHBZ\m7#^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.B(hZah0b_jn<^73Gke+.CS`ATcl]'#RI\URqX`ATcds*QUcpWr03fLG&tT5UUircro-gZ[Glo?Hp_5HiCB)kG`5^6tSikOhtoUN?=Y2q)jJ]KV6jFDh-SApWm;f4V@JcL!jR9[E\/qCK)&\c(]\l+):MT>`]L\,Uh34nm:gUO4#O;Y0and()GRhQKN<a<rjKD[W*T<9F.Je;eoSoD5oB\Nsf`Y=\-&-T/)G$_859k5CauNdOarqR4b]6"SoV8aXSH26Up+SJtPjrL25rHrBS4[a;QNA_sU^mDpY4YAXf>)cYtuRad@F;Y0and()GRhQKN<a<rjKD[W*T<9=>azzzzzzzzzzzz!'^D_bZ%t[~>endstream
endobj
11 0 obj
<<
/Contents 23 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.e28945bebb594f11c83bbac90aba8c31 10 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
12 0 obj
<<
/Contents 24 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
13 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3621 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0s^+9$q&Fqs/,gl02gI,?@ebho'Q]Jl/07UWiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiDfkGE/^Sf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543?FKH_.8gf@`Q543<T:L6DAacFP95js7CoqI1,a\g1nM,du\.@M@)!,\H0a[c.'l'@468B'(AIiVI!scakB6js7CoqI1,a\g1nM,du\.@M@)!,\H0a[c.'l'@468B'(AIiVI!scakB6js7CoqI1,a\g1nME8+I(13<%Nhn1a$pTDq6,-FLk.l0-Qo?B?QF71Sq,iY7l\2&-s52X"/1\\'#7O#!,Ke"r<n+4dc1NW"7D'\,0<4F])o02'E1Ged.dRGF`8VJZN2t-@_4#:sH.W$HjRT-dPF7VTQ]JDA<Y0oc`Y"=<t1H4dobr[_&mj`0"igNiV13<%Nhn1a$pTDq6,-FLk.l0-Qo?B?QF71Sq,iY7lE1(!:o7#<g2n7*+E(qglbV$&D^[(h;>ipCC-5Bct(Y?=Wp&5CQo0$?B$8/ZCCYnN+rs"hc*j/'<QeB>8mruHpK?JWQf;+#Am,FK.]AC<=A\Nq8;ScpfER"Adn)*%Yhnq=Ni%hpSk5DIWDfD-5iL3_bR9a(hIb4HU\BO\d9e*Zs0!9K7lhqc-k'OTb'oA=nM=YbUn)9^7,\C(&cHBe5LMKeMQs#P20:2JUY";&kAjt^l>ipCC-5DB*'oDO&RIB+'<$Z'V,gOSE^5$K%OdK:63%pWo*j/('@V/'g]NjTG\0_rIR2(SMEgcCTRT(PE<[>u6A\KOs%;u'#Sb'E<B'(AITk&U9X4TG994DL.@N.r%kHg&:o=?2Zjs7C/A:?_CfK$-.@V/AE)bT8UZ\k=F\g1nM,dsCWIQjgb3Nl(bAkleS9'5<CMOj@M,\H0a[\75\5-*<rY=i>::1>/7k3'(.Sb'E<B'(AITk&U9X4TG994DMYgfLq<12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kJ]j6h8c12l1*7*kI*\o,9?f"\;Df"\;Df"\;Df"\;Df"\;Df"\;Df"\;Df"\;Df"\<Cp\`Pjh^%qZF.'R_PuNV/.Qu\Lg<n3igq-1Y`-7K<mr@`.B4gR;,urs:9$d7AG-j%]pTBZ/nQi!SHX&YdR@/D'8X9(RddoW)*UV(p]rRr$HroS.*nQEqB'.rM;C0&XoR)^87lrMJmjb:Lhc5!:a0h\5RCRO,</L&n4l>;RdE]tk]1T*AGEnbLc."ZGm"e<RSTWoRXhW`Gk*nHl;K6>T\9[DDGII>0Njr'D=Vku4qWj\h^:>I@'mJ5_S%&BCB:Ei-LeG^XFlDJb^Y[Z+RlfV-EG&ReH0_YX[e]'G\5_6d(N/++l^_n,\K`^AGLhJ;\,L\dRr@_N9?!HEiT@8WhV%%\45s.XB3i#mlZ;O]qHH$/Ei%K8ZdQjs;0Kn23KYiBcC:(WIZ:WXcH_8OWHR."[..pr*H?6tj@ZiOAu1JoU[3fCF!=\cSMr'9r#0-:S=L>(;XM,"C#den46#UsaH^N'bt8qi7bJAdk<uIP4)\0Rpbg3S3'/L.V:p4$d`/IfG/W&oOXnu-S!>lE\XNG6UN8LphGmJ@4M14IHaoZ4ZeUS*GEl,hcgJIA*j0/;/@Qkc>p\%HZTE*>L[/)'bO%iG=%Tgkm*;*hiHePME][1U<Dr3H]CY03\=Stlgl@VCPuKikm_&?:Y%QiI[j1!?-.U;I4)_iglWH6km7;M(8[\0VcC=:]H</=34&Xp8;XHTYoB(D0Ss?Y;Ng+aQ<'/Fo]_U0hRT//*.%->Y'\l*6G@jY0C3"'YZ]r[+)[^I,`B1E(E&BY`bumYNV%!SeOlDqb;n/9dg?'q4ZdOS[Rn3(plmZ16:2P'<P$)Kd_+g_MBD*%B-E":49?F9BU#77q]JFmA=-HS;S>Basg/)`%.GgIUKr`=pD9c$7.r?]EM%oF&T#0%=e2CqgR?]ZEgdI$DAl%B#Eb_)MPfu`=$>q',40t93l`5*_bh8Da2V@gYE&Vi]VQ()KrX7N+S=QWoK:W#DG;ElEWnLkD^VJ[LfpSiuf_I1>2fj/>WXX.N$f'!sSZ-@VSc8b81M:@#g0j*Y^tm5fRAr0tq(H\GF*=G78_NQ-gq8J&/+4sePah.#2X&$&Rs;:1Y*)Dfq&XF+0&4*r2_4>HWK`n@iATo:c'rsanue-J\bR:aK.brlM)QsR.]JZ%n)61g_TeQpZgt8^9"Fa=DM'Rs]SSQtmjb<$S+#;okebT6GdHtDP"N:\*c?T_gq8J&/+4sePah.#2X&$&Rs;:1Y*)Dfq4>O->a^k$GP6E&U7Dq/Eb2uZ:#;@QVo5`CRI>QfpEnTCYq&o<Hf*ntM0;MXb*DeZ2gK>9SJ&PTA\Rn5hOA2V`3*@5msUDo-JBoR.p(k[hrMJ-G"V,DQ208qH#KFJ'"`0q^@t@YRqO1PB*FWiRqV!0gtDND[j)'CR@@mQc.q"K*4I-rQ^O=VkKVf8qAcsh"dbXHB]mXqg%l\t,6aF%RqV!0gtDND[j)'CR@@mQc.q"K*4I-rQ^O=VkKVf8qAcsh"dbXHB]mXqg%l\t,6aF%RqV!0gtDND[j)'CR@@mQc.q"K*4I/H/+[u@c*aft?=b>Bh0TdDi&]&hZ#a5_,3@X-'"?d[bI+Tr?=b>Bh0TdDi&]&hZ#a5_,3@X-'"?d[bI+Tr?=b>Bh0TdDi&]&hZ#a5_,3@X-'"?d[bI+Tr?=b>Bh0TdDi&]&hZ#a5_,3@X-'"?d[bI+Tr?=b>Bh0TdDi&]&hZ#a5_,3@X-'"=O(9l,HWFN$+_O4)&'[O9tGf*4b0MJMc(V2`$&:VM1Z%?AjOfAo(e)fsc*I.pqd*2P0gaa971k-dGKm_(M<8lo8]pF'n&D0tj0HYm_dY.,hI;;.Dlp>ij[g>FAbED>;bZn]&Wa`m3]_,7f'R_2.)@rC%bn(qi4UNFI4H&pCngpSTf^"3HYl&'9IT#<OObhmi&F)>mbEg^]8if:NeP&#\sQciW4&pM9BP?]'^]3OKeP.2b)S)i;]hW6NEPf+S^h^$eXpF_fCVBkScq^/j3\9GL-2'm64gc*?__7e$'Xso2hikA!e%IRLSF%o6]&bf"?D/eraR;5FSNjs"jCP-u#b?Ru1mI-jpS(JIBR;;BF-sP=qR5_B$/i2,?Y>Ma4P;7&c='T@?a^:fZ@4,XC`3-Vo>a)olftpM,]STp6RCOYoNO"8/P^*qSi\GRLrYf>U4"9bJG/\%TRf#%c(3WU<:$db\bVf33PV)6tba[6"Q^MX[f-jkU8XVNB.kWX0A5uW0<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!EW-4.C'pL~>endstream
endobj
14 0 obj
<<
/Contents 25 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.3d82fbc7fb155441d517c93ed9ec525d 13 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
15 0 obj
<<
/Contents 26 0 R /MediaBox [ 0 0 612 792 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
16 0 obj
<<
/PageMode /UseNone /Pages 18 0 R /Type /Catalog
>>
endobj
17 0 obj
<<
/Author (anonymous) /CreationDate (D:20251216142815+00'00') /Creator (anonymous) /Keywords () /ModDate (D:20251216142815+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
18 0 obj
<<
/Count 8 /Kids [ 5 0 R 6 0 R 8 0 R 9 0 R 11 0 R 12 0 R 14 0 R 15 0 R ] /Type /Pages
>>
endobj
19 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 261
>>
stream
GarW495=S`'SZ;W'k^[])"5]poB8qH=%/@qU>)&lKpEPq`^ToUj7jAr2hAmFc3IcS3]u1M!)nO?K#&(3$W`[Iq8D'E927i,D^h:d1ndTQ!o?uOgOi!M5;;R#n;G^&c9s)+r7(.`dIamA_=.6`V?\;0&JO?e+g!YX&8_+8XHlF=W/Ia'Xk$Qrk@3aA0PQh(F/A?*p4>/mR.MH!>TZ1)N#/`,?ZD:[7;^/hZ>/d(i^,*:I4^^bZ6b[:`%6eRJG9?mY#W4~>endstream
endobj
20 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 170
>>
stream
GarWp5mr90&-_"(^Z$9?6d9G5GL7PscscphYcOP./#`K?e<CYVG]S-!4U-ndo=#d^"Qqk!%AX+SVZcQY+jo#mgm_ZobJ9C)NY.>i9A^4+L=D=F(B57X3>:A[Gj.'WC58euaPELhe*k>#kjh012B&[7,F!'.Fi#)NkQ>n`2Yd~>endstream
endobj
21 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 242
>>
stream
GarW44U]+\&;KrWMK`$TRZ#Ejh%W'h#K7+SBoIXGUUC)N@r5(2Nk9o[Sql>31)AEh'u8=l^EAVi3IoO'Kiqi%7%;@\=.b]qJX4AdRf].g4aIOJ0IN7E2uH2"iZoh[jaDCb(OO.Q\4>L2't0AZX'_QXW`mKcn@qdY_Po+mf_[DIA3%@^p+P5rOHsf;mM@n1YBPg%,*^&!jN2t$Q>3PS1:d?;-!$J*A]<=N-^O:%Yn7OC#!>ZE~>endstream
endobj
22 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 167
>>
stream
GarW05mkI_&4Q=V`F#VQSZ,K\70UM]Mn-VGWC30XdbspQV83pXpp557*eT4-nNT1`#^08Rf8pba[K^cm7B44=jRnT)'K?Y!_o-'Xd$KGh6f*pL>lGBg3YUISI%0sL[)4K&0mV"rL1P41m3aEpO(O<Vc0Dlh-D:2:fWR1#~>endstream
endobj
23 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 262
>>
stream
GarW4bA+pK&4Q?iMRuQnE&;l#G'=F5<i)ToMf'h0Bh5HsNV`ZtS4DsU`6?#NEt=)Bqa\Qt%BqQhD$_Iq%Nq#cQoDYrG0fuGMnbKo"e&rWO(kiNfrkChKK6k2NT$;R4&2:j^[W8tSl$l)65/&U0l<?jnk)ku9ZPMRnim&[l+^EodQsF:`OoA=e=DZtn;OAr-`M2OWqp>'q3C45Kp)<'Bl(2:?1Sq>(.;"Lm=KDj<!OUS8E['-\TP@MP40+;#6Xi,0^;^6~>endstream
endobj
24 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 167
>>
stream
GarW0YmS?5&-_rY`KY,2[kYm/Lm<SM2O6iq`P>d;U4n)8L^>CNbM-K67PO4$pIc#YA[N="7;k`*bg6HG-3H1I:Oc@?^rETqVk2S`hAuD3XjG$hrY$;o0o!@8O*,PX[%Xbdo219TR[PYjYB"V@;M6R`QhNDP7g@'?7l*!B~>endstream
endobj
25 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 245
>>
stream
GarW4]*cD?&4QKpMHd)Lgt?4sg)58p(5c>K-G(3oLqu4Qh_c`/,/_X?Kl\)c+FR*G9`ZLXdk-+bF:O1[#^VPk(.0^d>^]N8"Y:8_eceNuo\pFCTl8;ADtoB8^e%/BH9Q'/leU)Ketm'gGAhG8d]3*X.^/,jZXEc>aFc1K9PN;qHF6sh^&:Uu&B+.aq>DL)I_A*B[q/R0b:Eqd>ihB1o8K'3Lb)J@(88&BB3;G3Vi%7"GQK1T:[J~>endstream
endobj
26 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 172
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CT3!/hd>6k,goQl7B?"*$l7Jjr"7HE)RNVF!h>6AQD_Ah8\RZl9o#.%!<n4-^Rok+rh0.sU3QjVR#*Q=T.@Tpg_1b8?ts3Bstq0s=Iu-oF$".&@bPK)uhhh*O"$~>endstream
endobj
xref
0 27
0000000000 65535 f
0000000061 00000 n
0000000102 00000 n
0000000209 00000 n
0000000321 00000 n
0000004077 00000 n
0000004335 00000 n
0000004530 00000 n
0000008451 00000 n
0000008709 00000 n
0000008904 00000 n
0000012557 00000 n
0000012817 00000 n
0000013013 00000 n
0000016826 00000 n
0000017086 00000 n
0000017282 00000 n
0000017352 00000 n
0000017614 00000 n
0000017720 00000 n
0000018072 00000 n
0000018333 00000 n
0000018666 00000 n
0000018924 00000 n
0000019277 00000 n
0000019535 00000 n
0000019871 00000 n
trailer
<<
/ID
[<11a4452bbe31319e89fba7a743537da0><11a4452bbe31319e89fba7a743537da0>]
% ReportLab generated PDF document -- digest (opensource)
/Info 17 0 R
/Root 16 0 R
/Size 27
>>
startxref
20134
%%EOF

View File

@@ -0,0 +1,181 @@
%PDF-1.3
%“Ś‹ž ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 4 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
5 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3461 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0bW:r$j4o4s3aL9.o/:sRKC1+V[Po_hnP="8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.EM=P;M`ictLh5:'u?=R'nd;IE]5Hh=BmqB2p^7X$0Q$9UiFPkD[m)hEDD7]3!20S(%m5Eepo,>73Ncpo[qg"0,Gt5J@p\hbEY.UOcVYbgK@oqO7DN/KYR@egT:O\Y"S^Nmne(=m!@M;\.mreAj`lssm2RjQmR*'f[]=0V/jtsN_^"C8&k'PptV(jd(Ymp-?-DiQUlg??aR5p7DE%a+(Q2+a1De[G>Bl&EKZ&,I(pUY]E@qJJG)r-?G9P(rih-1dREuNfk?>O(#o=aSKd[6HOfEV(Z'2t=fFn_3AbT-'E'3sZfj1^M@pYhQ7E1%B!q_i'CLMJZ]APP)MgR*7.Y/pg53RP?TA*/3L-50YH7,u"@RJ5[/9Q6C5NVbVGhM5l%_.?@umb=+S+0N]gQT<I'De%pX\0_kok!\7DNLBP"RS7[g'92lIB&8;Y13$pgHd09iRG2p8o0-ECM)-sFC\FmSgqH^TpYhQ7S=01ZZYsF;p79@=&(b@ObfogMI4I+_mo8Ft\0_l%B"lm`>FE$MV_[_Y246E[o=\bnb0967Q$FISai'U8mksuCAo?M*bkl?R-I0h_YM$B?F8J^DhM5l%EG"?[c+]I2gNP.=5$X;.1Gdp(p8uQo^/LHoiL3GZR2\raAeSG3ICLU;>is%i\_.+PGos32"IH[hA8X<AA_r2X1;RO>4IM[5E1-IZRS7[g)c,U.'3s[J\0_kok/NUqf`[Xe+0N]gQauWsDDo=BhM5l%_.@LHR@?oiRJ5[/9Q6C=:Zc7&>ipIE-50YH`fmsd"IFD+`\u,TrPk$]NL;edD'YO[I2buE1hPl,[ZP+_p2)p[e!QQPfLD$lgUH]`:1Im2@iJ!ODVrHt3K9FeNGTr/\U>Dmjtp]41q&NWk4WXSRF@Oke(@-QRG54@A56WH:1G57Ao?MGP<"Vj3K7l$RCR_b:ZaKGk$5CC.+u(L[aFc^qb6b_]O]p>fgaTjmPE\no9+M@B,b.F]?bTVcV*tKS8EA]mlo3K5;1^!EOO9f^ACUurOc[u`n<i5qsH8rp[aPr)eU*qn%6nfhp4shD4GHb^$e/6I6TC<[rJk(otL;sp\ha8ho=>=fDB;AhhFPj09^)KAJ38&9VV?L8MpH&M<8.ldJV05RX^_no.Ld9qHZg`b02a-m$D"%2.\6nf;,`[G2:]5WQ\V2c@4Gh=&YtOF%n^mA_13^REE`2l0OaBG;Wq]1Y8G/?Zt8UPc;l3PKnX1F]VM=136/NqdnAb9ps/J2<jIo?$A/;.Po\PZX7lf=5<1=SU;dP(A-q:-FpT?Fn1s1>L9Q0S)iGGeB)@_DF)%_Cm',a;^\2o]*8-oZUsS%9V$PXmM>H\bU0m00m3&T\6I=`1RmI^`mi+Cibh&sc>8Yj)cJ,VM7Wri3jVEGD+pLJ-LMZAlc^]d[kW$rRCHJJs-pTpHZ/#)PI^.2/_/Gu9ldRQT$2WWCT5#pBp+rKo47:$?VC&L8X%rrR4!(5rE?5)8Xe^PcTIWmmak?b:!t:GHfiH*GJBI/CQ^$TfeZFd^AG<;?^!=gc(929pYE$LqO43ODYD;<\aOu!e^l'@EjKDMb^K5$WP0]nZLJ^%HY#u61\3[enc_V2NHb$M)gp)%RGYQ;01^D,]VFZHi02I1r6C:L6.0i7*Bj-$T6+]-GAcILP+EW]kd`YIUbagAF!G%Ro\=[]cb7.BSXK;E)u5)]kJfT0mL;AEbfoP2a;6*b2r;r'Dt$>2Aq&o4^*)[NnW'2fK24Nao/eo%"\I%"GP'Z0I+"FNhmnk&i,4+8D*45U9lOt5(Y:H%gNYJ4S)E#I0<Sr*[ddmG2Slep?X1q4Cu`XmCk?Fi^UTlGfuB5df`]o]IW7MlZ]->RZO*cDrSi.cAfFP.AeSDgqSi-Obr20;bpKqYoS`%'Rr(9URn[j=kSMi,2qrR42k/aZcu)c8-TRTajWn-2h:0V>:?H.K8QTXcol?4Z\QM\UQ.esGSE+3uQBQEeG#L%A3LQAu,[ID*eB:EYk%6VF=)'\eEfuWs=\dD1g.f8NjCE.oPB<XE;_KLYR@E:`?)cZ0b=PIkAiWFaqb5fI-eXjPMG'4JbhVF=>A92cbB:e#8i1-tFRQ=g8G;/Vi_h'@1H2o><Z37\Ea<[a&ri:uh0UX]P'smD\5\=)b`2&(Pm5@E>ZY116t>@KpYJMpA7)Ji/leW#F/+)#V*VC?f+jW%d?qJl]slE4fpD#^99j27h!!U!Boq])FiC1L1hLXTfG0bKqW+XE:1[0q:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9@iJ\8WL&g=b[jOE:;4>9j"6dh3D"AU^/LHoRCY]P]2P,]<+kV\Q$K"$)s"^pPrVEYk.Xc^pR/TYm^lDcP>l2_4-b)`W>jp44-_ftFlpD:RJ3,\612?`R?LT_mQ6\ZT;`dj^,qT?8Tj10;jmBJ\j>br;jihKBC7jHH(V&TjM!^@3D"AU^/LHoRCY]P]2P,]<+kV\Q$K"$)s"`VbpKshhJ;heIJ#,$L#d]nmrG`@m^r4^I;<3g8o>f_?gbP]CkDQP]k60U=20o&8FDiA/iT9X^3d':\+\@Uj;*pUjhAp_-FiO$C\FlYoddS,jF4Z.EjH)?]D%bBCL@$4DBZPtm^q7jK)=uLB&D<D^QMelm[*f'2k/a>H`u,3p=6A-(6\RV^<=bJ\F89ip8rc9/%LApI_"ofZO-'3pR6MG?i<T7+h:tJ]8a.RlgO*ANA"r%CuY<'3^MfLff,D1riT#Cpi?)Q-Eb+a'/[FnIC"drn*1%805'0Yiqg8J60$/A2k.>VY"m@=Eq[a)Y.q"N1qoK.Z\e#:l3*)"BA[ObqR\dSisd?'T6oD_R;-aleNSse-CL'A2.`f0WDraO2OS)NhURji-Dsc/e(A2o3I+\)VOF#I[81:r8`o)>9poa:.b-_B9dZ9lG;Ws3af/8:1cCb4:>XNcW@"N@mF0]uOu[eh;l6"R9!qH)P=aot>tp`%E[oU'ND1afPBSlqWl_5>q`ONacB7HTe^^)FjdQ)cmKTR7qbD9Vk'+?_^P9A:.ET;&?(LdsY0!m+DK&4Rmo3A$I[=j@CUb=RP3b9\eX>=VRf")l#,`aD:3C^AGI]'8L:b8NahC\ZSbZQoafjZ@E([G)<**^]QYZ/-\/Us$loWbJRG[+pr#4u-V^2.7F`lhj\L&UoOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>j''C?8XL9P~>endstream
endobj
6 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3802 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0s\bV$q&G/J(%!dMEdPCi+mj":+lnVm=5/<WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!Wi@Pk5O39*E(tLG]=Iff*nLVJA9YDM]C4p&D/`3m8%Z>/INI)Ff49*4S%J.PEG]YhG"90TqgKU<#1mC0[%"\rkAb?X9m0%=\bggsf*9i;GI3jOn)n\-E(tLG]=Iff*nLVJA9YE8`&<k(gpb*Wakb1/R$fb8%41WA/9eF9?C-M:3>:.D17um52nS3pR@'BuYmi#Nq(-`rCL3?aR5kr8:bnZhE]:VmFd\Vb1U.B8oD'q]ZYNm6M4$@;gJBYtcZ1tVk&m)ZR5;)W-1gp`GI)'kQ\h+j'AH>=T?hO:]B47(R$fb8%41WA/9eF9?C-M:3S\hTaNT%`ls#mgH!Qj4iL3_VB"i'SXj#S5Y0?c^9e%nSh_k:3Ao:pVk'a`d'q(KYRXH\B2m4b'5$X;/bfk:U^6P+Uf9LV'Y";&ok.>6_b08,rb.J8:U`qVd?*eH\k2pethM5lEOdZ$Jfs`_Xo=?^G__nF7b^A%/>FE$I?((HGRT*g0^2*GEbhTk6bkl?R._*^*2DS2[>]!0Q26#Lh]@t>"V/Wgs&_Eh1bNrsg1R5i-`^F'q$8/ZcNQb?/<uVfm9e*ZsXu8%6.9p^``&4OP1:u8]9Vl^90bN$5K$3Lq,;YV%e](!^P6rqKX,Y>&$<J/[ED7pmbcWiZ;^ksg9Z/ffi%hpua@rFL[4r9FUr&DmY.GX@o.%8oqf#7Z>ab&l]9,+WK$1e;f;-9Kq6%=KRI_o<bkl?R.U8D1]"=(bYCas1&(dVoQ2.Sp)k$:I\BOhh9e'D9n%-,n3Nn%X]FWVi_Njr"],R10._*_"E(qfeRI@`!OZBUsbIeA;Ur&DmY.GX@o.%8oqf#7Z>ab&l]9,+WK$1gQ`&9B[J%dp!1M:0/cGVUr^Y&/&R@-&K1NOnOOnltfDpHSNR@'BuZ&Qs\p3^pnB$S?=S;D)nI^/(*1Ga)!B')d',P-gVhjg+&1GL[u@N1_Bm.oefbaaNX3>:/gr*mu2B4g:"bflL-7ckM6^,[u*B4>Ju`&9Bcf^m@UR5kp:F-LSfP;;UFZP/nmh8e@Go9=MJSt5(-mlp0RT;Tmpna&[,H1u=QrB+ZJM.\1scb#7Mn)l.k:-:VcH/<u)I6UMqGN.;4cL^Jame_:P]G&UdFIm[uGMg_Fk+-a?U@Z%p\GL`H1@N/f':n=Ba5-L]P^+XJS`i1S:$;MiroS*pl:LFDl#5ujWh/;NTDmtjV<UY?s64Ii<iVbPrh'2PDPcVimf2NimT-?ZjSkeNk&.$\8acWCDsgZ+T&fmCroS*pl:LFDl#5ujMT'u_giql&bY?$P;DN;PIuS56'/O\CEN,2Hgs'3dg<mj_gdGBs,r9c:f=5u\0f(a#QV,BDh>B.5*DOc%9uNl+135C(NGD#t1NO4LWKbW^c!TMbdDX8a6sM2f1O&HB\99\`1H,o49$,<5r&(Vt:!CgU`2-?eF#ST.CI]$oEt`PmPg%q-p$8So50Gf:pTDB`o>IdeE>qlek2kH"\9ab!<@2U9$J2rG]*_Wc'>)E*D,B2[Q[;fml?Qi?RCE\U>k<").U5,4lm`[X6%s)\mTkOIkD<JUi\m`Sc-*f$E:l>uX%_:Q's;hmG879P-[(c3gRuD@0DDWdeap_^13"74\E;o0<Od@HfThA1$_3&jA>\@(5+gZOeMCiI)k!\8S'PaAEV7PDfLBI&mcO,oI9\pV-FT&)MS&\3Frsf3S;D)nVW)JWTA@Q<1M:/9RAm]ccY)ulouriV7V4.<k4@8S>Wm-T[ZQu8]D6ht+'6dYM/?e#ibgrPh8e&%B4;gJWOSGDBD58Lk*jNL;.^ci]A-QNk'`Js\0a"UPhCf^/pC@,Gork5Y0"m.A[\;FbFMXNhFHgfCGKs$R;FA@EbCZ,pJJN]R`sPaAfJn)gf`b$I?^nE-8Tk1fnT&MG?28"+/LKjaikc:[\:@WSQ0Ra8*PnH135sRD(+jnB9et\;7bbUbhQ'-)p5eJ=lndoPchMC1O#):L@Qs@<k5d?5H\YegJCf8HhVng_9Mj7>gLR;Y3f#4pO$#Xc20A'ccXM8m8&-(Hre).q__X)b0@*V:OMna<l*&X2-eJMc*$G0I.r"h_9Mj7>gLR;Y3f#4pO$#Xc20A'ccXM8m8&-(Hre).q__X)b0@*V:OMna<l*&X2-eJMc*$G0I.r"h_9Mj7>gLR;Y3f#4pO$#Xc!(Lam41+kr*hH\<<DUC:i=#EY;3iTbZ'jXq_j\.n,BAHml<1(-/cKHjlX2T.cYm$9N;D/DaV)2m_?p>Shj;F!q+f>DSH"O1;;qq<0`"22O'^"ri;"H3AXY]i4]Z^k.CXCj*T'F<=-0R6b3$\^WQ>C1K.9Tmb:QU^AG)h^?<^>R?[Y^;Wd)d.\>tgaipnG-K6rIU<LfO<BSmXPF5]n9Z1ep7@BK(X*Ce:-SrBgR#'LiM_Zr0<q0ER:M+dX0bLl\(M-q@XQ$d.T$6P9@j5fC0$:i^=iGI<4IOmQ`^JSd?'KWFZ\mqWGqu_,NJY.S\g[/jB,/a8o42H7)\[31FA_2^c75FOk/kiM2C@EAkb?;ESQ.f(c'+Q$D+ldkX3Ae3htM2[Q('R.m5)#,bfo6L>\<*[bZ+I5Ca1b-3>Il`\N)Ir4ql\lb^<1)AQE]o9XW3b2DR(\;fS4jRkn"11U2q`bi_r1B'&1!<;T@*,;\pO'pi(63A]2L'ALUPHqqXl<c62V[ElcL1,GP$ELE)]1K3ZsZ&QuOk>Y\ujlXcdqf"VpE1(!K.&do)^!E<0'A'RBbNrt28Yrr_IK$mI\=OF?AlfpD.`G]^oB4B:orR(,]@p(Z.IMMS5AqmOB*FXTeV95ZES(*cGr'G'/%Eg+2O%0u]AD_sRu-H6_.@etTqkTAofdl^9O,mN0!hSf-'dJmp\FDmid+XER9aYXW>'Qic_!-0f<^(PltSmZV7>i>rk+Z/Se\EPgf`b$b^$bCqb5e^`3[V2RIbHepR/OFM.`*C1[!jTmk\qk'@/-eB?n\3hIkg`-D"4TcCC6E][+MJ9K]B2S2i6hH(TptR!;ZB3HJLZo0*hs0_)5bF6:,?k'\Ro@H(GOk0/+]bkk)h_Sie'c'e0DRJ3,Z"m%9odCu(bY'2\4p<1.m[D?G"]NO3>2j8$lgq-f1>is8"'s;a:\b=4[bI,/tcFd<=H8h%'^YHG+)dMOLRh`)M1V*5&^!!h"A^7qkiHdGHCVSZ:>T6r1baT?MG;Hf'bIu*,_.Cp)=lFZcPA@qg]3H:[k00;0Y'2\4p<1.m[D?G"]NO3>2q,]'Pg">YiEL/<n%'jG?PBoAA3QW.[DBQBR]([0gk(^bI+HgPpTA;+qDE7#9'5_J<u]r,Y)2Gq`%<C*cY$O#E::@bWa?FKTO^6YFg]'!l^Fc$:#(>`q0^cD#5>99UA?`e$VKRQ=]ZQt]<7"Uf>K6hREoMOD/esT-E:Dd\"I7qT67QX^$D,cIOSW0->m.mkKFrd'7J+eqg&o70@t:-Njsq[k+-q6M49jt3HI^G6soQ2^>?fQbOqC9,As6ZH"UK&io]?KcJ0!jdFZ%;Y;^ImE]n('Ln!UDhV$MM\9YWV1O$c3oJQ+(lV60I>gJg"i[4MjGP:\VDI0L/bT1[:IEakNH4r4jf5p)7\;@5cWiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!WiE)!Wf$BiN/nET~>endstream
endobj
7 0 obj
<<
/Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.1ec20b3a96e40a35266a0a8a0d634adb 5 0 R /FormXob.bbe0a4b6628a0e8125ab26a62825893b 6 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
8 0 obj
<<
/Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
9 0 obj
<<
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 290 /Length 3500 /Subtype /Image
/Type /XObject /Width 290
>>
stream
Gb"0M0s\bV$q&G/J($uOju)%+%1&)hn*)-NT`"8nzzzzzzzzzzzz!!'grT65NupmP_`]63jRce!oT8TqIFGMi(@D>9Q18%Wp<?-h,WY=WoE>BeutHu8YIA4O7SpKc+sL9F0lZs.b3omCWORUeq#Fn]1ff7pJ#G-kItht;A6pmP_`]63jRce!oT8TqIF@N3&*FmnO#.ck97`6:E%D03I(`QWUU&i9D1[aFc>'f5%G8^-ObfLFJ><m7)c-S_r'@N/VA=YXu(T>\r;M/@@JB>r)?I1e@5,du+nSeX'Eoh!BoPLr@VHWJ@\f-`;Z:LY8Kmo_Ad?D#0[5)F,u]k>=.H$p;]q^?<O]sAA.1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'f.Yl]\/XO/+Ys=-5A<mcb.qtW[m[)^*XRN1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'f.Yl]\/XO/+Ys=-5A<mcb.qtW[m[)^*XRN1XE_eQ`;S-5/&?Y1Gd@ifpA]ho00l8'u%mtD9P\Mk\;?)Y=XF$F&s;:;^o<38E=PaiQL$,`lqD>Xu6pgRT0&;GI9.]Q(k==7(su_^<Bl"bY4ksC*SkE8VJg=<uWqo.D"5(jD.ZPbM:XfbZ'J&2A5hS<;84m[4sJ&U8s8A^*XT/b[#)09Vprf,E]0$KeILK)`(DA]%T^9CJs-7XQ[gn40.j^hT+6D_O"EQQ.^@^iQJlpY=XF$Z_AtVn#XBmGopCW$=@C6=(^>mKeN$]^*XT/b_iRI^9\/Rk'_VO.X[X!?($+R'u%ohpmP1W1+Tpkqp$[=RJ65/WUOJ"FCk0:<VS?<j(hQObH0pMloV9;A_tJZUr&I$d?WC/<oM67:LY8MbP\bnpIT2]CRMpqmllSFHnFsAk1qDiNNZpmg:[;.[dgcL?^l83`&>>qq.oTiPM!n,14O/tI1k<0>3<$5]2)lT?d&ATH1smHj(k't2X`iUD'W$A9g"p/H/<t\qlZj@Rs6j=o=XsBpK^R_2t:^YkBZgdm^o&GDrTG<ch$SRh02"nhScaWT'+q-]C1'g]SU874jU`9GMi(XGn\LNHCf>Qm_8!9o-U&'oK;S+h0mmRk"Rt-k]u$5])/Y.baWi8dIY"AkBe/\3oGMcAUk_L);rMA#.X2i!H.gHJ/`tUi5T+.\FGmdDZ"(U:O*o%bOL")-=7^7DrE74n%8HFqc1)_qsI.l2X9/9=Xr<QpJLXbCr,l%R=&l$]nNdl^@1KblrVkln%1COg8K?+B;p:9h+-/%Z3B-0BC`H-pD2%Pq7aJ%Z<q/N^@0A.CSU;LS>Ge)G9:D2aqfB^S]TJQh-2j3jnnI0b'oU-pqAhRYDp-&E0eZ@h0kOd.U2CjG:$Z9F`64iQ1)?^./R#Qi;;q9^,G95_HAAGGP@N9hjJ)bTkmPnBP&2>q6mNRbVk[p.ML'C@j^(Kp6jTgZ9`&rR;L1/gVQ-1gJBf,9Jj)8R=&5kB4`+*#*k$W[P<ta$iA.a6eS+fdEFL\nnhg-R;F>k<$n'e`_=)ulnbsWAV8,n1Y\;=[tT6B[\7M6R:p1O1\nJ`cce;3%4W%9Cu];YgRj<\hRi@\^S#q;\'`3BG@'2DFDp_.g3E)3$iGVE:#8>Yn(i8??dQL.gM#W\4"p(2\i4mRD7k)U"b&c3-?#Z=p[5]00Bh9RD7&iiSJV&)h4)':2Vu(;!l(CTPIJrZHZrfS**lhrDLp#UDVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]ds]kIE*doS^q;DVjQe.sCQCb]dt()PtR=ZX#Ne^?[k]n7>Yqk"X@5,N$b[n+t<ZI$k_`GnY>faEOuZ]=tTY?Y5"1hF(X2o%i[0Y4&I/QW`::2c81eHoLr:lT;0:AQJTg:"6Qqhp&n(qT^R<R2*G]'6W]`GI-bM^9\/RAqb0[6sVnFh<b$An#XBm=lGi/;:ghU2uC>T40.j^<qtfOe?pOYc+`ZCc7440'u"rJJT(G.c#rLLN&!'U(Z28lDQ`kTc7&8cJ+:35jlX/Sk);&Kn/'u_;f8c8DpBd&!e9aR3p#M8s5o7q0CTe8X&Eo=qesb.o)aF3]fP9;])UoO1,&,5hlB[nY5<._..[Lin\%!Fk.:TTN&!'U(Z28lDQ`kTc7&;D]rq>1..d;(9\b4QZdNohWf>5rbj0%"E=9M)9$`?o2DU%CYHQ'd/bh(O4X[8`a;i@8^*XN&i6/4oS>^0IF"$YVRS;Lg0=0)JU8j3sU!2h<13!]9bY$3<W\uVf19[n'`%Ca>.m58[g;k8V]Y5^+\)>H2oUMjp,BG:)qO1+5JhOIYF/#[obb<8HCGKl;^<B3qM%\S,H5f%lH95tRk08_qgJBXiTC$Zs\'m6IhOH"!%41W;fe.Jp4)JKic&!(f:bk8-m;f,6dl(gpS1(WO-1g`]/pDV'D.D_QM%\Q>1-_DuEi6Cq2J1g9.'X4-oCLWfGBu>fA*2$m'&-5<5G.=`Vmk,5B&9%+Ymi#No@Ya?H95tRk08_qgJBXiTC$Zs\'m6IhOI,Nj6S(_kfW7]G@i>d]6GuK^GF1_VGb-dpCd3^o5%kcjh#ajEPF<U-Dj\TMt[kY47d8t.cn9e06+`_cR,Me^5M^upH.t_@OgKOGV='O1X@DF;SJ(`')+KZCgnmU]6GuK^GF1_VGb-dpCd5$SD?,d0=+!u_ELRn>rts0m[M:a=eTY?+/Q$@*@YXq:#sL!:q!ThdT+nZPdC66nmtiM>M)I1WbY,IfmOP01+SS@m%\[Q[3Of"^576*(!7<c;7c&HO`GX&7)$kPAIJA`?$5O*3P02R?Y5"tKmf2g\osm>h)CHLZU3?^5"\m^4&XAlS&gq!Tkn-ZV5pa>F_*aPG"-*$7)!s@;;.u'G3*prREq=mOkD[UDr,o,2X7_Vq-@@iZY!i\p.aV;G9<Z@\ntMtf9c<7fbp3+'D^eH7qn`9gQg[hANjmQ7V:OG^3THMg8NbLj`c-@c^LDeff,%3hL1VHlF(!o?!la#AnPZJ:#qdf+/Ot.D-)2<Qhd`9)4>mdq<$L'BqoS#Q/D7G5&5=2B&?"jH1t1iW7uLWGC>n*R[oSo2j&%8I1k:217u7s3aHUt;K^6R.'Y9Ko@YXqe('1+<S+m?'"_$sT=r*&?#B@7Fj6C(Yq%-lfdj/QeV5_Wf=ZqQ]2CDV]tug9D>7"Oc'p,d.jaf?/$.4ML+cQY]SR95;DOlX_E(t>pel7ZRjbNl-1fe?XOG^S03-W:M%[Eu17u7s3aHUt;K^6R.'Y9Ko@YXqe('1+<S+m?PTA#EbWE/3Y5NP"]T:Lk9Zk"(]B\*gf?O1@?-T1h40tujrH@#0O4)QPb.KOBlIp1.c2/npc(rQFZ`C8-G29flda_%6]JI1bg2GTfq^>apUs(p,X02DEh7SfseP+,u1V;r+DqE82-sb)nbWE/3Y5NP"]T:Lk9Zk"(]B\*gf?F9qzzzzzzzzzzzz5k,pqe-_`~>endstream
endobj
10 0 obj
<<
/Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
/FormXob.1280b7d13f0587f75dbba24117c3e12a 9 0 R
>>
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
11 0 obj
<<
/Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
12 0 obj
<<
/PageMode /UseNone /Pages 14 0 R /Type /Catalog
>>
endobj
13 0 obj
<<
/Author (anonymous) /CreationDate (D:20251216142815+00'00') /Creator (anonymous) /Keywords () /ModDate (D:20251216142815+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
14 0 obj
<<
/Count 5 /Kids [ 3 0 R 7 0 R 8 0 R 10 0 R 11 0 R ] /Type /Pages
>>
endobj
15 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 164
>>
stream
GarW05mkI_&4Q=V`ET>Mc.&b?;-+rnF+G1',/ca*pUAWf>EIgiipknB9RY?:(LXAhG(PtB're&F\nA'4a%aIp+-h"W@9D(-_!#HM*Z:^`FOHNUN-;cL_m8qodCk0^Akq$V4PUhHkMQ7^Ejj*/Mgoa@anH4$%uMYhOT~>endstream
endobj
16 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 306
>>
stream
GasbT4\rsL&4$!fMAlpjH?ZXMZl9aE"XK0lYb%&R$>PaP&&cf78Q/KO<^N*hq5!cWA-.^JqQm+$jrVMM!b1Zf5UJAHTA[O5a#Wj7rghI[YR$H&I1;qf=XrnMp^cl'VsjlS&LTtc"96#@mAfhO_96j,pMI1=[Fq,J31>/c9Cp=j48@sD.G@[NB&N,!B3"QR<e[.?4qhBfJFW&(KAC_sj$gSZhqF0T(5sE#WDeG4=a!P:El$187`l8mPLohVAbL$Y+1h)kXj-Qc=,3AkKqKh@36/9mF(-YNS\uo1I$tLMOSf*X#]ps~>endstream
endobj
17 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 185
>>
stream
GarW0:CDb>&4c2<MVk["e;d_gmE_c)_gI#HRqtN;"kVtu-`3[N_p#oKpB[c<lE@1;N3PAV-jDn$krJuTE8kQlWoro5dLb%\m(;?dMjquqaV%j/=&\ojFOWl2lj!LDQGM.KJ9B`,kY59<$TNAI\j,Z/r8d0V5!390b?H4<mLFNoiYn5PLd#8q4Ic~>endstream
endobj
18 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 244
>>
stream
GarW4b6l*?&4Q?hMRuh(23Tpmkt^cRET&,M[qV:g6EQRMs2I6!U^T$](X?G+!r#.NZmDs+Qu<6UTF4R17*n#s2&gSmk2Mk.09@0r[k9DgRu9WjKt]k!Ic1n'J.q+%HiE61]07.7.f1^O]tp[&Fn>&8hUMD]+;spqhR>>LX`Bap0=GTNaa\,&7Zqt_h]FP:T4bD(VQ.g\Pm&EGSuJ6sK$-Os9'08g6q!hekXZP?.6B5f2_i<IDu~>endstream
endobj
19 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 164
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CT3!/hd>6k,goQl7B?"*$l7Jjr"7HE)RrVF!h>6AQD_Ah8\RZl9o#.%!<n#GicFAepUZ\E#$(k,.:+.(JE9TULV0b8?ts/Mf%77fd-ZP$/#A!1Zb>/H~>endstream
endobj
xref
0 20
0000000000 65535 f
0000000061 00000 n
0000000102 00000 n
0000000209 00000 n
0000000404 00000 n
0000000516 00000 n
0000004168 00000 n
0000008161 00000 n
0000008467 00000 n
0000008662 00000 n
0000012353 00000 n
0000012612 00000 n
0000012808 00000 n
0000012878 00000 n
0000013140 00000 n
0000013226 00000 n
0000013481 00000 n
0000013878 00000 n
0000014154 00000 n
0000014489 00000 n
trailer
<<
/ID
[<3a098456c5603f47bfc8fb47cd3d7621><3a098456c5603f47bfc8fb47cd3d7621>]
% ReportLab generated PDF document -- digest (opensource)
/Info 13 0 R
/Root 12 0 R
/Size 20
>>
startxref
14744
%%EOF

View File

@@ -67,6 +67,7 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
"barcode_max_pages": None,
"barcode_enable_tag": None,
"barcode_tag_mapping": None,
"barcode_tag_split": None,
"ai_enabled": False,
"llm_embedding_backend": None,
"llm_embedding_model": None,

View File

@@ -838,3 +838,61 @@ class TestApiWorkflows(DirectoriesMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.action.refresh_from_db()
self.assertEqual(self.action.assign_title, "Patched Title")
def test_password_action_passwords_field(self):
"""
GIVEN:
- Nothing
WHEN:
- A workflow password removal action is created with passwords set
THEN:
- The passwords field is correctly stored and retrieved
"""
passwords = ["password1", "password2", "password3"]
response = self.client.post(
"/api/workflow_actions/",
json.dumps(
{
"type": WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
"passwords": passwords,
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data["passwords"], passwords)
def test_password_action_invalid_passwords_field(self):
"""
GIVEN:
- Nothing
WHEN:
- A workflow password removal action is created with invalid passwords field
THEN:
- The required validation error is raised
"""
for payload in [
{"type": WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL},
{
"type": WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
"passwords": "",
},
{
"type": WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
"passwords": [],
},
{
"type": WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
"passwords": ["", "password2"],
},
]:
response = self.client.post(
"/api/workflow_actions/",
json.dumps(payload),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn(
"Passwords are required",
str(response.data["non_field_errors"][0]),
)

View File

@@ -822,6 +822,35 @@ class TestTagBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
yield reader
reader.cleanup()
@override_settings(
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"},
)
def test_barcode_without_tag_match(self):
"""
GIVEN:
- Barcode that does not match any TAG mapping pattern
- TAG mapping configured for "TAG:" prefix only
WHEN:
- is_tag property is checked on an ASN barcode
THEN:
- Returns False
"""
test_file = self.BARCODE_SAMPLE_DIR / "barcode-39-asn-123.pdf"
with self.get_reader(test_file) as reader:
reader.detect()
self.assertGreater(
len(reader.barcodes),
0,
"Should have detected at least one barcode",
)
asn_barcode = reader.barcodes[0]
self.assertFalse(
asn_barcode.is_tag,
f"ASN barcode '{asn_barcode.value}' should not match TAG: pattern",
)
@override_settings(CONSUMER_ENABLE_TAG_BARCODE=True)
def test_scan_file_without_matching_barcodes(self):
"""
@@ -928,3 +957,163 @@ class TestTagBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
# expect error to be caught and logged only
tags = reader.metadata.tag_ids
self.assertEqual(tags, None)
@override_settings(
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_SPLIT=True,
CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"},
)
def test_split_on_tag_barcodes(self):
"""
GIVEN:
- PDF containing barcodes with TAG: prefix
- Tag barcode splitting is enabled with TAG: mapping
WHEN:
- File is processed
THEN:
- Splits should occur at pages with TAG barcodes
- Tags should NOT be assigned when tag splitting is enabled (they're assigned during re-consumption)
"""
test_file = self.BARCODE_SAMPLE_DIR / "split-by-tag-basic.pdf"
with self.get_reader(test_file) as reader:
reader.detect()
separator_page_numbers = reader.get_separation_pages()
self.assertDictEqual(separator_page_numbers, {1: True, 3: True})
tags = reader.metadata.tag_ids
self.assertIsNone(tags)
@override_settings(
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_SPLIT=False,
CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"},
)
def test_no_split_when_tag_split_disabled(self):
"""
GIVEN:
- PDF containing TAG barcodes (TAG:invoice, TAG:receipt)
- Tag barcode splitting is disabled
WHEN:
- File is processed
THEN:
- No separation pages are identified
- Tags are still extracted and assigned
"""
test_file = self.BARCODE_SAMPLE_DIR / "split-by-tag-basic.pdf"
with self.get_reader(test_file) as reader:
reader.run()
separator_page_numbers = reader.get_separation_pages()
self.assertDictEqual(separator_page_numbers, {})
tags = reader.metadata.tag_ids
self.assertEqual(len(tags), 2)
@override_settings(
CONSUMER_ENABLE_BARCODES=True,
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_SPLIT=True,
CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"},
CELERY_TASK_ALWAYS_EAGER=True,
OCR_MODE="skip",
)
def test_consume_barcode_file_tag_split_and_assignment(self):
"""
GIVEN:
- PDF containing TAG barcodes on pages 2 and 4 (TAG:invoice, TAG:receipt)
- Tag barcode splitting is enabled
WHEN:
- File is consumed
THEN:
- PDF is split into 3 documents at barcode pages
- Each split document has the appropriate TAG barcodes extracted and assigned
- Document 1: page 1 (no tags)
- Document 2: pages 2-3 with TAG:invoice
- Document 3: pages 4-5 with TAG:receipt
"""
test_file = self.BARCODE_SAMPLE_DIR / "split-by-tag-basic.pdf"
dst = settings.SCRATCH_DIR / "split-by-tag-basic.pdf"
shutil.copy(test_file, dst)
with mock.patch("documents.tasks.ProgressManager", DummyProgressManager):
result = tasks.consume_file(
ConsumableDocument(
source=DocumentSource.ConsumeFolder,
original_file=dst,
),
None,
)
self.assertEqual(result, "Barcode splitting complete!")
documents = Document.objects.all().order_by("id")
self.assertEqual(documents.count(), 3)
doc1 = documents[0]
self.assertEqual(doc1.tags.count(), 0)
doc2 = documents[1]
self.assertEqual(doc2.tags.count(), 1)
self.assertEqual(doc2.tags.first().name, "invoice")
doc3 = documents[2]
self.assertEqual(doc3.tags.count(), 1)
self.assertEqual(doc3.tags.first().name, "receipt")
@override_settings(
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_SPLIT=True,
CONSUMER_TAG_BARCODE_MAPPING={"ASN(.*)": "ASN_\\g<1>", "TAG:(.*)": "\\g<1>"},
)
def test_split_by_mixed_asn_tag_backwards_compat(self):
"""
GIVEN:
- PDF with mixed ASN and TAG barcodes
- Mapping that treats ASN barcodes as tags (backwards compatibility)
- ASN12345 on page 1, TAG:personal on page 3, ASN13456 on page 5, TAG:business on page 7
WHEN:
- File is consumed
THEN:
- Both ASN and TAG barcodes trigger splits
- Split points are at pages 3, 5, and 7 (page 1 never splits)
- 4 separate documents are produced
"""
test_file = self.BARCODE_SAMPLE_DIR / "split-by-tag-mixed-asn.pdf"
with self.get_reader(test_file) as reader:
reader.detect()
separator_pages = reader.get_separation_pages()
self.assertDictEqual(separator_pages, {2: True, 4: True, 6: True})
document_list = reader.separate_pages(separator_pages)
self.assertEqual(len(document_list), 4)
@override_settings(
CONSUMER_ENABLE_TAG_BARCODE=True,
CONSUMER_TAG_BARCODE_SPLIT=True,
CONSUMER_TAG_BARCODE_MAPPING={"TAG:(.*)": "\\g<1>"},
)
def test_split_by_tag_multiple_per_page(self):
"""
GIVEN:
- PDF with multiple TAG barcodes on same page
- TAG:invoice and TAG:expense on page 2, TAG:receipt on page 4
WHEN:
- File is processed
THEN:
- Pages with barcodes trigger splits
- Split points at pages 2 and 4
- 3 separate documents are produced
"""
test_file = self.BARCODE_SAMPLE_DIR / "split-by-tag-multiple-per-page.pdf"
with self.get_reader(test_file) as reader:
reader.detect()
separator_pages = reader.get_separation_pages()
self.assertDictEqual(separator_pages, {1: True, 3: True})
document_list = reader.separate_pages(separator_pages)
self.assertEqual(len(document_list), 3)

View File

@@ -2,6 +2,7 @@ import datetime
import json
import shutil
import socket
import tempfile
from datetime import timedelta
from pathlib import Path
from typing import TYPE_CHECKING
@@ -60,6 +61,7 @@ from documents.tests.utils import DirectoriesMixin
from documents.tests.utils import DummyProgressManager
from documents.tests.utils import FileSystemAssertsMixin
from documents.tests.utils import SampleDirMixin
from documents.workflows.actions import execute_password_removal_action
from paperless_mail.models import MailAccount
from paperless_mail.models import MailRule
@@ -3716,6 +3718,196 @@ class TestWorkflows(
mock_post.assert_called_once()
@mock.patch("documents.bulk_edit.remove_password")
def test_password_removal_action_attempts_multiple_passwords(
self,
mock_remove_password,
):
"""
GIVEN:
- Workflow password removal action
- Multiple passwords provided
WHEN:
- Document updated triggering the workflow
THEN:
- Password removal is attempted until one succeeds
"""
doc = Document.objects.create(
title="Protected",
checksum="pw-checksum",
)
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
passwords="wrong, right\n extra ",
)
workflow = Workflow.objects.create(name="Password workflow")
workflow.triggers.add(trigger)
workflow.actions.add(action)
mock_remove_password.side_effect = [
ValueError("wrong password"),
"OK",
]
run_workflows(trigger.type, doc)
assert mock_remove_password.call_count == 2
mock_remove_password.assert_has_calls(
[
mock.call(
[doc.id],
password="wrong",
update_document=True,
user=doc.owner,
),
mock.call(
[doc.id],
password="right",
update_document=True,
user=doc.owner,
),
],
)
@mock.patch("documents.bulk_edit.remove_password")
def test_password_removal_action_fails_without_correct_password(
self,
mock_remove_password,
):
"""
GIVEN:
- Workflow password removal action
- No correct password provided
WHEN:
- Document updated triggering the workflow
THEN:
- Password removal is attempted for all passwords and fails
"""
doc = Document.objects.create(
title="Protected",
checksum="pw-checksum-2",
)
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
passwords=" \n , ",
)
workflow = Workflow.objects.create(name="Password workflow missing passwords")
workflow.triggers.add(trigger)
workflow.actions.add(action)
run_workflows(trigger.type, doc)
mock_remove_password.assert_not_called()
@mock.patch("documents.bulk_edit.remove_password")
def test_password_removal_action_skips_without_passwords(
self,
mock_remove_password,
):
"""
GIVEN:
- Workflow password removal action with no passwords
WHEN:
- Workflow is run
THEN:
- Password removal is not attempted
"""
doc = Document.objects.create(
title="Protected",
checksum="pw-checksum-2",
)
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
passwords="",
)
workflow = Workflow.objects.create(name="Password workflow missing passwords")
workflow.triggers.add(trigger)
workflow.actions.add(action)
run_workflows(trigger.type, doc)
mock_remove_password.assert_not_called()
@mock.patch("documents.bulk_edit.remove_password")
def test_password_removal_consumable_document_deferred(
self,
mock_remove_password,
):
"""
GIVEN:
- Workflow password removal action
- Simulated consumption trigger (a ConsumableDocument is used)
WHEN:
- Document consumption is finished
THEN:
- Password removal is attempted
"""
action = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.PASSWORD_REMOVAL,
passwords="first, second",
)
temp_dir = Path(tempfile.mkdtemp())
original_file = temp_dir / "file.pdf"
original_file.write_bytes(b"pdf content")
consumable = ConsumableDocument(
source=DocumentSource.ApiUpload,
original_file=original_file,
)
execute_password_removal_action(action, consumable, logging_group=None)
mock_remove_password.assert_not_called()
mock_remove_password.side_effect = [
ValueError("bad password"),
"OK",
]
doc = Document.objects.create(
checksum="pw-checksum-consumed",
title="Protected",
)
document_consumption_finished.send(
sender=self.__class__,
document=doc,
)
assert mock_remove_password.call_count == 2
mock_remove_password.assert_has_calls(
[
mock.call(
[doc.id],
password="first",
update_document=True,
user=doc.owner,
),
mock.call(
[doc.id],
password="second",
update_document=True,
user=doc.owner,
),
],
)
# ensure handler disconnected after first run
document_consumption_finished.send(
sender=self.__class__,
document=doc,
)
assert mock_remove_password.call_count == 2
class TestWebhookSend:
def test_send_webhook_data_or_json(

View File

@@ -1,4 +1,5 @@
import logging
import re
from pathlib import Path
from django.conf import settings
@@ -14,6 +15,7 @@ from documents.models import Document
from documents.models import DocumentType
from documents.models import WorkflowAction
from documents.models import WorkflowTrigger
from documents.signals import document_consumption_finished
from documents.templating.workflows import parse_w_workflow_placeholders
from documents.workflows.webhooks import send_webhook
@@ -265,3 +267,74 @@ def execute_webhook_action(
f"Error occurred sending webhook: {e}",
extra={"group": logging_group},
)
def execute_password_removal_action(
action: WorkflowAction,
document: Document | ConsumableDocument,
logging_group,
) -> None:
"""
Try to remove a password from a document using the configured list.
"""
passwords = action.passwords
if not passwords:
logger.warning(
"Password removal action %s has no passwords configured",
action.pk,
extra={"group": logging_group},
)
return
passwords = [
password.strip()
for password in re.split(r"[,\n]", passwords)
if password.strip()
]
if isinstance(document, ConsumableDocument):
# hook the consumption-finished signal to attempt password removal later
def handler(sender, **kwargs):
consumed_document: Document = kwargs.get("document")
if consumed_document is not None:
execute_password_removal_action(
action,
consumed_document,
logging_group,
)
document_consumption_finished.disconnect(handler)
document_consumption_finished.connect(handler, weak=False)
return
# import here to avoid circular dependency
from documents.bulk_edit import remove_password
for password in passwords:
try:
remove_password(
[document.id],
password=password,
update_document=True,
user=document.owner,
)
logger.info(
"Removed password from document %s using workflow action %s",
document.pk,
action.pk,
extra={"group": logging_group},
)
return
except ValueError as e:
logger.warning(
"Password removal failed for document %s with supplied password: %s",
document.pk,
e,
extra={"group": logging_group},
)
logger.error(
"Password removal failed for document %s after trying all provided passwords",
document.pk,
extra={"group": logging_group},
)

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-27 18:56+0000\n"
"POT-Creation-Date: 2026-01-29 16:06+0000\n"
"PO-Revision-Date: 2022-02-17 04:17\n"
"Last-Translator: \n"
"Language-Team: English\n"
@@ -1786,35 +1786,39 @@ msgstr ""
msgid "Sets the tag barcode mapping"
msgstr ""
#: paperless/models.py:287
msgid "Enables AI features"
#: paperless/models.py:284
msgid "Enables splitting on tag barcodes"
msgstr ""
#: paperless/models.py:293
msgid "Enables AI features"
msgstr ""
#: paperless/models.py:299
msgid "Sets the LLM embedding backend"
msgstr ""
#: paperless/models.py:301
#: paperless/models.py:307
msgid "Sets the LLM embedding model"
msgstr ""
#: paperless/models.py:308
#: paperless/models.py:314
msgid "Sets the LLM backend"
msgstr ""
#: paperless/models.py:316
#: paperless/models.py:322
msgid "Sets the LLM model"
msgstr ""
#: paperless/models.py:323
#: paperless/models.py:329
msgid "Sets the LLM API key"
msgstr ""
#: paperless/models.py:330
#: paperless/models.py:336
msgid "Sets the LLM endpoint, optional"
msgstr ""
#: paperless/models.py:337
#: paperless/models.py:343
msgid "paperless application settings"
msgstr ""

View File

@@ -116,6 +116,7 @@ class BarcodeConfig(BaseConfig):
barcode_max_pages: int = dataclasses.field(init=False)
barcode_enable_tag: bool = dataclasses.field(init=False)
barcode_tag_mapping: dict[str, str] = dataclasses.field(init=False)
barcode_tag_split: bool = dataclasses.field(init=False)
def __post_init__(self) -> None:
app_config = self._get_config_instance()
@@ -153,6 +154,9 @@ class BarcodeConfig(BaseConfig):
self.barcode_tag_mapping = (
app_config.barcode_tag_mapping or settings.CONSUMER_TAG_BARCODE_MAPPING
)
self.barcode_tag_split = (
app_config.barcode_tag_split or settings.CONSUMER_TAG_BARCODE_SPLIT
)
@dataclasses.dataclass

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.1.7 on 2025-12-15 21:30
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("paperless", "0005_applicationconfiguration_ai_enabled_and_more"),
]
operations = [
migrations.AddField(
model_name="applicationconfiguration",
name="barcode_tag_split",
field=models.BooleanField(
null=True,
verbose_name="Enables splitting on tag barcodes",
),
),
]

View File

@@ -279,6 +279,12 @@ class ApplicationConfiguration(AbstractSingletonModel):
null=True,
)
# PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT
barcode_tag_split = models.BooleanField(
verbose_name=_("Enables splitting on tag barcodes"),
null=True,
)
"""
AI related settings
"""

View File

@@ -1149,6 +1149,10 @@ CONSUMER_TAG_BARCODE_MAPPING = dict(
),
)
CONSUMER_TAG_BARCODE_SPLIT: Final[bool] = __get_boolean(
"PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT",
)
CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED: Final[bool] = __get_boolean(
"PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED",
)

View File

@@ -12,6 +12,9 @@ from paperless_tika.parsers import TikaDocumentParser
reason="No Gotenberg/Tika servers to test with",
)
@pytest.mark.django_db()
@pytest.mark.live
@pytest.mark.gotenberg
@pytest.mark.tika
class TestTikaParserAgainstServer:
"""
This test case tests the Tika parsing against a live tika server,

View File

@@ -128,6 +128,8 @@ class TestTikaParser:
request = httpx_mock.get_request()
assert request is not None
expected_field_name = "pdfa"
content_type = request.headers["Content-Type"]