From 9e2b2a32fd0e967ad3184e9a5d091a29953acb91 Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Wed, 25 Oct 2017 16:22:10 -0700
Subject: Include composer dependencies in repo
---
.gitattributes | 21 +-
.gitignore | 1 -
.travis.yml | 2 +-
Dockerfile | 1 -
Makefile | 2 +-
doc/en_US/installation.markdown | 5 +-
doc/en_US/update.markdown | 3 +-
doc/es_ES/installation.markdown | 6 +-
doc/es_ES/update.markdown | 3 +-
doc/fr_FR/installation.markdown | 5 +-
doc/fr_FR/update.markdown | 3 +-
doc/ru_RU/installation.markdown | 10 +-
doc/ru_RU/update.markdown | 5 +-
doc/tr_TR/installation.markdown | 5 +-
doc/tr_TR/update.markdown | 3 +-
vendor/aferrandini/phpqrcode/.gitignore | 1 +
vendor/aferrandini/phpqrcode/LICENSE | 165 +++
vendor/aferrandini/phpqrcode/VERSION | 2 +
vendor/aferrandini/phpqrcode/cache/frame_1.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_1.png | Bin 0 -> 126 bytes
vendor/aferrandini/phpqrcode/cache/frame_10.dat | Bin 0 -> 204 bytes
vendor/aferrandini/phpqrcode/cache/frame_10.png | Bin 0 -> 202 bytes
vendor/aferrandini/phpqrcode/cache/frame_11.dat | Bin 0 -> 210 bytes
vendor/aferrandini/phpqrcode/cache/frame_11.png | Bin 0 -> 205 bytes
vendor/aferrandini/phpqrcode/cache/frame_12.dat | Bin 0 -> 222 bytes
vendor/aferrandini/phpqrcode/cache/frame_12.png | Bin 0 -> 216 bytes
vendor/aferrandini/phpqrcode/cache/frame_13.dat | Bin 0 -> 223 bytes
vendor/aferrandini/phpqrcode/cache/frame_13.png | Bin 0 -> 210 bytes
vendor/aferrandini/phpqrcode/cache/frame_14.dat | Bin 0 -> 227 bytes
vendor/aferrandini/phpqrcode/cache/frame_14.png | Bin 0 -> 213 bytes
vendor/aferrandini/phpqrcode/cache/frame_15.dat | Bin 0 -> 242 bytes
vendor/aferrandini/phpqrcode/cache/frame_15.png | Bin 0 -> 219 bytes
vendor/aferrandini/phpqrcode/cache/frame_16.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_16.png | Bin 0 -> 211 bytes
vendor/aferrandini/phpqrcode/cache/frame_17.dat | Bin 0 -> 237 bytes
vendor/aferrandini/phpqrcode/cache/frame_17.png | Bin 0 -> 211 bytes
vendor/aferrandini/phpqrcode/cache/frame_18.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_18.png | Bin 0 -> 228 bytes
vendor/aferrandini/phpqrcode/cache/frame_19.dat | 3 +
vendor/aferrandini/phpqrcode/cache/frame_19.png | Bin 0 -> 225 bytes
vendor/aferrandini/phpqrcode/cache/frame_2.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_2.png | Bin 0 -> 144 bytes
vendor/aferrandini/phpqrcode/cache/frame_20.dat | Bin 0 -> 250 bytes
vendor/aferrandini/phpqrcode/cache/frame_20.png | Bin 0 -> 225 bytes
vendor/aferrandini/phpqrcode/cache/frame_21.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_21.png | Bin 0 -> 235 bytes
vendor/aferrandini/phpqrcode/cache/frame_22.dat | 3 +
vendor/aferrandini/phpqrcode/cache/frame_22.png | Bin 0 -> 226 bytes
vendor/aferrandini/phpqrcode/cache/frame_23.dat | 3 +
vendor/aferrandini/phpqrcode/cache/frame_23.png | Bin 0 -> 220 bytes
vendor/aferrandini/phpqrcode/cache/frame_24.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_24.png | Bin 0 -> 242 bytes
vendor/aferrandini/phpqrcode/cache/frame_25.dat | 3 +
vendor/aferrandini/phpqrcode/cache/frame_25.png | Bin 0 -> 242 bytes
vendor/aferrandini/phpqrcode/cache/frame_26.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_26.png | Bin 0 -> 244 bytes
vendor/aferrandini/phpqrcode/cache/frame_27.dat | Bin 0 -> 284 bytes
vendor/aferrandini/phpqrcode/cache/frame_27.png | Bin 0 -> 237 bytes
vendor/aferrandini/phpqrcode/cache/frame_28.dat | Bin 0 -> 318 bytes
vendor/aferrandini/phpqrcode/cache/frame_28.png | Bin 0 -> 234 bytes
vendor/aferrandini/phpqrcode/cache/frame_29.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_29.png | Bin 0 -> 232 bytes
vendor/aferrandini/phpqrcode/cache/frame_3.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_3.png | Bin 0 -> 147 bytes
vendor/aferrandini/phpqrcode/cache/frame_30.dat | Bin 0 -> 324 bytes
vendor/aferrandini/phpqrcode/cache/frame_30.png | Bin 0 -> 255 bytes
vendor/aferrandini/phpqrcode/cache/frame_31.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_31.png | Bin 0 -> 260 bytes
vendor/aferrandini/phpqrcode/cache/frame_32.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_32.png | Bin 0 -> 262 bytes
vendor/aferrandini/phpqrcode/cache/frame_33.dat | 14 +
vendor/aferrandini/phpqrcode/cache/frame_33.png | Bin 0 -> 253 bytes
vendor/aferrandini/phpqrcode/cache/frame_34.dat | Bin 0 -> 331 bytes
vendor/aferrandini/phpqrcode/cache/frame_34.png | Bin 0 -> 256 bytes
vendor/aferrandini/phpqrcode/cache/frame_35.dat | Bin 0 -> 342 bytes
vendor/aferrandini/phpqrcode/cache/frame_35.png | Bin 0 -> 243 bytes
vendor/aferrandini/phpqrcode/cache/frame_36.dat | Bin 0 -> 370 bytes
vendor/aferrandini/phpqrcode/cache/frame_36.png | Bin 0 -> 272 bytes
vendor/aferrandini/phpqrcode/cache/frame_37.dat | Bin 0 -> 376 bytes
vendor/aferrandini/phpqrcode/cache/frame_37.png | Bin 0 -> 279 bytes
vendor/aferrandini/phpqrcode/cache/frame_38.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_38.png | Bin 0 -> 279 bytes
vendor/aferrandini/phpqrcode/cache/frame_39.dat | Bin 0 -> 404 bytes
vendor/aferrandini/phpqrcode/cache/frame_39.png | Bin 0 -> 264 bytes
vendor/aferrandini/phpqrcode/cache/frame_4.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_4.png | Bin 0 -> 149 bytes
vendor/aferrandini/phpqrcode/cache/frame_40.dat | 2 +
vendor/aferrandini/phpqrcode/cache/frame_40.png | Bin 0 -> 267 bytes
vendor/aferrandini/phpqrcode/cache/frame_5.dat | 1 +
vendor/aferrandini/phpqrcode/cache/frame_5.png | Bin 0 -> 150 bytes
vendor/aferrandini/phpqrcode/cache/frame_6.dat | Bin 0 -> 132 bytes
vendor/aferrandini/phpqrcode/cache/frame_6.png | Bin 0 -> 151 bytes
vendor/aferrandini/phpqrcode/cache/frame_7.dat | Bin 0 -> 196 bytes
vendor/aferrandini/phpqrcode/cache/frame_7.png | Bin 0 -> 189 bytes
vendor/aferrandini/phpqrcode/cache/frame_8.dat | Bin 0 -> 201 bytes
vendor/aferrandini/phpqrcode/cache/frame_8.png | Bin 0 -> 204 bytes
vendor/aferrandini/phpqrcode/cache/frame_9.dat | Bin 0 -> 206 bytes
vendor/aferrandini/phpqrcode/cache/frame_9.png | Bin 0 -> 199 bytes
.../phpqrcode/cache/mask_0/mask_101_0.dat | Bin 0 -> 157 bytes
.../phpqrcode/cache/mask_0/mask_105_0.dat | Bin 0 -> 162 bytes
.../phpqrcode/cache/mask_0/mask_109_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_113_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_117_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_121_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_125_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_129_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_133_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_137_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_141_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_145_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_149_0.dat | 3 +
.../phpqrcode/cache/mask_0/mask_153_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_157_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_161_0.dat | Bin 0 -> 241 bytes
.../phpqrcode/cache/mask_0/mask_165_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_169_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_173_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_177_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_21_0.dat | Bin 0 -> 48 bytes
.../phpqrcode/cache/mask_0/mask_25_0.dat | Bin 0 -> 57 bytes
.../phpqrcode/cache/mask_0/mask_29_0.dat | Bin 0 -> 59 bytes
.../phpqrcode/cache/mask_0/mask_33_0.dat | Bin 0 -> 62 bytes
.../phpqrcode/cache/mask_0/mask_37_0.dat | Bin 0 -> 65 bytes
.../phpqrcode/cache/mask_0/mask_41_0.dat | Bin 0 -> 68 bytes
.../phpqrcode/cache/mask_0/mask_45_0.dat | Bin 0 -> 106 bytes
.../phpqrcode/cache/mask_0/mask_49_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_53_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_57_0.dat | 4 +
.../phpqrcode/cache/mask_0/mask_61_0.dat | Bin 0 -> 119 bytes
.../phpqrcode/cache/mask_0/mask_65_0.dat | Bin 0 -> 123 bytes
.../phpqrcode/cache/mask_0/mask_69_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_73_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_77_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_81_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_85_0.dat | 2 +
.../phpqrcode/cache/mask_0/mask_89_0.dat | 1 +
.../phpqrcode/cache/mask_0/mask_93_0.dat | 3 +
.../phpqrcode/cache/mask_0/mask_97_0.dat | Bin 0 -> 150 bytes
.../phpqrcode/cache/mask_1/mask_101_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_105_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_109_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_113_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_117_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_121_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_125_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_129_1.dat | Bin 0 -> 164 bytes
.../phpqrcode/cache/mask_1/mask_133_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_137_1.dat | 3 +
.../phpqrcode/cache/mask_1/mask_141_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_145_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_149_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_153_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_157_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_161_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_165_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_169_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_173_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_177_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_21_1.dat | Bin 0 -> 42 bytes
.../phpqrcode/cache/mask_1/mask_25_1.dat | Bin 0 -> 48 bytes
.../phpqrcode/cache/mask_1/mask_29_1.dat | Bin 0 -> 50 bytes
.../phpqrcode/cache/mask_1/mask_33_1.dat | Bin 0 -> 53 bytes
.../phpqrcode/cache/mask_1/mask_37_1.dat | Bin 0 -> 56 bytes
.../phpqrcode/cache/mask_1/mask_41_1.dat | Bin 0 -> 58 bytes
.../phpqrcode/cache/mask_1/mask_45_1.dat | Bin 0 -> 82 bytes
.../phpqrcode/cache/mask_1/mask_49_1.dat | Bin 0 -> 84 bytes
.../phpqrcode/cache/mask_1/mask_53_1.dat | Bin 0 -> 87 bytes
.../phpqrcode/cache/mask_1/mask_57_1.dat | Bin 0 -> 92 bytes
.../phpqrcode/cache/mask_1/mask_61_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_65_1.dat | Bin 0 -> 99 bytes
.../phpqrcode/cache/mask_1/mask_69_1.dat | Bin 0 -> 102 bytes
.../phpqrcode/cache/mask_1/mask_73_1.dat | Bin 0 -> 104 bytes
.../phpqrcode/cache/mask_1/mask_77_1.dat | Bin 0 -> 110 bytes
.../phpqrcode/cache/mask_1/mask_81_1.dat | Bin 0 -> 114 bytes
.../phpqrcode/cache/mask_1/mask_85_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_89_1.dat | 1 +
.../phpqrcode/cache/mask_1/mask_93_1.dat | 2 +
.../phpqrcode/cache/mask_1/mask_97_1.dat | 2 +
.../phpqrcode/cache/mask_2/mask_101_2.dat | 3 +
.../phpqrcode/cache/mask_2/mask_105_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_109_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_113_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_117_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_121_2.dat | Bin 0 -> 127 bytes
.../phpqrcode/cache/mask_2/mask_125_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_129_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_133_2.dat | 10 +
.../phpqrcode/cache/mask_2/mask_137_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_141_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_145_2.dat | 4 +
.../phpqrcode/cache/mask_2/mask_149_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_153_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_157_2.dat | 3 +
.../phpqrcode/cache/mask_2/mask_161_2.dat | Bin 0 -> 190 bytes
.../phpqrcode/cache/mask_2/mask_165_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_169_2.dat | Bin 0 -> 196 bytes
.../phpqrcode/cache/mask_2/mask_173_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_177_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_21_2.dat | Bin 0 -> 35 bytes
.../phpqrcode/cache/mask_2/mask_25_2.dat | Bin 0 -> 41 bytes
.../phpqrcode/cache/mask_2/mask_29_2.dat | Bin 0 -> 45 bytes
.../phpqrcode/cache/mask_2/mask_33_2.dat | Bin 0 -> 47 bytes
.../phpqrcode/cache/mask_2/mask_37_2.dat | Bin 0 -> 47 bytes
.../phpqrcode/cache/mask_2/mask_41_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_45_2.dat | Bin 0 -> 68 bytes
.../phpqrcode/cache/mask_2/mask_49_2.dat | Bin 0 -> 70 bytes
.../phpqrcode/cache/mask_2/mask_53_2.dat | Bin 0 -> 73 bytes
.../phpqrcode/cache/mask_2/mask_57_2.dat | Bin 0 -> 76 bytes
.../phpqrcode/cache/mask_2/mask_61_2.dat | Bin 0 -> 78 bytes
.../phpqrcode/cache/mask_2/mask_65_2.dat | Bin 0 -> 89 bytes
.../phpqrcode/cache/mask_2/mask_69_2.dat | Bin 0 -> 88 bytes
.../phpqrcode/cache/mask_2/mask_73_2.dat | Bin 0 -> 94 bytes
.../phpqrcode/cache/mask_2/mask_77_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_81_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_85_2.dat | 2 +
.../phpqrcode/cache/mask_2/mask_89_2.dat | 1 +
.../phpqrcode/cache/mask_2/mask_93_2.dat | Bin 0 -> 103 bytes
.../phpqrcode/cache/mask_2/mask_97_2.dat | 2 +
.../phpqrcode/cache/mask_3/mask_101_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_105_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_109_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_113_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_117_3.dat | 4 +
.../phpqrcode/cache/mask_3/mask_121_3.dat | Bin 0 -> 212 bytes
.../phpqrcode/cache/mask_3/mask_125_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_129_3.dat | 8 +
.../phpqrcode/cache/mask_3/mask_133_3.dat | Bin 0 -> 216 bytes
.../phpqrcode/cache/mask_3/mask_137_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_141_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_145_3.dat | 3 +
.../phpqrcode/cache/mask_3/mask_149_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_153_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_157_3.dat | Bin 0 -> 248 bytes
.../phpqrcode/cache/mask_3/mask_161_3.dat | 3 +
.../phpqrcode/cache/mask_3/mask_165_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_169_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_173_3.dat | 1 +
.../phpqrcode/cache/mask_3/mask_177_3.dat | Bin 0 -> 312 bytes
.../phpqrcode/cache/mask_3/mask_21_3.dat | Bin 0 -> 60 bytes
.../phpqrcode/cache/mask_3/mask_25_3.dat | Bin 0 -> 75 bytes
.../phpqrcode/cache/mask_3/mask_29_3.dat | Bin 0 -> 75 bytes
.../phpqrcode/cache/mask_3/mask_33_3.dat | Bin 0 -> 79 bytes
.../phpqrcode/cache/mask_3/mask_37_3.dat | Bin 0 -> 83 bytes
.../phpqrcode/cache/mask_3/mask_41_3.dat | Bin 0 -> 85 bytes
.../phpqrcode/cache/mask_3/mask_45_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_49_3.dat | Bin 0 -> 127 bytes
.../phpqrcode/cache/mask_3/mask_53_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_57_3.dat | Bin 0 -> 126 bytes
.../phpqrcode/cache/mask_3/mask_61_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_65_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_69_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_73_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_77_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_81_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_85_3.dat | Bin 0 -> 160 bytes
.../phpqrcode/cache/mask_3/mask_89_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_93_3.dat | 2 +
.../phpqrcode/cache/mask_3/mask_97_3.dat | Bin 0 -> 175 bytes
.../phpqrcode/cache/mask_4/mask_101_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_105_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_109_4.dat | Bin 0 -> 182 bytes
.../phpqrcode/cache/mask_4/mask_113_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_117_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_121_4.dat | Bin 0 -> 208 bytes
.../phpqrcode/cache/mask_4/mask_125_4.dat | Bin 0 -> 213 bytes
.../phpqrcode/cache/mask_4/mask_129_4.dat | Bin 0 -> 220 bytes
.../phpqrcode/cache/mask_4/mask_133_4.dat | 3 +
.../phpqrcode/cache/mask_4/mask_137_4.dat | Bin 0 -> 248 bytes
.../phpqrcode/cache/mask_4/mask_141_4.dat | Bin 0 -> 254 bytes
.../phpqrcode/cache/mask_4/mask_145_4.dat | Bin 0 -> 255 bytes
.../phpqrcode/cache/mask_4/mask_149_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_153_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_157_4.dat | 1 +
.../phpqrcode/cache/mask_4/mask_161_4.dat | 1 +
.../phpqrcode/cache/mask_4/mask_165_4.dat | 3 +
.../phpqrcode/cache/mask_4/mask_169_4.dat | Bin 0 -> 297 bytes
.../phpqrcode/cache/mask_4/mask_173_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_177_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_21_4.dat | Bin 0 -> 57 bytes
.../phpqrcode/cache/mask_4/mask_25_4.dat | Bin 0 -> 76 bytes
.../phpqrcode/cache/mask_4/mask_29_4.dat | Bin 0 -> 78 bytes
.../phpqrcode/cache/mask_4/mask_33_4.dat | Bin 0 -> 89 bytes
.../phpqrcode/cache/mask_4/mask_37_4.dat | Bin 0 -> 86 bytes
.../phpqrcode/cache/mask_4/mask_41_4.dat | Bin 0 -> 89 bytes
.../phpqrcode/cache/mask_4/mask_45_4.dat | Bin 0 -> 120 bytes
.../phpqrcode/cache/mask_4/mask_49_4.dat | Bin 0 -> 124 bytes
.../phpqrcode/cache/mask_4/mask_53_4.dat | Bin 0 -> 128 bytes
.../phpqrcode/cache/mask_4/mask_57_4.dat | Bin 0 -> 130 bytes
.../phpqrcode/cache/mask_4/mask_61_4.dat | Bin 0 -> 132 bytes
.../phpqrcode/cache/mask_4/mask_65_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_69_4.dat | 1 +
.../phpqrcode/cache/mask_4/mask_73_4.dat | 3 +
.../phpqrcode/cache/mask_4/mask_77_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_81_4.dat | 3 +
.../phpqrcode/cache/mask_4/mask_85_4.dat | Bin 0 -> 154 bytes
.../phpqrcode/cache/mask_4/mask_89_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_93_4.dat | 2 +
.../phpqrcode/cache/mask_4/mask_97_4.dat | Bin 0 -> 176 bytes
.../phpqrcode/cache/mask_5/mask_101_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_105_5.dat | Bin 0 -> 224 bytes
.../phpqrcode/cache/mask_5/mask_109_5.dat | Bin 0 -> 211 bytes
.../phpqrcode/cache/mask_5/mask_113_5.dat | 9 +
.../phpqrcode/cache/mask_5/mask_117_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_121_5.dat | Bin 0 -> 256 bytes
.../phpqrcode/cache/mask_5/mask_125_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_129_5.dat | Bin 0 -> 259 bytes
.../phpqrcode/cache/mask_5/mask_133_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_137_5.dat | 3 +
.../phpqrcode/cache/mask_5/mask_141_5.dat | Bin 0 -> 297 bytes
.../phpqrcode/cache/mask_5/mask_145_5.dat | Bin 0 -> 300 bytes
.../phpqrcode/cache/mask_5/mask_149_5.dat | 3 +
.../phpqrcode/cache/mask_5/mask_153_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_157_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_161_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_165_5.dat | Bin 0 -> 332 bytes
.../phpqrcode/cache/mask_5/mask_169_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_173_5.dat | 4 +
.../phpqrcode/cache/mask_5/mask_177_5.dat | 11 +
.../phpqrcode/cache/mask_5/mask_21_5.dat | Bin 0 -> 74 bytes
.../phpqrcode/cache/mask_5/mask_25_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_29_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_33_5.dat | Bin 0 -> 106 bytes
.../phpqrcode/cache/mask_5/mask_37_5.dat | Bin 0 -> 103 bytes
.../phpqrcode/cache/mask_5/mask_41_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_45_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_49_5.dat | Bin 0 -> 146 bytes
.../phpqrcode/cache/mask_5/mask_53_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_57_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_61_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_65_5.dat | Bin 0 -> 163 bytes
.../phpqrcode/cache/mask_5/mask_69_5.dat | Bin 0 -> 167 bytes
.../phpqrcode/cache/mask_5/mask_73_5.dat | Bin 0 -> 184 bytes
.../phpqrcode/cache/mask_5/mask_77_5.dat | 1 +
.../phpqrcode/cache/mask_5/mask_81_5.dat | 3 +
.../phpqrcode/cache/mask_5/mask_85_5.dat | Bin 0 -> 186 bytes
.../phpqrcode/cache/mask_5/mask_89_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_93_5.dat | 2 +
.../phpqrcode/cache/mask_5/mask_97_5.dat | 1 +
.../phpqrcode/cache/mask_6/mask_101_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_105_6.dat | 3 +
.../phpqrcode/cache/mask_6/mask_109_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_113_6.dat | 3 +
.../phpqrcode/cache/mask_6/mask_117_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_121_6.dat | Bin 0 -> 309 bytes
.../phpqrcode/cache/mask_6/mask_125_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_129_6.dat | Bin 0 -> 310 bytes
.../phpqrcode/cache/mask_6/mask_133_6.dat | Bin 0 -> 296 bytes
.../phpqrcode/cache/mask_6/mask_137_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_141_6.dat | 10 +
.../phpqrcode/cache/mask_6/mask_145_6.dat | Bin 0 -> 357 bytes
.../phpqrcode/cache/mask_6/mask_149_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_153_6.dat | Bin 0 -> 367 bytes
.../phpqrcode/cache/mask_6/mask_157_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_161_6.dat | Bin 0 -> 399 bytes
.../phpqrcode/cache/mask_6/mask_165_6.dat | Bin 0 -> 400 bytes
.../phpqrcode/cache/mask_6/mask_169_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_173_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_177_6.dat | 14 +
.../phpqrcode/cache/mask_6/mask_21_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_25_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_29_6.dat | 3 +
.../phpqrcode/cache/mask_6/mask_33_6.dat | Bin 0 -> 124 bytes
.../phpqrcode/cache/mask_6/mask_37_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_41_6.dat | Bin 0 -> 132 bytes
.../phpqrcode/cache/mask_6/mask_45_6.dat | Bin 0 -> 189 bytes
.../phpqrcode/cache/mask_6/mask_49_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_53_6.dat | Bin 0 -> 195 bytes
.../phpqrcode/cache/mask_6/mask_57_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_61_6.dat | 2 +
.../phpqrcode/cache/mask_6/mask_65_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_69_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_73_6.dat | Bin 0 -> 230 bytes
.../phpqrcode/cache/mask_6/mask_77_6.dat | 1 +
.../phpqrcode/cache/mask_6/mask_81_6.dat | 3 +
.../phpqrcode/cache/mask_6/mask_85_6.dat | Bin 0 -> 229 bytes
.../phpqrcode/cache/mask_6/mask_89_6.dat | Bin 0 -> 263 bytes
.../phpqrcode/cache/mask_6/mask_93_6.dat | Bin 0 -> 276 bytes
.../phpqrcode/cache/mask_6/mask_97_6.dat | 2 +
.../phpqrcode/cache/mask_7/mask_101_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_105_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_109_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_113_7.dat | 11 +
.../phpqrcode/cache/mask_7/mask_117_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_121_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_125_7.dat | Bin 0 -> 288 bytes
.../phpqrcode/cache/mask_7/mask_129_7.dat | Bin 0 -> 282 bytes
.../phpqrcode/cache/mask_7/mask_133_7.dat | Bin 0 -> 281 bytes
.../phpqrcode/cache/mask_7/mask_137_7.dat | 5 +
.../phpqrcode/cache/mask_7/mask_141_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_145_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_149_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_153_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_157_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_161_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_165_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_169_7.dat | Bin 0 -> 383 bytes
.../phpqrcode/cache/mask_7/mask_173_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_177_7.dat | Bin 0 -> 407 bytes
.../phpqrcode/cache/mask_7/mask_21_7.dat | 4 +
.../phpqrcode/cache/mask_7/mask_25_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_29_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_33_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_37_7.dat | Bin 0 -> 122 bytes
.../phpqrcode/cache/mask_7/mask_41_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_45_7.dat | Bin 0 -> 173 bytes
.../phpqrcode/cache/mask_7/mask_49_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_53_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_57_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_61_7.dat | 2 +
.../phpqrcode/cache/mask_7/mask_65_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_69_7.dat | Bin 0 -> 202 bytes
.../phpqrcode/cache/mask_7/mask_73_7.dat | Bin 0 -> 221 bytes
.../phpqrcode/cache/mask_7/mask_77_7.dat | Bin 0 -> 226 bytes
.../phpqrcode/cache/mask_7/mask_81_7.dat | 1 +
.../phpqrcode/cache/mask_7/mask_85_7.dat | Bin 0 -> 213 bytes
.../phpqrcode/cache/mask_7/mask_89_7.dat | Bin 0 -> 244 bytes
.../phpqrcode/cache/mask_7/mask_93_7.dat | Bin 0 -> 248 bytes
.../phpqrcode/cache/mask_7/mask_97_7.dat | 2 +
vendor/aferrandini/phpqrcode/composer.json | 21 +
vendor/aferrandini/phpqrcode/lib/PHPQRCode.php | 42 +
.../phpqrcode/lib/PHPQRCode/Autoloader.php | 48 +
.../phpqrcode/lib/PHPQRCode/Constants.php | 58 +
.../phpqrcode/lib/PHPQRCode/FrameFiller.php | 96 ++
.../phpqrcode/lib/PHPQRCode/QRbitstream.php | 182 +++
.../aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php | 158 ++
.../phpqrcode/lib/PHPQRCode/QRencode.php | 137 ++
.../phpqrcode/lib/PHPQRCode/QRimage.php | 95 ++
.../phpqrcode/lib/PHPQRCode/QRinput.php | 486 +++++++
.../phpqrcode/lib/PHPQRCode/QRinputItem.php | 246 ++++
.../aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php | 325 +++++
.../phpqrcode/lib/PHPQRCode/QRrawcode.php | 117 ++
.../aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php | 56 +
.../phpqrcode/lib/PHPQRCode/QRrsItem.php | 162 +++
.../phpqrcode/lib/PHPQRCode/QRrsblock.php | 25 +
.../aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php | 586 ++++++++
.../phpqrcode/lib/PHPQRCode/QRsplit.php | 316 ++++
.../aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php | 35 +
.../phpqrcode/lib/PHPQRCode/QRtools.php | 171 +++
vendor/aferrandini/phpqrcode/readme.md | 37 +
vendor/autoload.php | 7 +
vendor/bin/picofeed | 1 +
vendor/christian-riesen/base32/.gitignore | 3 +
vendor/christian-riesen/base32/.scrutinizer.yml | 14 +
vendor/christian-riesen/base32/.travis.yml | 19 +
vendor/christian-riesen/base32/LICENSE | 19 +
vendor/christian-riesen/base32/README.md | 60 +
vendor/christian-riesen/base32/build.xml | 130 ++
vendor/christian-riesen/base32/composer.json | 33 +
vendor/christian-riesen/base32/phpunit.xml.dist | 32 +
vendor/christian-riesen/base32/src/Base32.php | 146 ++
.../christian-riesen/base32/tests/Base32Test.php | 51 +
vendor/christian-riesen/base32/tests/bootstrap.php | 5 +
vendor/christian-riesen/otp/.gitignore | 5 +
vendor/christian-riesen/otp/.travis.yml | 11 +
vendor/christian-riesen/otp/LICENSE | 20 +
vendor/christian-riesen/otp/README.md | 105 ++
vendor/christian-riesen/otp/composer.json | 28 +
vendor/christian-riesen/otp/example/index.php | 100 ++
vendor/christian-riesen/otp/phpunit.xml.dist | 15 +
.../otp/src/Otp/GoogleAuthenticator.php | 189 +++
vendor/christian-riesen/otp/src/Otp/Otp.php | 310 ++++
.../christian-riesen/otp/src/Otp/OtpInterface.php | 65 +
.../otp/tests/Otp/GoogleAuthenticatorTest.php | 88 ++
vendor/christian-riesen/otp/tests/Otp/OtpTest.php | 124 ++
vendor/composer/ClassLoader.php | 445 ++++++
vendor/composer/LICENSE | 21 +
vendor/composer/autoload_classmap.php | 901 ++++++++++++
vendor/composer/autoload_files.php | 15 +
vendor/composer/autoload_namespaces.php | 20 +
vendor/composer/autoload_psr4.php | 17 +
vendor/composer/autoload_real.php | 70 +
vendor/composer/autoload_static.php | 1049 ++++++++++++++
vendor/composer/installed.json | 1051 ++++++++++++++
vendor/eluceo/ical/.gitignore | 3 +
vendor/eluceo/ical/.php_cs | 26 +
vendor/eluceo/ical/.scrutinizer.yml | 20 +
vendor/eluceo/ical/.travis.yml | 19 +
vendor/eluceo/ical/CHANGELOG.md | 31 +
vendor/eluceo/ical/LICENSE | 19 +
vendor/eluceo/ical/README.md | 158 ++
vendor/eluceo/ical/UPGRADE.md | 9 +
vendor/eluceo/ical/composer.json | 43 +
vendor/eluceo/ical/examples/example1.php | 30 +
vendor/eluceo/ical/examples/example2.php | 31 +
vendor/eluceo/ical/examples/example3.php | 36 +
vendor/eluceo/ical/examples/example4.php | 35 +
vendor/eluceo/ical/examples/example5.php | 66 +
vendor/eluceo/ical/examples/example6.php | 30 +
vendor/eluceo/ical/examples/example7.php | 33 +
vendor/eluceo/ical/phpunit.xml.dist | 21 +
vendor/eluceo/ical/src/Eluceo/iCal/Component.php | 172 +++
.../ical/src/Eluceo/iCal/Component/Alarm.php | 151 ++
.../ical/src/Eluceo/iCal/Component/Calendar.php | 323 +++++
.../ical/src/Eluceo/iCal/Component/Event.php | 783 ++++++++++
.../ical/src/Eluceo/iCal/Component/Timezone.php | 57 +
.../src/Eluceo/iCal/Component/TimezoneRule.php | 215 +++
.../eluceo/ical/src/Eluceo/iCal/ParameterBag.php | 108 ++
vendor/eluceo/ical/src/Eluceo/iCal/Property.php | 148 ++
.../ical/src/Eluceo/iCal/Property/ArrayValue.php | 43 +
.../src/Eluceo/iCal/Property/DateTimeProperty.php | 38 +
.../src/Eluceo/iCal/Property/DateTimesProperty.php | 41 +
.../src/Eluceo/iCal/Property/Event/Attendees.php | 102 ++
.../src/Eluceo/iCal/Property/Event/Description.php | 66 +
.../src/Eluceo/iCal/Property/Event/Organizer.php | 39 +
.../Eluceo/iCal/Property/Event/RecurrenceId.php | 130 ++
.../Eluceo/iCal/Property/Event/RecurrenceRule.php | 444 ++++++
.../ical/src/Eluceo/iCal/Property/StringValue.php | 61 +
.../src/Eluceo/iCal/Property/ValueInterface.php | 24 +
vendor/eluceo/ical/src/Eluceo/iCal/PropertyBag.php | 79 +
.../ical/src/Eluceo/iCal/Util/ComponentUtil.php | 48 +
.../eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php | 69 +
.../src/Eluceo/iCal/Util/PropertyValueUtil.php | 40 +
.../iCal/Component/CalendarIntegrationTest.php | 64 +
.../ical/tests/Eluceo/iCal/ComponentTest.php | 45 +
.../ical/tests/Eluceo/iCal/ParameterBagTest.php | 35 +
.../tests/Eluceo/iCal/Property/ArrayValueTest.php | 26 +
.../Eluceo/iCal/Property/Event/DescriptionTest.php | 17 +
.../Eluceo/iCal/Property/Event/OrganizerTest.php | 63 +
.../iCal/Property/Event/RecurrenceRuleTest.php | 21 +
.../tests/Eluceo/iCal/Property/StringValueTest.php | 63 +
.../ical/tests/Eluceo/iCal/PropertyBagTest.php | 18 +
.../eluceo/ical/tests/Eluceo/iCal/PropertyTest.php | 42 +
vendor/erusev/parsedown/.travis.yml | 16 +
vendor/erusev/parsedown/LICENSE.txt | 20 +
vendor/erusev/parsedown/Parsedown.php | 1528 ++++++++++++++++++++
vendor/erusev/parsedown/README.md | 57 +
vendor/erusev/parsedown/composer.json | 18 +
vendor/erusev/parsedown/phpunit.xml.dist | 8 +
vendor/erusev/parsedown/test/CommonMarkTest.php | 74 +
vendor/erusev/parsedown/test/ParsedownTest.php | 159 ++
vendor/erusev/parsedown/test/TestParsedown.php | 5 +
vendor/erusev/parsedown/test/bootstrap.php | 3 +
.../parsedown/test/data/aesthetic_table.html | 18 +
.../erusev/parsedown/test/data/aesthetic_table.md | 4 +
.../erusev/parsedown/test/data/aligned_table.html | 21 +
vendor/erusev/parsedown/test/data/aligned_table.md | 4 +
vendor/erusev/parsedown/test/data/atx_heading.html | 9 +
vendor/erusev/parsedown/test/data/atx_heading.md | 17 +
.../erusev/parsedown/test/data/automatic_link.html | 1 +
.../erusev/parsedown/test/data/automatic_link.md | 1 +
.../parsedown/test/data/block-level_html.html | 12 +
.../erusev/parsedown/test/data/block-level_html.md | 16 +
vendor/erusev/parsedown/test/data/code_block.html | 8 +
vendor/erusev/parsedown/test/data/code_block.md | 10 +
vendor/erusev/parsedown/test/data/code_span.html | 6 +
vendor/erusev/parsedown/test/data/code_span.md | 11 +
.../parsedown/test/data/compound_blockquote.html | 9 +
.../parsedown/test/data/compound_blockquote.md | 10 +
.../parsedown/test/data/compound_emphasis.html | 2 +
.../parsedown/test/data/compound_emphasis.md | 4 +
.../erusev/parsedown/test/data/compound_list.html | 12 +
vendor/erusev/parsedown/test/data/compound_list.md | 7 +
.../parsedown/test/data/deeply_nested_list.html | 12 +
.../parsedown/test/data/deeply_nested_list.md | 6 +
vendor/erusev/parsedown/test/data/em_strong.html | 8 +
vendor/erusev/parsedown/test/data/em_strong.md | 15 +
vendor/erusev/parsedown/test/data/email.html | 1 +
vendor/erusev/parsedown/test/data/email.md | 1 +
vendor/erusev/parsedown/test/data/emphasis.html | 8 +
vendor/erusev/parsedown/test/data/emphasis.md | 13 +
vendor/erusev/parsedown/test/data/escaping.html | 6 +
vendor/erusev/parsedown/test/data/escaping.md | 11 +
.../parsedown/test/data/fenced_code_block.html | 6 +
.../parsedown/test/data/fenced_code_block.md | 14 +
.../parsedown/test/data/horizontal_rule.html | 5 +
.../erusev/parsedown/test/data/horizontal_rule.md | 9 +
.../erusev/parsedown/test/data/html_comment.html | 5 +
vendor/erusev/parsedown/test/data/html_comment.md | 8 +
vendor/erusev/parsedown/test/data/html_entity.html | 1 +
vendor/erusev/parsedown/test/data/html_entity.md | 1 +
.../parsedown/test/data/image_reference.html | 2 +
.../erusev/parsedown/test/data/image_reference.md | 5 +
vendor/erusev/parsedown/test/data/image_title.html | 2 +
vendor/erusev/parsedown/test/data/image_title.md | 3 +
.../parsedown/test/data/implicit_reference.html | 4 +
.../parsedown/test/data/implicit_reference.md | 13 +
vendor/erusev/parsedown/test/data/inline_link.html | 6 +
vendor/erusev/parsedown/test/data/inline_link.md | 11 +
.../parsedown/test/data/inline_link_title.html | 6 +
.../parsedown/test/data/inline_link_title.md | 11 +
.../erusev/parsedown/test/data/inline_title.html | 1 +
vendor/erusev/parsedown/test/data/inline_title.md | 1 +
.../parsedown/test/data/lazy_blockquote.html | 6 +
.../erusev/parsedown/test/data/lazy_blockquote.md | 5 +
vendor/erusev/parsedown/test/data/lazy_list.html | 4 +
vendor/erusev/parsedown/test/data/lazy_list.md | 2 +
vendor/erusev/parsedown/test/data/line_break.html | 2 +
vendor/erusev/parsedown/test/data/line_break.md | 2 +
.../test/data/multiline_list_paragraph.html | 7 +
.../test/data/multiline_list_paragraph.md | 4 +
.../test/data/nested_block-level_html.html | 10 +
.../parsedown/test/data/nested_block-level_html.md | 11 +
.../erusev/parsedown/test/data/ordered_list.html | 13 +
vendor/erusev/parsedown/test/data/ordered_list.md | 11 +
.../erusev/parsedown/test/data/paragraph_list.html | 12 +
.../erusev/parsedown/test/data/paragraph_list.md | 9 +
.../parsedown/test/data/reference_title.html | 2 +
.../erusev/parsedown/test/data/reference_title.md | 6 +
.../parsedown/test/data/self-closing_html.html | 12 +
.../parsedown/test/data/self-closing_html.md | 12 +
.../parsedown/test/data/separated_nested_list.html | 9 +
.../parsedown/test/data/separated_nested_list.md | 4 +
.../erusev/parsedown/test/data/setext_header.html | 5 +
vendor/erusev/parsedown/test/data/setext_header.md | 12 +
.../parsedown/test/data/simple_blockquote.html | 11 +
.../parsedown/test/data/simple_blockquote.md | 7 +
.../erusev/parsedown/test/data/simple_table.html | 37 +
vendor/erusev/parsedown/test/data/simple_table.md | 11 +
.../parsedown/test/data/span-level_html.html | 5 +
.../erusev/parsedown/test/data/span-level_html.md | 8 +
.../parsedown/test/data/sparse_dense_list.html | 7 +
.../parsedown/test/data/sparse_dense_list.md | 4 +
vendor/erusev/parsedown/test/data/sparse_html.html | 8 +
vendor/erusev/parsedown/test/data/sparse_html.md | 8 +
vendor/erusev/parsedown/test/data/sparse_list.html | 15 +
vendor/erusev/parsedown/test/data/sparse_list.md | 9 +
.../parsedown/test/data/special_characters.html | 6 +
.../parsedown/test/data/special_characters.md | 13 +
.../erusev/parsedown/test/data/strikethrough.html | 3 +
vendor/erusev/parsedown/test/data/strikethrough.md | 5 +
vendor/erusev/parsedown/test/data/strong_em.html | 6 +
vendor/erusev/parsedown/test/data/strong_em.md | 11 +
.../test/data/tab-indented_code_block.html | 6 +
.../parsedown/test/data/tab-indented_code_block.md | 6 +
.../parsedown/test/data/table_inline_markdown.html | 22 +
.../parsedown/test/data/table_inline_markdown.md | 5 +
.../erusev/parsedown/test/data/text_reference.html | 8 +
.../erusev/parsedown/test/data/text_reference.md | 21 +
.../erusev/parsedown/test/data/unordered_list.html | 10 +
.../erusev/parsedown/test/data/unordered_list.md | 8 +
.../erusev/parsedown/test/data/untidy_table.html | 18 +
vendor/erusev/parsedown/test/data/untidy_table.md | 4 +
.../parsedown/test/data/url_autolinking.html | 3 +
.../erusev/parsedown/test/data/url_autolinking.md | 5 +
vendor/erusev/parsedown/test/data/whitespace.html | 1 +
vendor/erusev/parsedown/test/data/whitespace.md | 5 +
vendor/fguillot/json-rpc/LICENSE | 21 +
vendor/fguillot/json-rpc/src/JsonRPC/Client.php | 194 +++
.../JsonRPC/Exception/AccessDeniedException.php | 15 +
.../Exception/AuthenticationFailureException.php | 15 +
.../Exception/ConnectionFailureException.php | 15 +
.../Exception/InvalidJsonFormatException.php | 15 +
.../Exception/InvalidJsonRpcFormatException.php | 15 +
.../Exception/ResponseEncodingFailureException.php | 15 +
.../src/JsonRPC/Exception/ResponseException.php | 62 +
.../src/JsonRPC/Exception/ServerErrorException.php | 15 +
.../fguillot/json-rpc/src/JsonRPC/HttpClient.php | 365 +++++
.../json-rpc/src/JsonRPC/MiddlewareHandler.php | 114 ++
.../json-rpc/src/JsonRPC/MiddlewareInterface.php | 27 +
.../json-rpc/src/JsonRPC/ProcedureHandler.php | 264 ++++
.../src/JsonRPC/Request/BatchRequestParser.php | 55 +
.../src/JsonRPC/Request/RequestBuilder.php | 129 ++
.../json-rpc/src/JsonRPC/Request/RequestParser.php | 200 +++
.../src/JsonRPC/Response/ResponseBuilder.php | 324 +++++
.../src/JsonRPC/Response/ResponseParser.php | 154 ++
vendor/fguillot/json-rpc/src/JsonRPC/Server.php | 386 +++++
.../src/JsonRPC/Validator/HostValidator.php | 30 +
.../JsonRPC/Validator/JsonEncodingValidator.php | 44 +
.../src/JsonRPC/Validator/JsonFormatValidator.php | 30 +
.../src/JsonRPC/Validator/RpcFormatValidator.php | 35 +
.../src/JsonRPC/Validator/UserValidator.php | 21 +
vendor/fguillot/picodb/LICENSE | 21 +
.../picodb/lib/PicoDb/Builder/BaseBuilder.php | 86 ++
.../picodb/lib/PicoDb/Builder/ConditionBuilder.php | 377 +++++
.../picodb/lib/PicoDb/Builder/InsertBuilder.php | 36 +
.../lib/PicoDb/Builder/OrConditionBuilder.php | 43 +
.../picodb/lib/PicoDb/Builder/UpdateBuilder.php | 56 +
vendor/fguillot/picodb/lib/PicoDb/Database.php | 370 +++++
vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php | 234 +++
vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php | 178 +++
vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php | 252 ++++
.../fguillot/picodb/lib/PicoDb/Driver/Postgres.php | 196 +++
.../fguillot/picodb/lib/PicoDb/Driver/Sqlite.php | 193 +++
.../fguillot/picodb/lib/PicoDb/DriverFactory.php | 45 +
vendor/fguillot/picodb/lib/PicoDb/Hashtable.php | 112 ++
vendor/fguillot/picodb/lib/PicoDb/LargeObject.php | 167 +++
vendor/fguillot/picodb/lib/PicoDb/SQLException.php | 15 +
vendor/fguillot/picodb/lib/PicoDb/Schema.php | 119 ++
.../picodb/lib/PicoDb/StatementHandler.php | 353 +++++
vendor/fguillot/picodb/lib/PicoDb/Table.php | 721 +++++++++
vendor/fguillot/picodb/lib/PicoDb/UrlParser.php | 93 ++
vendor/fguillot/simple-queue/LICENSE | 21 +
.../simple-queue/src/Adapter/AmqpQueueAdapter.php | 138 ++
.../src/Adapter/AwsSqsQueueAdapter.php | 150 ++
.../src/Adapter/BeanstalkQueueAdapter.php | 120 ++
.../src/Adapter/DisqueQueueAdapter.php | 109 ++
.../src/Adapter/MemoryQueueAdapter.php | 100 ++
.../src/Exception/NotSupportedException.php | 14 +
vendor/fguillot/simple-queue/src/Job.php | 98 ++
vendor/fguillot/simple-queue/src/Queue.php | 92 ++
.../simple-queue/src/QueueAdapterInterface.php | 58 +
vendor/fguillot/simple-validator/LICENSE | 21 +
.../src/SimpleValidator/Validator.php | 44 +
.../src/SimpleValidator/Validators/Alpha.php | 15 +
.../SimpleValidator/Validators/AlphaNumeric.php | 15 +
.../src/SimpleValidator/Validators/Base.php | 37 +
.../src/SimpleValidator/Validators/Date.php | 45 +
.../src/SimpleValidator/Validators/Email.php | 67 +
.../src/SimpleValidator/Validators/Equals.php | 27 +
.../src/SimpleValidator/Validators/Exists.php | 38 +
.../src/SimpleValidator/Validators/GreaterThan.php | 23 +
.../src/SimpleValidator/Validators/InArray.php | 23 +
.../src/SimpleValidator/Validators/Integer.php | 25 +
.../src/SimpleValidator/Validators/Ip.php | 15 +
.../src/SimpleValidator/Validators/Length.php | 26 +
.../src/SimpleValidator/Validators/MaxLength.php | 24 +
.../src/SimpleValidator/Validators/MinLength.php | 24 +
.../src/SimpleValidator/Validators/NotEmpty.php | 15 +
.../src/SimpleValidator/Validators/NotEquals.php | 28 +
.../src/SimpleValidator/Validators/NotInArray.php | 15 +
.../src/SimpleValidator/Validators/Numeric.php | 15 +
.../src/SimpleValidator/Validators/Range.php | 33 +
.../src/SimpleValidator/Validators/Required.php | 11 +
.../src/SimpleValidator/Validators/Unique.php | 48 +
vendor/fguillot/simpleLogger/LICENSE | 21 +
.../simpleLogger/src/SimpleLogger/Base.php | 89 ++
.../simpleLogger/src/SimpleLogger/File.php | 48 +
.../simpleLogger/src/SimpleLogger/Logger.php | 94 ++
.../simpleLogger/src/SimpleLogger/Stderr.php | 25 +
.../simpleLogger/src/SimpleLogger/Stdout.php | 25 +
.../simpleLogger/src/SimpleLogger/Syslog.php | 72 +
vendor/gregwar/captcha/.gitignore | 3 +
vendor/gregwar/captcha/.travis.yml | 12 +
vendor/gregwar/captcha/CaptchaBuilder.php | 720 +++++++++
vendor/gregwar/captcha/CaptchaBuilderInterface.php | 30 +
vendor/gregwar/captcha/Font/captcha0.ttf | Bin 0 -> 49224 bytes
vendor/gregwar/captcha/Font/captcha1.ttf | Bin 0 -> 76232 bytes
vendor/gregwar/captcha/Font/captcha2.ttf | Bin 0 -> 33984 bytes
vendor/gregwar/captcha/Font/captcha3.ttf | Bin 0 -> 15976 bytes
vendor/gregwar/captcha/Font/captcha4.ttf | Bin 0 -> 906980 bytes
vendor/gregwar/captcha/Font/captcha5.ttf | Bin 0 -> 49724 bytes
vendor/gregwar/captcha/ImageFileHandler.php | 106 ++
vendor/gregwar/captcha/LICENSE | 19 +
vendor/gregwar/captcha/PhraseBuilder.php | 34 +
vendor/gregwar/captcha/PhraseBuilderInterface.php | 21 +
vendor/gregwar/captcha/README.md | 108 ++
vendor/gregwar/captcha/autoload.php | 16 +
vendor/gregwar/captcha/composer.json | 28 +
vendor/gregwar/captcha/demo/demo.php | 14 +
vendor/gregwar/captcha/demo/fingerprint.php | 15 +
vendor/gregwar/captcha/demo/index.php | 15 +
vendor/gregwar/captcha/demo/ocr.php | 42 +
vendor/gregwar/captcha/demo/output.php | 15 +
vendor/miniflux/picofeed/LICENSE | 21 +
vendor/miniflux/picofeed/lib/PicoFeed/Base.php | 38 +
.../picofeed/lib/PicoFeed/Client/Client.php | 719 +++++++++
.../lib/PicoFeed/Client/ClientException.php | 14 +
.../miniflux/picofeed/lib/PicoFeed/Client/Curl.php | 402 +++++
.../lib/PicoFeed/Client/ForbiddenException.php | 10 +
.../picofeed/lib/PicoFeed/Client/HttpHeaders.php | 79 +
.../Client/InvalidCertificateException.php | 12 +
.../lib/PicoFeed/Client/InvalidUrlException.php | 12 +
.../lib/PicoFeed/Client/MaxRedirectException.php | 12 +
.../lib/PicoFeed/Client/MaxSizeException.php | 12 +
.../picofeed/lib/PicoFeed/Client/Stream.php | 205 +++
.../lib/PicoFeed/Client/TimeoutException.php | 12 +
.../lib/PicoFeed/Client/UnauthorizedException.php | 10 +
.../miniflux/picofeed/lib/PicoFeed/Client/Url.php | 290 ++++
.../picofeed/lib/PicoFeed/Encoding/Encoding.php | 33 +
.../picofeed/lib/PicoFeed/Filter/Attribute.php | 700 +++++++++
.../picofeed/lib/PicoFeed/Filter/Filter.php | 155 ++
.../miniflux/picofeed/lib/PicoFeed/Filter/Html.php | 243 ++++
.../miniflux/picofeed/lib/PicoFeed/Filter/Tag.php | 218 +++
.../Generator/ContentGeneratorInterface.php | 23 +
.../PicoFeed/Generator/FileContentGenerator.php | 36 +
.../PicoFeed/Generator/YoutubeContentGenerator.php | 67 +
.../picofeed/lib/PicoFeed/Logging/Logger.php | 114 ++
.../miniflux/picofeed/lib/PicoFeed/Parser/Atom.php | 382 +++++
.../picofeed/lib/PicoFeed/Parser/DateParser.php | 128 ++
.../miniflux/picofeed/lib/PicoFeed/Parser/Feed.php | 315 ++++
.../miniflux/picofeed/lib/PicoFeed/Parser/Item.php | 534 +++++++
.../lib/PicoFeed/Parser/MalformedXmlException.php | 13 +
.../picofeed/lib/PicoFeed/Parser/Parser.php | 404 ++++++
.../lib/PicoFeed/Parser/ParserException.php | 15 +
.../lib/PicoFeed/Parser/ParserInterface.php | 182 +++
.../picofeed/lib/PicoFeed/Parser/Rss10.php | 306 ++++
.../picofeed/lib/PicoFeed/Parser/Rss20.php | 319 ++++
.../picofeed/lib/PicoFeed/Parser/Rss91.php | 13 +
.../picofeed/lib/PicoFeed/Parser/Rss92.php | 13 +
.../lib/PicoFeed/Parser/XmlEntityException.php | 13 +
.../picofeed/lib/PicoFeed/Parser/XmlParser.php | 246 ++++
.../picofeed/lib/PicoFeed/PicoFeedException.php | 14 +
.../PicoFeed/Processor/ContentFilterProcessor.php | 37 +
.../Processor/ContentGeneratorProcessor.php | 49 +
.../lib/PicoFeed/Processor/ItemPostProcessor.php | 106 ++
.../PicoFeed/Processor/ItemProcessorInterface.php | 25 +
.../lib/PicoFeed/Processor/ScraperProcessor.php | 96 ++
.../picofeed/lib/PicoFeed/Reader/Favicon.php | 186 +++
.../picofeed/lib/PicoFeed/Reader/Reader.php | 190 +++
.../lib/PicoFeed/Reader/ReaderException.php | 14 +
.../Reader/SubscriptionNotFoundException.php | 12 +
.../Reader/UnsupportedFeedFormatException.php | 12 +
.../lib/PicoFeed/Rules/.blog.lemonde.fr.php | 14 +
.../lib/PicoFeed/Rules/.blogs.nytimes.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/.igen.fr.php | 13 +
.../picofeed/lib/PicoFeed/Rules/.nytimes.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/.over-blog.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/.phoronix.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/.slate.com.php | 20 +
.../lib/PicoFeed/Rules/.theguardian.com.php | 14 +
.../picofeed/lib/PicoFeed/Rules/.wikipedia.org.php | 29 +
.../picofeed/lib/PicoFeed/Rules/.wired.com.php | 44 +
.../picofeed/lib/PicoFeed/Rules/.wsj.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/01net.com.php | 18 +
.../lib/PicoFeed/Rules/abstrusegoose.com.php | 8 +
.../lib/PicoFeed/Rules/adventuregamers.com.php | 23 +
.../lib/PicoFeed/Rules/alainonline.net.php | 14 +
.../picofeed/lib/PicoFeed/Rules/aljazeera.com.php | 25 +
.../picofeed/lib/PicoFeed/Rules/allafrica.com.php | 20 +
.../lib/PicoFeed/Rules/allgemeine-zeitung.de.php | 23 +
.../lib/PicoFeed/Rules/amazingsuperpowers.com.php | 8 +
.../lib/PicoFeed/Rules/anythingcomic.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/ap.org.php | 13 +
.../picofeed/lib/PicoFeed/Rules/areadvd.de.php | 10 +
.../lib/PicoFeed/Rules/arstechnica.com.php | 25 +
.../lib/PicoFeed/Rules/awkwardzombie.com.php | 10 +
.../lib/PicoFeed/Rules/backchannel.com.php | 18 +
.../lib/PicoFeed/Rules/bangkokpost.com.php | 19 +
.../picofeed/lib/PicoFeed/Rules/bgr.com.php | 15 +
.../lib/PicoFeed/Rules/bigfootjustice.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/bigpicture.ru.php | 31 +
.../lib/PicoFeed/Rules/bizjournals.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/biztimes.com.php | 22 +
.../lib/PicoFeed/Rules/bleepingcomputer.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/blog.fefe.de.php | 13 +
.../lib/PicoFeed/Rules/blog.mapillary.com.php | 11 +
.../lib/PicoFeed/Rules/brewers.mlb.com.php | 22 +
.../lib/PicoFeed/Rules/buenosairesherald.com.php | 17 +
.../picofeed/lib/PicoFeed/Rules/bunicomic.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/buttersafe.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/cad-comic.com.php | 12 +
.../lib/PicoFeed/Rules/chaoslife.findchaos.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/chinafile.com.php | 18 +
.../lib/PicoFeed/Rules/cliquerefresh.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/cnet.com.php | 37 +
.../picofeed/lib/PicoFeed/Rules/consomac.fr.php | 13 +
.../lib/PicoFeed/Rules/cowbirdsinlove.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/crash.net.php | 28 +
.../picofeed/lib/PicoFeed/Rules/csmonitor.com.php | 19 +
.../picofeed/lib/PicoFeed/Rules/dailyjs.com.php | 19 +
.../lib/PicoFeed/Rules/dailyreporter.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/dailytech.com.php | 13 +
.../lib/PicoFeed/Rules/degroupnews.com.php | 14 +
.../picofeed/lib/PicoFeed/Rules/derstandard.at.php | 14 +
.../picofeed/lib/PicoFeed/Rules/dilbert.com.php | 11 +
.../lib/PicoFeed/Rules/discovermagazine.com.php | 26 +
.../lib/PicoFeed/Rules/distrowatch.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/dozodomo.com.php | 15 +
.../lib/PicoFeed/Rules/drawingboardcomic.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/e-w-e.ru.php | 22 +
.../picofeed/lib/PicoFeed/Rules/economist.com.php | 25 +
.../PicoFeed/Rules/encyclopedie.naheulbeuk.com.php | 13 +
.../lib/PicoFeed/Rules/endlessorigami.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/engadget.com.php | 10 +
.../lib/PicoFeed/Rules/escapistmagazine.com.php | 45 +
.../picofeed/lib/PicoFeed/Rules/espn.go.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/exocomics.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/explosm.net.php | 13 +
.../lib/PicoFeed/Rules/extrafabulouscomics.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/factroom.ru.php | 27 +
.../lib/PicoFeed/Rules/fastcodesign.com.php | 13 +
.../lib/PicoFeed/Rules/fastcoexist.com.php | 13 +
.../lib/PicoFeed/Rules/fastcompany.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/ffworld.com.php | 13 +
.../lib/PicoFeed/Rules/foreignpolicy.com.php | 21 +
.../picofeed/lib/PicoFeed/Rules/fossbytes.com.php | 18 +
.../lib/PicoFeed/Rules/fototelegraf.ru.php | 19 +
.../lib/PicoFeed/Rules/fowllanguagecomics.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/geek.com.php | 17 +
.../picofeed/lib/PicoFeed/Rules/geektimes.ru.php | 12 +
.../lib/PicoFeed/Rules/gerbilwithajetpack.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/giantitp.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/github.com.php | 14 +
.../picofeed/lib/PicoFeed/Rules/gocomics.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/golem.de.php | 20 +
.../picofeed/lib/PicoFeed/Rules/gorabbit.ru.php | 19 +
.../picofeed/lib/PicoFeed/Rules/habrahabr.ru.php | 12 +
.../picofeed/lib/PicoFeed/Rules/happletea.com.php | 18 +
.../picofeed/lib/PicoFeed/Rules/hardware.fr.php | 11 +
.../picofeed/lib/PicoFeed/Rules/heise.de.php | 12 +
.../lib/PicoFeed/Rules/hotshowlife.com.php | 23 +
.../lib/PicoFeed/Rules/huffingtonpost.com.php | 13 +
.../lib/PicoFeed/Rules/imogenquest.net.php | 8 +
.../picofeed/lib/PicoFeed/Rules/indiehaven.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/ing.dk.php | 12 +
.../lib/PicoFeed/Rules/invisiblebread.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/ir.amd.com.php | 10 +
.../lib/PicoFeed/Rules/japantimes.co.jp.php | 21 +
.../picofeed/lib/PicoFeed/Rules/japantoday.com.php | 15 +
.../lib/PicoFeed/Rules/journaldugeek.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/jsonline.com.php | 37 +
.../lib/PicoFeed/Rules/justcoolidea.ru.php | 19 +
.../picofeed/lib/PicoFeed/Rules/kanpai.fr.php | 13 +
.../lib/PicoFeed/Rules/karriere.jobfinder.dk.php | 12 +
.../picofeed/lib/PicoFeed/Rules/kodi.tv.php | 11 +
.../lib/PicoFeed/Rules/koreaherald.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/koreatimes.php | 14 +
.../lib/PicoFeed/Rules/lastplacecomics.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/legorafi.fr.php | 22 +
.../picofeed/lib/PicoFeed/Rules/lejapon.fr.php | 17 +
.../lib/PicoFeed/Rules/lesjoiesducode.fr.php | 13 +
.../picofeed/lib/PicoFeed/Rules/lfg.co.php | 12 +
.../picofeed/lib/PicoFeed/Rules/lifehacker.com.php | 18 +
.../picofeed/lib/PicoFeed/Rules/lifehacker.ru.php | 22 +
.../picofeed/lib/PicoFeed/Rules/linux.org.php | 14 +
.../picofeed/lib/PicoFeed/Rules/linux.org.ru.php | 13 +
.../lib/PicoFeed/Rules/linuxinsider.com.php | 20 +
.../miniflux/picofeed/lib/PicoFeed/Rules/lists.php | 13 +
.../lib/PicoFeed/Rules/loadingartist.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/loldwell.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/lukesurl.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/macg.co.php | 13 +
.../picofeed/lib/PicoFeed/Rules/marc.info.php | 13 +
.../lib/PicoFeed/Rules/marriedtothesea.com.php | 12 +
.../picofeed/lib/PicoFeed/Rules/marycagle.com.php | 13 +
.../Rules/maximumble.thebookofbiff.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/medium.com.php | 19 +
.../picofeed/lib/PicoFeed/Rules/mercworks.net.php | 17 +
.../picofeed/lib/PicoFeed/Rules/metronieuws.nl.php | 10 +
.../picofeed/lib/PicoFeed/Rules/milwaukeenns.php | 14 +
.../lib/PicoFeed/Rules/mokepon.smackjeeves.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/monandroid.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/monwindows.com.php | 13 +
.../lib/PicoFeed/Rules/moya-planeta.ru.php | 21 +
.../lib/PicoFeed/Rules/mrlovenstein.com.php | 9 +
.../picofeed/lib/PicoFeed/Rules/muckrock.com.php | 20 +
.../lib/PicoFeed/Rules/mynorthshorenow.com.php | 27 +
.../lib/PicoFeed/Rules/nakedCapitalism.php | 11 +
.../picofeed/lib/PicoFeed/Rules/nasa.gov.php | 14 +
.../picofeed/lib/PicoFeed/Rules/nat-geo.ru.php | 11 +
.../lib/PicoFeed/Rules/nationaljournal.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/nature.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/nba.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/nedroid.com.php | 8 +
.../lib/PicoFeed/Rules/networkworld.com.php | 20 +
.../lib/PicoFeed/Rules/neustadt-ticker.de.php | 15 +
.../picofeed/lib/PicoFeed/Rules/nextinpact.com.php | 18 +
.../lib/PicoFeed/Rules/niceteethcomic.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/nichtlustig.de.php | 8 +
.../picofeed/lib/PicoFeed/Rules/oglaf.com.php | 19 +
.../picofeed/lib/PicoFeed/Rules/onhax.net.php | 15 +
.../picofeed/lib/PicoFeed/Rules/onmilwaukee.php | 24 +
.../lib/PicoFeed/Rules/openculture.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/opennet.ru.php | 13 +
.../lib/PicoFeed/Rules/openrightsgroup.org.php | 20 +
.../picofeed/lib/PicoFeed/Rules/opensource.com.php | 22 +
.../picofeed/lib/PicoFeed/Rules/optipess.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/osnews.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/pastebin.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/peebleslab.com.php | 9 +
.../lib/PicoFeed/Rules/penny-arcade.com.php | 21 +
.../picofeed/lib/PicoFeed/Rules/pixelbeat.org.php | 12 +
.../lib/PicoFeed/Rules/plus.google.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/popstrip.com.php | 8 +
.../lib/PicoFeed/Rules/publicpolicyforum.org.php | 15 +
.../picofeed/lib/PicoFeed/Rules/publy.ru.php | 24 +
.../lib/PicoFeed/Rules/putaindecode.fr.php | 16 +
.../picofeed/lib/PicoFeed/Rules/recode.net.php | 20 +
.../lib/PicoFeed/Rules/retractionwatch.com.php | 18 +
.../lib/PicoFeed/Rules/rockpapershotgun.com.php | 11 +
.../lib/PicoFeed/Rules/rue89.nouvelobs.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php | 20 +
.../picofeed/lib/PicoFeed/Rules/satwcomic.com.php | 13 +
.../lib/PicoFeed/Rules/scrumalliance.org.php | 12 +
.../lib/PicoFeed/Rules/securityfocus.com.php | 17 +
.../lib/PicoFeed/Rules/sentfromthemoon.com.php | 18 +
.../picofeed/lib/PicoFeed/Rules/sitepoint.com.php | 13 +
.../picofeed/lib/PicoFeed/Rules/slashdot.org.php | 11 +
.../lib/PicoFeed/Rules/smallhousebliss.com.php | 19 +
.../lib/PicoFeed/Rules/smarthomewelt.de.php | 10 +
.../lib/PicoFeed/Rules/smashingmagazine.com.php | 10 +
.../lib/PicoFeed/Rules/smbc-comics.com.php | 14 +
.../picofeed/lib/PicoFeed/Rules/snopes.com.php | 22 +
.../lib/PicoFeed/Rules/soundandvision.com.php | 21 +
.../picofeed/lib/PicoFeed/Rules/spiegel.de.php | 11 +
.../lib/PicoFeed/Rules/stereophile.com.php | 11 +
.../picofeed/lib/PicoFeed/Rules/stupidfox.net.php | 13 +
.../lib/PicoFeed/Rules/subtraction.com.php | 15 +
.../miniflux/picofeed/lib/PicoFeed/Rules/sz.de.php | 10 +
.../picofeed/lib/PicoFeed/Rules/takprosto.cc.php | 21 +
.../picofeed/lib/PicoFeed/Rules/techcrunch.com.php | 15 +
.../lib/PicoFeed/Rules/the-ebook-reader.com.php | 15 +
.../lib/PicoFeed/Rules/theatlantic.com.php | 23 +
.../lib/PicoFeed/Rules/theawkwardyeti.com.php | 12 +
.../lib/PicoFeed/Rules/thecodinglove.com.php | 10 +
.../lib/PicoFeed/Rules/thedoghousediaries.com.php | 18 +
.../lib/PicoFeed/Rules/thegamercat.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/thehindu.com.php | 19 +
.../picofeed/lib/PicoFeed/Rules/thelocal.se.php | 17 +
.../lib/PicoFeed/Rules/themerepublic.net.php | 10 +
.../lib/PicoFeed/Rules/themoscowtimes.com.php | 18 +
.../lib/PicoFeed/Rules/thenewslens.com.php | 21 +
.../lib/PicoFeed/Rules/theodd1sout.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/theonion.com.php | 12 +
.../lib/PicoFeed/Rules/thestandard.com.hk.php | 22 +
.../lib/PicoFeed/Rules/threepanelsoul.com.php | 11 +
.../PicoFeed/Rules/timesofindia.indiatimes.com.php | 14 +
.../lib/PicoFeed/Rules/travel-dealz.de.php | 15 +
.../picofeed/lib/PicoFeed/Rules/treehugger.com.php | 14 +
.../lib/PicoFeed/Rules/treelobsters.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/twogag.com.php | 8 +
.../lib/PicoFeed/Rules/twokinds.keenspot.com.php | 10 +
.../picofeed/lib/PicoFeed/Rules/undeadly.org.php | 14 +
.../picofeed/lib/PicoFeed/Rules/upi.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/usatoday.com.php | 27 +
.../picofeed/lib/PicoFeed/Rules/version2.dk.php | 12 +
.../picofeed/lib/PicoFeed/Rules/vgcats.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/vuxml.org.php | 17 +
.../lib/PicoFeed/Rules/wausaudailyherald.com.php | 27 +
.../picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php | 33 +
.../picofeed/lib/PicoFeed/Rules/www.bdgest.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/www.bgr.in.php | 23 +
.../lib/PicoFeed/Rules/www.businessweek.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/www.cnn.com.php | 24 +
.../lib/PicoFeed/Rules/www.developpez.com.php | 21 +
.../lib/PicoFeed/Rules/www.egscomics.com.php | 12 +
.../Rules/www.fakingnews.firstpost.com.php | 17 +
.../picofeed/lib/PicoFeed/Rules/www.forbes.com.php | 20 +
.../lib/PicoFeed/Rules/www.franceculture.fr.php | 14 +
.../lib/PicoFeed/Rules/www.futura-sciences.com.php | 19 +
.../lib/PicoFeed/Rules/www.geekculture.com.php | 13 +
.../lib/PicoFeed/Rules/www.howtogeek.com.php | 14 +
.../picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php | 18 +
.../lib/PicoFeed/Rules/www.lesnumeriques.com.php | 25 +
.../lib/PicoFeed/Rules/www.mac4ever.com.php | 13 +
.../lib/PicoFeed/Rules/www.makeuseof.com.php | 18 +
.../PicoFeed/Rules/www.monsieur-le-chien.fr.php | 11 +
.../picofeed/lib/PicoFeed/Rules/www.npr.org.php | 28 +
.../lib/PicoFeed/Rules/www.numerama.com.php | 15 +
.../lib/PicoFeed/Rules/www.oneindia.com.php | 14 +
.../lib/PicoFeed/Rules/www.pseudo-sciences.org.php | 16 +
.../lib/PicoFeed/Rules/www.sciencemag.org.php | 16 +
.../picofeed/lib/PicoFeed/Rules/www.slate.fr.php | 19 +
.../lib/PicoFeed/Rules/www.universfreebox.com.php | 15 +
.../picofeed/lib/PicoFeed/Rules/www.zeit.de.php | 41 +
.../picofeed/lib/PicoFeed/Rules/xkcd.com.php | 8 +
.../picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php | 21 +
.../picofeed/lib/PicoFeed/Rules/zdnet.com.php | 23 +
.../lib/PicoFeed/Scraper/CandidateParser.php | 283 ++++
.../lib/PicoFeed/Scraper/ParserInterface.php | 20 +
.../picofeed/lib/PicoFeed/Scraper/RuleLoader.php | 107 ++
.../picofeed/lib/PicoFeed/Scraper/RuleParser.php | 102 ++
.../picofeed/lib/PicoFeed/Scraper/Scraper.php | 279 ++++
.../lib/PicoFeed/Serialization/Subscription.php | 175 +++
.../PicoFeed/Serialization/SubscriptionList.php | 75 +
.../Serialization/SubscriptionListBuilder.php | 204 +++
.../Serialization/SubscriptionListParser.php | 100 ++
.../PicoFeed/Serialization/SubscriptionParser.php | 142 ++
.../lib/PicoFeed/Syndication/AtomFeedBuilder.php | 65 +
.../lib/PicoFeed/Syndication/AtomHelper.php | 139 ++
.../lib/PicoFeed/Syndication/AtomItemBuilder.php | 63 +
.../lib/PicoFeed/Syndication/FeedBuilder.php | 185 +++
.../lib/PicoFeed/Syndication/ItemBuilder.php | 209 +++
.../lib/PicoFeed/Syndication/Rss20FeedBuilder.php | 76 +
.../lib/PicoFeed/Syndication/Rss20Helper.php | 115 ++
.../lib/PicoFeed/Syndication/Rss20ItemBuilder.php | 67 +
vendor/miniflux/picofeed/picofeed | 135 ++
vendor/paragonie/random_compat/CHANGELOG.md | 260 ++++
vendor/paragonie/random_compat/ERRATA.md | 34 +
vendor/paragonie/random_compat/LICENSE | 22 +
vendor/paragonie/random_compat/README.md | 176 +++
vendor/paragonie/random_compat/SECURITY.md | 108 ++
vendor/paragonie/random_compat/build-phar.sh | 5 +
vendor/paragonie/random_compat/composer.json | 35 +
.../random_compat/dist/random_compat.phar.pubkey | 5 +
.../dist/random_compat.phar.pubkey.asc | 11 +
.../random_compat/lib/byte_safe_strings.php | 181 +++
vendor/paragonie/random_compat/lib/cast_to_int.php | 71 +
.../paragonie/random_compat/lib/error_polyfill.php | 42 +
vendor/paragonie/random_compat/lib/random.php | 197 +++
.../random_compat/lib/random_bytes_com_dotnet.php | 81 ++
.../random_compat/lib/random_bytes_dev_urandom.php | 148 ++
.../random_compat/lib/random_bytes_libsodium.php | 86 ++
.../lib/random_bytes_libsodium_legacy.php | 86 ++
.../random_compat/lib/random_bytes_mcrypt.php | 76 +
vendor/paragonie/random_compat/lib/random_int.php | 191 +++
.../paragonie/random_compat/other/build_phar.php | 57 +
vendor/pimple/pimple/.gitignore | 3 +
vendor/pimple/pimple/.travis.yml | 32 +
vendor/pimple/pimple/CHANGELOG | 35 +
vendor/pimple/pimple/LICENSE | 19 +
vendor/pimple/pimple/README.rst | 201 +++
vendor/pimple/pimple/composer.json | 25 +
vendor/pimple/pimple/ext/pimple/.gitignore | 30 +
vendor/pimple/pimple/ext/pimple/README.md | 12 +
vendor/pimple/pimple/ext/pimple/config.m4 | 63 +
vendor/pimple/pimple/ext/pimple/config.w32 | 13 +
vendor/pimple/pimple/ext/pimple/php_pimple.h | 121 ++
vendor/pimple/pimple/ext/pimple/pimple.c | 922 ++++++++++++
vendor/pimple/pimple/ext/pimple/pimple_compat.h | 81 ++
vendor/pimple/pimple/ext/pimple/tests/001.phpt | 45 +
vendor/pimple/pimple/ext/pimple/tests/002.phpt | 15 +
vendor/pimple/pimple/ext/pimple/tests/003.phpt | 16 +
vendor/pimple/pimple/ext/pimple/tests/004.phpt | 30 +
vendor/pimple/pimple/ext/pimple/tests/005.phpt | 27 +
vendor/pimple/pimple/ext/pimple/tests/006.phpt | 51 +
vendor/pimple/pimple/ext/pimple/tests/007.phpt | 22 +
vendor/pimple/pimple/ext/pimple/tests/008.phpt | 29 +
vendor/pimple/pimple/ext/pimple/tests/009.phpt | 13 +
vendor/pimple/pimple/ext/pimple/tests/010.phpt | 45 +
vendor/pimple/pimple/ext/pimple/tests/011.phpt | 19 +
vendor/pimple/pimple/ext/pimple/tests/012.phpt | 28 +
vendor/pimple/pimple/ext/pimple/tests/013.phpt | 33 +
vendor/pimple/pimple/ext/pimple/tests/014.phpt | 30 +
vendor/pimple/pimple/ext/pimple/tests/015.phpt | 17 +
vendor/pimple/pimple/ext/pimple/tests/016.phpt | 24 +
vendor/pimple/pimple/ext/pimple/tests/017.phpt | 17 +
vendor/pimple/pimple/ext/pimple/tests/017_1.phpt | 17 +
vendor/pimple/pimple/ext/pimple/tests/018.phpt | 23 +
vendor/pimple/pimple/ext/pimple/tests/019.phpt | 18 +
vendor/pimple/pimple/ext/pimple/tests/bench.phpb | 51 +
.../pimple/ext/pimple/tests/bench_shared.phpb | 25 +
vendor/pimple/pimple/phpunit.xml.dist | 14 +
vendor/pimple/pimple/src/Pimple/Container.php | 282 ++++
.../pimple/src/Pimple/ServiceProviderInterface.php | 46 +
.../pimple/src/Pimple/Tests/Fixtures/Invokable.php | 38 +
.../src/Pimple/Tests/Fixtures/NonInvokable.php | 34 +
.../Tests/Fixtures/PimpleServiceProvider.php | 54 +
.../pimple/src/Pimple/Tests/Fixtures/Service.php | 35 +
.../Tests/PimpleServiceProviderInterfaceTest.php | 76 +
.../pimple/pimple/src/Pimple/Tests/PimpleTest.php | 440 ++++++
vendor/psr/log/.gitignore | 1 +
vendor/psr/log/LICENSE | 19 +
vendor/psr/log/Psr/Log/AbstractLogger.php | 128 ++
.../psr/log/Psr/Log/InvalidArgumentException.php | 7 +
vendor/psr/log/Psr/Log/LogLevel.php | 18 +
vendor/psr/log/Psr/Log/LoggerAwareInterface.php | 18 +
vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 26 +
vendor/psr/log/Psr/Log/LoggerInterface.php | 123 ++
vendor/psr/log/Psr/Log/LoggerTrait.php | 140 ++
vendor/psr/log/Psr/Log/NullLogger.php | 28 +
.../psr/log/Psr/Log/Test/LoggerInterfaceTest.php | 140 ++
vendor/psr/log/README.md | 45 +
vendor/psr/log/composer.json | 26 +
vendor/ramsey/array_column/.gitignore | 6 +
vendor/ramsey/array_column/.travis.yml | 26 +
vendor/ramsey/array_column/CHANGELOG.md | 37 +
vendor/ramsey/array_column/LICENSE | 19 +
vendor/ramsey/array_column/README.md | 91 ++
vendor/ramsey/array_column/composer.json | 27 +
vendor/ramsey/array_column/phpunit.xml.dist | 21 +
vendor/ramsey/array_column/src/array_column.php | 115 ++
.../ramsey/array_column/tests/ArrayColumnTest.php | 422 ++++++
vendor/ramsey/array_column/tests/bootstrap.php | 5 +
vendor/swiftmailer/swiftmailer/.gitattributes | 9 +
vendor/swiftmailer/swiftmailer/.gitignore | 4 +
vendor/swiftmailer/swiftmailer/.travis.yml | 27 +
vendor/swiftmailer/swiftmailer/CHANGES | 241 +++
vendor/swiftmailer/swiftmailer/LICENSE | 19 +
vendor/swiftmailer/swiftmailer/README | 15 +
vendor/swiftmailer/swiftmailer/VERSION | 1 +
vendor/swiftmailer/swiftmailer/composer.json | 37 +
vendor/swiftmailer/swiftmailer/doc/headers.rst | 742 ++++++++++
.../swiftmailer/swiftmailer/doc/help-resources.rst | 44 +
.../swiftmailer/doc/including-the-files.rst | 46 +
vendor/swiftmailer/swiftmailer/doc/index.rst | 16 +
vendor/swiftmailer/swiftmailer/doc/installing.rst | 89 ++
.../swiftmailer/swiftmailer/doc/introduction.rst | 135 ++
vendor/swiftmailer/swiftmailer/doc/japanese.rst | 22 +
vendor/swiftmailer/swiftmailer/doc/messages.rst | 1061 ++++++++++++++
vendor/swiftmailer/swiftmailer/doc/overview.rst | 159 ++
vendor/swiftmailer/swiftmailer/doc/plugins.rst | 385 +++++
vendor/swiftmailer/swiftmailer/doc/sending.rst | 571 ++++++++
.../swiftmailer/doc/uml/Encoders.graffle | Bin 0 -> 3503 bytes
.../swiftmailer/swiftmailer/doc/uml/Mime.graffle | Bin 0 -> 5575 bytes
.../swiftmailer/doc/uml/Transports.graffle | Bin 0 -> 3061 bytes
.../swiftmailer/swiftmailer/lib/classes/Swift.php | 80 +
.../swiftmailer/lib/classes/Swift/Attachment.php | 71 +
.../ByteStream/AbstractFilterableInputStream.php | 181 +++
.../classes/Swift/ByteStream/ArrayByteStream.php | 182 +++
.../classes/Swift/ByteStream/FileByteStream.php | 231 +++
.../Swift/ByteStream/TemporaryFileByteStream.php | 42 +
.../lib/classes/Swift/CharacterReader.php | 67 +
.../CharacterReader/GenericFixedWidthReader.php | 97 ++
.../Swift/CharacterReader/UsAsciiReader.php | 84 ++
.../classes/Swift/CharacterReader/Utf8Reader.php | 176 +++
.../lib/classes/Swift/CharacterReaderFactory.php | 26 +
.../SimpleCharacterReaderFactory.php | 124 ++
.../lib/classes/Swift/CharacterStream.php | 89 ++
.../Swift/CharacterStream/ArrayCharacterStream.php | 293 ++++
.../Swift/CharacterStream/NgCharacterStream.php | 267 ++++
.../lib/classes/Swift/ConfigurableSpool.php | 63 +
.../lib/classes/Swift/DependencyContainer.php | 373 +++++
.../lib/classes/Swift/DependencyException.php | 27 +
.../swiftmailer/lib/classes/Swift/EmbeddedFile.php | 69 +
.../swiftmailer/lib/classes/Swift/Encoder.php | 28 +
.../lib/classes/Swift/Encoder/Base64Encoder.php | 58 +
.../lib/classes/Swift/Encoder/QpEncoder.php | 300 ++++
.../lib/classes/Swift/Encoder/Rfc2231Encoder.php | 92 ++
.../swiftmailer/lib/classes/Swift/Encoding.php | 64 +
.../lib/classes/Swift/Events/CommandEvent.php | 65 +
.../lib/classes/Swift/Events/CommandListener.php | 24 +
.../swiftmailer/lib/classes/Swift/Events/Event.php | 38 +
.../lib/classes/Swift/Events/EventDispatcher.php | 83 ++
.../lib/classes/Swift/Events/EventListener.php | 18 +
.../lib/classes/Swift/Events/EventObject.php | 63 +
.../lib/classes/Swift/Events/ResponseEvent.php | 65 +
.../lib/classes/Swift/Events/ResponseListener.php | 24 +
.../lib/classes/Swift/Events/SendEvent.php | 129 ++
.../lib/classes/Swift/Events/SendListener.php | 31 +
.../classes/Swift/Events/SimpleEventDispatcher.php | 156 ++
.../classes/Swift/Events/TransportChangeEvent.php | 27 +
.../Swift/Events/TransportChangeListener.php | 45 +
.../Swift/Events/TransportExceptionEvent.php | 46 +
.../Swift/Events/TransportExceptionListener.php | 24 +
.../lib/classes/Swift/FailoverTransport.php | 45 +
.../swiftmailer/lib/classes/Swift/FileSpool.php | 208 +++
.../swiftmailer/lib/classes/Swift/FileStream.php | 24 +
.../swiftmailer/lib/classes/Swift/Filterable.php | 32 +
.../swiftmailer/lib/classes/Swift/Image.php | 61 +
.../lib/classes/Swift/InputByteStream.php | 75 +
.../swiftmailer/lib/classes/Swift/IoException.php | 29 +
.../swiftmailer/lib/classes/Swift/KeyCache.php | 105 ++
.../lib/classes/Swift/KeyCache/ArrayKeyCache.php | 206 +++
.../lib/classes/Swift/KeyCache/DiskKeyCache.php | 321 ++++
.../classes/Swift/KeyCache/KeyCacheInputStream.php | 51 +
.../lib/classes/Swift/KeyCache/NullKeyCache.php | 115 ++
.../Swift/KeyCache/SimpleKeyCacheInputStream.php | 127 ++
.../lib/classes/Swift/LoadBalancedTransport.php | 45 +
.../lib/classes/Swift/MailTransport.php | 47 +
.../swiftmailer/lib/classes/Swift/Mailer.php | 114 ++
.../Swift/Mailer/ArrayRecipientIterator.php | 55 +
.../lib/classes/Swift/Mailer/RecipientIterator.php | 32 +
.../swiftmailer/lib/classes/Swift/MemorySpool.php | 110 ++
.../swiftmailer/lib/classes/Swift/Message.php | 291 ++++
.../lib/classes/Swift/Mime/Attachment.php | 149 ++
.../lib/classes/Swift/Mime/CharsetObserver.php | 24 +
.../lib/classes/Swift/Mime/ContentEncoder.php | 34 +
.../Mime/ContentEncoder/Base64ContentEncoder.php | 104 ++
.../Mime/ContentEncoder/NativeQpContentEncoder.php | 123 ++
.../Mime/ContentEncoder/PlainContentEncoder.php | 162 +++
.../Swift/Mime/ContentEncoder/QpContentEncoder.php | 134 ++
.../Mime/ContentEncoder/QpContentEncoderProxy.php | 98 ++
.../Mime/ContentEncoder/RawContentEncoder.php | 64 +
.../lib/classes/Swift/Mime/EmbeddedFile.php | 45 +
.../lib/classes/Swift/Mime/EncodingObserver.php | 24 +
.../swiftmailer/lib/classes/Swift/Mime/Grammar.php | 176 +++
.../swiftmailer/lib/classes/Swift/Mime/Header.php | 93 ++
.../lib/classes/Swift/Mime/HeaderEncoder.php | 24 +
.../Mime/HeaderEncoder/Base64HeaderEncoder.php | 55 +
.../Swift/Mime/HeaderEncoder/QpHeaderEncoder.php | 65 +
.../lib/classes/Swift/Mime/HeaderFactory.php | 78 +
.../lib/classes/Swift/Mime/HeaderSet.php | 169 +++
.../classes/Swift/Mime/Headers/AbstractHeader.php | 503 +++++++
.../lib/classes/Swift/Mime/Headers/DateHeader.php | 125 ++
.../Swift/Mime/Headers/IdentificationHeader.php | 180 +++
.../classes/Swift/Mime/Headers/MailboxHeader.php | 353 +++++
.../classes/Swift/Mime/Headers/OpenDKIMHeader.php | 133 ++
.../Swift/Mime/Headers/ParameterizedHeader.php | 258 ++++
.../lib/classes/Swift/Mime/Headers/PathHeader.php | 143 ++
.../Swift/Mime/Headers/UnstructuredHeader.php | 112 ++
.../swiftmailer/lib/classes/Swift/Mime/Message.php | 223 +++
.../lib/classes/Swift/Mime/MimeEntity.php | 117 ++
.../lib/classes/Swift/Mime/MimePart.php | 212 +++
.../lib/classes/Swift/Mime/ParameterizedHeader.php | 34 +
.../lib/classes/Swift/Mime/SimpleHeaderFactory.php | 193 +++
.../lib/classes/Swift/Mime/SimpleHeaderSet.php | 414 ++++++
.../lib/classes/Swift/Mime/SimpleMessage.php | 655 +++++++++
.../lib/classes/Swift/Mime/SimpleMimeEntity.php | 843 +++++++++++
.../swiftmailer/lib/classes/Swift/MimePart.php | 59 +
.../lib/classes/Swift/NullTransport.php | 39 +
.../lib/classes/Swift/OutputByteStream.php | 46 +
.../lib/classes/Swift/Plugins/AntiFloodPlugin.php | 141 ++
.../Swift/Plugins/BandwidthMonitorPlugin.php | 164 +++
.../Swift/Plugins/Decorator/Replacements.php | 31 +
.../lib/classes/Swift/Plugins/DecoratorPlugin.php | 204 +++
.../classes/Swift/Plugins/ImpersonatePlugin.php | 69 +
.../lib/classes/Swift/Plugins/Logger.php | 36 +
.../lib/classes/Swift/Plugins/LoggerPlugin.php | 142 ++
.../classes/Swift/Plugins/Loggers/ArrayLogger.php | 72 +
.../classes/Swift/Plugins/Loggers/EchoLogger.php | 58 +
.../lib/classes/Swift/Plugins/MessageLogger.php | 74 +
.../classes/Swift/Plugins/Pop/Pop3Connection.php | 31 +
.../classes/Swift/Plugins/Pop/Pop3Exception.php | 27 +
.../classes/Swift/Plugins/PopBeforeSmtpPlugin.php | 273 ++++
.../classes/Swift/Plugins/RedirectingPlugin.php | 213 +++
.../lib/classes/Swift/Plugins/Reporter.php | 32 +
.../lib/classes/Swift/Plugins/ReporterPlugin.php | 61 +
.../Swift/Plugins/Reporters/HitReporter.php | 59 +
.../Swift/Plugins/Reporters/HtmlReporter.php | 39 +
.../lib/classes/Swift/Plugins/Sleeper.php | 24 +
.../lib/classes/Swift/Plugins/ThrottlerPlugin.php | 200 +++
.../lib/classes/Swift/Plugins/Timer.php | 24 +
.../swiftmailer/lib/classes/Swift/Preferences.php | 103 ++
.../lib/classes/Swift/ReplacementFilterFactory.php | 27 +
.../lib/classes/Swift/RfcComplianceException.php | 27 +
.../lib/classes/Swift/SendmailTransport.php | 45 +
.../lib/classes/Swift/SignedMessage.php | 23 +
.../swiftmailer/lib/classes/Swift/Signer.php | 20 +
.../lib/classes/Swift/Signers/BodySigner.php | 33 +
.../lib/classes/Swift/Signers/DKIMSigner.php | 698 +++++++++
.../lib/classes/Swift/Signers/DomainKeySigner.php | 525 +++++++
.../lib/classes/Swift/Signers/HeaderSigner.php | 65 +
.../lib/classes/Swift/Signers/OpenDKIMSigner.php | 190 +++
.../lib/classes/Swift/Signers/SMimeSigner.php | 436 ++++++
.../lib/classes/Swift/SmtpTransport.php | 58 +
.../swiftmailer/lib/classes/Swift/Spool.php | 53 +
.../lib/classes/Swift/SpoolTransport.php | 47 +
.../swiftmailer/lib/classes/Swift/StreamFilter.php | 35 +
.../StreamFilters/ByteArrayReplacementFilter.php | 170 +++
.../StreamFilters/StringReplacementFilter.php | 66 +
.../StringReplacementFilterFactory.php | 45 +
.../lib/classes/Swift/SwiftException.php | 29 +
.../swiftmailer/lib/classes/Swift/Transport.php | 54 +
.../Swift/Transport/AbstractSmtpTransport.php | 496 +++++++
.../Transport/Esmtp/Auth/CramMd5Authenticator.php | 81 ++
.../Transport/Esmtp/Auth/LoginAuthenticator.php | 51 +
.../Transport/Esmtp/Auth/NTLMAuthenticator.php | 720 +++++++++
.../Transport/Esmtp/Auth/PlainAuthenticator.php | 50 +
.../Transport/Esmtp/Auth/XOAuth2Authenticator.php | 70 +
.../classes/Swift/Transport/Esmtp/AuthHandler.php | 263 ++++
.../Swift/Transport/Esmtp/Authenticator.php | 35 +
.../lib/classes/Swift/Transport/EsmtpHandler.php | 86 ++
.../lib/classes/Swift/Transport/EsmtpTransport.php | 413 ++++++
.../classes/Swift/Transport/FailoverTransport.php | 88 ++
.../lib/classes/Swift/Transport/IoBuffer.php | 67 +
.../Swift/Transport/LoadBalancedTransport.php | 183 +++
.../lib/classes/Swift/Transport/MailInvoker.php | 32 +
.../lib/classes/Swift/Transport/MailTransport.php | 295 ++++
.../lib/classes/Swift/Transport/NullTransport.php | 93 ++
.../classes/Swift/Transport/SendmailTransport.php | 160 ++
.../classes/Swift/Transport/SimpleMailInvoker.php | 39 +
.../lib/classes/Swift/Transport/SmtpAgent.php | 36 +
.../lib/classes/Swift/Transport/SpoolTransport.php | 117 ++
.../lib/classes/Swift/Transport/StreamBuffer.php | 325 +++++
.../lib/classes/Swift/TransportException.php | 29 +
.../swiftmailer/lib/classes/Swift/Validate.php | 43 +
.../swiftmailer/lib/dependency_maps/cache_deps.php | 23 +
.../lib/dependency_maps/message_deps.php | 9 +
.../swiftmailer/lib/dependency_maps/mime_deps.php | 123 ++
.../lib/dependency_maps/transport_deps.php | 76 +
vendor/swiftmailer/swiftmailer/lib/mime_types.php | 1007 +++++++++++++
vendor/swiftmailer/swiftmailer/lib/preferences.php | 25 +
vendor/swiftmailer/swiftmailer/lib/swift_init.php | 28 +
.../swiftmailer/swiftmailer/lib/swift_required.php | 30 +
.../swiftmailer/lib/swift_required_pear.php | 30 +
.../lib/swiftmailer_generate_mimes_config.php | 193 +++
vendor/swiftmailer/swiftmailer/phpunit.xml.dist | 39 +
.../tests/IdenticalBinaryConstraint.php | 62 +
.../swiftmailer/tests/StreamCollector.php | 11 +
.../swiftmailer/tests/SwiftMailerSmokeTestCase.php | 46 +
.../swiftmailer/tests/SwiftMailerTestCase.php | 34 +
.../tests/_samples/charsets/iso-2022-jp/one.txt | 11 +
.../tests/_samples/charsets/iso-8859-1/one.txt | 19 +
.../tests/_samples/charsets/utf-8/one.txt | 22 +
.../tests/_samples/charsets/utf-8/three.txt | 45 +
.../tests/_samples/charsets/utf-8/two.txt | 3 +
.../swiftmailer/tests/_samples/dkim/dkim.test.priv | 15 +
.../swiftmailer/tests/_samples/dkim/dkim.test.pub | 6 +
.../swiftmailer/tests/_samples/files/data.txt | 1 +
.../tests/_samples/files/swiftmailer.png | Bin 0 -> 3194 bytes
.../swiftmailer/tests/_samples/files/textfile.zip | Bin 0 -> 202 bytes
.../swiftmailer/tests/_samples/smime/CA.srl | 1 +
.../swiftmailer/tests/_samples/smime/ca.crt | 21 +
.../swiftmailer/tests/_samples/smime/ca.key | 27 +
.../tests/_samples/smime/create-cert.sh | 40 +
.../swiftmailer/tests/_samples/smime/encrypt.crt | 19 +
.../swiftmailer/tests/_samples/smime/encrypt.key | 27 +
.../swiftmailer/tests/_samples/smime/encrypt2.crt | 19 +
.../swiftmailer/tests/_samples/smime/encrypt2.key | 27 +
.../tests/_samples/smime/intermediate.crt | 19 +
.../tests/_samples/smime/intermediate.key | 27 +
.../swiftmailer/tests/_samples/smime/sign.crt | 19 +
.../swiftmailer/tests/_samples/smime/sign.key | 27 +
.../swiftmailer/tests/_samples/smime/sign2.crt | 19 +
.../swiftmailer/tests/_samples/smime/sign2.key | 27 +
.../swiftmailer/tests/acceptance.conf.php.default | 44 +
.../acceptance/Swift/AttachmentAcceptanceTest.php | 12 +
.../ByteStream/FileByteStreamAcceptanceTest.php | 174 +++
.../SimpleCharacterReaderFactoryAcceptanceTest.php | 179 +++
.../Swift/DependencyContainerAcceptanceTest.php | 24 +
.../Swift/EmbeddedFileAcceptanceTest.php | 12 +
.../Swift/Encoder/Base64EncoderAcceptanceTest.php | 45 +
.../Swift/Encoder/QpEncoderAcceptanceTest.php | 54 +
.../Swift/Encoder/Rfc2231EncoderAcceptanceTest.php | 50 +
.../acceptance/Swift/EncodingAcceptanceTest.php | 30 +
.../Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php | 173 +++
.../Swift/KeyCache/DiskKeyCacheAcceptanceTest.php | 183 +++
.../acceptance/Swift/MessageAcceptanceTest.php | 57 +
.../Swift/Mime/AttachmentAcceptanceTest.php | 125 ++
.../Base64ContentEncoderAcceptanceTest.php | 56 +
.../NativeQpContentEncoderAcceptanceTest.php | 88 ++
.../PlainContentEncoderAcceptanceTest.php | 88 ++
.../QpContentEncoderAcceptanceTest.php | 160 ++
.../Swift/Mime/EmbeddedFileAcceptanceTest.php | 138 ++
.../Base64HeaderEncoderAcceptanceTest.php | 32 +
.../Swift/Mime/MimePartAcceptanceTest.php | 129 ++
.../Swift/Mime/SimpleMessageAcceptanceTest.php | 1251 ++++++++++++++++
.../acceptance/Swift/MimePartAcceptanceTest.php | 15 +
.../AbstractStreamBufferAcceptanceTest.php | 133 ++
.../StreamBuffer/BasicSocketAcceptanceTest.php | 33 +
.../StreamBuffer/ProcessAcceptanceTest.php | 26 +
.../Transport/StreamBuffer/SocketTimeoutTest.php | 67 +
.../StreamBuffer/SslSocketAcceptanceTest.php | 40 +
.../StreamBuffer/TlsSocketAcceptanceTest.php | 39 +
vendor/swiftmailer/swiftmailer/tests/bootstrap.php | 21 +
.../swiftmailer/tests/bug/Swift/Bug111Test.php | 42 +
.../swiftmailer/tests/bug/Swift/Bug118Test.php | 20 +
.../swiftmailer/tests/bug/Swift/Bug206Test.php | 38 +
.../swiftmailer/tests/bug/Swift/Bug274Test.php | 21 +
.../swiftmailer/tests/bug/Swift/Bug34Test.php | 75 +
.../swiftmailer/tests/bug/Swift/Bug35Test.php | 73 +
.../swiftmailer/tests/bug/Swift/Bug38Test.php | 194 +++
.../swiftmailer/tests/bug/Swift/Bug518Test.php | 38 +
.../swiftmailer/tests/bug/Swift/Bug51Test.php | 121 ++
.../swiftmailer/tests/bug/Swift/Bug534Test.php | 38 +
.../swiftmailer/tests/bug/Swift/Bug650Test.php | 36 +
.../swiftmailer/tests/bug/Swift/Bug71Test.php | 20 +
.../swiftmailer/tests/bug/Swift/Bug76Test.php | 82 ++
.../BugFileByteStreamConsecutiveReadCallsTest.php | 19 +
.../tests/fixtures/MimeEntityFixture.php | 59 +
.../swiftmailer/tests/smoke.conf.php.default | 63 +
.../smoke/Swift/Smoke/AttachmentSmokeTest.php | 33 +
.../tests/smoke/Swift/Smoke/BasicSmokeTest.php | 23 +
.../Swift/Smoke/HtmlWithAttachmentSmokeTest.php | 31 +
.../smoke/Swift/Smoke/InternationalSmokeTest.php | 40 +
.../unit/Swift/ByteStream/ArrayByteStreamTest.php | 203 +++
.../GenericFixedWidthReaderTest.php | 43 +
.../Swift/CharacterReader/UsAsciiReaderTest.php | 52 +
.../unit/Swift/CharacterReader/Utf8ReaderTest.php | 65 +
.../CharacterStream/ArrayCharacterStreamTest.php | 360 +++++
.../tests/unit/Swift/DependencyContainerTest.php | 175 +++
.../tests/unit/Swift/Encoder/Base64EncoderTest.php | 173 +++
.../tests/unit/Swift/Encoder/QpEncoderTest.php | 402 +++++
.../unit/Swift/Encoder/Rfc2231EncoderTest.php | 141 ++
.../tests/unit/Swift/Events/CommandEventTest.php | 36 +
.../tests/unit/Swift/Events/EventObjectTest.php | 34 +
.../tests/unit/Swift/Events/ResponseEventTest.php | 40 +
.../tests/unit/Swift/Events/SendEventTest.php | 99 ++
.../Swift/Events/SimpleEventDispatcherTest.php | 142 ++
.../unit/Swift/Events/TransportChangeEventTest.php | 32 +
.../Swift/Events/TransportExceptionEventTest.php | 43 +
.../unit/Swift/KeyCache/ArrayKeyCacheTest.php | 242 ++++
.../KeyCache/SimpleKeyCacheInputStreamTest.php | 73 +
.../Swift/Mailer/ArrayRecipientIteratorTest.php | 42 +
.../swiftmailer/tests/unit/Swift/MailerTest.php | 147 ++
.../swiftmailer/tests/unit/Swift/MessageTest.php | 130 ++
.../unit/Swift/Mime/AbstractMimeEntityTest.php | 1054 ++++++++++++++
.../tests/unit/Swift/Mime/AttachmentTest.php | 320 ++++
.../ContentEncoder/Base64ContentEncoderTest.php | 323 +++++
.../ContentEncoder/PlainContentEncoderTest.php | 173 +++
.../Mime/ContentEncoder/QpContentEncoderTest.php | 518 +++++++
.../tests/unit/Swift/Mime/EmbeddedFileTest.php | 57 +
.../Mime/HeaderEncoder/Base64HeaderEncoderTest.php | 13 +
.../Mime/HeaderEncoder/QpHeaderEncoderTest.php | 223 +++
.../unit/Swift/Mime/Headers/DateHeaderTest.php | 69 +
.../Mime/Headers/IdentificationHeaderTest.php | 189 +++
.../unit/Swift/Mime/Headers/MailboxHeaderTest.php | 327 +++++
.../Swift/Mime/Headers/ParameterizedHeaderTest.php | 400 +++++
.../unit/Swift/Mime/Headers/PathHeaderTest.php | 77 +
.../Swift/Mime/Headers/UnstructuredHeaderTest.php | 355 +++++
.../tests/unit/Swift/Mime/MimePartTest.php | 233 +++
.../unit/Swift/Mime/SimpleHeaderFactoryTest.php | 168 +++
.../tests/unit/Swift/Mime/SimpleHeaderSetTest.php | 739 ++++++++++
.../tests/unit/Swift/Mime/SimpleMessageTest.php | 829 +++++++++++
.../tests/unit/Swift/Mime/SimpleMimeEntityTest.php | 11 +
.../unit/Swift/Plugins/AntiFloodPluginTest.php | 95 ++
.../Swift/Plugins/BandwidthMonitorPluginTest.php | 130 ++
.../unit/Swift/Plugins/DecoratorPluginTest.php | 269 ++++
.../tests/unit/Swift/Plugins/LoggerPluginTest.php | 190 +++
.../unit/Swift/Plugins/Loggers/ArrayLoggerTest.php | 65 +
.../unit/Swift/Plugins/Loggers/EchoLoggerTest.php | 24 +
.../unit/Swift/Plugins/PopBeforeSmtpPluginTest.php | 103 ++
.../unit/Swift/Plugins/RedirectingPluginTest.php | 185 +++
.../unit/Swift/Plugins/ReporterPluginTest.php | 88 ++
.../Swift/Plugins/Reporters/HitReporterTest.php | 64 +
.../Swift/Plugins/Reporters/HtmlReporterTest.php | 54 +
.../unit/Swift/Plugins/ThrottlerPluginTest.php | 104 ++
.../tests/unit/Swift/Signers/DKIMSignerTest.php | 227 +++
.../unit/Swift/Signers/OpenDKIMSignerTest.php | 45 +
.../tests/unit/Swift/Signers/SMimeSignerTest.php | 554 +++++++
.../ByteArrayReplacementFilterTest.php | 131 ++
.../StringReplacementFilterFactoryTest.php | 38 +
.../StreamFilters/StringReplacementFilterTest.php | 55 +
.../Transport/AbstractSmtpEventSupportTest.php | 560 +++++++
.../unit/Swift/Transport/AbstractSmtpTest.php | 1249 ++++++++++++++++
.../Esmtp/Auth/CramMd5AuthenticatorTest.php | 66 +
.../Esmtp/Auth/LoginAuthenticatorTest.php | 66 +
.../Transport/Esmtp/Auth/NTLMAuthenticatorTest.php | 235 +++
.../Esmtp/Auth/PlainAuthenticatorTest.php | 69 +
.../unit/Swift/Transport/Esmtp/AuthHandlerTest.php | 167 +++
.../EsmtpTransport/ExtensionSupportTest.php | 528 +++++++
.../unit/Swift/Transport/EsmtpTransportTest.php | 297 ++++
.../unit/Swift/Transport/FailoverTransportTest.php | 520 +++++++
.../Swift/Transport/LoadBalancedTransportTest.php | 751 ++++++++++
.../unit/Swift/Transport/MailTransportTest.php | 535 +++++++
.../unit/Swift/Transport/SendmailTransportTest.php | 151 ++
.../unit/Swift/Transport/StreamBufferTest.php | 45 +
vendor/symfony/console/.gitignore | 3 +
vendor/symfony/console/Application.php | 1144 +++++++++++++++
vendor/symfony/console/CHANGELOG.md | 73 +
vendor/symfony/console/Command/Command.php | 681 +++++++++
vendor/symfony/console/Command/HelpCommand.php | 93 ++
vendor/symfony/console/Command/ListCommand.php | 97 ++
vendor/symfony/console/ConsoleEvents.php | 61 +
.../console/Descriptor/ApplicationDescription.php | 160 ++
vendor/symfony/console/Descriptor/Descriptor.php | 122 ++
.../console/Descriptor/DescriptorInterface.php | 31 +
.../symfony/console/Descriptor/JsonDescriptor.php | 166 +++
.../console/Descriptor/MarkdownDescriptor.php | 143 ++
.../symfony/console/Descriptor/TextDescriptor.php | 287 ++++
.../symfony/console/Descriptor/XmlDescriptor.php | 263 ++++
.../symfony/console/Event/ConsoleCommandEvent.php | 62 +
vendor/symfony/console/Event/ConsoleEvent.php | 67 +
.../console/Event/ConsoleExceptionEvent.php | 67 +
.../console/Event/ConsoleTerminateEvent.php | 58 +
.../console/Exception/CommandNotFoundException.php | 43 +
.../console/Exception/ExceptionInterface.php | 21 +
.../console/Exception/InvalidArgumentException.php | 19 +
.../console/Exception/InvalidOptionException.php | 21 +
.../symfony/console/Exception/LogicException.php | 19 +
.../symfony/console/Exception/RuntimeException.php | 19 +
.../symfony/console/Formatter/OutputFormatter.php | 240 +++
.../console/Formatter/OutputFormatterInterface.php | 69 +
.../console/Formatter/OutputFormatterStyle.php | 221 +++
.../Formatter/OutputFormatterStyleInterface.php | 64 +
.../Formatter/OutputFormatterStyleStack.php | 123 ++
.../console/Helper/DebugFormatterHelper.php | 127 ++
vendor/symfony/console/Helper/DescriptorHelper.php | 97 ++
vendor/symfony/console/Helper/DialogHelper.php | 502 +++++++
vendor/symfony/console/Helper/FormatterHelper.php | 82 ++
vendor/symfony/console/Helper/Helper.php | 119 ++
vendor/symfony/console/Helper/HelperInterface.php | 41 +
vendor/symfony/console/Helper/HelperSet.php | 117 ++
vendor/symfony/console/Helper/InputAwareHelper.php | 33 +
vendor/symfony/console/Helper/ProcessHelper.php | 151 ++
vendor/symfony/console/Helper/ProgressBar.php | 621 ++++++++
vendor/symfony/console/Helper/ProgressHelper.php | 471 ++++++
.../symfony/console/Helper/ProgressIndicator.php | 324 +++++
vendor/symfony/console/Helper/QuestionHelper.php | 449 ++++++
.../console/Helper/SymfonyQuestionHelper.php | 107 ++
vendor/symfony/console/Helper/Table.php | 663 +++++++++
vendor/symfony/console/Helper/TableCell.php | 79 +
vendor/symfony/console/Helper/TableHelper.php | 269 ++++
vendor/symfony/console/Helper/TableSeparator.php | 29 +
vendor/symfony/console/Helper/TableStyle.php | 258 ++++
vendor/symfony/console/Input/ArgvInput.php | 351 +++++
vendor/symfony/console/Input/ArrayInput.php | 210 +++
vendor/symfony/console/Input/Input.php | 236 +++
vendor/symfony/console/Input/InputArgument.php | 131 ++
.../symfony/console/Input/InputAwareInterface.php | 28 +
vendor/symfony/console/Input/InputDefinition.php | 457 ++++++
vendor/symfony/console/Input/InputInterface.php | 152 ++
vendor/symfony/console/Input/InputOption.php | 212 +++
vendor/symfony/console/Input/StringInput.php | 85 ++
vendor/symfony/console/LICENSE | 19 +
vendor/symfony/console/Logger/ConsoleLogger.php | 119 ++
vendor/symfony/console/Output/BufferedOutput.php | 48 +
vendor/symfony/console/Output/ConsoleOutput.php | 156 ++
.../console/Output/ConsoleOutputInterface.php | 35 +
vendor/symfony/console/Output/NullOutput.php | 111 ++
vendor/symfony/console/Output/Output.php | 165 +++
vendor/symfony/console/Output/OutputInterface.php | 91 ++
vendor/symfony/console/Output/StreamOutput.php | 105 ++
vendor/symfony/console/Question/ChoiceQuestion.php | 177 +++
.../console/Question/ConfirmationQuestion.php | 61 +
vendor/symfony/console/Question/Question.php | 250 ++++
vendor/symfony/console/README.md | 20 +
.../symfony/console/Resources/bin/hiddeninput.exe | Bin 0 -> 9216 bytes
vendor/symfony/console/Shell.php | 233 +++
vendor/symfony/console/Style/OutputStyle.php | 116 ++
vendor/symfony/console/Style/StyleInterface.php | 159 ++
vendor/symfony/console/Style/SymfonyStyle.php | 440 ++++++
.../symfony/console/Tester/ApplicationTester.php | 128 ++
vendor/symfony/console/Tester/CommandTester.php | 132 ++
vendor/symfony/console/Tests/ApplicationTest.php | 1146 +++++++++++++++
.../symfony/console/Tests/Command/CommandTest.php | 395 +++++
.../console/Tests/Command/HelpCommandTest.php | 70 +
.../console/Tests/Command/ListCommandTest.php | 112 ++
.../Tests/Descriptor/AbstractDescriptorTest.php | 106 ++
.../Tests/Descriptor/JsonDescriptorTest.php | 35 +
.../Tests/Descriptor/MarkdownDescriptorTest.php | 27 +
.../console/Tests/Descriptor/ObjectsProvider.php | 77 +
.../Tests/Descriptor/TextDescriptorTest.php | 27 +
.../console/Tests/Descriptor/XmlDescriptorTest.php | 27 +
.../console/Tests/Fixtures/BarBucCommand.php | 11 +
.../Tests/Fixtures/DescriptorApplication1.php | 18 +
.../Tests/Fixtures/DescriptorApplication2.php | 24 +
.../console/Tests/Fixtures/DescriptorCommand1.php | 27 +
.../console/Tests/Fixtures/DescriptorCommand2.php | 32 +
.../symfony/console/Tests/Fixtures/DummyOutput.php | 36 +
.../symfony/console/Tests/Fixtures/Foo1Command.php | 26 +
.../symfony/console/Tests/Fixtures/Foo2Command.php | 21 +
.../symfony/console/Tests/Fixtures/Foo3Command.php | 29 +
.../symfony/console/Tests/Fixtures/Foo4Command.php | 11 +
.../symfony/console/Tests/Fixtures/Foo5Command.php | 10 +
.../symfony/console/Tests/Fixtures/Foo6Command.php | 12 +
.../symfony/console/Tests/Fixtures/FooCommand.php | 33 +
.../Tests/Fixtures/FooSubnamespaced1Command.php | 26 +
.../Tests/Fixtures/FooSubnamespaced2Command.php | 26 +
.../console/Tests/Fixtures/FoobarCommand.php | 25 +
.../Style/SymfonyStyle/command/command_0.php | 11 +
.../Style/SymfonyStyle/command/command_1.php | 13 +
.../Style/SymfonyStyle/command/command_10.php | 17 +
.../Style/SymfonyStyle/command/command_11.php | 13 +
.../Style/SymfonyStyle/command/command_2.php | 16 +
.../Style/SymfonyStyle/command/command_3.php | 12 +
.../Style/SymfonyStyle/command/command_4.php | 34 +
.../Style/SymfonyStyle/command/command_5.php | 37 +
.../Style/SymfonyStyle/command/command_6.php | 16 +
.../Style/SymfonyStyle/command/command_7.php | 15 +
.../Style/SymfonyStyle/command/command_8.php | 26 +
.../Style/SymfonyStyle/command/command_9.php | 11 +
.../Style/SymfonyStyle/output/output_0.txt | 3 +
.../Style/SymfonyStyle/output/output_1.txt | 9 +
.../Style/SymfonyStyle/output/output_10.txt | 7 +
.../Style/SymfonyStyle/output/output_11.txt | 6 +
.../Style/SymfonyStyle/output/output_2.txt | 13 +
.../Style/SymfonyStyle/output/output_3.txt | 7 +
.../Style/SymfonyStyle/output/output_4.txt | 32 +
.../Style/SymfonyStyle/output/output_5.txt | 18 +
.../Style/SymfonyStyle/output/output_6.txt | 6 +
.../Style/SymfonyStyle/output/output_7.txt | 5 +
.../Style/SymfonyStyle/output/output_8.txt | 9 +
.../Style/SymfonyStyle/output/output_9.txt | 5 +
.../symfony/console/Tests/Fixtures/TestCommand.php | 28 +
.../console/Tests/Fixtures/application_1.json | 1 +
.../console/Tests/Fixtures/application_1.md | 201 +++
.../console/Tests/Fixtures/application_1.txt | 17 +
.../console/Tests/Fixtures/application_1.xml | 110 ++
.../console/Tests/Fixtures/application_2.json | 1 +
.../console/Tests/Fixtures/application_2.md | 396 +++++
.../console/Tests/Fixtures/application_2.txt | 22 +
.../console/Tests/Fixtures/application_2.xml | 190 +++
.../console/Tests/Fixtures/application_astext1.txt | 20 +
.../console/Tests/Fixtures/application_astext2.txt | 16 +
.../console/Tests/Fixtures/application_asxml1.txt | 146 ++
.../console/Tests/Fixtures/application_asxml2.txt | 37 +
.../console/Tests/Fixtures/application_gethelp.txt | 1 +
.../Fixtures/application_renderexception1.txt | 6 +
.../Fixtures/application_renderexception2.txt | 8 +
.../Fixtures/application_renderexception3.txt | 18 +
.../application_renderexception3decorated.txt | 18 +
.../Fixtures/application_renderexception4.txt | 7 +
.../application_renderexception_doublewidth1.txt | 8 +
...ation_renderexception_doublewidth1decorated.txt | 8 +
.../application_renderexception_doublewidth2.txt | 9 +
.../console/Tests/Fixtures/application_run1.txt | 17 +
.../console/Tests/Fixtures/application_run2.txt | 29 +
.../console/Tests/Fixtures/application_run3.txt | 27 +
.../console/Tests/Fixtures/application_run4.txt | 1 +
.../symfony/console/Tests/Fixtures/command_1.json | 1 +
vendor/symfony/console/Tests/Fixtures/command_1.md | 11 +
.../symfony/console/Tests/Fixtures/command_1.txt | 7 +
.../symfony/console/Tests/Fixtures/command_1.xml | 12 +
.../symfony/console/Tests/Fixtures/command_2.json | 1 +
vendor/symfony/console/Tests/Fixtures/command_2.md | 33 +
.../symfony/console/Tests/Fixtures/command_2.txt | 13 +
.../symfony/console/Tests/Fixtures/command_2.xml | 21 +
.../console/Tests/Fixtures/command_astext.txt | 18 +
.../console/Tests/Fixtures/command_asxml.txt | 38 +
.../console/Tests/Fixtures/definition_astext.txt | 11 +
.../console/Tests/Fixtures/definition_asxml.txt | 39 +
.../console/Tests/Fixtures/input_argument_1.json | 1 +
.../console/Tests/Fixtures/input_argument_1.md | 7 +
.../console/Tests/Fixtures/input_argument_1.txt | 1 +
.../console/Tests/Fixtures/input_argument_1.xml | 5 +
.../console/Tests/Fixtures/input_argument_2.json | 1 +
.../console/Tests/Fixtures/input_argument_2.md | 7 +
.../console/Tests/Fixtures/input_argument_2.txt | 1 +
.../console/Tests/Fixtures/input_argument_2.xml | 5 +
.../console/Tests/Fixtures/input_argument_3.json | 1 +
.../console/Tests/Fixtures/input_argument_3.md | 7 +
.../console/Tests/Fixtures/input_argument_3.txt | 1 +
.../console/Tests/Fixtures/input_argument_3.xml | 7 +
.../console/Tests/Fixtures/input_argument_4.json | 1 +
.../console/Tests/Fixtures/input_argument_4.md | 8 +
.../console/Tests/Fixtures/input_argument_4.txt | 2 +
.../console/Tests/Fixtures/input_argument_4.xml | 6 +
.../console/Tests/Fixtures/input_definition_1.json | 1 +
.../console/Tests/Fixtures/input_definition_1.md | 0
.../console/Tests/Fixtures/input_definition_1.txt | 0
.../console/Tests/Fixtures/input_definition_1.xml | 5 +
.../console/Tests/Fixtures/input_definition_2.json | 1 +
.../console/Tests/Fixtures/input_definition_2.md | 9 +
.../console/Tests/Fixtures/input_definition_2.txt | 2 +
.../console/Tests/Fixtures/input_definition_2.xml | 10 +
.../console/Tests/Fixtures/input_definition_3.json | 1 +
.../console/Tests/Fixtures/input_definition_3.md | 11 +
.../console/Tests/Fixtures/input_definition_3.txt | 2 +
.../console/Tests/Fixtures/input_definition_3.xml | 9 +
.../console/Tests/Fixtures/input_definition_4.json | 1 +
.../console/Tests/Fixtures/input_definition_4.md | 21 +
.../console/Tests/Fixtures/input_definition_4.txt | 5 +
.../console/Tests/Fixtures/input_definition_4.xml | 14 +
.../console/Tests/Fixtures/input_option_1.json | 1 +
.../console/Tests/Fixtures/input_option_1.md | 9 +
.../console/Tests/Fixtures/input_option_1.txt | 1 +
.../console/Tests/Fixtures/input_option_1.xml | 4 +
.../console/Tests/Fixtures/input_option_2.json | 1 +
.../console/Tests/Fixtures/input_option_2.md | 9 +
.../console/Tests/Fixtures/input_option_2.txt | 1 +
.../console/Tests/Fixtures/input_option_2.xml | 7 +
.../console/Tests/Fixtures/input_option_3.json | 1 +
.../console/Tests/Fixtures/input_option_3.md | 9 +
.../console/Tests/Fixtures/input_option_3.txt | 1 +
.../console/Tests/Fixtures/input_option_3.xml | 5 +
.../console/Tests/Fixtures/input_option_4.json | 1 +
.../console/Tests/Fixtures/input_option_4.md | 9 +
.../console/Tests/Fixtures/input_option_4.txt | 1 +
.../console/Tests/Fixtures/input_option_4.xml | 5 +
.../console/Tests/Fixtures/input_option_5.json | 1 +
.../console/Tests/Fixtures/input_option_5.md | 10 +
.../console/Tests/Fixtures/input_option_5.txt | 2 +
.../console/Tests/Fixtures/input_option_5.xml | 6 +
.../console/Tests/Fixtures/input_option_6.json | 1 +
.../console/Tests/Fixtures/input_option_6.md | 9 +
.../console/Tests/Fixtures/input_option_6.txt | 1 +
.../console/Tests/Fixtures/input_option_6.xml | 5 +
.../Formatter/OutputFormatterStyleStackTest.php | 70 +
.../Tests/Formatter/OutputFormatterStyleTest.php | 99 ++
.../Tests/Formatter/OutputFormatterTest.php | 273 ++++
.../console/Tests/Helper/FormatterHelperTest.php | 92 ++
.../symfony/console/Tests/Helper/HelperSetTest.php | 133 ++
vendor/symfony/console/Tests/Helper/HelperTest.php | 54 +
.../Tests/Helper/LegacyDialogHelperTest.php | 263 ++++
.../Tests/Helper/LegacyProgressHelperTest.php | 224 +++
.../console/Tests/Helper/LegacyTableHelperTest.php | 316 ++++
.../console/Tests/Helper/ProcessHelperTest.php | 117 ++
.../console/Tests/Helper/ProgressBarTest.php | 664 +++++++++
.../console/Tests/Helper/ProgressIndicatorTest.php | 182 +++
.../console/Tests/Helper/QuestionHelperTest.php | 435 ++++++
.../console/Tests/Helper/TableStyleTest.php | 27 +
vendor/symfony/console/Tests/Helper/TableTest.php | 645 +++++++++
.../symfony/console/Tests/Input/ArgvInputTest.php | 317 ++++
.../symfony/console/Tests/Input/ArrayInputTest.php | 138 ++
.../console/Tests/Input/InputArgumentTest.php | 111 ++
.../console/Tests/Input/InputDefinitionTest.php | 437 ++++++
.../console/Tests/Input/InputOptionTest.php | 204 +++
vendor/symfony/console/Tests/Input/InputTest.php | 132 ++
.../console/Tests/Input/StringInputTest.php | 99 ++
.../console/Tests/Logger/ConsoleLoggerTest.php | 58 +
.../console/Tests/Output/ConsoleOutputTest.php | 25 +
.../console/Tests/Output/NullOutputTest.php | 39 +
vendor/symfony/console/Tests/Output/OutputTest.php | 175 +++
.../console/Tests/Output/StreamOutputTest.php | 60 +
.../console/Tests/Style/SymfonyStyleTest.php | 89 ++
.../console/Tests/Tester/ApplicationTesterTest.php | 69 +
.../console/Tests/Tester/CommandTesterTest.php | 84 ++
vendor/symfony/console/composer.json | 44 +
vendor/symfony/console/phpunit.xml.dist | 39 +
vendor/symfony/event-dispatcher/.gitignore | 3 +
vendor/symfony/event-dispatcher/CHANGELOG.md | 23 +
.../ContainerAwareEventDispatcher.php | 187 +++
.../Debug/TraceableEventDispatcher.php | 339 +++++
.../Debug/TraceableEventDispatcherInterface.php | 34 +
.../event-dispatcher/Debug/WrappedListener.php | 71 +
.../DependencyInjection/RegisterListenersPass.php | 109 ++
vendor/symfony/event-dispatcher/Event.php | 120 ++
.../symfony/event-dispatcher/EventDispatcher.php | 177 +++
.../event-dispatcher/EventDispatcherInterface.php | 88 ++
.../event-dispatcher/EventSubscriberInterface.php | 46 +
vendor/symfony/event-dispatcher/GenericEvent.php | 186 +++
.../event-dispatcher/ImmutableEventDispatcher.php | 93 ++
vendor/symfony/event-dispatcher/LICENSE | 19 +
vendor/symfony/event-dispatcher/README.md | 15 +
.../Tests/AbstractEventDispatcherTest.php | 382 +++++
.../Tests/ContainerAwareEventDispatcherTest.php | 273 ++++
.../Tests/Debug/TraceableEventDispatcherTest.php | 199 +++
.../RegisterListenersPassTest.php | 200 +++
.../event-dispatcher/Tests/EventDispatcherTest.php | 22 +
.../symfony/event-dispatcher/Tests/EventTest.php | 96 ++
.../event-dispatcher/Tests/GenericEventTest.php | 139 ++
.../Tests/ImmutableEventDispatcherTest.php | 105 ++
vendor/symfony/event-dispatcher/composer.json | 44 +
vendor/symfony/event-dispatcher/phpunit.xml.dist | 29 +
vendor/symfony/polyfill-mbstring/LICENSE | 19 +
vendor/symfony/polyfill-mbstring/Mbstring.php | 664 +++++++++
vendor/symfony/polyfill-mbstring/README.md | 13 +
.../Resources/unidata/lowerCase.php | 1101 ++++++++++++++
.../Resources/unidata/upperCase.php | 1109 ++++++++++++++
vendor/symfony/polyfill-mbstring/bootstrap.php | 56 +
vendor/symfony/polyfill-mbstring/composer.json | 34 +
vendor/zendframework/zendxml/.gitignore | 5 +
vendor/zendframework/zendxml/.travis.yml | 43 +
vendor/zendframework/zendxml/CHANGELOG.md | 24 +
vendor/zendframework/zendxml/LICENSE.md | 12 +
vendor/zendframework/zendxml/README.md | 50 +
vendor/zendframework/zendxml/composer.json | 40 +
.../ZendXml/Exception/ExceptionInterface.php | 14 +
.../ZendXml/Exception/InvalidArgumentException.php | 17 +
.../library/ZendXml/Exception/RuntimeException.php | 17 +
.../zendxml/library/ZendXml/Security.php | 374 +++++
vendor/zendframework/zendxml/tests/Bootstrap.php | 92 ++
.../zendxml/tests/ZendXmlTest/MultibyteTest.php | 125 ++
.../zendxml/tests/ZendXmlTest/SecurityTest.php | 135 ++
.../zendframework/zendxml/tests/phpunit.xml.dist | 27 +
1787 files changed, 123616 insertions(+), 45 deletions(-)
create mode 100644 vendor/aferrandini/phpqrcode/.gitignore
create mode 100755 vendor/aferrandini/phpqrcode/LICENSE
create mode 100755 vendor/aferrandini/phpqrcode/VERSION
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_1.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_10.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_10.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_11.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_11.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_12.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_12.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_13.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_13.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_14.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_14.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_15.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_15.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_16.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_16.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_17.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_17.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_18.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_18.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_19.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_19.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_2.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_20.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_20.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_21.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_21.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_22.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_22.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_23.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_23.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_24.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_24.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_25.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_25.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_26.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_26.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_27.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_27.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_28.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_28.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_29.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_29.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_3.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_30.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_30.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_31.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_31.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_32.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_32.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_33.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_33.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_34.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_34.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_35.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_35.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_36.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_36.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_37.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_37.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_38.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_38.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_39.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_39.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_4.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_40.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_40.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_5.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_6.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_7.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_8.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_8.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_9.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/frame_9.png
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_101_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_105_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_109_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_113_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_117_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_121_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_125_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_129_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_133_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_137_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_141_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_145_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_149_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_153_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_157_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_161_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_165_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_169_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_173_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_177_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_21_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_25_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_29_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_33_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_37_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_41_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_45_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_49_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_53_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_57_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_61_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_65_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_69_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_73_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_77_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_81_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_85_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_89_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_93_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_0/mask_97_0.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_101_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_105_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_109_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_113_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_117_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_121_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_125_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_129_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_133_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_137_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_141_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_145_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_149_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_153_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_157_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_161_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_165_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_169_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_173_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_177_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_21_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_25_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_29_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_33_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_37_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_41_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_45_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_49_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_53_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_57_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_61_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_65_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_69_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_73_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_77_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_81_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_85_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_89_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_93_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_1/mask_97_1.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_101_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_105_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_109_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_113_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_117_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_121_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_125_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_129_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_133_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_137_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_141_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_145_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_149_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_153_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_157_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_161_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_165_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_169_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_173_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_177_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_21_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_25_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_29_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_33_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_37_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_41_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_45_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_49_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_53_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_57_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_61_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_65_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_69_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_73_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_77_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_81_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_85_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_89_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_93_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_2/mask_97_2.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_101_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_105_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_109_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_113_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_117_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_121_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_125_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_129_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_133_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_137_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_141_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_145_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_149_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_153_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_157_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_161_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_165_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_169_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_173_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_177_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_21_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_25_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_29_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_33_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_37_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_41_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_45_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_49_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_53_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_57_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_61_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_65_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_69_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_73_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_77_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_81_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_85_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_89_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_93_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_3/mask_97_3.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_101_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_105_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_109_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_113_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_117_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_121_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_125_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_129_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_133_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_137_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_141_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_145_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_149_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_153_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_157_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_161_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_165_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_169_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_173_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_177_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_21_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_25_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_29_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_33_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_37_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_41_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_45_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_49_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_53_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_57_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_61_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_65_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_69_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_73_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_77_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_81_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_85_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_89_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_93_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_4/mask_97_4.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_101_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_105_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_109_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_113_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_117_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_121_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_125_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_129_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_133_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_137_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_141_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_145_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_149_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_153_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_157_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_161_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_165_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_169_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_173_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_177_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_21_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_25_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_29_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_33_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_37_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_41_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_45_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_49_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_53_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_57_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_61_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_65_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_69_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_73_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_77_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_81_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_85_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_89_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_93_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_5/mask_97_5.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_101_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_105_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_109_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_113_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_117_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_121_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_125_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_129_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_133_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_137_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_141_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_145_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_149_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_153_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_157_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_161_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_165_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_169_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_173_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_177_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_21_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_25_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_29_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_33_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_37_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_41_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_45_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_49_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_53_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_57_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_61_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_65_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_69_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_73_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_77_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_81_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_85_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_89_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_93_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_6/mask_97_6.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_101_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_105_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_109_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_113_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_117_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_121_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_125_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_129_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_133_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_137_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_141_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_145_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_149_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_153_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_157_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_161_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_165_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_169_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_173_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_177_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_21_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_25_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_29_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_33_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_37_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_41_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_45_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_49_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_53_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_57_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_61_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_65_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_69_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_73_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_77_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_81_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_85_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_89_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_93_7.dat
create mode 100755 vendor/aferrandini/phpqrcode/cache/mask_7/mask_97_7.dat
create mode 100644 vendor/aferrandini/phpqrcode/composer.json
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/Autoloader.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/Constants.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/FrameFiller.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php
create mode 100644 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php
create mode 100755 vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php
create mode 100755 vendor/aferrandini/phpqrcode/readme.md
create mode 100644 vendor/autoload.php
create mode 120000 vendor/bin/picofeed
create mode 100644 vendor/christian-riesen/base32/.gitignore
create mode 100644 vendor/christian-riesen/base32/.scrutinizer.yml
create mode 100644 vendor/christian-riesen/base32/.travis.yml
create mode 100644 vendor/christian-riesen/base32/LICENSE
create mode 100644 vendor/christian-riesen/base32/README.md
create mode 100644 vendor/christian-riesen/base32/build.xml
create mode 100644 vendor/christian-riesen/base32/composer.json
create mode 100644 vendor/christian-riesen/base32/phpunit.xml.dist
create mode 100644 vendor/christian-riesen/base32/src/Base32.php
create mode 100644 vendor/christian-riesen/base32/tests/Base32Test.php
create mode 100644 vendor/christian-riesen/base32/tests/bootstrap.php
create mode 100644 vendor/christian-riesen/otp/.gitignore
create mode 100644 vendor/christian-riesen/otp/.travis.yml
create mode 100644 vendor/christian-riesen/otp/LICENSE
create mode 100644 vendor/christian-riesen/otp/README.md
create mode 100644 vendor/christian-riesen/otp/composer.json
create mode 100644 vendor/christian-riesen/otp/example/index.php
create mode 100644 vendor/christian-riesen/otp/phpunit.xml.dist
create mode 100644 vendor/christian-riesen/otp/src/Otp/GoogleAuthenticator.php
create mode 100644 vendor/christian-riesen/otp/src/Otp/Otp.php
create mode 100644 vendor/christian-riesen/otp/src/Otp/OtpInterface.php
create mode 100644 vendor/christian-riesen/otp/tests/Otp/GoogleAuthenticatorTest.php
create mode 100644 vendor/christian-riesen/otp/tests/Otp/OtpTest.php
create mode 100644 vendor/composer/ClassLoader.php
create mode 100644 vendor/composer/LICENSE
create mode 100644 vendor/composer/autoload_classmap.php
create mode 100644 vendor/composer/autoload_files.php
create mode 100644 vendor/composer/autoload_namespaces.php
create mode 100644 vendor/composer/autoload_psr4.php
create mode 100644 vendor/composer/autoload_real.php
create mode 100644 vendor/composer/autoload_static.php
create mode 100644 vendor/composer/installed.json
create mode 100644 vendor/eluceo/ical/.gitignore
create mode 100644 vendor/eluceo/ical/.php_cs
create mode 100644 vendor/eluceo/ical/.scrutinizer.yml
create mode 100644 vendor/eluceo/ical/.travis.yml
create mode 100644 vendor/eluceo/ical/CHANGELOG.md
create mode 100644 vendor/eluceo/ical/LICENSE
create mode 100644 vendor/eluceo/ical/README.md
create mode 100644 vendor/eluceo/ical/UPGRADE.md
create mode 100644 vendor/eluceo/ical/composer.json
create mode 100644 vendor/eluceo/ical/examples/example1.php
create mode 100644 vendor/eluceo/ical/examples/example2.php
create mode 100644 vendor/eluceo/ical/examples/example3.php
create mode 100644 vendor/eluceo/ical/examples/example4.php
create mode 100644 vendor/eluceo/ical/examples/example5.php
create mode 100644 vendor/eluceo/ical/examples/example6.php
create mode 100644 vendor/eluceo/ical/examples/example7.php
create mode 100644 vendor/eluceo/ical/phpunit.xml.dist
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component/Event.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/ParameterBag.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/PropertyBag.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php
create mode 100644 vendor/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Component/CalendarIntegrationTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/ComponentTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/ParameterBagTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Property/ArrayValueTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/DescriptionTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/OrganizerTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/RecurrenceRuleTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/Property/StringValueTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/PropertyBagTest.php
create mode 100644 vendor/eluceo/ical/tests/Eluceo/iCal/PropertyTest.php
create mode 100644 vendor/erusev/parsedown/.travis.yml
create mode 100644 vendor/erusev/parsedown/LICENSE.txt
create mode 100755 vendor/erusev/parsedown/Parsedown.php
create mode 100644 vendor/erusev/parsedown/README.md
create mode 100644 vendor/erusev/parsedown/composer.json
create mode 100644 vendor/erusev/parsedown/phpunit.xml.dist
create mode 100644 vendor/erusev/parsedown/test/CommonMarkTest.php
create mode 100644 vendor/erusev/parsedown/test/ParsedownTest.php
create mode 100644 vendor/erusev/parsedown/test/TestParsedown.php
create mode 100644 vendor/erusev/parsedown/test/bootstrap.php
create mode 100644 vendor/erusev/parsedown/test/data/aesthetic_table.html
create mode 100644 vendor/erusev/parsedown/test/data/aesthetic_table.md
create mode 100644 vendor/erusev/parsedown/test/data/aligned_table.html
create mode 100644 vendor/erusev/parsedown/test/data/aligned_table.md
create mode 100644 vendor/erusev/parsedown/test/data/atx_heading.html
create mode 100644 vendor/erusev/parsedown/test/data/atx_heading.md
create mode 100644 vendor/erusev/parsedown/test/data/automatic_link.html
create mode 100644 vendor/erusev/parsedown/test/data/automatic_link.md
create mode 100644 vendor/erusev/parsedown/test/data/block-level_html.html
create mode 100644 vendor/erusev/parsedown/test/data/block-level_html.md
create mode 100644 vendor/erusev/parsedown/test/data/code_block.html
create mode 100644 vendor/erusev/parsedown/test/data/code_block.md
create mode 100644 vendor/erusev/parsedown/test/data/code_span.html
create mode 100644 vendor/erusev/parsedown/test/data/code_span.md
create mode 100644 vendor/erusev/parsedown/test/data/compound_blockquote.html
create mode 100644 vendor/erusev/parsedown/test/data/compound_blockquote.md
create mode 100644 vendor/erusev/parsedown/test/data/compound_emphasis.html
create mode 100644 vendor/erusev/parsedown/test/data/compound_emphasis.md
create mode 100644 vendor/erusev/parsedown/test/data/compound_list.html
create mode 100644 vendor/erusev/parsedown/test/data/compound_list.md
create mode 100644 vendor/erusev/parsedown/test/data/deeply_nested_list.html
create mode 100644 vendor/erusev/parsedown/test/data/deeply_nested_list.md
create mode 100644 vendor/erusev/parsedown/test/data/em_strong.html
create mode 100644 vendor/erusev/parsedown/test/data/em_strong.md
create mode 100644 vendor/erusev/parsedown/test/data/email.html
create mode 100644 vendor/erusev/parsedown/test/data/email.md
create mode 100644 vendor/erusev/parsedown/test/data/emphasis.html
create mode 100644 vendor/erusev/parsedown/test/data/emphasis.md
create mode 100644 vendor/erusev/parsedown/test/data/escaping.html
create mode 100644 vendor/erusev/parsedown/test/data/escaping.md
create mode 100644 vendor/erusev/parsedown/test/data/fenced_code_block.html
create mode 100644 vendor/erusev/parsedown/test/data/fenced_code_block.md
create mode 100644 vendor/erusev/parsedown/test/data/horizontal_rule.html
create mode 100644 vendor/erusev/parsedown/test/data/horizontal_rule.md
create mode 100644 vendor/erusev/parsedown/test/data/html_comment.html
create mode 100644 vendor/erusev/parsedown/test/data/html_comment.md
create mode 100644 vendor/erusev/parsedown/test/data/html_entity.html
create mode 100644 vendor/erusev/parsedown/test/data/html_entity.md
create mode 100644 vendor/erusev/parsedown/test/data/image_reference.html
create mode 100644 vendor/erusev/parsedown/test/data/image_reference.md
create mode 100644 vendor/erusev/parsedown/test/data/image_title.html
create mode 100644 vendor/erusev/parsedown/test/data/image_title.md
create mode 100644 vendor/erusev/parsedown/test/data/implicit_reference.html
create mode 100644 vendor/erusev/parsedown/test/data/implicit_reference.md
create mode 100644 vendor/erusev/parsedown/test/data/inline_link.html
create mode 100644 vendor/erusev/parsedown/test/data/inline_link.md
create mode 100644 vendor/erusev/parsedown/test/data/inline_link_title.html
create mode 100644 vendor/erusev/parsedown/test/data/inline_link_title.md
create mode 100644 vendor/erusev/parsedown/test/data/inline_title.html
create mode 100644 vendor/erusev/parsedown/test/data/inline_title.md
create mode 100644 vendor/erusev/parsedown/test/data/lazy_blockquote.html
create mode 100644 vendor/erusev/parsedown/test/data/lazy_blockquote.md
create mode 100644 vendor/erusev/parsedown/test/data/lazy_list.html
create mode 100644 vendor/erusev/parsedown/test/data/lazy_list.md
create mode 100644 vendor/erusev/parsedown/test/data/line_break.html
create mode 100644 vendor/erusev/parsedown/test/data/line_break.md
create mode 100644 vendor/erusev/parsedown/test/data/multiline_list_paragraph.html
create mode 100644 vendor/erusev/parsedown/test/data/multiline_list_paragraph.md
create mode 100644 vendor/erusev/parsedown/test/data/nested_block-level_html.html
create mode 100644 vendor/erusev/parsedown/test/data/nested_block-level_html.md
create mode 100644 vendor/erusev/parsedown/test/data/ordered_list.html
create mode 100644 vendor/erusev/parsedown/test/data/ordered_list.md
create mode 100644 vendor/erusev/parsedown/test/data/paragraph_list.html
create mode 100644 vendor/erusev/parsedown/test/data/paragraph_list.md
create mode 100644 vendor/erusev/parsedown/test/data/reference_title.html
create mode 100644 vendor/erusev/parsedown/test/data/reference_title.md
create mode 100644 vendor/erusev/parsedown/test/data/self-closing_html.html
create mode 100644 vendor/erusev/parsedown/test/data/self-closing_html.md
create mode 100644 vendor/erusev/parsedown/test/data/separated_nested_list.html
create mode 100644 vendor/erusev/parsedown/test/data/separated_nested_list.md
create mode 100644 vendor/erusev/parsedown/test/data/setext_header.html
create mode 100644 vendor/erusev/parsedown/test/data/setext_header.md
create mode 100644 vendor/erusev/parsedown/test/data/simple_blockquote.html
create mode 100644 vendor/erusev/parsedown/test/data/simple_blockquote.md
create mode 100644 vendor/erusev/parsedown/test/data/simple_table.html
create mode 100644 vendor/erusev/parsedown/test/data/simple_table.md
create mode 100644 vendor/erusev/parsedown/test/data/span-level_html.html
create mode 100644 vendor/erusev/parsedown/test/data/span-level_html.md
create mode 100644 vendor/erusev/parsedown/test/data/sparse_dense_list.html
create mode 100644 vendor/erusev/parsedown/test/data/sparse_dense_list.md
create mode 100644 vendor/erusev/parsedown/test/data/sparse_html.html
create mode 100644 vendor/erusev/parsedown/test/data/sparse_html.md
create mode 100644 vendor/erusev/parsedown/test/data/sparse_list.html
create mode 100644 vendor/erusev/parsedown/test/data/sparse_list.md
create mode 100644 vendor/erusev/parsedown/test/data/special_characters.html
create mode 100644 vendor/erusev/parsedown/test/data/special_characters.md
create mode 100644 vendor/erusev/parsedown/test/data/strikethrough.html
create mode 100644 vendor/erusev/parsedown/test/data/strikethrough.md
create mode 100644 vendor/erusev/parsedown/test/data/strong_em.html
create mode 100644 vendor/erusev/parsedown/test/data/strong_em.md
create mode 100644 vendor/erusev/parsedown/test/data/tab-indented_code_block.html
create mode 100644 vendor/erusev/parsedown/test/data/tab-indented_code_block.md
create mode 100644 vendor/erusev/parsedown/test/data/table_inline_markdown.html
create mode 100644 vendor/erusev/parsedown/test/data/table_inline_markdown.md
create mode 100644 vendor/erusev/parsedown/test/data/text_reference.html
create mode 100644 vendor/erusev/parsedown/test/data/text_reference.md
create mode 100644 vendor/erusev/parsedown/test/data/unordered_list.html
create mode 100644 vendor/erusev/parsedown/test/data/unordered_list.md
create mode 100644 vendor/erusev/parsedown/test/data/untidy_table.html
create mode 100644 vendor/erusev/parsedown/test/data/untidy_table.md
create mode 100644 vendor/erusev/parsedown/test/data/url_autolinking.html
create mode 100644 vendor/erusev/parsedown/test/data/url_autolinking.md
create mode 100644 vendor/erusev/parsedown/test/data/whitespace.html
create mode 100644 vendor/erusev/parsedown/test/data/whitespace.md
create mode 100644 vendor/fguillot/json-rpc/LICENSE
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Client.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/AuthenticationFailureException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ConnectionFailureException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonFormatException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonRpcFormatException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ResponseEncodingFailureException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Server.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/JsonEncodingValidator.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/JsonFormatValidator.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/RpcFormatValidator.php
create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/UserValidator.php
create mode 100644 vendor/fguillot/picodb/LICENSE
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/BaseBuilder.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Database.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Hashtable.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/LargeObject.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/SQLException.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Schema.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Table.php
create mode 100644 vendor/fguillot/picodb/lib/PicoDb/UrlParser.php
create mode 100644 vendor/fguillot/simple-queue/LICENSE
create mode 100644 vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php
create mode 100644 vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php
create mode 100644 vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php
create mode 100644 vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php
create mode 100644 vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php
create mode 100644 vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php
create mode 100644 vendor/fguillot/simple-queue/src/Job.php
create mode 100644 vendor/fguillot/simple-queue/src/Queue.php
create mode 100644 vendor/fguillot/simple-queue/src/QueueAdapterInterface.php
create mode 100644 vendor/fguillot/simple-validator/LICENSE
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validator.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php
create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php
create mode 100644 vendor/fguillot/simpleLogger/LICENSE
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/File.php
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php
create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php
create mode 100644 vendor/gregwar/captcha/.gitignore
create mode 100644 vendor/gregwar/captcha/.travis.yml
create mode 100644 vendor/gregwar/captcha/CaptchaBuilder.php
create mode 100644 vendor/gregwar/captcha/CaptchaBuilderInterface.php
create mode 100644 vendor/gregwar/captcha/Font/captcha0.ttf
create mode 100644 vendor/gregwar/captcha/Font/captcha1.ttf
create mode 100644 vendor/gregwar/captcha/Font/captcha2.ttf
create mode 100644 vendor/gregwar/captcha/Font/captcha3.ttf
create mode 100644 vendor/gregwar/captcha/Font/captcha4.ttf
create mode 100644 vendor/gregwar/captcha/Font/captcha5.ttf
create mode 100644 vendor/gregwar/captcha/ImageFileHandler.php
create mode 100644 vendor/gregwar/captcha/LICENSE
create mode 100644 vendor/gregwar/captcha/PhraseBuilder.php
create mode 100644 vendor/gregwar/captcha/PhraseBuilderInterface.php
create mode 100644 vendor/gregwar/captcha/README.md
create mode 100644 vendor/gregwar/captcha/autoload.php
create mode 100644 vendor/gregwar/captcha/composer.json
create mode 100644 vendor/gregwar/captcha/demo/demo.php
create mode 100644 vendor/gregwar/captcha/demo/fingerprint.php
create mode 100644 vendor/gregwar/captcha/demo/index.php
create mode 100644 vendor/gregwar/captcha/demo/ocr.php
create mode 100644 vendor/gregwar/captcha/demo/output.php
create mode 100644 vendor/miniflux/picofeed/LICENSE
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Base.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/Client.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/Curl.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/HttpHeaders.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/InvalidUrlException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/MaxRedirectException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/MaxSizeException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/Stream.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/UnauthorizedException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Client/Url.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Filter/Attribute.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Filter/Html.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Item.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Parser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/ParserInterface.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss10.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss92.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/XmlEntityException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Parser/XmlParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.blog.lemonde.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.igen.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.nytimes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.over-blog.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.phoronix.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.slate.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.theguardian.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wikipedia.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wired.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wsj.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/01net.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/adventuregamers.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/alainonline.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/aljazeera.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/allafrica.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/allgemeine-zeitung.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/ap.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/areadvd.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/arstechnica.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/awkwardzombie.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/backchannel.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bangkokpost.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bgr.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigfootjustice.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigpicture.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bizjournals.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/biztimes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bleepingcomputer.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.fefe.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.mapillary.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/brewers.mlb.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/buenosairesherald.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/bunicomic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/buttersafe.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/cad-comic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/chaoslife.findchaos.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/chinafile.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/cliquerefresh.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/cnet.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/consomac.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/crash.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/csmonitor.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyjs.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyreporter.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailytech.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/degroupnews.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/derstandard.at.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/dilbert.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/discovermagazine.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/distrowatch.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/dozodomo.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/e-w-e.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/economist.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/encyclopedie.naheulbeuk.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/engadget.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/espn.go.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/exocomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/explosm.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/factroom.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcodesign.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcoexist.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcompany.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/ffworld.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/foreignpolicy.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fossbytes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fototelegraf.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/fowllanguagecomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/geek.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/geektimes.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/gerbilwithajetpack.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/giantitp.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/github.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/gocomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/golem.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/gorabbit.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/habrahabr.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/happletea.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/hardware.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/heise.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/hotshowlife.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/huffingtonpost.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/imogenquest.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/indiehaven.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/ing.dk.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/ir.amd.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantimes.co.jp.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantoday.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/journaldugeek.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/jsonline.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/justcoolidea.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/kanpai.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/karriere.jobfinder.dk.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/kodi.tv.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreaherald.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreatimes.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/legorafi.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lejapon.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lesjoiesducode.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lfg.co.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/linuxinsider.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lists.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/loadingartist.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/loldwell.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/lukesurl.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/macg.co.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/marc.info.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/marycagle.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/maximumble.thebookofbiff.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/medium.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/mercworks.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/metronieuws.nl.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/milwaukeenns.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/mokepon.smackjeeves.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/monandroid.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/monwindows.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/moya-planeta.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/muckrock.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/mynorthshorenow.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nakedCapitalism.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nasa.gov.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nat-geo.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nationaljournal.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nature.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nba.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nedroid.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/networkworld.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/neustadt-ticker.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nextinpact.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/niceteethcomic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/nichtlustig.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/oglaf.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/onhax.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/onmilwaukee.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/openculture.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/opennet.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/openrightsgroup.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/opensource.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/optipess.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/osnews.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/pastebin.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/peebleslab.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/penny-arcade.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/plus.google.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/popstrip.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/publicpolicyforum.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/publy.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/putaindecode.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/recode.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/retractionwatch.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/rockpapershotgun.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/rue89.nouvelobs.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/satwcomic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/scrumalliance.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/securityfocus.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/sitepoint.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/slashdot.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/smallhousebliss.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/smarthomewelt.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/smashingmagazine.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/snopes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/soundandvision.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/spiegel.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/stereophile.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/stupidfox.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/subtraction.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/sz.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/takprosto.cc.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/techcrunch.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/the-ebook-reader.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/theatlantic.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thecodinglove.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thegamercat.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thehindu.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thelocal.se.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/themerepublic.net.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/themoscowtimes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thenewslens.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/theodd1sout.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/theonion.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/thestandard.com.hk.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/threepanelsoul.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/timesofindia.indiatimes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/travel-dealz.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/treehugger.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/treelobsters.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/twogag.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/twokinds.keenspot.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/undeadly.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/upi.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/usatoday.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/version2.dk.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/vgcats.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/vuxml.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/wausaudailyherald.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bdgest.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bgr.in.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.businessweek.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.cnn.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.developpez.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.egscomics.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.fakingnews.firstpost.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.forbes.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.franceculture.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.futura-sciences.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.geekculture.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.howtogeek.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lesnumeriques.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.mac4ever.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.makeuseof.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.monsieur-le-chien.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.npr.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.numerama.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.oneindia.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.pseudo-sciences.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.sciencemag.org.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.slate.fr.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.universfreebox.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.zeit.de.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/xkcd.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Rules/zdnet.com.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Scraper/RuleLoader.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php
create mode 100644 vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php
create mode 100755 vendor/miniflux/picofeed/picofeed
create mode 100644 vendor/paragonie/random_compat/CHANGELOG.md
create mode 100644 vendor/paragonie/random_compat/ERRATA.md
create mode 100644 vendor/paragonie/random_compat/LICENSE
create mode 100644 vendor/paragonie/random_compat/README.md
create mode 100644 vendor/paragonie/random_compat/SECURITY.md
create mode 100755 vendor/paragonie/random_compat/build-phar.sh
create mode 100644 vendor/paragonie/random_compat/composer.json
create mode 100644 vendor/paragonie/random_compat/dist/random_compat.phar.pubkey
create mode 100644 vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc
create mode 100644 vendor/paragonie/random_compat/lib/byte_safe_strings.php
create mode 100644 vendor/paragonie/random_compat/lib/cast_to_int.php
create mode 100644 vendor/paragonie/random_compat/lib/error_polyfill.php
create mode 100644 vendor/paragonie/random_compat/lib/random.php
create mode 100644 vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php
create mode 100644 vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php
create mode 100644 vendor/paragonie/random_compat/lib/random_bytes_libsodium.php
create mode 100644 vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php
create mode 100644 vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php
create mode 100644 vendor/paragonie/random_compat/lib/random_int.php
create mode 100644 vendor/paragonie/random_compat/other/build_phar.php
create mode 100644 vendor/pimple/pimple/.gitignore
create mode 100644 vendor/pimple/pimple/.travis.yml
create mode 100644 vendor/pimple/pimple/CHANGELOG
create mode 100644 vendor/pimple/pimple/LICENSE
create mode 100644 vendor/pimple/pimple/README.rst
create mode 100644 vendor/pimple/pimple/composer.json
create mode 100644 vendor/pimple/pimple/ext/pimple/.gitignore
create mode 100644 vendor/pimple/pimple/ext/pimple/README.md
create mode 100644 vendor/pimple/pimple/ext/pimple/config.m4
create mode 100644 vendor/pimple/pimple/ext/pimple/config.w32
create mode 100644 vendor/pimple/pimple/ext/pimple/php_pimple.h
create mode 100644 vendor/pimple/pimple/ext/pimple/pimple.c
create mode 100644 vendor/pimple/pimple/ext/pimple/pimple_compat.h
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/001.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/002.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/003.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/004.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/005.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/006.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/007.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/008.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/009.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/010.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/011.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/012.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/013.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/014.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/015.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/016.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/017.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/018.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/019.phpt
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench.phpb
create mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
create mode 100644 vendor/pimple/pimple/phpunit.xml.dist
create mode 100644 vendor/pimple/pimple/src/Pimple/Container.php
create mode 100644 vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
create mode 100644 vendor/psr/log/.gitignore
create mode 100644 vendor/psr/log/LICENSE
create mode 100644 vendor/psr/log/Psr/Log/AbstractLogger.php
create mode 100644 vendor/psr/log/Psr/Log/InvalidArgumentException.php
create mode 100644 vendor/psr/log/Psr/Log/LogLevel.php
create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareInterface.php
create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareTrait.php
create mode 100644 vendor/psr/log/Psr/Log/LoggerInterface.php
create mode 100644 vendor/psr/log/Psr/Log/LoggerTrait.php
create mode 100644 vendor/psr/log/Psr/Log/NullLogger.php
create mode 100644 vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
create mode 100644 vendor/psr/log/README.md
create mode 100644 vendor/psr/log/composer.json
create mode 100644 vendor/ramsey/array_column/.gitignore
create mode 100644 vendor/ramsey/array_column/.travis.yml
create mode 100644 vendor/ramsey/array_column/CHANGELOG.md
create mode 100644 vendor/ramsey/array_column/LICENSE
create mode 100644 vendor/ramsey/array_column/README.md
create mode 100644 vendor/ramsey/array_column/composer.json
create mode 100644 vendor/ramsey/array_column/phpunit.xml.dist
create mode 100644 vendor/ramsey/array_column/src/array_column.php
create mode 100644 vendor/ramsey/array_column/tests/ArrayColumnTest.php
create mode 100644 vendor/ramsey/array_column/tests/bootstrap.php
create mode 100644 vendor/swiftmailer/swiftmailer/.gitattributes
create mode 100644 vendor/swiftmailer/swiftmailer/.gitignore
create mode 100644 vendor/swiftmailer/swiftmailer/.travis.yml
create mode 100644 vendor/swiftmailer/swiftmailer/CHANGES
create mode 100644 vendor/swiftmailer/swiftmailer/LICENSE
create mode 100644 vendor/swiftmailer/swiftmailer/README
create mode 100644 vendor/swiftmailer/swiftmailer/VERSION
create mode 100644 vendor/swiftmailer/swiftmailer/composer.json
create mode 100644 vendor/swiftmailer/swiftmailer/doc/headers.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/help-resources.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/including-the-files.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/index.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/installing.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/introduction.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/japanese.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/messages.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/overview.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/plugins.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/sending.rst
create mode 100644 vendor/swiftmailer/swiftmailer/doc/uml/Encoders.graffle
create mode 100644 vendor/swiftmailer/swiftmailer/doc/uml/Mime.graffle
create mode 100644 vendor/swiftmailer/swiftmailer/doc/uml/Transports.graffle
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Attachment.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/EmbeddedFile.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/Event.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventObject.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendEvent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/FailoverTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Filterable.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Image.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/IoException.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Grammar.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderSet.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimePart.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Exception.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Preferences.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/RfcComplianceException.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/SendmailTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/classes/Swift/Validate.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/mime_types.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/preferences.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/swift_init.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/swift_required.php
create mode 100644 vendor/swiftmailer/swiftmailer/lib/swift_required_pear.php
create mode 100755 vendor/swiftmailer/swiftmailer/lib/swiftmailer_generate_mimes_config.php
create mode 100644 vendor/swiftmailer/swiftmailer/phpunit.xml.dist
create mode 100644 vendor/swiftmailer/swiftmailer/tests/IdenticalBinaryConstraint.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/StreamCollector.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/SwiftMailerSmokeTestCase.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/SwiftMailerTestCase.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/charsets/iso-2022-jp/one.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/charsets/iso-8859-1/one.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/one.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/three.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/two.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/dkim/dkim.test.priv
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/dkim/dkim.test.pub
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/files/data.txt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/files/swiftmailer.png
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/files/textfile.zip
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/CA.srl
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/create-cert.sh
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.crt
create mode 100644 vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.key
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance.conf.php.default
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/AttachmentAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/ByteStream/FileByteStreamAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Base64EncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EncodingAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MessageAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MimePartAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bootstrap.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug111Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug118Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug274Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug34Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug35Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug38Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug518Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug51Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug534Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug71Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug76Test.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/bug/Swift/BugFileByteStreamConsecutiveReadCallsTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/fixtures/MimeEntityFixture.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/smoke.conf.php.default
create mode 100644 vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/AttachmentSmokeTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/BasicSmokeTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/InternationalSmokeTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/DependencyContainerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Base64EncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/CommandEventTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/EventObjectTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/ResponseEventTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SendEventTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SimpleEventDispatcherTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportChangeEventTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportExceptionEventTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/MailerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/MessageTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AbstractMimeEntityTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AttachmentTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/EmbeddedFileTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/DateHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/PathHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/MimePartTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderSetTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMessageTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMimeEntityTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/AntiFloodPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/DecoratorPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/LoggerPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/RedirectingPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ReporterPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ThrottlerPluginTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/DKIMSignerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/OpenDKIMSignerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/SMimeSignerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/NTLMAuthenticatorTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/FailoverTransportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/LoadBalancedTransportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/MailTransportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/SendmailTransportTest.php
create mode 100644 vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/StreamBufferTest.php
create mode 100644 vendor/symfony/console/.gitignore
create mode 100644 vendor/symfony/console/Application.php
create mode 100644 vendor/symfony/console/CHANGELOG.md
create mode 100644 vendor/symfony/console/Command/Command.php
create mode 100644 vendor/symfony/console/Command/HelpCommand.php
create mode 100644 vendor/symfony/console/Command/ListCommand.php
create mode 100644 vendor/symfony/console/ConsoleEvents.php
create mode 100644 vendor/symfony/console/Descriptor/ApplicationDescription.php
create mode 100644 vendor/symfony/console/Descriptor/Descriptor.php
create mode 100644 vendor/symfony/console/Descriptor/DescriptorInterface.php
create mode 100644 vendor/symfony/console/Descriptor/JsonDescriptor.php
create mode 100644 vendor/symfony/console/Descriptor/MarkdownDescriptor.php
create mode 100644 vendor/symfony/console/Descriptor/TextDescriptor.php
create mode 100644 vendor/symfony/console/Descriptor/XmlDescriptor.php
create mode 100644 vendor/symfony/console/Event/ConsoleCommandEvent.php
create mode 100644 vendor/symfony/console/Event/ConsoleEvent.php
create mode 100644 vendor/symfony/console/Event/ConsoleExceptionEvent.php
create mode 100644 vendor/symfony/console/Event/ConsoleTerminateEvent.php
create mode 100644 vendor/symfony/console/Exception/CommandNotFoundException.php
create mode 100644 vendor/symfony/console/Exception/ExceptionInterface.php
create mode 100644 vendor/symfony/console/Exception/InvalidArgumentException.php
create mode 100644 vendor/symfony/console/Exception/InvalidOptionException.php
create mode 100644 vendor/symfony/console/Exception/LogicException.php
create mode 100644 vendor/symfony/console/Exception/RuntimeException.php
create mode 100644 vendor/symfony/console/Formatter/OutputFormatter.php
create mode 100644 vendor/symfony/console/Formatter/OutputFormatterInterface.php
create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyle.php
create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
create mode 100644 vendor/symfony/console/Helper/DebugFormatterHelper.php
create mode 100644 vendor/symfony/console/Helper/DescriptorHelper.php
create mode 100644 vendor/symfony/console/Helper/DialogHelper.php
create mode 100644 vendor/symfony/console/Helper/FormatterHelper.php
create mode 100644 vendor/symfony/console/Helper/Helper.php
create mode 100644 vendor/symfony/console/Helper/HelperInterface.php
create mode 100644 vendor/symfony/console/Helper/HelperSet.php
create mode 100644 vendor/symfony/console/Helper/InputAwareHelper.php
create mode 100644 vendor/symfony/console/Helper/ProcessHelper.php
create mode 100644 vendor/symfony/console/Helper/ProgressBar.php
create mode 100644 vendor/symfony/console/Helper/ProgressHelper.php
create mode 100644 vendor/symfony/console/Helper/ProgressIndicator.php
create mode 100644 vendor/symfony/console/Helper/QuestionHelper.php
create mode 100644 vendor/symfony/console/Helper/SymfonyQuestionHelper.php
create mode 100644 vendor/symfony/console/Helper/Table.php
create mode 100644 vendor/symfony/console/Helper/TableCell.php
create mode 100644 vendor/symfony/console/Helper/TableHelper.php
create mode 100644 vendor/symfony/console/Helper/TableSeparator.php
create mode 100644 vendor/symfony/console/Helper/TableStyle.php
create mode 100644 vendor/symfony/console/Input/ArgvInput.php
create mode 100644 vendor/symfony/console/Input/ArrayInput.php
create mode 100644 vendor/symfony/console/Input/Input.php
create mode 100644 vendor/symfony/console/Input/InputArgument.php
create mode 100644 vendor/symfony/console/Input/InputAwareInterface.php
create mode 100644 vendor/symfony/console/Input/InputDefinition.php
create mode 100644 vendor/symfony/console/Input/InputInterface.php
create mode 100644 vendor/symfony/console/Input/InputOption.php
create mode 100644 vendor/symfony/console/Input/StringInput.php
create mode 100644 vendor/symfony/console/LICENSE
create mode 100644 vendor/symfony/console/Logger/ConsoleLogger.php
create mode 100644 vendor/symfony/console/Output/BufferedOutput.php
create mode 100644 vendor/symfony/console/Output/ConsoleOutput.php
create mode 100644 vendor/symfony/console/Output/ConsoleOutputInterface.php
create mode 100644 vendor/symfony/console/Output/NullOutput.php
create mode 100644 vendor/symfony/console/Output/Output.php
create mode 100644 vendor/symfony/console/Output/OutputInterface.php
create mode 100644 vendor/symfony/console/Output/StreamOutput.php
create mode 100644 vendor/symfony/console/Question/ChoiceQuestion.php
create mode 100644 vendor/symfony/console/Question/ConfirmationQuestion.php
create mode 100644 vendor/symfony/console/Question/Question.php
create mode 100644 vendor/symfony/console/README.md
create mode 100644 vendor/symfony/console/Resources/bin/hiddeninput.exe
create mode 100644 vendor/symfony/console/Shell.php
create mode 100644 vendor/symfony/console/Style/OutputStyle.php
create mode 100644 vendor/symfony/console/Style/StyleInterface.php
create mode 100644 vendor/symfony/console/Style/SymfonyStyle.php
create mode 100644 vendor/symfony/console/Tester/ApplicationTester.php
create mode 100644 vendor/symfony/console/Tester/CommandTester.php
create mode 100644 vendor/symfony/console/Tests/ApplicationTest.php
create mode 100644 vendor/symfony/console/Tests/Command/CommandTest.php
create mode 100644 vendor/symfony/console/Tests/Command/HelpCommandTest.php
create mode 100644 vendor/symfony/console/Tests/Command/ListCommandTest.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php
create mode 100644 vendor/symfony/console/Tests/Descriptor/XmlDescriptorTest.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/BarBucCommand.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorApplication1.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand1.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand2.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/DummyOutput.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo1Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo2Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo3Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo4Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo5Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Foo6Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/FooCommand.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/FooSubnamespaced1Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/FooSubnamespaced2Command.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/FoobarCommand.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_0.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_6.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/TestCommand.php
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_astext1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_astext2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_asxml1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_asxml2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_gethelp.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_run1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_run2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_run3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/application_run4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_astext.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/command_asxml.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/definition_astext.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/definition_asxml.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.xml
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.json
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.md
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.txt
create mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.xml
create mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php
create mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php
create mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/FormatterHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/HelperSetTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/HelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/ProcessHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/ProgressBarTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/QuestionHelperTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/TableStyleTest.php
create mode 100644 vendor/symfony/console/Tests/Helper/TableTest.php
create mode 100644 vendor/symfony/console/Tests/Input/ArgvInputTest.php
create mode 100644 vendor/symfony/console/Tests/Input/ArrayInputTest.php
create mode 100644 vendor/symfony/console/Tests/Input/InputArgumentTest.php
create mode 100644 vendor/symfony/console/Tests/Input/InputDefinitionTest.php
create mode 100644 vendor/symfony/console/Tests/Input/InputOptionTest.php
create mode 100644 vendor/symfony/console/Tests/Input/InputTest.php
create mode 100644 vendor/symfony/console/Tests/Input/StringInputTest.php
create mode 100644 vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php
create mode 100644 vendor/symfony/console/Tests/Output/ConsoleOutputTest.php
create mode 100644 vendor/symfony/console/Tests/Output/NullOutputTest.php
create mode 100644 vendor/symfony/console/Tests/Output/OutputTest.php
create mode 100644 vendor/symfony/console/Tests/Output/StreamOutputTest.php
create mode 100644 vendor/symfony/console/Tests/Style/SymfonyStyleTest.php
create mode 100644 vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php
create mode 100644 vendor/symfony/console/Tests/Tester/CommandTesterTest.php
create mode 100644 vendor/symfony/console/composer.json
create mode 100644 vendor/symfony/console/phpunit.xml.dist
create mode 100644 vendor/symfony/event-dispatcher/.gitignore
create mode 100644 vendor/symfony/event-dispatcher/CHANGELOG.md
create mode 100644 vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
create mode 100644 vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
create mode 100644 vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
create mode 100644 vendor/symfony/event-dispatcher/Debug/WrappedListener.php
create mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
create mode 100644 vendor/symfony/event-dispatcher/Event.php
create mode 100644 vendor/symfony/event-dispatcher/EventDispatcher.php
create mode 100644 vendor/symfony/event-dispatcher/EventDispatcherInterface.php
create mode 100644 vendor/symfony/event-dispatcher/EventSubscriberInterface.php
create mode 100644 vendor/symfony/event-dispatcher/GenericEvent.php
create mode 100644 vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php
create mode 100644 vendor/symfony/event-dispatcher/LICENSE
create mode 100644 vendor/symfony/event-dispatcher/README.md
create mode 100644 vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/EventTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/GenericEventTest.php
create mode 100644 vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php
create mode 100644 vendor/symfony/event-dispatcher/composer.json
create mode 100644 vendor/symfony/event-dispatcher/phpunit.xml.dist
create mode 100644 vendor/symfony/polyfill-mbstring/LICENSE
create mode 100644 vendor/symfony/polyfill-mbstring/Mbstring.php
create mode 100644 vendor/symfony/polyfill-mbstring/README.md
create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
create mode 100644 vendor/symfony/polyfill-mbstring/bootstrap.php
create mode 100644 vendor/symfony/polyfill-mbstring/composer.json
create mode 100644 vendor/zendframework/zendxml/.gitignore
create mode 100644 vendor/zendframework/zendxml/.travis.yml
create mode 100644 vendor/zendframework/zendxml/CHANGELOG.md
create mode 100644 vendor/zendframework/zendxml/LICENSE.md
create mode 100644 vendor/zendframework/zendxml/README.md
create mode 100644 vendor/zendframework/zendxml/composer.json
create mode 100644 vendor/zendframework/zendxml/library/ZendXml/Exception/ExceptionInterface.php
create mode 100644 vendor/zendframework/zendxml/library/ZendXml/Exception/InvalidArgumentException.php
create mode 100644 vendor/zendframework/zendxml/library/ZendXml/Exception/RuntimeException.php
create mode 100644 vendor/zendframework/zendxml/library/ZendXml/Security.php
create mode 100644 vendor/zendframework/zendxml/tests/Bootstrap.php
create mode 100644 vendor/zendframework/zendxml/tests/ZendXmlTest/MultibyteTest.php
create mode 100644 vendor/zendframework/zendxml/tests/ZendXmlTest/SecurityTest.php
create mode 100755 vendor/zendframework/zendxml/tests/phpunit.xml.dist
diff --git a/.gitattributes b/.gitattributes
index 92a0d686..5ca66a71 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,15 +1,30 @@
app/constants.php export-subst
+.github export-ignore
.gitattributes export-ignore
.gitignore export-ignore
-.docker export-ignore
-.scrutinizer.yml export-ignore
+.dockerignore export-ignore
.travis.yml export-ignore
+
+docker export-ignore
Dockerfile export-ignore
docker-compose.yml export-ignore
Makefile export-ignore
README.md export-ignore
Vagrantfile export-ignore
-issue_template.md export-ignore
data/*.sqlite export-ignore
tests export-ignore
+CONTRIBUTING export-ignore
+app.json export-ignore
+bower.json export-ignore
+composer.json export-ignore
+composer.lock export-ignore
+gulpfile.js export-ignore
+package.json export-ignore
+
+assets/sass export-ignore
+assets/js/components export-ignore
+assets/js/core export-ignore
+assets/js/polyfills export-ignore
+assets/js/src export-ignore
+assets/sass export-ignore
diff --git a/.gitignore b/.gitignore
index f6dc2fd3..d4975f31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,7 +18,6 @@ Thumbs.db
config.php
data/files
data/cache
-/vendor
*.bak
!docker/kanboard/config.php
node_modules
diff --git a/.travis.yml b/.travis.yml
index 0f0a2e5b..a2f8e600 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ matrix:
before_script:
- if [[ $TRAVIS_PHP_VERSION != 7.x ]]; then phpenv config-rm xdebug.ini; fi
- phpenv config-add tests/php.ini
- - composer install
+ - composer install --dev
- npm install
script:
diff --git a/Dockerfile b/Dockerfile
index 99e940bb..e1d4d52a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,6 @@ COPY docker/crontab/cronjob.alpine /var/spool/cron/crontabs/nginx
COPY docker/services.d/cron /etc/services.d/cron
COPY docker/php/env.conf /etc/php7/php-fpm.d/env.conf
-RUN cd /var/www/app && composer --prefer-dist --no-dev --optimize-autoloader --quiet install
RUN chown -R nginx:nginx /var/www/app/data /var/www/app/plugins
VOLUME /var/www/app/data
diff --git a/Makefile b/Makefile
index 985aded7..7851f1e5 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ archive:
@ echo "Build archive: version=${version}, destination=${dst}"
@ rm -rf ${BUILD_DIR}/kanboard ${BUILD_DIR}/kanboard-*.zip
@ cd ${BUILD_DIR} && git clone --depth 1 -q https://github.com/kanboard/kanboard.git
- @ cd ${BUILD_DIR}/kanboard && composer --prefer-dist --no-dev --optimize-autoloader --quiet install
+ @ cd ${BUILD_DIR}/kanboard
@ rm -rf ${BUILD_DIR}/kanboard/data/*.sqlite
@ rm -rf ${BUILD_DIR}/kanboard/data/*.log
@ rm -rf ${BUILD_DIR}/kanboard/data/files
diff --git a/doc/en_US/installation.markdown b/doc/en_US/installation.markdown
index 8b8add99..543ca4d0 100644
--- a/doc/en_US/installation.markdown
+++ b/doc/en_US/installation.markdown
@@ -26,11 +26,8 @@ People who are using a remote database (Mysql/Postgresql) and a remote object st
From the git repository (development version)
---------------------------------------------
-You must install [composer](https://getcomposer.org/) to use this method.
-
1. `git clone https://github.com/kanboard/kanboard.git`
-2. `composer install --no-dev`
-3. Go to the third step just above
+2. Go to the third step just above
Note: This method will install the **current development version**, use at your own risk.
diff --git a/doc/en_US/update.markdown b/doc/en_US/update.markdown
index 76cac27a..516b704b 100644
--- a/doc/en_US/update.markdown
+++ b/doc/en_US/update.markdown
@@ -30,8 +30,7 @@ From the repository (development version)
-----------------------------------------
1. `git pull`
-2. `composer install --no-dev`
-3. Login and check if everything is ok
+2. Login and check if everything is ok
Note: This method will install the **current development version**, use at your own risk.
diff --git a/doc/es_ES/installation.markdown b/doc/es_ES/installation.markdown
index f3dfc495..308b0e2b 100644
--- a/doc/es_ES/installation.markdown
+++ b/doc/es_ES/installation.markdown
@@ -27,12 +27,8 @@ Las personas que están utilizando una base de datos remota (MySQL / PostgreSQL)
Desde el repositorio (versión de desarrollo)
-----------------------------------------
-
-Debe instalar [compositora] (https://getcomposer.org/)para utilizar este método.
-
1. ` git clone https: // github.com / kanboard / kanboard.git`
-2. ` composer instalar --no- dev`
-3. Ir a la tercera etapa justo por encima
+2. Ir a la tercera etapa justo por encima
Nota: Este método se instalará la versión de **desarrollo actual** , utilice a su propio riesgo .
diff --git a/doc/es_ES/update.markdown b/doc/es_ES/update.markdown
index 06789d74..ae5d7a5e 100755
--- a/doc/es_ES/update.markdown
+++ b/doc/es_ES/update.markdown
@@ -28,7 +28,6 @@ Desde el repositorio (development version)
-----------------------------------------
1. `git pull`
-2. `composer install --no-dev`
-3. Inicia la sesión y comprobar si todo está bien
+2. Inicia la sesión y comprobar si todo está bien
Nota: Este método se instalará la **versión de desarrollo actual**, utilice a su propio riesgo.
diff --git a/doc/fr_FR/installation.markdown b/doc/fr_FR/installation.markdown
index 9e4cb47a..84626151 100644
--- a/doc/fr_FR/installation.markdown
+++ b/doc/fr_FR/installation.markdown
@@ -26,11 +26,8 @@ Les gens qui utilisent une base de données distante (Mysql/Postgresql) ou un sy
Depuis le dépôt git (version de développement)
----------------------------------------------
-Vous devez installer [composer](https://getcomposer.org/) pour utiliser cette méthode.
-
1. `git clone https://github.com/kanboard/kanboard.git`
-2. `composer install --no-dev`
-3. Allez à l'étape 3) juste au-dessus
+2. Allez à l'étape 3) juste au-dessus
Cette méthode va installer **la version en cours de développement**, utilisez là à vos risques.
diff --git a/doc/fr_FR/update.markdown b/doc/fr_FR/update.markdown
index 68468e50..ed248b58 100644
--- a/doc/fr_FR/update.markdown
+++ b/doc/fr_FR/update.markdown
@@ -30,8 +30,7 @@ Depuis le dépôt git (version de développement)
---------------------------------------------
1. `git pull`
-2. `composer install --no-dev`
-3. Testez que tout fonctionne correctement
+2. Testez que tout fonctionne correctement
Cette méthode va installer **la version en cours de développement**, utilisez là à vos risques.
diff --git a/doc/ru_RU/installation.markdown b/doc/ru_RU/installation.markdown
index ff989b19..5bc4f66c 100644
--- a/doc/ru_RU/installation.markdown
+++ b/doc/ru_RU/installation.markdown
@@ -47,16 +47,8 @@
Инсталяция из репозитория (разрабатываемая версия)[¶](#from-the-repository-development-version "Ссылка на этот заголовок")
--------------------------------------------------------------------------------------------------------------------------
-
-
-Вы можете установить [composer](https://getcomposer.org/) для этого метода инсталяции.
-
-
1. `git clone https://github.com/fguillot/kanboard.git`
-
-2. `composer install --no-dev`
-
-3. Далее, перейдите к третьему шагу [Инсталяция из архива](installation.html#from-the-archive-stable-version)
+2. Далее, перейдите к третьему шагу [Инсталяция из архива](installation.html#from-the-archive-stable-version)
diff --git a/doc/ru_RU/update.markdown b/doc/ru_RU/update.markdown
index 7cfabdb0..84483f7b 100644
--- a/doc/ru_RU/update.markdown
+++ b/doc/ru_RU/update.markdown
@@ -42,10 +42,7 @@
1. `git pull`
-
-2. `composer install --no-dev`
-
-3. Выполните вход и проверьте, что все работает корректно
+2. Выполните вход и проверьте, что все работает корректно
**Внимание**: Выполняя обновление из разрабатываемой версии, вы должны понимать, что это нестабильная версия и берете все риски по работе Канборд на себя.
diff --git a/doc/tr_TR/installation.markdown b/doc/tr_TR/installation.markdown
index 23093e56..c46c379d 100644
--- a/doc/tr_TR/installation.markdown
+++ b/doc/tr_TR/installation.markdown
@@ -26,11 +26,8 @@ Uzak bir veritabanı (Mysql/Postgresql) ve uzak nesne depolama birimi (Aws S3 ve
Git deposundan (geliştirme versiyonu)
---------------------------------------------
-Bu yöntemi kullanmak için [composer](https://getcomposer.org/) yüklemelisiniz.
-
1. `git clone https://github.com/kanboard/kanboard.git`
-2. `composer install --no-dev`
-3. Yukarıdaki üçüncü adıma geçin
+2. Yukarıdaki üçüncü adıma geçin
Not: Bu yöntem, **mevcut geliştirme sürümünü** yükleyecektir, kendi sorumluluğunuzdadır.
diff --git a/doc/tr_TR/update.markdown b/doc/tr_TR/update.markdown
index 842b1b5a..1ca0a654 100644
--- a/doc/tr_TR/update.markdown
+++ b/doc/tr_TR/update.markdown
@@ -30,8 +30,7 @@ Depodan-repository (geliştirme versiyonu)
-----------------------------------------
1. `git pull`
-2. `composer install --no-dev`
-3. Giriş yapın ve her şeyin yolunda olduğunu kontrol edin
+2. Giriş yapın ve her şeyin yolunda olduğunu kontrol edin
Not: Bu yöntem, **mevcut geliştirme sürümünü** yükleyecektir, bu versiyonu kullanmanız kendi sorumluluğunuzdadır.
diff --git a/vendor/aferrandini/phpqrcode/.gitignore b/vendor/aferrandini/phpqrcode/.gitignore
new file mode 100644
index 00000000..485dee64
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/vendor/aferrandini/phpqrcode/LICENSE b/vendor/aferrandini/phpqrcode/LICENSE
new file mode 100755
index 00000000..18833032
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/vendor/aferrandini/phpqrcode/VERSION b/vendor/aferrandini/phpqrcode/VERSION
new file mode 100755
index 00000000..e0d3a2ee
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/VERSION
@@ -0,0 +1,2 @@
+1.1.5
+2012021604
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_1.dat b/vendor/aferrandini/phpqrcode/cache/frame_1.dat
new file mode 100755
index 00000000..be28feac
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_1.dat
@@ -0,0 +1,2 @@
+xڝ
E9u`"PńC牗T!0$
+EɲQmh۾9{kI" 9Ln)Ap־>^zmnŖ;mn
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_1.png b/vendor/aferrandini/phpqrcode/cache/frame_1.png
new file mode 100755
index 00000000..86ce6e98
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_1.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_10.dat b/vendor/aferrandini/phpqrcode/cache/frame_10.dat
new file mode 100755
index 00000000..aff163f6
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_10.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_10.png b/vendor/aferrandini/phpqrcode/cache/frame_10.png
new file mode 100755
index 00000000..dbfcd70b
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_10.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_11.dat b/vendor/aferrandini/phpqrcode/cache/frame_11.dat
new file mode 100755
index 00000000..95af68a4
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_11.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_11.png b/vendor/aferrandini/phpqrcode/cache/frame_11.png
new file mode 100755
index 00000000..c07c761f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_11.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_12.dat b/vendor/aferrandini/phpqrcode/cache/frame_12.dat
new file mode 100755
index 00000000..73228b36
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_12.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_12.png b/vendor/aferrandini/phpqrcode/cache/frame_12.png
new file mode 100755
index 00000000..8ba67822
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_12.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_13.dat b/vendor/aferrandini/phpqrcode/cache/frame_13.dat
new file mode 100755
index 00000000..2256f0e3
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_13.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_13.png b/vendor/aferrandini/phpqrcode/cache/frame_13.png
new file mode 100755
index 00000000..6e49d35a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_13.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_14.dat b/vendor/aferrandini/phpqrcode/cache/frame_14.dat
new file mode 100755
index 00000000..e9ae0932
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_14.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_14.png b/vendor/aferrandini/phpqrcode/cache/frame_14.png
new file mode 100755
index 00000000..efc36c03
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_14.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_15.dat b/vendor/aferrandini/phpqrcode/cache/frame_15.dat
new file mode 100755
index 00000000..18727818
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_15.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_15.png b/vendor/aferrandini/phpqrcode/cache/frame_15.png
new file mode 100755
index 00000000..a9f416c7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_15.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_16.dat b/vendor/aferrandini/phpqrcode/cache/frame_16.dat
new file mode 100755
index 00000000..60af6784
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_16.dat
@@ -0,0 +1 @@
+xA E]sIX;n6`qW6`%A/3!!g̡1N)E|;>6⸏97$c]kkw1[mC͜cR>E,hʼnp#xFyWVWG3+˓S}Ğ#G8b^c^cpc&3YQ"vk9܇} ĿQL/
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_16.png b/vendor/aferrandini/phpqrcode/cache/frame_16.png
new file mode 100755
index 00000000..6ac8fe89
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_16.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_17.dat b/vendor/aferrandini/phpqrcode/cache/frame_17.dat
new file mode 100755
index 00000000..87f0cf59
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_17.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_17.png b/vendor/aferrandini/phpqrcode/cache/frame_17.png
new file mode 100755
index 00000000..5b929ac7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_17.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_18.dat b/vendor/aferrandini/phpqrcode/cache/frame_18.dat
new file mode 100755
index 00000000..bb7138c1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_18.dat
@@ -0,0 +1,2 @@
+xA
+0E]օ,2;s&͚hO1&09OIv@DD&ىKXFv<dq9<%hYs!(ds;~||b(Yůg#`KSĶsidߍLg:әt/gmkM3{4rTQes><әt3;H#љt3Y+oghٽlnF>i^#awm;g~pgNs{6zp'
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_18.png b/vendor/aferrandini/phpqrcode/cache/frame_18.png
new file mode 100755
index 00000000..ee0d6a35
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_18.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_19.dat b/vendor/aferrandini/phpqrcode/cache/frame_19.dat
new file mode 100755
index 00000000..95e26adc
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_19.dat
@@ -0,0 +1,3 @@
+xA
+ E.No7ћiiRN2W%x@ڜ'
+u6.*S;}àTzrt%,};)ZLP$qgLdJ;w.]z#[͝Og" B}};w#1Gb;w_C+w@Dfu2N9R7|pWkk
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_19.png b/vendor/aferrandini/phpqrcode/cache/frame_19.png
new file mode 100755
index 00000000..20fddd84
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_19.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_2.dat b/vendor/aferrandini/phpqrcode/cache/frame_2.dat
new file mode 100755
index 00000000..7e42f31c
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_2.dat
@@ -0,0 +1 @@
+x͒
F{v&&Y+?Z1S'y!a815&۴HٞclF1#6f6O7C֏8gIfB\DԻ(
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_2.png b/vendor/aferrandini/phpqrcode/cache/frame_2.png
new file mode 100755
index 00000000..9c150ebe
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_2.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_20.dat b/vendor/aferrandini/phpqrcode/cache/frame_20.dat
new file mode 100755
index 00000000..d5ecc1d8
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_20.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_20.png b/vendor/aferrandini/phpqrcode/cache/frame_20.png
new file mode 100755
index 00000000..23a061d5
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_20.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_21.dat b/vendor/aferrandini/phpqrcode/cache/frame_21.dat
new file mode 100755
index 00000000..1974dd9d
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_21.dat
@@ -0,0 +1 @@
+xA E]sIX;n6Upв]٘<i-eW)ŕ
H\jvqHL\6ЅrILܹ%@Vv(P4|Xngɝ~]Du1Us S\,2N?DKF-:eJ]p_,a0`X`w,`X]5Y4{2vJs9)u۹,]^_7$_
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_21.png b/vendor/aferrandini/phpqrcode/cache/frame_21.png
new file mode 100755
index 00000000..291598c7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_21.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_22.dat b/vendor/aferrandini/phpqrcode/cache/frame_22.dat
new file mode 100755
index 00000000..0f01802d
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_22.dat
@@ -0,0 +1,3 @@
+xA
+0E]{.]{{{ZBepwe@VERZ3"*2o4y)i#dbdF҅I"4WIu45x.ZS{8k={o.q[:帒qy
+)t#N8dCj-OOG}:/:sz!)^IO-
7p
7$}>ɷ7p
tssrs
Vmҹ}R~7&?7ԦIbh{<Mi-
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_23.png b/vendor/aferrandini/phpqrcode/cache/frame_23.png
new file mode 100755
index 00000000..b8f16ae2
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_23.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_24.dat b/vendor/aferrandini/phpqrcode/cache/frame_24.dat
new file mode 100755
index 00000000..7b92e29c
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_24.dat
@@ -0,0 +1 @@
+xA EMX0;nVP4HSSxU3/OLiJ4VJC%6VR&DBHjDJ??BlcDZ'UXUޏ0ywįj똳3ścj{:GqGNv;笓J<]#8#8H'GqGtr:9#8#8ؓhNt_>teS^\gQe?vuo;>*wlm
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_24.png b/vendor/aferrandini/phpqrcode/cache/frame_24.png
new file mode 100755
index 00000000..397c64f8
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_24.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_25.dat b/vendor/aferrandini/phpqrcode/cache/frame_25.dat
new file mode 100755
index 00000000..ba125182
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_25.dat
@@ -0,0 +1,3 @@
+xA
+ s낋]rxY51mMBG
+*Sx|Ua5ƵZ-,1HPRjX5iG>WR/+uT廯ӯ嗴u[Sa[kv5+5nJ%+VXbŊ߬u'SRtzZ++VXbŊٟٟٟ+VXb}Ŋ+VXVI+kq[toVZvoNVw}{r<ýR"R]
Wr}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_25.png b/vendor/aferrandini/phpqrcode/cache/frame_25.png
new file mode 100755
index 00000000..25bc4454
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_25.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_26.dat b/vendor/aferrandini/phpqrcode/cache/frame_26.dat
new file mode 100755
index 00000000..d34a73f1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_26.dat
@@ -0,0 +1,2 @@
+xA
+ Eօ,t77ћU E)i7*~cXEBFC6:&L,Mv.KgոYM>>mۚ?vmg?ұηdCUIkE\Msfafa>[sӈ9쬩ެ8b]LgEo w1
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_26.png b/vendor/aferrandini/phpqrcode/cache/frame_26.png
new file mode 100755
index 00000000..f4a6b393
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_26.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_27.dat b/vendor/aferrandini/phpqrcode/cache/frame_27.dat
new file mode 100755
index 00000000..b4d9ffd4
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_27.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_27.png b/vendor/aferrandini/phpqrcode/cache/frame_27.png
new file mode 100755
index 00000000..8419ec23
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_27.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_28.dat b/vendor/aferrandini/phpqrcode/cache/frame_28.dat
new file mode 100755
index 00000000..8cbaa196
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_28.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_28.png b/vendor/aferrandini/phpqrcode/cache/frame_28.png
new file mode 100755
index 00000000..7609d8e1
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_28.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_29.dat b/vendor/aferrandini/phpqrcode/cache/frame_29.dat
new file mode 100755
index 00000000..5e4a7110
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_29.dat
@@ -0,0 +1,2 @@
+xA a @n7+*4!?J 抮]STf)sI"Ȕb0|"Luٸ,E1\6*uQ?>aυR-rn.ꯋ\T:*)|),,x_}:^RUoɢu~މX`XЏЏЏЏ_`X`XЏЏЏ_`X`XЏЏЏЏwbX`PU)D"c{z3<}^?bm잃a.]
+{Q6uT,9
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_29.png b/vendor/aferrandini/phpqrcode/cache/frame_29.png
new file mode 100755
index 00000000..ffe072c8
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_29.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_3.dat b/vendor/aferrandini/phpqrcode/cache/frame_3.dat
new file mode 100755
index 00000000..188d531c
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_3.dat
@@ -0,0 +1 @@
+x
E{v&&Y+bk'ya:TXl$W+ӏv9}gR@H0YPBEm?s"bt2cn:ﺭ;YzQ7
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_3.png b/vendor/aferrandini/phpqrcode/cache/frame_3.png
new file mode 100755
index 00000000..945ee7cb
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_3.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_30.dat b/vendor/aferrandini/phpqrcode/cache/frame_30.dat
new file mode 100755
index 00000000..44cf3d31
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_30.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_30.png b/vendor/aferrandini/phpqrcode/cache/frame_30.png
new file mode 100755
index 00000000..75dbddd2
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_30.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_31.dat b/vendor/aferrandini/phpqrcode/cache/frame_31.dat
new file mode 100755
index 00000000..ce429d0a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_31.dat
@@ -0,0 +1 @@
+xA a
&r4yķ!mV3Iv!Ҝ2i\NSS4EF2+65e/Ws]!?p=S~Đ?+x6r6y}ǴeR1-WllҌXz/>V櫷:ñA8-+mTbllltM&]ll&]Ill&]y
6`
6`iuyXWi\tz>.zk
t77wJϔ4w҈85
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_31.png b/vendor/aferrandini/phpqrcode/cache/frame_31.png
new file mode 100755
index 00000000..b14d1fa2
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_31.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_32.dat b/vendor/aferrandini/phpqrcode/cache/frame_32.dat
new file mode 100755
index 00000000..aaa0808e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_32.dat
@@ -0,0 +1,2 @@
+x
+ ־. Dl,Mz6Ç gcJD;'.AIqމI,IrYFk%DOy|EDD(L_Y>*ߚ?aOkL_<[c>c˘uLI%#0#0#otѢ}4fv_)Eph5R881#0#0itZ#0#0#0itZ#0#0#0itZl0#09q"HܜHQ"L5}-Yk`>z鸳4&p!!`:5
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_32.png b/vendor/aferrandini/phpqrcode/cache/frame_32.png
new file mode 100755
index 00000000..58d42db3
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_32.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_33.dat b/vendor/aferrandini/phpqrcode/cache/frame_33.dat
new file mode 100755
index 00000000..a2613755
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_33.dat
@@ -0,0 +1,14 @@
+xA a@n7+*L++柮bb*LCckHrjJ5Yi~0_TT}e>5b_w͟?\Rai+7W\wLUNL
++
++jOkc\˩|%o}8
++
++
++3g
++
++
++3g@
++
++
++:RXB9I=ko/Swؘٯ`gr_ٙYVSYzIefnmQoz
>
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_33.png b/vendor/aferrandini/phpqrcode/cache/frame_33.png
new file mode 100755
index 00000000..924c728e
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_33.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_34.dat b/vendor/aferrandini/phpqrcode/cache/frame_34.dat
new file mode 100755
index 00000000..7ceb0259
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_34.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_34.png b/vendor/aferrandini/phpqrcode/cache/frame_34.png
new file mode 100755
index 00000000..a477042d
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_34.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_35.dat b/vendor/aferrandini/phpqrcode/cache/frame_35.dat
new file mode 100755
index 00000000..56bc3e28
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_35.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_35.png b/vendor/aferrandini/phpqrcode/cache/frame_35.png
new file mode 100755
index 00000000..d29806c6
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_35.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_36.dat b/vendor/aferrandini/phpqrcode/cache/frame_36.dat
new file mode 100755
index 00000000..282c60d2
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_36.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_36.png b/vendor/aferrandini/phpqrcode/cache/frame_36.png
new file mode 100755
index 00000000..96ecb421
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_36.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_37.dat b/vendor/aferrandini/phpqrcode/cache/frame_37.dat
new file mode 100755
index 00000000..015c0f24
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_37.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_37.png b/vendor/aferrandini/phpqrcode/cache/frame_37.png
new file mode 100755
index 00000000..fcc51627
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_37.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_38.dat b/vendor/aferrandini/phpqrcode/cache/frame_38.dat
new file mode 100755
index 00000000..71cf53eb
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_38.dat
@@ -0,0 +1 @@
+xA0ЎuA2;Нk(gytp9$D\e^'t-aIFMSkIŤ:7|LkN8N7i}i,[WgӴ?31iN}}=OM:4)SL2eʔ)SL#$
JJM:}]L٧SQL2eʔ)SL2աPt(:)SL2eʔ)S:ECq2eʔ)SL2eʔECѡ8O2eʔ)SL2eTCѡPL2eʔ)SL2ݓsJCIKԂi93n_+Ri4\g;%
}an
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_38.png b/vendor/aferrandini/phpqrcode/cache/frame_38.png
new file mode 100755
index 00000000..89238f3c
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_38.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_39.dat b/vendor/aferrandini/phpqrcode/cache/frame_39.dat
new file mode 100755
index 00000000..53511f73
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_39.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_39.png b/vendor/aferrandini/phpqrcode/cache/frame_39.png
new file mode 100755
index 00000000..1dc9cd1b
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_39.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_4.dat b/vendor/aferrandini/phpqrcode/cache/frame_4.dat
new file mode 100755
index 00000000..67b30e82
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_4.dat
@@ -0,0 +1 @@
+x
E=u
pجQCOM'ˏ$ @3eF\FNXRyؾC{a8RŃa2@qkH1(`cj~0ܨعnXGĀ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_4.png b/vendor/aferrandini/phpqrcode/cache/frame_4.png
new file mode 100755
index 00000000..b72f9e70
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_4.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_40.dat b/vendor/aferrandini/phpqrcode/cache/frame_40.dat
new file mode 100755
index 00000000..90d36dd1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_40.dat
@@ -0,0 +1,2 @@
+xA@Ь@o7`Qfe䕫PA><]߳bZn^AQ}[9^]ynajM܇K̘1cƌ3f̘1{W5}{7lMޚxI<Kαyl3f̘1cƌ3f̘1ۻٻ={αyl3f̘1cƌ3f̘1ۻٻ={αyl3f̘1cƌ3f̘1ۻٻ={αyl3f̘1cƌ3f̘1ۻٻ={αyl3f̘1cƌ3f̘SʑӒ7HKg\u_r'4[-]qL8ƝY1q!/(%
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_40.png b/vendor/aferrandini/phpqrcode/cache/frame_40.png
new file mode 100755
index 00000000..8034d862
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/frame_40.png differ
diff --git a/vendor/aferrandini/phpqrcode/cache/frame_5.dat b/vendor/aferrandini/phpqrcode/cache/frame_5.dat
new file mode 100755
index 00000000..d5dafe18
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/frame_5.dat
@@ -0,0 +1 @@
+x1 Eu7ЛZ|NDB0@R$l,->VKZ[I9+Es=ϤL1̄[FZU4?i<;7;P#W-[ݯ6ddddddc",;"sk摑Q&erw######L.摑Иy1^˲\3 v
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_117_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_117_0.dat
new file mode 100755
index 00000000..781c7f87
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_117_0.dat
@@ -0,0 +1,2 @@
+xA
+0}OrR,#3,o5Cq:;;wvNJZG=m}
ѱ2iRkj_YYYYYYYYe_/WVVVVVVkd-Ϻ,#OZc]|{ž$
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_121_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_121_0.dat
new file mode 100755
index 00000000..68810c34
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_121_0.dat
@@ -0,0 +1 @@
+x1 О/w
YMS8>2SFOEcW\ۼ{cpKGBКmxhfffffff/s22W|*d1*5̬RWas\xm~8߮r0wjsdm&y
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_125_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_125_0.dat
new file mode 100755
index 00000000..2c73ef1a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_125_0.dat
@@ -0,0 +1,2 @@
+xA
+ н_TH`3AOL4k(ewGW. #2} \Ygggggggggg_d>j^s;;;;;;;;;;'q;;;;;;;;;'˰qu_PYw{e=dG/
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_129_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_129_0.dat
new file mode 100755
index 00000000..812ee8a6
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_129_0.dat
@@ -0,0 +1,2 @@
+x1
+ /*DE'hgt-}_pV \"b=s[J=8Dho۞'0X ۴e0`j"0`Wf`^P0`2Ȁ d07(Y/XLGby"pT
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_137_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_137_0.dat
new file mode 100755
index 00000000..f6d993b0
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_137_0.dat
@@ -0,0 +1 @@
+x1 О/+FZ?JL7Ժ*Ba%L~˻ʓCJYIWJ .K]R0a $INTwlLaL0a &Ld@PO0a &L0e@P?a &L0aDe@ &L0aMIlL&)dlgacR<$v,ɺ?U2]
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_141_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_141_0.dat
new file mode 100755
index 00000000..8c685c8e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_141_0.dat
@@ -0,0 +1,2 @@
+x=
+0нi9'EDx͘%I9+E{$m^&uS"D6ڟ]98UMbҾY[2拉Ĉ#F1bĈ%iRN潝ѳ#;#F1bĈN1i#F1bĈ#FtZ}Nk1bĈ#F1bktZ;#F1bFV-u"IoD-*7uj>bMV+
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_149_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_149_0.dat
new file mode 100755
index 00000000..d2583502
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_149_0.dat
@@ -0,0 +1,3 @@
+xA
+ н_MEQXP.|94e{JLv#^n[?;
+ZIV-*w˒1*+VXbŊXgwqX}JRYbŊ+VXbeΠwfeΠ^bŊ+VXbʜAʜAbŊ+VXbŊ9ٜAbŊ+VXbŊl0*0Tj`?Ϊ;X=zZr*
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_153_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_153_0.dat
new file mode 100755
index 00000000..fc79e9ed
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_153_0.dat
@@ -0,0 +1 @@
+x1 Н/礑h&F`Ҽ@I;PZ^X͌mf.=5[if-R+!wr˜g\j̘1cƌ3f̘1cfo.2?1z
`ƌ3f̘1cƌzƌ3f̘1cƌ3fztf3f̘1cƌ3f̘kk030cƌ3f̘1c9;Ď`vf͚̆ZϘW9
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_157_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_157_0.dat
new file mode 100755
index 00000000..ad749f30
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_157_0.dat
@@ -0,0 +1,2 @@
+xA
+ н_QRY
k*q͵=j7~nN.p%ڵsi.رcǎ;vر{.-W2={mgy+رcǎ;vɳ2;yּcǎ;vرcNɳ;vرcǎ;v2I9+DyI4ˠ5:Wvdqߜܴ<d2x%[U%2]&K,Ydɒ%ˡ,Sr2yd=,k_{Xdɒ%K,Yd)0m,Ydɒ%K,Yd)0m,Ydɒ%K,Yme,e%K,Ydɒ%K,eq
Ò%K,Ydɒe:I9EQ=LsI{ZtR}Sn:|R[?_*SL2eʔ)SL&ϦIO2O2eʔ)SL2e*C1PPSL2eʔ)SLP22)SL2eʔ)SLe(}2)SL2eʔ)SLe(}2)SL2eʔ)Sic7;"ޙFͦސٙvL^2}oO'r
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_173_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_173_0.dat
new file mode 100755
index 00000000..5ef85e7a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_173_0.dat
@@ -0,0 +1 @@
+x10ޯT [4v2ƽok݇;Ӳ]f֞dljlG0n+mG˖-[lٲe"Y}oV[lٲe˖-[lٲeհՃ[2lٲe˖-[lٲeհՃ[2lٲe˖-[lٲeհՃ[lٲe˖-[lٲeValٲe˖-[lٲef[BmаE;N-ۜT/rl?*
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_177_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_177_0.dat
new file mode 100755
index 00000000..78a26a77
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_177_0.dat
@@ -0,0 +1,2 @@
+x1
+0>I9+?߁iևd̹xֈxN/է|{ظ8d0h=cFf̘1cƌ3f̘qq=w6;l4cƕ<nj3f̘1cƌ3fXһ1ֻcƌ3f̘1cƌ3fXbwnj3f̘1cƌ3f̘M'X&1cƌ3f̘1cƌ3ֻnn1cƌ3f̘1cƌÍ3U<
\7+(<OƌΊnj4@
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_21_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_21_0.dat
new file mode 100755
index 00000000..368c9941
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_21_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_25_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_25_0.dat
new file mode 100755
index 00000000..e4a5b6d8
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_25_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_29_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_29_0.dat
new file mode 100755
index 00000000..74a216b4
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_29_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_33_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_33_0.dat
new file mode 100755
index 00000000..2ec712a7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_33_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_37_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_37_0.dat
new file mode 100755
index 00000000..1588cfce
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_37_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_41_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_41_0.dat
new file mode 100755
index 00000000..e369027e
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_41_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_45_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_45_0.dat
new file mode 100755
index 00000000..452f126c
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_45_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_49_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_49_0.dat
new file mode 100755
index 00000000..fdd2aac1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_49_0.dat
@@ -0,0 +1,2 @@
+xK E9o#?H/6g$-,X]
+xݘ;X9<Ѻq2AfH7/5We{#fި?4=N >
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_53_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_53_0.dat
new file mode 100755
index 00000000..572d279e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_53_0.dat
@@ -0,0 +1,2 @@
+xK
+@!йoQϺ:(m&s-6Z{m4YX.F٭XZij=:έb忑VH8#[Y^Xe
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_57_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_57_0.dat
new file mode 100755
index 00000000..ea81e6dc
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_57_0.dat
@@ -0,0 +1,4 @@
+xA
+ {^s=YL՚
(
+ouj)
+Z7yv,ԴwVQ iGiҤDfەwo4ѤoLLȼ}4
h
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_61_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_61_0.dat
new file mode 100755
index 00000000..93d2444d
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_61_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_65_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_65_0.dat
new file mode 100755
index 00000000..df29d7bf
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_65_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_69_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_69_0.dat
new file mode 100755
index 00000000..8a2cfbd7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_69_0.dat
@@ -0,0 +1 @@
+xK =_+mBd|Q"s+1"),=Ea T"ŐnE-3,KYw=ZZT.,K1#֞!Ŋ+V嬪.2XbŊ+VX.kBzwձ̀gkYZ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_89_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_89_0.dat
new file mode 100755
index 00000000..aaa4c526
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_89_0.dat
@@ -0,0 +1 @@
+x1 ὧi9'Hl?L^"&M?bq?˸,9!z]VScƌ3_c!`n3f̘1č 3f̘1/f>.Uc˻;
2;Y+7
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_93_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_93_0.dat
new file mode 100755
index 00000000..e218fa0e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_93_0.dat
@@ -0,0 +1,3 @@
+xK
+ EyV,OmޠrPH0{2bc{tQ]
+{Q{{弬֒ǎ;v_ڳ}L}l߱cǎ;v̑̑̑رcǎ.Legw3qeѾ@i
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_0/mask_97_0.dat b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_97_0.dat
new file mode 100755
index 00000000..74ac719d
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_0/mask_97_0.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_101_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_101_1.dat
new file mode 100755
index 00000000..ec939b52
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_101_1.dat
@@ -0,0 +1,2 @@
+x1
+ н\QEd 1N<#Ֆ-7u.lԦeiXXXXXRZVVeIo1,,,,,v%?gaaaaYK&K=/+ۍ˱ގ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_105_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_105_1.dat
new file mode 100755
index 00000000..e1f5c99b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_105_1.dat
@@ -0,0 +1 @@
+x1 Ӕ_Υb
KB?"*#WʘtgӎJqUM9TLLvǤLLLLLLzgG01111yiߘ4m=՛n+2
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_109_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_109_1.dat
new file mode 100755
index 00000000..7e0d6d16
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_109_1.dat
@@ -0,0 +1 @@
+xֱ
>ӘK}:!iY'*3]fsmb[JƶŖK9}cccccc'u.6Ʀs6666R[^g{/lٷ7͂
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_113_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_113_1.dat
new file mode 100755
index 00000000..1dd666d9
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_113_1.dat
@@ -0,0 +1 @@
+x1
-8fL(pBlDM9";-;?1p{\%-3:@ad4*Nadddddd########c]751xYu
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_117_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_117_1.dat
new file mode 100755
index 00000000..8921f643
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_117_1.dat
@@ -0,0 +1,2 @@
+xֻ
>ӘK$^8YQSV'z8jzʇ^]סekXYYYYYYYjݵ#
++yeeeeeeee#WVVVVVVVV;"+yeeeeeeel'e;b&^9{/J$p
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_121_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_121_1.dat
new file mode 100755
index 00000000..64bd8ba0
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_121_1.dat
@@ -0,0 +1,2 @@
+x1
+ н\CPbїE$DdƩYtڅλ0$ήꝝga7yٯ痽Y??{{D
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_129_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_129_1.dat
new file mode 100755
index 00000000..62cd1c9a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_129_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_133_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_133_1.dat
new file mode 100755
index 00000000..18d68dce
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_133_1.dat
@@ -0,0 +1 @@
+x1 Ӕ_΅hh|"zۉ-*dNHQĢRÂ,X`c9Y(na_`,X,X,X`#:8,X`Bd¾`,X|ϢY\X;7-;`
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_137_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_137_1.dat
new file mode 100755
index 00000000..284d7bea
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_137_1.dat
@@ -0,0 +1,3 @@
+x1
+0ӤKh]D,-t #ڌQ[T Ks7_?9|B&X^L0a&3M&L0a &2D4c0a &LȀЌe &L0abwȀf,&L0a7&y2anoL<01O
+
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_141_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_141_1.dat
new file mode 100755
index 00000000..83220ddb
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_141_1.dat
@@ -0,0 +1,2 @@
+x1
+ >946)3$`suʮ>Wd
)g'M{3\d6ubذaÆ
6lؼn]Nذ9FްaÆ
6lذa3a#oذaÆ
6lذذ5e16lذaÆ
]Sbk6lذaÆ
mͤ;CcfIdsG
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_145_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_145_1.dat
new file mode 100755
index 00000000..6a9950f7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_145_1.dat
@@ -0,0 +1 @@
+x!0@k4a)q2i.YCUO{35UZFn]fN>bdwtzJF}F1bĈ#F(F6r1bĈ#F1E1ilF1bĈ#FtF#F1bĈ#FtZ}##F1bĈleHGܣ@ٝ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_149_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_149_1.dat
new file mode 100755
index 00000000..02a3cdc6
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_149_1.dat
@@ -0,0 +1 @@
+x1 Ӕ_΅qH_Xci#Gd̘Ք՛gLU^ݮVR>dKVXbŊ+VXeoXJ_bŊ+VXb;ݙ+}Ŋ+VXbŊ+VAVngŊ+VXbŊ}++VXbŊVj>hewf*`uTq
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_153_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_153_1.dat
new file mode 100755
index 00000000..2abfca20
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_153_1.dat
@@ -0,0 +1,2 @@
+x1
+0\9btEc'HH9efߞmffM#.̘1cƌ3f̘1cf73f̘g̘1cƌ3f̘1co2c]?3f̘1cƌ3f5Mf3f̘1cƌ3f̘17utf3f̘1cƌ3f̘=lj3>V
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_157_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_157_1.dat
new file mode 100755
index 00000000..17344b89
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_157_1.dat
@@ -0,0 +1,2 @@
+x1
+ >94Sd/51V)SkJv7eGcǎ;vرc]Zٱc'رcǎ;vر+رg;vرcǎ;}V`N+رcǎ;v:;v;vرcǎ;;}Vޱcǎ;vص'vz#;]klwoA`
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_161_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_161_1.dat
new file mode 100755
index 00000000..669ade1b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_161_1.dat
@@ -0,0 +1 @@
+x10_΅Xšyi~Qbkvp7'M
u=]([2dȐ+\'22dȐ!C2s0/3d()2dȐ!C241dh 2dȐ!C2dhcȐSL2eʔ)SL2M
SLSL2eʔ)SL2M}LSSL2eʔ)SLeSy)SŔ)SL2eʔ)S;ٔ)S;)SL2eʔ)Sv()Sv()SL2eʔ)SLdT6}a*3mljmzC'
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_173_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_173_1.dat
new file mode 100755
index 00000000..436918c0
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_173_1.dat
@@ -0,0 +1 @@
+x1 Ӕ_Υ''@y]X1?"g:1犝fn˶˻mm.?lٲe˖-F>glٲ2lٲe˖-[lٲeO`˖e˖-[lٲe˖-[l lٲlٲe˖-[lٲeVO`˖e˖-[lٲe˖-[z0}[z0y˖-[lٲe˖-[Ee[hOVWö=t*|
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_177_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_177_1.dat
new file mode 100755
index 00000000..12e2e522
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_177_1.dat
@@ -0,0 +1 @@
+x1 Ep0X,a#r}6}nj~\8ƌ3f̘1cƌ7{3f,y3f̘1cƌ3fX_`X&3f̘1cƌ3f̘M_1cy̘1cƌ3f̘1cƌ+3f,y3f̘1cƌ3fX_bX&3f̘1cƌ3fx2dX'x[cy|
3
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_21_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_21_1.dat
new file mode 100755
index 00000000..f87e0a11
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_21_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_25_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_25_1.dat
new file mode 100755
index 00000000..3a225e30
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_25_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_29_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_29_1.dat
new file mode 100755
index 00000000..0a1cb3b5
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_29_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_33_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_33_1.dat
new file mode 100755
index 00000000..318949df
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_33_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_37_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_37_1.dat
new file mode 100755
index 00000000..5bd9e3aa
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_37_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_41_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_41_1.dat
new file mode 100755
index 00000000..52e9e58f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_41_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_45_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_45_1.dat
new file mode 100755
index 00000000..b35c567d
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_45_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_49_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_49_1.dat
new file mode 100755
index 00000000..d20d7171
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_49_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_53_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_53_1.dat
new file mode 100755
index 00000000..a676d7df
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_53_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_57_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_57_1.dat
new file mode 100755
index 00000000..896ed435
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_57_1.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_61_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_61_1.dat
new file mode 100755
index 00000000..4165a4bd
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_61_1.dat
@@ -0,0 +1 @@
+x30CbpPi`@&H^nadQG{n_.4Iy킎`)-5*(of[sm}6YM ;;;;;G{zطz1vw}=wuL%?"=~ei
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_1/mask_97_1.dat b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_97_1.dat
new file mode 100755
index 00000000..24fa60fc
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_1/mask_97_1.dat
@@ -0,0 +1,2 @@
+x1
+0н1\tncKD"H$DH$D"Q&WerH$D"*x[(?/'nd
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_117_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_117_2.dat
new file mode 100755
index 00000000..b4dcce46
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_117_2.dat
@@ -0,0 +1,2 @@
+x1
+ >94!m dOs\0X,la5#E>Z[ַRT*JR?Q-*T*JR?UW*JRTݟ+JRԤ~m5;S&+
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_121_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_121_2.dat
new file mode 100755
index 00000000..a2a0097b
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_121_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_125_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_125_2.dat
new file mode 100755
index 00000000..0ea40fda
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_125_2.dat
@@ -0,0 +1 @@
+x! PӔ_@
U(kp@^Mڮ5-:VF_\t:NtyNqt:NtG;Nt:.8:NtzA}yNq;+n&
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_129_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_129_2.dat
new file mode 100755
index 00000000..bf048394
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_129_2.dat
@@ -0,0 +1,2 @@
+x1
+0н_KVڡ'.!w]A0X~ !࣠fK# xFy4vey@^+~ L#veI
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_133_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_133_2.dat
new file mode 100755
index 00000000..9e78b6de
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_133_2.dat
@@ -0,0 +1,10 @@
+x1
+ н&`LQ-g=Aqbʪl
fƄȚ44&
)OȚYF4444444444c4~9S:3ЌטpǮ>
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_145_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_145_2.dat
new file mode 100755
index 00000000..9ff2bbf3
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_145_2.dat
@@ -0,0 +1,4 @@
+x1
+ нr]
+,tQ^&C~
+щj~mɾ.FgMDDDDDDDDDDDSTDHdZL+ɴDDDDDDDDDDD2-'"""""""":BתEYDd
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_149_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_149_2.dat
new file mode 100755
index 00000000..d52e0484
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_149_2.dat
@@ -0,0 +1 @@
+x;@/gcaGBXB'-ouէUQdRVOmT*ǫ;;j廝Ee2PQQQQQQQQQQQTTTTTTTTTTTTr33R&Tskz_e2P=d
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_153_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_153_2.dat
new file mode 100755
index 00000000..3b060410
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_153_2.dat
@@ -0,0 +1,2 @@
+x1
+0Ӥ8ZP!BZu賶"bu*)]MFFFFFFFFFFFF%= #ddddddddddddr
ot2yFFFFFFFFFFFF& #k5L
2222222222(Y7"d@H
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_157_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_157_2.dat
new file mode 100755
index 00000000..2baf535e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_157_2.dat
@@ -0,0 +1,3 @@
+x1
+0>s6MqUH1X&U̘f/u-'.[KGGGGGGGGGGH|NG(ttttttttttNF;::::::::::}Nz$
+>nA#^AG(t =3{
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_161_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_161_2.dat
new file mode 100755
index 00000000..d2df7594
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_161_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_165_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_165_2.dat
new file mode 100755
index 00000000..2e6cd7c6
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_165_2.dat
@@ -0,0 +1,2 @@
+x1
+0Ӥ?BVUG%*+_fs MIIIIIIIII2d;l4()))))))))))eqJنIDIIIIIIIIIII)۠mPRRRRRRRRRRR6l
JJJJJJJJJJJJن}RaQRRRRRRRRRRNeK?R퐔͔&W3U
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_169_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_169_2.dat
new file mode 100755
index 00000000..4052062b
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_169_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_173_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_173_2.dat
new file mode 100755
index 00000000..0a30ba53
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_173_2.dat
@@ -0,0 +1 @@
+x+@Pift:>y &dU߬S[]5Z;a5V۞A[Z˴VՃI0ZZZZZZZZZZZZZZ=-Lhi`VFK?ݧhioJ0}o
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_177_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_177_2.dat
new file mode 100755
index 00000000..d2c52f99
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_177_2.dat
@@ -0,0 +1,2 @@
+x1
+ E>Y4V$~,C&U;Ook5bϙGx9%&&&&&&&&&&&n$OL|v#&&&&&&&&&&&&&bbݍXw#&l7bbbbbbbbbbbbbbM"l7bbbbbbbbbbbbbbMa!&݈3)U*F>
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_45_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_45_2.dat
new file mode 100755
index 00000000..ad44ff18
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_45_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_49_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_49_2.dat
new file mode 100755
index 00000000..6e8edff2
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_49_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_53_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_53_2.dat
new file mode 100755
index 00000000..682cae2a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_53_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_57_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_57_2.dat
new file mode 100755
index 00000000..66a5c056
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_57_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_61_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_61_2.dat
new file mode 100755
index 00000000..77d3815e
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_61_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_65_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_65_2.dat
new file mode 100755
index 00000000..caf184ad
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_65_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_69_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_69_2.dat
new file mode 100755
index 00000000..6a3801bf
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_69_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_73_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_73_2.dat
new file mode 100755
index 00000000..74945b71
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_73_2.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_77_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_77_2.dat
new file mode 100755
index 00000000..903cba4a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_77_2.dat
@@ -0,0 +1 @@
+x1 н_CM>Gt ѫe+FWZEm&gއFѶhF+t/FYvFj[*7a
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_81_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_81_2.dat
new file mode 100755
index 00000000..17a9ac2a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_81_2.dat
@@ -0,0 +1,2 @@
+x1
+0н_KҩVi!O\"A]:xbW1uȦ&_T 6H$U^D~bׯb=gX
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_85_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_85_2.dat
new file mode 100755
index 00000000..72c74ff9
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_85_2.dat
@@ -0,0 +1,2 @@
+x1
+0=1\B7O$A0$8Wwjguu槊RT*uS֧JRTJRRޢN浘V
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_2/mask_89_2.dat b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_89_2.dat
new file mode 100755
index 00000000..06c9a4fe
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_2/mask_89_2.dat
@@ -0,0 +1 @@
+xٱ 0>/&E*cQqŃzf$rM)_%s_d3KO1^aL,$H"$KzRPt[I&X9$H"$I$ysI$DI$ɓI$I$Dɍ%es!=LAZ5'̓IVrn/2oƅ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_113_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_113_3.dat
new file mode 100755
index 00000000..023b2730
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_113_3.dat
@@ -0,0 +1,2 @@
+xA
+0D}NrnDFj2KCt?WݲZi.qoP%Smj7ަ:*N:@:***fW9d2*j*}S@`*j৪6Jlѿ}}էTUa24hnt
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_117_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_117_3.dat
new file mode 100755
index 00000000..79cc04d1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_117_3.dat
@@ -0,0 +1,4 @@
+x1
+0]Q.xIB$?~!z#E)RHZ@bl-)ݿ<ߧ*OUR"5&5*ieJ]+
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_145_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_145_3.dat
new file mode 100755
index 00000000..338b7e7a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_145_3.dat
@@ -0,0 +1,3 @@
+x
+@|:^Jy̡yMj-'
+9VS֦K9e)PyUwe-m jԨQF5jԨRi٫F4_wk}0+jRBRF5jԨQeOMBJHjԨQF5jwP״˪IH I5jԨQFͳc w5jԨQF:zS*2UZ_C*e_OZ%dIȯb
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_149_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_149_3.dat
new file mode 100755
index 00000000..30bc5fab
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_149_3.dat
@@ -0,0 +1 @@
+xA0}Oܠ⦐H頯'Z2{oV|Ι%>yR{!8ÂI+JpI|#f5κ[PA $H Q})&X{ט+Wb`I)5%d
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_153_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_153_3.dat
new file mode 100755
index 00000000..89cdec03
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_153_3.dat
@@ -0,0 +1,2 @@
+xA
+0}Ns˹)7mJ,}8X=cW^GeN}o%uJV/{%O>}ӧO}K~O>}ӧO>Q=/ї>}ӧO>}u{ח>}ӧO>}u{蟪/%?}ӧO>}ׯ.N4VMmRt(1|
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_177_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_177_3.dat
new file mode 100755
index 00000000..9586979a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_177_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_21_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_21_3.dat
new file mode 100755
index 00000000..bcb4eec4
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_21_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_25_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_25_3.dat
new file mode 100755
index 00000000..0ffc375f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_25_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_29_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_29_3.dat
new file mode 100755
index 00000000..6150ac12
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_29_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_33_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_33_3.dat
new file mode 100755
index 00000000..6053b5e3
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_33_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_37_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_37_3.dat
new file mode 100755
index 00000000..5dea5b9c
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_37_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_41_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_41_3.dat
new file mode 100755
index 00000000..ca9ddc2a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_41_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_45_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_45_3.dat
new file mode 100755
index 00000000..3daad97f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_45_3.dat
@@ -0,0 +1,2 @@
+xK
+ DsFJ(&)0dЇFg![8=&iaD)d8&Aլa1'II׳79 ex߾ I&֝CuJy
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_49_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_49_3.dat
new file mode 100755
index 00000000..7f6508dd
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_49_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_53_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_53_3.dat
new file mode 100755
index 00000000..8800beab
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_53_3.dat
@@ -0,0 +1,2 @@
+xK
+0Ds !
-(.Bp&|"-t&`qQ-"9_+)Be/H8D%a~}spKFN=,;;a^t4\FSN
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_57_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_57_3.dat
new file mode 100755
index 00000000..4e1e5da3
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_57_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_61_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_61_3.dat
new file mode 100755
index 00000000..bf1a3cc7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_61_3.dat
@@ -0,0 +1,2 @@
+xA
+0fz4-%*dp!yZܫu(~=&ۓ)R2"/"<9FΊ=rb"/rw"2B#3-0-KW
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_65_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_65_3.dat
new file mode 100755
index 00000000..85892089
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_65_3.dat
@@ -0,0 +1,2 @@
+xQ
+ D4\?R,!O-Nv1:cZu"UMÕF ~jK-la[^q^Q\=o-laZpUB@IKJzɢ|1Í
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_69_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_69_3.dat
new file mode 100755
index 00000000..55318a87
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_69_3.dat
@@ -0,0 +1,2 @@
+x
+0{&2'd l=,Fy;$쇤WE-R:%T,O2g"",Ȣ/DyĈɧ{O䮳",:NvEWN#(&,,]x
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_73_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_73_3.dat
new file mode 100755
index 00000000..15be77f6
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_73_3.dat
@@ -0,0 +1,2 @@
+xQ
+0C{g;JJ?dԬK=RasJhTJ6exka\$nIE,-/XB*х=wee4t̒tLщtt߫b gFf qoddn-?
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_77_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_77_3.dat
new file mode 100755
index 00000000..ec782804
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_77_3.dat
@@ -0,0 +1,2 @@
+xA
+0&BiRaK"t`I@|fXyilE:Sza18GifK*?:YC1쌞졘(ቷJ*jl*TRIKR^ؙks)c)c)JZa
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_81_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_81_3.dat
new file mode 100755
index 00000000..47bc0f79
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_81_3.dat
@@ -0,0 +1,2 @@
+x1
+ F=\,JGAġhj>#3X:kԹ\FM
Jhu3>TZ{PSgP'kVjժU_ۯUV=P
oO:Wҝj[Wxm
5
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_85_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_85_3.dat
new file mode 100755
index 00000000..02c4f8cd
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_85_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_89_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_89_3.dat
new file mode 100755
index 00000000..2b4cb59f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_89_3.dat
@@ -0,0 +1,2 @@
+x1 ὧ)*.@U
|eŵ6ۢw5*)
oiK4nk>1}d>@
4XYCo ۡ1<AhFt
+
4@51Wr>7G}}x7|NgN
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_93_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_93_3.dat
new file mode 100755
index 00000000..b4cc8a97
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_93_3.dat
@@ -0,0 +1,2 @@
+xA
+0D}NrnJɪQ~B06na<<ׇe6MRCPL̓i9M2 LkŮdDv*"aXjBdAddZTdAdqY0exqeN&WVQvc
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_3/mask_97_3.dat b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_97_3.dat
new file mode 100755
index 00000000..7adc9eba
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_3/mask_97_3.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_101_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_101_4.dat
new file mode 100755
index 00000000..1c97dc04
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_101_4.dat
@@ -0,0 +1,2 @@
+xA Fs^1bИ]4m+8+Ve^HR]\c
+oWN#X+lHEcp\^.9qW9":.BB\0aPǨcp\ONqjpG}}$.˅
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_105_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_105_4.dat
new file mode 100755
index 00000000..0211cdb3
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_105_4.dat
@@ -0,0 +1,2 @@
+xK
+0D=Mr˹ATeEFL2#鹢_I!딤Ѻ-իkmO]sST6*'8 N$'NZ^}rU*G9r|c[cN[_=5^J 1*qv
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_117_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_117_4.dat
new file mode 100755
index 00000000..38672591
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_117_4.dat
@@ -0,0 +1,2 @@
+x
+ н_s]4Dgn2Jj}ҾRsSWGRɧ)5Em#ܯk_"z3\rʕ+r
Lk|/{;'/#\p\p>#\p\p#>qp\p.$Iq dGR_4
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_137_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_137_4.dat
new file mode 100755
index 00000000..0c09c487
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_137_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_141_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_141_4.dat
new file mode 100755
index 00000000..62b03f24
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_141_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_145_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_145_4.dat
new file mode 100755
index 00000000..33fb2112
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_145_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_149_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_149_4.dat
new file mode 100755
index 00000000..de99310f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_149_4.dat
@@ -0,0 +1,2 @@
+x
+!н_sm +XӋ9=.=Zka]ޒ>Kjo|SSWKZmj\Ъ2 W\qW\q"~jvtv_\qW\qW\q%g3}+++r9ArW\qW\qŕA g3WA W\qW\qW]V~v{D3Ȝ!\W^Tڍ[S7vۜgq?
+{peo383838{YXz,_OYfe3s38383\C!Ms38383r
\C?37938383\C!07M8383q,mMrskWv3~WWB
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_157_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_157_4.dat
new file mode 100755
index 00000000..ad5fcf69
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_157_4.dat
@@ -0,0 +1 @@
+x10ޯs4"FP=iRX¢X0멪u 4ftl}m➭S|юSP5<]rwqwq^QN6ÏZsߙ,wqwqǝ>Μ5g;;Y}Vgw,wqwqw>9wqwq>3gY;[ww?P3Ƙggt퐮;].3w4A
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_161_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_161_4.dat
new file mode 100755
index 00000000..7604c454
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_161_4.dat
@@ -0,0 +1 @@
+xA@fs!AL_|,4l)iml0' +E]N\x#2/_{7g9쏼ٷ}2r!?}-#Te9C9C9~6Sʇ겺!r!r!ۘse9C9C94_Ɯ|.r!r!s/s0 2r!r8}DwrDXΡ|x|!2
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_165_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_165_4.dat
new file mode 100755
index 00000000..d83d6316
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_165_4.dat
@@ -0,0 +1,3 @@
+xA
+1}Or."*?fPLHIkΫZQ8
+Gyqk-n5+?|֎kKnEŹK.K.?2.|EJ{2<:.Ku\K.K.ǝmu)_8\r%\r%\Џ;'2!_8\r%\r%\Џ;'2!_\r%\r%\rinC?nn9
RK.K.;.HqY'ݽNF?K㕢,R| My*3
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_169_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_169_4.dat
new file mode 100755
index 00000000..4aac95c1
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_169_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_173_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_173_4.dat
new file mode 100755
index 00000000..9df4d865
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_173_4.dat
@@ -0,0 +1,2 @@
+xK
+1}Nrna~ZY!Jt^5(/jkz[pj_?~v:|jwՖ_mXzo6?naCe
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_81_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_81_4.dat
new file mode 100755
index 00000000..dd652161
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_81_4.dat
@@ -0,0 +1,3 @@
+xA
+0yMyXEm7"892ѸQ1ݳ+xx;t35DIY1x\:u}e/ #Th<
+UBz<5G<5{G<5<饫>]Urxu
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_85_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_85_4.dat
new file mode 100755
index 00000000..c8d5123e
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_85_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_89_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_89_4.dat
new file mode 100755
index 00000000..5b9bd7ec
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_89_4.dat
@@ -0,0 +1,2 @@
+x1
+0ὧI9% Vڀfr0}z=#9ҕ:~s1BՁg&4pgq.p.&gT05rgsgqrg捯u38k.Egmb*&7?
:
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_93_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_93_4.dat
new file mode 100755
index 00000000..be7f5e52
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_93_4.dat
@@ -0,0 +1,2 @@
+xK
+ ὧIn$}PŌB]N@%sfkҫ}CzoA}aʽ2|~D&l=Ywq}q\EYjK_ywqwz$==;_>+pH9Di
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_4/mask_97_4.dat b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_97_4.dat
new file mode 100755
index 00000000..5d848caa
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_4/mask_97_4.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_101_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_101_5.dat
new file mode 100755
index 00000000..c21869e8
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_101_5.dat
@@ -0,0 +1,2 @@
+x
+ E+%=M3Cbv
ѬNkûgqkqq{%Oo,iKee3[|iVh]``0ʕz˴T0Gu/q8F13:W>#ȕ0c0Q8E=F#+aX͞+cV%9W>Q]TkY-gLqD艋
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_105_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_105_5.dat
new file mode 100755
index 00000000..bc8798c6
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_105_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_109_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_109_5.dat
new file mode 100755
index 00000000..25a39440
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_109_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_113_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_113_5.dat
new file mode 100755
index 00000000..25f42b8b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_113_5.dat
@@ -0,0 +1,9 @@
+x
+0D^6I63[[EDqc+jy81\c
+7c?u}DK4},kkg--3[UƂyUXUXSV:ϫ՝,|кS⫰
+
+
+Vɫ*X[*
+
+
+zU*NV*JUXUXSXijTi4fZkU^_~Ux}ծZ/r
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_117_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_117_5.dat
new file mode 100755
index 00000000..f236940d
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_117_5.dat
@@ -0,0 +1 @@
+x D|Mn/*{M+pI_&m-ѾC32u?o-kgB7wc=U%yoRhӯșDo:ֶyRJkQ^aaaqOgiJ;qOg)ӊ000[vö>=>000Ofz3=>000.3Z$8\pw4:Zp:qX 7
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_121_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_121_5.dat
new file mode 100755
index 00000000..9bb5c415
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_121_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_125_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_125_5.dat
new file mode 100755
index 00000000..2161c50a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_125_5.dat
@@ -0,0 +1,2 @@
+xA
+ E&fc;S$?؏Q4YahûyJ}9g==li.;nh_wz.qCWȧy
uPk;<<<|*q,
mkWqNl%
yyyy^2䰅sX|aaaa3ϙ9lH<<<<̿웁[n`Tq8^vy
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_129_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_129_5.dat
new file mode 100755
index 00000000..f0c1d650
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_129_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_133_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_133_5.dat
new file mode 100755
index 00000000..46be8b09
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_133_5.dat
@@ -0,0 +1,2 @@
+xA
+0DѽOcr]4%1mCTxΜ[Dv={FEϏq?ݿ9keѭ}'2^c4G:3=JK-F0`#Hw'#<{~Z4:BG舻F0`G~:`#?#tw-`#?##t#F0r}Q}eR;M/k1mX=hsH"k M:3qOW}9ԖIH1G;-sڶ?[%M
+ v#;zg^3d}69Ψޙ@7҄#gv`;׳ީ\$wlv`v;ލ}7wߑa;vkA#gv`=N2wxgWӤ@n?c}SQ:Zd?+9vz)P
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_141_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_141_5.dat
new file mode 100755
index 00000000..60c1a8e8
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_141_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_145_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_145_5.dat
new file mode 100755
index 00000000..9303c07f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_145_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_149_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_149_5.dat
new file mode 100755
index 00000000..4256cefd
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_149_5.dat
@@ -0,0 +1,3 @@
+x[
+0&c}-s+'^;Ax=Q_gUݏﵪxGTȺV¹UUE_IǴ;T1̠
+]W2 2|o5uꆬuI:(WKU躒rPAdAdA;
vo_zNO{2rPA9 2 29}^O挞rwQdAdAnMA9(dAdA^WZ.+G^K`}`_Fk
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_153_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_153_5.dat
new file mode 100755
index 00000000..deea09d7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_153_5.dat
@@ -0,0 +1,2 @@
+x
+@wfЬ`D"Ie<:au,7Of۳uP6~szs,jլcVZvߨms^uHYu&l&l&_9
;]^jsO;ܔrSn&l&l9yכzArSnM6dM6dM6ރ@/$7ܔl&l&lzŽzACrSnM6dM6dOl7ᰚUuN֛FcPPS,l;HO
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_157_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_157_5.dat
new file mode 100755
index 00000000..176e2a69
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_157_5.dat
@@ -0,0 +1 @@
+x10Dާri( r* \~>C*vs]Ŝ_{W!zﶬ/)˙vV6V,f1Ybn^o>\O],,b,f1YyVgYYYb,f1+ʳ<˳<˳1YbŬ<+ʳ,,b,f1YyVgYYYb,fukys77}vmb=wsw)tW:
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_161_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_161_5.dat
new file mode 100755
index 00000000..70d5fb00
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_161_5.dat
@@ -0,0 +1,2 @@
+xI
+@нDp@
o|m rHk㨤~co^Jzװ#5l¦S_92[}ZÊ=T2ƀP2[cV衆CYf'-X9>v~usK5`e,2,2,2-///o_q}K\reYfeYf峖o+/,\feYfeYfٳexB.e2,2,̲g+l\r16,2,>ϰ=te&_4=tU}/>>>Or5/u>/g}g}gOsvO}/g}g}ٷGo-w{r_{g}g}g_n=n]4Nkβ_M8m?SF<
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_173_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_173_5.dat
new file mode 100755
index 00000000..f9a67413
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_173_5.dat
@@ -0,0 +1,4 @@
+x[
+0&G1gD)[CzeDѷц=RN6FJmJqP}xs_}GFy;
+[;]ek[QbTmy&0 L`̄Y?رw؛ fcVN9&0 L`ׄZ}0=F=F9ANL`&0 L`BzYfI=F9AN&0 L`&0 fIsr ' L`&0 L`<i͒"9AN&0 L`VaBX",Um>
+=wZgBΜP!8
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_177_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_177_5.dat
new file mode 100755
index 00000000..b07c636b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_177_5.dat
@@ -0,0 +1,11 @@
+xъ0~ܾحuO,"%
:$Xui=ѶՃgƸ?Ώq.So~zW:=h1cq]Ƕi!r8Ɓ`+X
+V jj;8ƁX+
+oV`+X
+V?[1^h-ֳ5Z;rmS+
+oV`+X
+V;Z,YMB+
+V`+X
+VZeڦ}r\!W`+X
+V`+3Km>SB+
+V`+X
+Vc㊛{g;^Qq5ZUݮQL0+*&YDq*6
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_21_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_21_5.dat
new file mode 100755
index 00000000..04f97ea6
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_21_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_25_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_25_5.dat
new file mode 100755
index 00000000..c20b59b1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_25_5.dat
@@ -0,0 +1,2 @@
+xڝa
+@!4ʢ
?,""j?n=GZy:DR
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_33_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_33_5.dat
new file mode 100755
index 00000000..726d7fd7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_33_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_37_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_37_5.dat
new file mode 100755
index 00000000..6d32ca6f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_37_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_41_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_41_5.dat
new file mode 100755
index 00000000..e07c6172
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_41_5.dat
@@ -0,0 +1,2 @@
+xTA
+ 5?7XMtxҴx ?@7@~"N$Sɰ{+CA'r\Pp<ޏ- ͺ:S3sԉۻީz#qw >
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_45_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_45_5.dat
new file mode 100755
index 00000000..5168a17f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_45_5.dat
@@ -0,0 +1 @@
+xUA 5?U:N&Z":;4P1=bNvSGM1˛n'(κ J{Eѵs] ,sq
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_49_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_49_5.dat
new file mode 100755
index 00000000..9f3f3cd7
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_49_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_53_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_53_5.dat
new file mode 100755
index 00000000..449807ba
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_53_5.dat
@@ -0,0 +1 @@
+xVA "zYf5ƐJC
A;l\,dR.\(e_ еaNi5\żaLP(;2שjN6O
u+l{y6od^
C[%
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_57_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_57_5.dat
new file mode 100755
index 00000000..c7dd81f3
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_57_5.dat
@@ -0,0 +1,2 @@
+xVA
+ 5?NlZHAbBZ0aMd`1z'"<Ր19nvͨ.)bݻ~;9Z#tB~
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_65_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_65_5.dat
new file mode 100755
index 00000000..ecd93806
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_65_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_69_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_69_5.dat
new file mode 100755
index 00000000..ead4edc1
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_69_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_73_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_73_5.dat
new file mode 100755
index 00000000..00001176
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_73_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_77_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_77_5.dat
new file mode 100755
index 00000000..1652cdc2
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_77_5.dat
@@ -0,0 +1 @@
+xQ Cw#&C`T6ƹB(9
'ֆڢzk"hv.`cXB5[(F>71/34Ϊz^'[FyglgM>OTL4ϔ{&3Wy*ʧb*`<3;Vo0/s6n0ya[mcE
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_81_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_81_5.dat
new file mode 100755
index 00000000..71215e95
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_81_5.dat
@@ -0,0 +1,3 @@
+x
+ C~M?tzU4" }tMX2|.ɋ˙F\~m4Xu
+ٔ, w:EƄ>X̯=_]g>>zמ/)5ךkkkZsXXY{ܮ}~mt:S#&;U#)
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_85_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_85_5.dat
new file mode 100755
index 00000000..09cf0e28
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_85_5.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_89_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_89_5.dat
new file mode 100755
index 00000000..5fff5306
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_89_5.dat
@@ -0,0 +1,2 @@
+x
+ 45enpQ Gcfl^^;;b5;`kU߮j`NsO=\[a6~nLD?
!6uF%w*Ȭkf77SĆbÆXodw_mbClNۙ
ck&YVoܡBעبAl6
Jjx
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_5/mask_93_5.dat b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_93_5.dat
new file mode 100755
index 00000000..ec4240bd
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_5/mask_93_5.dat
@@ -0,0 +1,2 @@
+xK
+0D>&&
fP^8BY5s(imҮ=f3/wۧEyYQwf[}
[90303ef̙3'3=,ͼwxDַ.,;s%g,,,=Rὓ7uKKTD<(n lYhV۹sޕyPEtyY]ns
;ss,!LkԅcbL12cX91Z#XEn#;svT~L~LR11vs.1111J1&؍Ń111J1&ƞgKLƪjlk{gڞ5K1/ǐ~,ac$
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_105_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_105_6.dat
new file mode 100755
index 00000000..a58fec74
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_105_6.dat
@@ -0,0 +1,3 @@
+xQ
+@DskBZ#o)Sd}Gܷl쯯^)G]S4S?#BZ:+{sHKNiI!me1
+RWe9!``Uyˀu:檞U=w-oԺwB}cMK蹰{{=y蹰{{=y蹰{wScaoi'fyO=CyO=Cy[{S=;|v4}ϯ20
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_109_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_109_6.dat
new file mode 100755
index 00000000..be7b4749
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_109_6.dat
@@ -0,0 +1 @@
+xA0~ρDBHCHV20nuol쯯˻=ۢs9[l'?7R"&2:7QqX_n
]$՚EIY*Lq0 0 0{LJз(s\ɳwX-7^ItIII$~?N0 0 0O'Itg7L$L-Iuzrfr
M^'}(O~R]1YLĞu9Qӕ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_113_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_113_6.dat
new file mode 100755
index 00000000..397f5274
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_113_6.dat
@@ -0,0 +1,3 @@
+x E5NՉbF6on,m>gS9RWcǕ9&%1_cx= GR^w-z?dzv=,}ԥ?ǹژ:9m==@U䲉UXUXVe~by4Wi:e=ɼÆ$<>Ov'Cytaaaa~|'9liΣ<<<<Iæ<:<<<ٕWDzy:.z=
ݓʯ
sVöE=ll_k0_#vίmj
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_129_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_129_6.dat
new file mode 100755
index 00000000..b4695c3f
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_129_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_133_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_133_6.dat
new file mode 100755
index 00000000..40911dc5
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_133_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_137_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_137_6.dat
new file mode 100755
index 00000000..43ccb68c
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_137_6.dat
@@ -0,0 +1,2 @@
+x E5?e^4fHp[1-e)UQV]UWN5o*8|۩W6bk?{f|>s֪r666rҟ=vڲWy-'
+Ο;qtQE>U϶f곭xN]Tc(s❮7tAw`v`v`v`kvwfwt;];;;;;!ޙ;ao];l;;;÷|ʷ(3}l.?"މr};\}S-Aw<9;EV'ם
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_141_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_141_6.dat
new file mode 100755
index 00000000..0340409a
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_141_6.dat
@@ -0,0 +1,10 @@
+xa F4/c]زȐ[=[E럓sm,fn/|kj\j?g[q(NOZc5SGGP[oMVָfvL<WóCaz6U~һ{`nݻdvVy~rZ"qk{>g$XKU}m\bjaGx,f1Yb]z̞^.5[?嬜r,f1YY>grVb,f1Y>g,rVmYb,f,|VY9Yb,f,|VY9+g1Ybً ̦M7>2{9z϶hm3l|9xټ#f#x6 -v%N'
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_161_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_161_6.dat
new file mode 100755
index 00000000..ecec68b1
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_161_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_165_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_165_6.dat
new file mode 100755
index 00000000..d641dfa3
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_165_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_169_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_169_6.dat
new file mode 100755
index 00000000..ae689723
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_169_6.dat
@@ -0,0 +1 @@
+xJ0i9[Jɘk{1b!gnhHkS뉭-V?KIׁ1큏1ƣݎ/`/z)*=3ڏg6^k65CY>㵾+'{է_Vˊx-J<ӛܗr_>>i;rO}/g}g}ٿ}}xO}/g}g}ٷGo/{{r_>>o/z^#}g}ٿd'ʳ|QRNS3YڳZ'msEǷj5
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_173_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_173_6.dat
new file mode 100755
index 00000000..95fa97c7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_173_6.dat
@@ -0,0 +1 @@
+xa09MrM S*:a_-5hh_)uZ֭[loےsmKN{H?x`l#f9>ڟ[eЄώߓ ?^m*/Kmhy%v-nKlkKL`&& g5(gwxYܞa¬pVcZ[#O=SN9&0 L`DŽ 'tjj]QN9&0 L`sYRc@QN9 L`&0 L`"YRc\ ' r&0 L`EH9AN&0 L`&7p6`|hms
R5Ƙȉ k\X/ )g9
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_177_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_177_6.dat
new file mode 100755
index 00000000..e9f0476f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_177_6.dat
@@ -0,0 +1,14 @@
+xn {ڤ*4v۴u1{f{_,,K9o 4ǵ7lniJiggir<-MG
+
+
+
+xuV+zRCr9+Gq6QWb"Qe"WL+
+ XXXXX/|~j,nmuMۤ+
+
XXXXXYa,X;M+
+ XXXXXe)oӘf|5H늚7/D
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_21_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_21_6.dat
new file mode 100755
index 00000000..6bd505b4
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_21_6.dat
@@ -0,0 +1 @@
+xڝQ C9M{i]X1-C!D7
Wٜ&rD)~]<M 3(>{AaS
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_25_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_25_6.dat
new file mode 100755
index 00000000..d45083aa
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_25_6.dat
@@ -0,0 +1 @@
+xڝQA 52)e+(XmZt*(ڹ;tJ<峂_ڤ3oڴ"̢azh}&qvSG֙,-J4}oS[}w
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_29_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_29_6.dat
new file mode 100755
index 00000000..0408e224
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_29_6.dat
@@ -0,0 +1,3 @@
+xRA
+0XcL(4EԈB
+8CܾnM+lǝՆO1]&ڍ4UD-6-$:6dZ?ylf?
8?߲_ݏ`8G1`B`;+}&s]<iK'l'9%.7
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_65_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_65_6.dat
new file mode 100755
index 00000000..550fc8fe
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_65_6.dat
@@ -0,0 +1 @@
+xWQ i{KNLk?e$Qik41{`+!ڮM
?1b8.^wsnFj5EaQX|=w@2v<ŋŞ|4w\UXBQz+TTcBz/48,5`ȱ OV$
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_69_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_69_6.dat
new file mode 100755
index 00000000..a3e4fa0f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_69_6.dat
@@ -0,0 +1 @@
+xK @dTh hLSSEq eY@<+*|窮%>z*7e6QS`.>sE'%@[6@P0h
aFxtpl2Q-g1Nfeo^0FdT>N_OwG3ug{3<[Ժb?'6^
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_73_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_73_6.dat
new file mode 100755
index 00000000..ab71b70a
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_73_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_77_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_77_6.dat
new file mode 100755
index 00000000..ad5a660e
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_77_6.dat
@@ -0,0 +1 @@
+x E۲iVa.FpSTY4q~z=:͒
6m8:#0PضiDy:2Š'Zs&}滜\r0\ŚXw;iPȔL)Seԕ{hDu9LbJSS))gZ{e)qJdLw+#3-V0շljڠS-S
9=ݯ5PPq1M?g
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_81_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_81_6.dat
new file mode 100755
index 00000000..28a6d075
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_81_6.dat
@@ -0,0 +1,3 @@
+xQ0D9
rRLvk`0 ;i6\|_cc1huio#2}x*.Yt&
+ְq/K;3ve̢ȊAH?`]5Kw!}{Zû߲W
+yⷾ^_ykk^Kתb-bYSڸ'֜Nu#MfHSQ?|]IAiMyyuW
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_85_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_85_6.dat
new file mode 100755
index 00000000..d5403e49
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_85_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_89_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_89_6.dat
new file mode 100755
index 00000000..eeeb5d19
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_89_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_93_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_93_6.dat
new file mode 100755
index 00000000..6ff38db6
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_93_6.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_6/mask_97_6.dat b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_97_6.dat
new file mode 100755
index 00000000..3a2072ef
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_6/mask_97_6.dat
@@ -0,0 +1,2 @@
+xa0sdFx[=4Hoj34&s}*aVc&35arW^aLClzq,1x
SQN]/Giu`&w%,%DY"Kt+HE'|R2(v1vqiqd,%D~%ػJj}ͺĺgY"Kd,+K
+]Wt+sF/)].zN'`>1='#`+bl]Z
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_101_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_101_7.dat
new file mode 100755
index 00000000..1f6bc512
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_101_7.dat
@@ -0,0 +1 @@
+xQ C}rm`fjT#54'tfaЇo$cmOJ23c<6Xn0F
)
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_105_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_105_7.dat
new file mode 100755
index 00000000..6b0cacfe
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_105_7.dat
@@ -0,0 +1,2 @@
+xA
+0EFaMҙNPx)pQ_~|ñ(bF$.aoWGNPUǖM%{oHQUlִL^>+m#{{eo&Y2soM)gncO9sZ3wo+{=f.zޣ{{=zGcskCQϞp^&{^NʷU
e5}EwGn+o
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_109_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_109_7.dat
new file mode 100755
index 00000000..9875cbe8
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_109_7.dat
@@ -0,0 +1,2 @@
+xA
+0D9Mr}*_x-d:"NJ-k"⨚d{ջגɬ|'rQ5+ s)c7-1nn햺qɔJtg^ʉw̘Ň-?*&Mm@ee5^
+c
+
+,b\13j4TZfŢo*
+
+
+:Ut*
+
+
+Xů0"%6ed8rSNsUnk5XejުuVXg,l`u!hXZ\VlM|[ͬ000#hF'c]i>Hataaa~<ÆzyqkO000㪞Faaa)2˰fÒ%z8tO=3=3:cw
+V$
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_121_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_121_7.dat
new file mode 100755
index 00000000..d5d577f7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_121_7.dat
@@ -0,0 +1,2 @@
+x[
+ Edi;^az,#6ƞ^rh&^amY9_غ5Cr6t^^WlEز~ɿ|MmmS}(
۰
۰
۰}mQ]ZVq]vѲ"M1fG,qBmtaaazeF3cxIDmtaaamný$n۰
۰
۰
ۏa[}`[yޖ)n<4K/Oslnlm/G
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_125_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_125_7.dat
new file mode 100755
index 00000000..f9ec0887
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_125_7.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_129_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_129_7.dat
new file mode 100755
index 00000000..9bf51d52
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_129_7.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_133_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_133_7.dat
new file mode 100755
index 00000000..b643ffed
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_133_7.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_137_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_137_7.dat
new file mode 100755
index 00000000..11d212bf
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_137_7.dat
@@ -0,0 +1,5 @@
+x
+ F4/
c_ǂ+{SK<o[l
+Ο
+07։Vl;b7fMS;1LCvR|KMH
+#Н(Sqd
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_141_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_141_7.dat
new file mode 100755
index 00000000..98dffab0
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_141_7.dat
@@ -0,0 +1 @@
+xA E=
rITY@Ä0!|1tbG0ԗѤs2Z/oa\qzOnҋMntX"KmeM}CpPL^S0S0S0SL )ǔژY߾%b,Sl?zC)tLLLLI2zRXh@)tLLLLI1zbϷB)~0S0S0S07)|B)))3ՖL%tfwM*:~hZsnc$1UTtJg8OYE
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_145_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_145_7.dat
new file mode 100755
index 00000000..4aa2bac1
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_145_7.dat
@@ -0,0 +1,2 @@
+x
+ E5?W6Z-^2qbGX6(Ɖu"LbbGuμGk:HwA[jmHݞ3OkQ{l|TEmJfL?2"&)kRfc̉F,z=5X5X5X7F\pUs#5X5X5XFdYk!a
`
`
`o8ct
]CC
gM5[N%khZp?Iܣϲ^n$Y7AZP[
fȓ0
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_149_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_149_7.dat
new file mode 100755
index 00000000..809f0055
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_149_7.dat
@@ -0,0 +1 @@
+xn {?
uچ2G$ncFKb3֪tPc̥7[?9:['9'*ӖGah_/z+6XB>2qYJ0黏Bfa 19c7G Ol,^꽓3A:H 1Ab0X4%٫#d>&C 1Ab+g嬜,f1Yb|Y>+g嬜,f1Ylio.\Ɲo=gϙ-yk_TA
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_161_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_161_7.dat
new file mode 100755
index 00000000..35ba8ff4
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_161_7.dat
@@ -0,0 +1 @@
+xю y/皨E)Ʈ1~493,˵+ZT=ZeC.~iߏ&>,6e~,lW]
2\;2j"e,rXݵV(c쵵ZӖ18ީ/,'t.ee,cX2߱,_|yt|]t.cX2e,cy/ɗys.eLe,cX2lo|Z{+2]bl,cX2e{+֊[A2]X2e,c9CX;QIQH8R҈G"z,&;'o97%P8%6oǽ;]NWn[f7v
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_29_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_29_7.dat
new file mode 100755
index 00000000..e3d7391b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_29_7.dat
@@ -0,0 +1,2 @@
+xR9 QpX$lŲf!I2pgSMZj"te0#ԛ`_1-cha~/Eh4"~
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_37_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_37_7.dat
new file mode 100755
index 00000000..87d9a1a9
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_37_7.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_41_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_41_7.dat
new file mode 100755
index 00000000..8acec04f
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_41_7.dat
@@ -0,0 +1 @@
+xTA 5[fDY(O^bR3/~t/L"7SQQ5j\Sib#Նȏ+ǣw#zx?㽧A-wu曑Y7$b.%A;wRoxG}?
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_45_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_45_7.dat
new file mode 100755
index 00000000..dbba31d0
Binary files /dev/null and b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_45_7.dat differ
diff --git a/vendor/aferrandini/phpqrcode/cache/mask_7/mask_49_7.dat b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_49_7.dat
new file mode 100755
index 00000000..be5dce8b
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/cache/mask_7/mask_49_7.dat
@@ -0,0 +1 @@
+xV0khC-X.ukv
o40T%96U5*sI{`_>S?}(:yTl{G&E\6}"AXXϬ
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/composer.json b/vendor/aferrandini/phpqrcode/composer.json
new file mode 100644
index 00000000..ff793567
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/composer.json
@@ -0,0 +1,21 @@
+{
+ "name": "aferrandini/phpqrcode",
+ "description": "PHPQRCode porting and changed for PHP 5.3 compatibility",
+ "keywords": ["php", "qrcode", "barcode"],
+ "homepage": "https://github.com/aferrandini/PHPQRCode",
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Ariel Ferrandini",
+ "email": "arielferrandini@gmail.com",
+ "homepage": "http://www.ferrandini.com/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-0": { "PHPQRCode": "lib/" }
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode.php
new file mode 100644
index 00000000..e96c5e3d
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode.php
@@ -0,0 +1,42 @@
+width = $width;
+ $this->frame = $frame;
+ $this->x = $width - 1;
+ $this->y = $width - 1;
+ $this->dir = -1;
+ $this->bit = -1;
+ }
+
+ //----------------------------------------------------------------------
+ public function setFrameAt($at, $val)
+ {
+ $this->frame[$at['y']][$at['x']] = chr($val);
+ }
+
+ //----------------------------------------------------------------------
+ public function getFrameAt($at)
+ {
+ return ord($this->frame[$at['y']][$at['x']]);
+ }
+
+ //----------------------------------------------------------------------
+ public function next()
+ {
+ do {
+
+ if($this->bit == -1) {
+ $this->bit = 0;
+ return array('x'=>$this->x, 'y'=>$this->y);
+ }
+
+ $x = $this->x;
+ $y = $this->y;
+ $w = $this->width;
+
+ if($this->bit == 0) {
+ $x--;
+ $this->bit++;
+ } else {
+ $x++;
+ $y += $this->dir;
+ $this->bit--;
+ }
+
+ if($this->dir < 0) {
+ if($y < 0) {
+ $y = 0;
+ $x -= 2;
+ $this->dir = 1;
+ if($x == 6) {
+ $x--;
+ $y = 9;
+ }
+ }
+ } else {
+ if($y == $w) {
+ $y = $w - 1;
+ $x -= 2;
+ $this->dir = -1;
+ if($x == 6) {
+ $x--;
+ $y -= 8;
+ }
+ }
+ }
+ if($x < 0 || $y < 0) return null;
+
+ $this->x = $x;
+ $this->y = $y;
+
+ } while(ord($this->frame[$y][$x]) & 0x80);
+
+ return array('x'=>$x, 'y'=>$y);
+ }
+
+} ;
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php
new file mode 100755
index 00000000..93606f13
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php
@@ -0,0 +1,182 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRbitstream {
+
+ public $data = array();
+
+ //----------------------------------------------------------------------
+ public function size()
+ {
+ return count($this->data);
+ }
+
+ //----------------------------------------------------------------------
+ public function allocate($setLength)
+ {
+ $this->data = array_fill(0, $setLength, 0);
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public static function newFromNum($bits, $num)
+ {
+ $bstream = new QRbitstream();
+ $bstream->allocate($bits);
+
+ $mask = 1 << ($bits - 1);
+ for($i=0; $i<$bits; $i++) {
+ if($num & $mask) {
+ $bstream->data[$i] = 1;
+ } else {
+ $bstream->data[$i] = 0;
+ }
+ $mask = $mask >> 1;
+ }
+
+ return $bstream;
+ }
+
+ //----------------------------------------------------------------------
+ public static function newFromBytes($size, $data)
+ {
+ $bstream = new QRbitstream();
+ $bstream->allocate($size * 8);
+ $p=0;
+
+ for($i=0; $i<$size; $i++) {
+ $mask = 0x80;
+ for($j=0; $j<8; $j++) {
+ if($data[$i] & $mask) {
+ $bstream->data[$p] = 1;
+ } else {
+ $bstream->data[$p] = 0;
+ }
+ $p++;
+ $mask = $mask >> 1;
+ }
+ }
+
+ return $bstream;
+ }
+
+ //----------------------------------------------------------------------
+ public function append(QRbitstream $arg)
+ {
+ if (is_null($arg)) {
+ return -1;
+ }
+
+ if($arg->size() == 0) {
+ return 0;
+ }
+
+ if($this->size() == 0) {
+ $this->data = $arg->data;
+ return 0;
+ }
+
+ $this->data = array_values(array_merge($this->data, $arg->data));
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function appendNum($bits, $num)
+ {
+ if ($bits == 0)
+ return 0;
+
+ $b = QRbitstream::newFromNum($bits, $num);
+
+ if(is_null($b))
+ return -1;
+
+ $ret = $this->append($b);
+ unset($b);
+
+ return $ret;
+ }
+
+ //----------------------------------------------------------------------
+ public function appendBytes($size, $data)
+ {
+ if ($size == 0)
+ return 0;
+
+ $b = QRbitstream::newFromBytes($size, $data);
+
+ if(is_null($b))
+ return -1;
+
+ $ret = $this->append($b);
+ unset($b);
+
+ return $ret;
+ }
+
+ //----------------------------------------------------------------------
+ public function toByte()
+ {
+
+ $size = $this->size();
+
+ if($size == 0) {
+ return array();
+ }
+
+ $data = array_fill(0, (int)(($size + 7) / 8), 0);
+ $bytes = (int)($size / 8);
+
+ $p = 0;
+
+ for($i=0; $i<$bytes; $i++) {
+ $v = 0;
+ for($j=0; $j<8; $j++) {
+ $v = $v << 1;
+ $v |= $this->data[$p];
+ $p++;
+ }
+ $data[$i] = $v;
+ }
+
+ if($size & 7) {
+ $v = 0;
+ for($j=0; $j<($size & 7); $j++) {
+ $v = $v << 1;
+ $v |= $this->data[$p];
+ $p++;
+ }
+ $data[$bytes] = $v;
+ }
+
+ return $data;
+ }
+
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php
new file mode 100644
index 00000000..08b60243
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php
@@ -0,0 +1,158 @@
+getVersion() < 0 || $input->getVersion() > Constants::QRSPEC_VERSION_MAX) {
+ throw new Exception('wrong version');
+ }
+ if($input->getErrorCorrectionLevel() > Constants::QR_ECLEVEL_H) {
+ throw new Exception('wrong level');
+ }
+
+ $raw = new QRrawcode($input);
+
+ QRtools::markTime('after_raw');
+
+ $version = $raw->version;
+ $width = QRspec::getWidth($version);
+ $frame = QRspec::newFrame($version);
+
+ $filler = new FrameFiller($width, $frame);
+ if(is_null($filler)) {
+ return NULL;
+ }
+
+ // inteleaved data and ecc codes
+ for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
+ $code = $raw->getCode();
+ $bit = 0x80;
+ for($j=0; $j<8; $j++) {
+ $addr = $filler->next();
+ $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
+ $bit = $bit >> 1;
+ }
+ }
+
+ QRtools::markTime('after_filler');
+
+ unset($raw);
+
+ // remainder bits
+ $j = QRspec::getRemainder($version);
+ for($i=0; $i<$j; $i++) {
+ $addr = $filler->next();
+ $filler->setFrameAt($addr, 0x02);
+ }
+
+ $frame = $filler->frame;
+ unset($filler);
+
+
+ // masking
+ $maskObj = new QRmask();
+ if($mask < 0) {
+
+ if (Constants::QR_FIND_BEST_MASK) {
+ $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
+ } else {
+ $masked = $maskObj->makeMask($width, $frame, (intval(Constants::QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
+ }
+ } else {
+ $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
+ }
+
+ if($masked == NULL) {
+ return NULL;
+ }
+
+ QRtools::markTime('after_mask');
+
+ $this->version = $version;
+ $this->width = $width;
+ $this->data = $masked;
+
+ return $this;
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeInput(QRinput $input)
+ {
+ return $this->encodeMask($input, -1);
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeString8bit($string, $version, $level)
+ {
+ if(string == NULL) {
+ throw new Exception('empty string!');
+ return NULL;
+ }
+
+ $input = new QRinput($version, $level);
+ if($input == NULL) return NULL;
+
+ $ret = $input->append($input, Constants::QR_MODE_8, strlen($string), str_split($string));
+ if($ret < 0) {
+ unset($input);
+ return NULL;
+ }
+ return $this->encodeInput($input);
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeString($string, $version, $level, $hint, $casesensitive)
+ {
+
+ if($hint != Constants::QR_MODE_8 && $hint != Constants::QR_MODE_KANJI) {
+ throw new Exception('bad hint');
+ return NULL;
+ }
+
+ $input = new QRinput($version, $level);
+ if($input == NULL) return NULL;
+
+ $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
+ if($ret < 0) {
+ return NULL;
+ }
+
+ return $this->encodeInput($input);
+ }
+
+ //----------------------------------------------------------------------
+ public static function png($text, $outfile = false, $level = Constants::QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
+ {
+ $enc = QRencode::factory($level, $size, $margin);
+ return $enc->encodePNG($text, $outfile, $saveandprint=false);
+ }
+
+ //----------------------------------------------------------------------
+ public static function text($text, $outfile = false, $level = Constants::QR_ECLEVEL_L, $size = 3, $margin = 4)
+ {
+ $enc = QRencode::factory($level, $size, $margin);
+ return $enc->encode($text, $outfile);
+ }
+
+ //----------------------------------------------------------------------
+ public static function raw($text, $outfile = false, $level = Constants::QR_ECLEVEL_L, $size = 3, $margin = 4)
+ {
+ $enc = QRencode::factory($level, $size, $margin);
+ return $enc->encodeRAW($text, $outfile);
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php
new file mode 100755
index 00000000..d05ab6b7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php
@@ -0,0 +1,137 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+use Exception;
+
+class QRencode {
+
+ public $casesensitive = true;
+ public $eightbit = false;
+
+ public $version = 0;
+ public $size = 3;
+ public $margin = 4;
+
+ public $structured = 0; // not supported yet
+
+ public $level = Constants::QR_ECLEVEL_L;
+ public $hint = Constants::QR_MODE_8;
+
+ //----------------------------------------------------------------------
+ public static function factory($level = Constants::QR_ECLEVEL_L, $size = 3, $margin = 4)
+ {
+ $enc = new QRencode();
+ $enc->size = $size;
+ $enc->margin = $margin;
+
+ switch ($level.'') {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ $enc->level = $level;
+ break;
+ case 'l':
+ case 'L':
+ $enc->level = Constants::QR_ECLEVEL_L;
+ break;
+ case 'm':
+ case 'M':
+ $enc->level = Constants::QR_ECLEVEL_M;
+ break;
+ case 'q':
+ case 'Q':
+ $enc->level = Constants::QR_ECLEVEL_Q;
+ break;
+ case 'h':
+ case 'H':
+ $enc->level = Constants::QR_ECLEVEL_H;
+ break;
+ }
+
+ return $enc;
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeRAW($intext, $outfile = false)
+ {
+ $code = new QRcode();
+
+ if($this->eightbit) {
+ $code->encodeString8bit($intext, $this->version, $this->level);
+ } else {
+ $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
+ }
+
+ return $code->data;
+ }
+
+ //----------------------------------------------------------------------
+ public function encode($intext, $outfile = false)
+ {
+ $code = new QRcode();
+
+ if($this->eightbit) {
+ $code->encodeString8bit($intext, $this->version, $this->level);
+ } else {
+ $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
+ }
+
+ QRtools::markTime('after_encode');
+
+ if ($outfile!== false) {
+ file_put_contents($outfile, join("\n", QRtools::binarize($code->data)));
+ } else {
+ return QRtools::binarize($code->data);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function encodePNG($intext, $outfile = false,$saveandprint=false)
+ {
+ try {
+ ob_start();
+ $tab = $this->encode($intext);
+ $err = ob_get_contents();
+ ob_end_clean();
+
+ if ($err != '')
+ QRtools::log($outfile, "ERROR: " . $err);
+
+ $maxSize = (int)(Constants::QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
+
+ QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ die();
+
+ QRtools::log($outfile, $e->getMessage());
+ }
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php
new file mode 100755
index 00000000..430a16f8
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php
@@ -0,0 +1,95 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRimage {
+
+ //----------------------------------------------------------------------
+ public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
+ {
+ $image = self::image($frame, $pixelPerPoint, $outerFrame);
+
+ if ($filename === false) {
+ Header("Content-type: image/png");
+ ImagePng($image);
+ } else {
+ if($saveandprint===TRUE){
+ ImagePng($image, $filename);
+ header("Content-type: image/png");
+ ImagePng($image);
+ }else{
+ ImagePng($image, $filename);
+ }
+ }
+
+ ImageDestroy($image);
+ }
+
+ //----------------------------------------------------------------------
+ public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
+ {
+ $image = self::image($frame, $pixelPerPoint, $outerFrame);
+
+ if ($filename === false) {
+ Header("Content-type: image/jpeg");
+ ImageJpeg($image, null, $q);
+ } else {
+ ImageJpeg($image, $filename, $q);
+ }
+
+ ImageDestroy($image);
+ }
+
+ //----------------------------------------------------------------------
+ private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
+ {
+ $h = count($frame);
+ $w = strlen($frame[0]);
+
+ $imgW = $w + 2*$outerFrame;
+ $imgH = $h + 2*$outerFrame;
+
+ $base_image =ImageCreate($imgW, $imgH);
+
+ $col[0] = ImageColorAllocate($base_image,255,255,255);
+ $col[1] = ImageColorAllocate($base_image,0,0,0);
+
+ imagefill($base_image, 0, 0, $col[0]);
+
+ for($y=0; $y<$h; $y++) {
+ for($x=0; $x<$w; $x++) {
+ if ($frame[$y][$x] == '1') {
+ ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
+ }
+ }
+ }
+
+ $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
+ ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
+ ImageDestroy($base_image);
+
+ return $target_image;
+ }
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php
new file mode 100755
index 00000000..8bdd21e7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php
@@ -0,0 +1,486 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+use Exception;
+
+class QRinput {
+
+ public $items;
+
+ private $version;
+ private $level;
+
+ //----------------------------------------------------------------------
+ public function __construct($version = 0, $level = Constants::QR_ECLEVEL_L)
+ {
+ if ($version < 0 || $version > Constants::QRSPEC_VERSION_MAX || $level > Constants::QR_ECLEVEL_H) {
+ throw new Exception('Invalid version no');
+ return NULL;
+ }
+
+ $this->version = $version;
+ $this->level = $level;
+ }
+
+ //----------------------------------------------------------------------
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ //----------------------------------------------------------------------
+ public function setVersion($version)
+ {
+ if($version < 0 || $version > Constants::QRSPEC_VERSION_MAX) {
+ throw new Exception('Invalid version no');
+ return -1;
+ }
+
+ $this->version = $version;
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function getErrorCorrectionLevel()
+ {
+ return $this->level;
+ }
+
+ //----------------------------------------------------------------------
+ public function setErrorCorrectionLevel($level)
+ {
+ if($level > Constants::QR_ECLEVEL_H) {
+ throw new Exception('Invalid ECLEVEL');
+ return -1;
+ }
+
+ $this->level = $level;
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function appendEntry(QRinputItem $entry)
+ {
+ $this->items[] = $entry;
+ }
+
+ //----------------------------------------------------------------------
+ public function append($mode, $size, $data)
+ {
+ try {
+ $entry = new QRinputItem($mode, $size, $data);
+ $this->items[] = $entry;
+ return 0;
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+
+ public function insertStructuredAppendHeader($size, $index, $parity)
+ {
+ if( $size > Constants::MAX_STRUCTURED_SYMBOLS ) {
+ throw new Exception('insertStructuredAppendHeader wrong size');
+ }
+
+ if( $index <= 0 || $index > Constants::MAX_STRUCTURED_SYMBOLS ) {
+ throw new Exception('insertStructuredAppendHeader wrong index');
+ }
+
+ $buf = array($size, $index, $parity);
+
+ try {
+ $entry = new QRinputItem(Constants::QR_MODE_STRUCTURE, 3, buf);
+ array_unshift($this->items, $entry);
+ return 0;
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function calcParity()
+ {
+ $parity = 0;
+
+ foreach($this->items as $item) {
+ if($item->mode != Constants::QR_MODE_STRUCTURE) {
+ for($i=$item->size-1; $i>=0; $i--) {
+ $parity ^= $item->data[$i];
+ }
+ }
+ }
+
+ return $parity;
+ }
+
+ //----------------------------------------------------------------------
+ public static function checkModeNum($size, $data)
+ {
+ for($i=0; $i<$size; $i++) {
+ if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ public static function estimateBitsModeNum($size)
+ {
+ $w = (int)$size / 3;
+ $bits = $w * 10;
+
+ switch($size - $w * 3) {
+ case 1:
+ $bits += 4;
+ break;
+ case 2:
+ $bits += 7;
+ break;
+ default:
+ break;
+ }
+
+ return $bits;
+ }
+
+ //----------------------------------------------------------------------
+ public static $anTable = array(
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ );
+
+ //----------------------------------------------------------------------
+ public static function lookAnTable($c)
+ {
+ return (($c > 127)?-1:self::$anTable[$c]);
+ }
+
+ //----------------------------------------------------------------------
+ public static function checkModeAn($size, $data)
+ {
+ for($i=0; $i<$size; $i++) {
+ if (self::lookAnTable(ord($data[$i])) == -1) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ public static function estimateBitsModeAn($size)
+ {
+ $w = (int)($size / 2);
+ $bits = $w * 11;
+
+ if($size & 1) {
+ $bits += 6;
+ }
+
+ return $bits;
+ }
+
+ //----------------------------------------------------------------------
+ public static function estimateBitsMode8($size)
+ {
+ return $size * 8;
+ }
+
+ //----------------------------------------------------------------------
+ public function estimateBitsModeKanji($size)
+ {
+ return (int)(($size / 2) * 13);
+ }
+
+ //----------------------------------------------------------------------
+ public static function checkModeKanji($size, $data)
+ {
+ if($size & 1)
+ return false;
+
+ for($i=0; $i<$size; $i+=2) {
+ $val = (ord($data[$i]) << 8) | ord($data[$i+1]);
+ if( $val < 0x8140
+ || ($val > 0x9ffc && $val < 0xe040)
+ || $val > 0xebbf) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /***********************************************************************
+ * Validation
+ **********************************************************************/
+
+ public static function check($mode, $size, $data)
+ {
+ if($size <= 0)
+ return false;
+
+ switch($mode) {
+ case Constants::QR_MODE_NUM: return self::checkModeNum($size, $data); break;
+ case Constants::QR_MODE_AN: return self::checkModeAn($size, $data); break;
+ case Constants::QR_MODE_KANJI: return self::checkModeKanji($size, $data); break;
+ case Constants::QR_MODE_8: return true; break;
+ case Constants::QR_MODE_STRUCTURE: return true; break;
+
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+
+ //----------------------------------------------------------------------
+ public function estimateBitStreamSize($version)
+ {
+ $bits = 0;
+
+ foreach($this->items as $item) {
+ $bits += $item->estimateBitStreamSizeOfEntry($version);
+ }
+
+ return $bits;
+ }
+
+ //----------------------------------------------------------------------
+ public function estimateVersion()
+ {
+ $version = 0;
+ $prev = 0;
+ do {
+ $prev = $version;
+ $bits = $this->estimateBitStreamSize($prev);
+ $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
+ if ($version < 0) {
+ return -1;
+ }
+ } while ($version > $prev);
+
+ return $version;
+ }
+
+ //----------------------------------------------------------------------
+ public static function lengthOfCode($mode, $version, $bits)
+ {
+ $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
+ switch($mode) {
+ case Constants::QR_MODE_NUM:
+ $chunks = (int)($payload / 10);
+ $remain = $payload - $chunks * 10;
+ $size = $chunks * 3;
+ if($remain >= 7) {
+ $size += 2;
+ } else if($remain >= 4) {
+ $size += 1;
+ }
+ break;
+ case Constants::QR_MODE_AN:
+ $chunks = (int)($payload / 11);
+ $remain = $payload - $chunks * 11;
+ $size = $chunks * 2;
+ if($remain >= 6)
+ $size++;
+ break;
+ case Constants::QR_MODE_8:
+ $size = (int)($payload / 8);
+ break;
+ case Constants::QR_MODE_KANJI:
+ $size = (int)(($payload / 13) * 2);
+ break;
+ case Constants::QR_MODE_STRUCTURE:
+ $size = (int)($payload / 8);
+ break;
+ default:
+ $size = 0;
+ break;
+ }
+
+ $maxsize = QRspec::maximumWords($mode, $version);
+ if($size < 0) $size = 0;
+ if($size > $maxsize) $size = $maxsize;
+
+ return $size;
+ }
+
+ //----------------------------------------------------------------------
+ public function createBitStream()
+ {
+ $total = 0;
+
+ foreach($this->items as $item) {
+ $bits = $item->encodeBitStream($this->version);
+
+ if($bits < 0)
+ return -1;
+
+ $total += $bits;
+ }
+
+ return $total;
+ }
+
+ //----------------------------------------------------------------------
+ public function convertData()
+ {
+ $ver = $this->estimateVersion();
+ if($ver > $this->getVersion()) {
+ $this->setVersion($ver);
+ }
+
+ for(;;) {
+ $bits = $this->createBitStream();
+
+ if($bits < 0)
+ return -1;
+
+ $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
+ if($ver < 0) {
+ throw new Exception('WRONG VERSION');
+ return -1;
+ } else if($ver > $this->getVersion()) {
+ $this->setVersion($ver);
+ } else {
+ break;
+ }
+ }
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function appendPaddingBit(&$bstream)
+ {
+ $bits = $bstream->size();
+ $maxwords = QRspec::getDataLength($this->version, $this->level);
+ $maxbits = $maxwords * 8;
+
+ if ($maxbits == $bits) {
+ return 0;
+ }
+
+ if ($maxbits - $bits < 5) {
+ return $bstream->appendNum($maxbits - $bits, 0);
+ }
+
+ $bits += 4;
+ $words = (int)(($bits + 7) / 8);
+
+ $padding = new QRbitstream();
+ $ret = $padding->appendNum($words * 8 - $bits + 4, 0);
+
+ if($ret < 0)
+ return $ret;
+
+ $padlen = $maxwords - $words;
+
+ if($padlen > 0) {
+
+ $padbuf = array();
+ for($i=0; $i<$padlen; $i++) {
+ $padbuf[$i] = ($i&1)?0x11:0xec;
+ }
+
+ $ret = $padding->appendBytes($padlen, $padbuf);
+
+ if($ret < 0)
+ return $ret;
+
+ }
+
+ $ret = $bstream->append($padding);
+
+ return $ret;
+ }
+
+ //----------------------------------------------------------------------
+ public function mergeBitStream()
+ {
+ if($this->convertData() < 0) {
+ return null;
+ }
+
+ $bstream = new QRbitstream();
+
+ foreach($this->items as $item) {
+ $ret = $bstream->append($item->bstream);
+ if($ret < 0) {
+ return null;
+ }
+ }
+
+ return $bstream;
+ }
+
+ //----------------------------------------------------------------------
+ public function getBitStream()
+ {
+
+ $bstream = $this->mergeBitStream();
+
+ if($bstream == null) {
+ return null;
+ }
+
+ $ret = $this->appendPaddingBit($bstream);
+ if($ret < 0) {
+ return null;
+ }
+
+ return $bstream;
+ }
+
+ //----------------------------------------------------------------------
+ public function getByteStream()
+ {
+ $bstream = $this->getBitStream();
+ if($bstream == null) {
+ return null;
+ }
+
+ return $bstream->toByte();
+ }
+}
+
+
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php
new file mode 100644
index 00000000..1e5eb18d
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php
@@ -0,0 +1,246 @@
+mode = $mode;
+ $this->size = $size;
+ $this->data = $setData;
+ $this->bstream = $bstream;
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeModeNum($version)
+ {
+ try {
+
+ $words = (int)($this->size / 3);
+ $bs = new QRbitstream();
+
+ $val = 0x1;
+ $bs->appendNum(4, $val);
+ $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_NUM, $version), $this->size);
+
+ for($i=0; $i<$words; $i++) {
+ $val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
+ $val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
+ $val += (ord($this->data[$i*3+2]) - ord('0'));
+ $bs->appendNum(10, $val);
+ }
+
+ if($this->size - $words * 3 == 1) {
+ $val = ord($this->data[$words*3]) - ord('0');
+ $bs->appendNum(4, $val);
+ } else if($this->size - $words * 3 == 2) {
+ $val = (ord($this->data[$words*3 ]) - ord('0')) * 10;
+ $val += (ord($this->data[$words*3+1]) - ord('0'));
+ $bs->appendNum(7, $val);
+ }
+
+ $this->bstream = $bs;
+ return 0;
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeModeAn($version)
+ {
+ try {
+ $words = (int)($this->size / 2);
+ $bs = new QRbitstream();
+
+ $bs->appendNum(4, 0x02);
+ $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_AN, $version), $this->size);
+
+ for($i=0; $i<$words; $i++) {
+ $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
+ $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
+
+ $bs->appendNum(11, $val);
+ }
+
+ if($this->size & 1) {
+ $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
+ $bs->appendNum(6, $val);
+ }
+
+ $this->bstream = $bs;
+ return 0;
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeMode8($version)
+ {
+ try {
+ $bs = new QRbitstream();
+
+ $bs->appendNum(4, 0x4);
+ $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_8, $version), $this->size);
+
+ for($i=0; $i<$this->size; $i++) {
+ $bs->appendNum(8, ord($this->data[$i]));
+ }
+
+ $this->bstream = $bs;
+ return 0;
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeModeKanji($version)
+ {
+ try {
+
+ $bs = new QRbitstream();
+
+ $bs->appendNum(4, 0x8);
+ $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_KANJI, $version), (int)($this->size / 2));
+
+ for($i=0; $i<$this->size; $i+=2) {
+ $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
+ if($val <= 0x9ffc) {
+ $val -= 0x8140;
+ } else {
+ $val -= 0xc140;
+ }
+
+ $h = ($val >> 8) * 0xc0;
+ $val = ($val & 0xff) + $h;
+
+ $bs->appendNum(13, $val);
+ }
+
+ $this->bstream = $bs;
+ return 0;
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeModeStructure()
+ {
+ try {
+ $bs = new QRbitstream();
+
+ $bs->appendNum(4, 0x03);
+ $bs->appendNum(4, ord($this->data[1]) - 1);
+ $bs->appendNum(4, ord($this->data[0]) - 1);
+ $bs->appendNum(8, ord($this->data[2]));
+
+ $this->bstream = $bs;
+ return 0;
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function estimateBitStreamSizeOfEntry($version)
+ {
+ $bits = 0;
+
+ if($version == 0)
+ $version = 1;
+
+ switch($this->mode) {
+ case Constants::QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break;
+ case Constants::QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break;
+ case Constants::QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break;
+ case Constants::QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
+ case Constants::QR_MODE_STRUCTURE: return Constants::STRUCTURE_HEADER_BITS;
+ default:
+ return 0;
+ }
+
+ $l = QRspec::lengthIndicator($this->mode, $version);
+ $m = 1 << $l;
+ $num = (int)(($this->size + $m - 1) / $m);
+
+ $bits += $num * (4 + $l);
+
+ return $bits;
+ }
+
+ //----------------------------------------------------------------------
+ public function encodeBitStream($version)
+ {
+ try {
+
+ unset($this->bstream);
+ $words = QRspec::maximumWords($this->mode, $version);
+
+ if($this->size > $words) {
+
+ $st1 = new QRinputItem($this->mode, $words, $this->data);
+ $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
+
+ $st1->encodeBitStream($version);
+ $st2->encodeBitStream($version);
+
+ $this->bstream = new QRbitstream();
+ $this->bstream->append($st1->bstream);
+ $this->bstream->append($st2->bstream);
+
+ unset($st1);
+ unset($st2);
+
+ } else {
+
+ $ret = 0;
+
+ switch($this->mode) {
+ case Constants::QR_MODE_NUM: $ret = $this->encodeModeNum($version); break;
+ case Constants::QR_MODE_AN: $ret = $this->encodeModeAn($version); break;
+ case Constants::QR_MODE_8: $ret = $this->encodeMode8($version); break;
+ case Constants::QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
+ case Constants::QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break;
+
+ default:
+ break;
+ }
+
+ if($ret < 0)
+ return -1;
+ }
+
+ return $this->bstream->size();
+
+ } catch (Exception $e) {
+ return -1;
+ }
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php
new file mode 100755
index 00000000..2be76f47
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php
@@ -0,0 +1,325 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRmask {
+
+ public $runLength = array();
+
+ //----------------------------------------------------------------------
+ public function __construct()
+ {
+ $this->runLength = array_fill(0, Constants::QRSPEC_WIDTH_MAX + 1, 0);
+ }
+
+ //----------------------------------------------------------------------
+ public function writeFormatInformation($width, &$frame, $mask, $level)
+ {
+ $blacks = 0;
+ $format = QRspec::getFormatInfo($mask, $level);
+
+ for($i=0; $i<8; $i++) {
+ if($format & 1) {
+ $blacks += 2;
+ $v = 0x85;
+ } else {
+ $v = 0x84;
+ }
+
+ $frame[8][$width - 1 - $i] = chr($v);
+ if($i < 6) {
+ $frame[$i][8] = chr($v);
+ } else {
+ $frame[$i + 1][8] = chr($v);
+ }
+ $format = $format >> 1;
+ }
+
+ for($i=0; $i<7; $i++) {
+ if($format & 1) {
+ $blacks += 2;
+ $v = 0x85;
+ } else {
+ $v = 0x84;
+ }
+
+ $frame[$width - 7 + $i][8] = chr($v);
+ if($i == 0) {
+ $frame[8][7] = chr($v);
+ } else {
+ $frame[8][6 - $i] = chr($v);
+ }
+
+ $format = $format >> 1;
+ }
+
+ return $blacks;
+ }
+
+ //----------------------------------------------------------------------
+ public function mask0($x, $y) { return ($x+$y)&1; }
+ public function mask1($x, $y) { return ($y&1); }
+ public function mask2($x, $y) { return ($x%3); }
+ public function mask3($x, $y) { return ($x+$y)%3; }
+ public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
+ public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
+ public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
+ public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
+
+ //----------------------------------------------------------------------
+ private function generateMaskNo($maskNo, $width, $frame)
+ {
+ $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
+
+ for($y=0; $y<$width; $y++) {
+ for($x=0; $x<$width; $x++) {
+ if(ord($frame[$y][$x]) & 0x80) {
+ $bitMask[$y][$x] = 0;
+ } else {
+ $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
+ $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
+ }
+
+ }
+ }
+
+ return $bitMask;
+ }
+
+ //----------------------------------------------------------------------
+ public static function serial($bitFrame)
+ {
+ $codeArr = array();
+
+ foreach ($bitFrame as $line)
+ $codeArr[] = join('', $line);
+
+ return gzcompress(join("\n", $codeArr), 9);
+ }
+
+ //----------------------------------------------------------------------
+ public static function unserial($code)
+ {
+ $codeArr = array();
+
+ $codeLines = explode("\n", gzuncompress($code));
+ foreach ($codeLines as $line)
+ $codeArr[] = str_split($line);
+
+ return $codeArr;
+ }
+
+ //----------------------------------------------------------------------
+ public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
+ {
+ $b = 0;
+ $bitMask = array();
+
+ $fileName = Constants::QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
+
+ if (Constants::QR_CACHEABLE) {
+ if (file_exists($fileName)) {
+ $bitMask = self::unserial(file_get_contents($fileName));
+ } else {
+ $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
+ if (!file_exists(Constants::QR_CACHE_DIR.'mask_'.$maskNo))
+ mkdir(Constants::QR_CACHE_DIR.'mask_'.$maskNo);
+ file_put_contents($fileName, self::serial($bitMask));
+ }
+ } else {
+ $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
+ }
+
+ if ($maskGenOnly)
+ return;
+
+ $d = $s;
+
+ for($y=0; $y<$width; $y++) {
+ for($x=0; $x<$width; $x++) {
+ if($bitMask[$y][$x] == 1) {
+ $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
+ }
+ $b += (int)(ord($d[$y][$x]) & 1);
+ }
+ }
+
+ return $b;
+ }
+
+ //----------------------------------------------------------------------
+ public function makeMask($width, $frame, $maskNo, $level)
+ {
+ $masked = array_fill(0, $width, str_repeat("\0", $width));
+ $this->makeMaskNo($maskNo, $width, $frame, $masked);
+ $this->writeFormatInformation($width, $masked, $maskNo, $level);
+
+ return $masked;
+ }
+
+ //----------------------------------------------------------------------
+ public function calcN1N3($length)
+ {
+ $demerit = 0;
+
+ for($i=0; $i<$length; $i++) {
+
+ if($this->runLength[$i] >= 5) {
+ $demerit += (Constants::N1 + ($this->runLength[$i] - 5));
+ }
+ if($i & 1) {
+ if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
+ $fact = (int)($this->runLength[$i] / 3);
+ if(($this->runLength[$i-2] == $fact) &&
+ ($this->runLength[$i-1] == $fact) &&
+ ($this->runLength[$i+1] == $fact) &&
+ ($this->runLength[$i+2] == $fact)) {
+ if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
+ $demerit += Constants::N3;
+ } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
+ $demerit += Constants::N3;
+ }
+ }
+ }
+ }
+ }
+ return $demerit;
+ }
+
+ //----------------------------------------------------------------------
+ public function evaluateSymbol($width, $frame)
+ {
+ $head = 0;
+ $demerit = 0;
+
+ for($y=0; $y<$width; $y++) {
+ $head = 0;
+ $this->runLength[0] = 1;
+
+ $frameY = $frame[$y];
+
+ if ($y>0)
+ $frameYM = $frame[$y-1];
+
+ for($x=0; $x<$width; $x++) {
+ if(($x > 0) && ($y > 0)) {
+ $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
+ $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
+
+ if(($b22 | ($w22 ^ 1))&1) {
+ $demerit += Constants::N2;
+ }
+ }
+ if(($x == 0) && (ord($frameY[$x]) & 1)) {
+ $this->runLength[0] = -1;
+ $head = 1;
+ $this->runLength[$head] = 1;
+ } else if($x > 0) {
+ if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
+ $head++;
+ $this->runLength[$head] = 1;
+ } else {
+ $this->runLength[$head]++;
+ }
+ }
+ }
+
+ $demerit += $this->calcN1N3($head+1);
+ }
+
+ for($x=0; $x<$width; $x++) {
+ $head = 0;
+ $this->runLength[0] = 1;
+
+ for($y=0; $y<$width; $y++) {
+ if($y == 0 && (ord($frame[$y][$x]) & 1)) {
+ $this->runLength[0] = -1;
+ $head = 1;
+ $this->runLength[$head] = 1;
+ } else if($y > 0) {
+ if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
+ $head++;
+ $this->runLength[$head] = 1;
+ } else {
+ $this->runLength[$head]++;
+ }
+ }
+ }
+
+ $demerit += $this->calcN1N3($head+1);
+ }
+
+ return $demerit;
+ }
+
+
+ //----------------------------------------------------------------------
+ public function mask($width, $frame, $level)
+ {
+ $minDemerit = PHP_INT_MAX;
+ $bestMaskNum = 0;
+ $bestMask = array();
+
+ $checked_masks = array(0,1,2,3,4,5,6,7);
+
+ if (Constants::QR_FIND_FROM_RANDOM !== false) {
+
+ $howManuOut = 8-(Constants::QR_FIND_FROM_RANDOM % 9);
+ for ($i = 0; $i < $howManuOut; $i++) {
+ $remPos = rand (0, count($checked_masks)-1);
+ unset($checked_masks[$remPos]);
+ $checked_masks = array_values($checked_masks);
+ }
+
+ }
+
+ $bestMask = $frame;
+
+ foreach($checked_masks as $i) {
+ $mask = array_fill(0, $width, str_repeat("\0", $width));
+
+ $demerit = 0;
+ $blacks = 0;
+ $blacks = $this->makeMaskNo($i, $width, $frame, $mask);
+ $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
+ $blacks = (int)(100 * $blacks / ($width * $width));
+ $demerit = (int)((int)(abs($blacks - 50) / 5) * Constants::N4);
+ $demerit += $this->evaluateSymbol($width, $mask);
+
+ if($demerit < $minDemerit) {
+ $minDemerit = $demerit;
+ $bestMask = $mask;
+ $bestMaskNum = $i;
+ }
+ }
+
+ return $bestMask;
+ }
+
+ //----------------------------------------------------------------------
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php
new file mode 100644
index 00000000..25eae7c8
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php
@@ -0,0 +1,117 @@
+datacode = $input->getByteStream();
+ if(is_null($this->datacode)) {
+ throw new Exception('null input string');
+ }
+
+ QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
+
+ $this->version = $input->getVersion();
+ $this->b1 = QRspec::rsBlockNum1($spec);
+ $this->dataLength = QRspec::rsDataLength($spec);
+ $this->eccLength = QRspec::rsEccLength($spec);
+ $this->ecccode = array_fill(0, $this->eccLength, 0);
+ $this->blocks = QRspec::rsBlockNum($spec);
+
+ $ret = $this->init($spec);
+ if($ret < 0) {
+ throw new Exception('block alloc error');
+ return null;
+ }
+
+ $this->count = 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function init(array $spec)
+ {
+ $dl = QRspec::rsDataCodes1($spec);
+ $el = QRspec::rsEccCodes1($spec);
+ $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
+
+
+ $blockNo = 0;
+ $dataPos = 0;
+ $eccPos = 0;
+ for($i=0; $iecccode,$eccPos);
+ $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
+ $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
+
+ $dataPos += $dl;
+ $eccPos += $el;
+ $blockNo++;
+ }
+
+ if(QRspec::rsBlockNum2($spec) == 0)
+ return 0;
+
+ $dl = QRspec::rsDataCodes2($spec);
+ $el = QRspec::rsEccCodes2($spec);
+ $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
+
+ if($rs == NULL) return -1;
+
+ for($i=0; $iecccode,$eccPos);
+ $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
+ $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
+
+ $dataPos += $dl;
+ $eccPos += $el;
+ $blockNo++;
+ }
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ public function getCode()
+ {
+ $ret = null;
+
+ if($this->count < $this->dataLength) {
+ $row = $this->count % $this->blocks;
+ $col = $this->count / $this->blocks;
+ if($col >= $this->rsblocks[0]->dataLength) {
+ $row += $this->b1;
+ }
+ $ret = $this->rsblocks[$row]->data[$col];
+ } else if($this->count < $this->dataLength + $this->eccLength) {
+ $row = ($this->count - $this->dataLength) % $this->blocks;
+ $col = ($this->count - $this->dataLength) / $this->blocks;
+ $ret = $this->rsblocks[$row]->ecc[$col];
+ } else {
+ return 0;
+ }
+ $this->count++;
+
+ return $ret;
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php
new file mode 100755
index 00000000..66f0d5e7
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php
@@ -0,0 +1,56 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRrs {
+
+ public static $items = array();
+
+ //----------------------------------------------------------------------
+ public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
+ {
+ foreach(self::$items as $rs) {
+ if($rs->pad != $pad) continue;
+ if($rs->nroots != $nroots) continue;
+ if($rs->mm != $symsize) continue;
+ if($rs->gfpoly != $gfpoly) continue;
+ if($rs->fcr != $fcr) continue;
+ if($rs->prim != $prim) continue;
+
+ return $rs;
+ }
+
+ $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
+ array_unshift(self::$items, $rs);
+
+ return $rs;
+ }
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php
new file mode 100644
index 00000000..ce63a8c3
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php
@@ -0,0 +1,162 @@
+= $this->nn) {
+ $x -= $this->nn;
+ $x = ($x >> $this->mm) + ($x & $this->nn);
+ }
+
+ return $x;
+ }
+
+ //----------------------------------------------------------------------
+ public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
+ {
+ // Common code for intializing a Reed-Solomon control block (char or int symbols)
+ // Copyright 2004 Phil Karn, KA9Q
+ // May be used under the terms of the GNU Lesser General Public License (LGPL)
+
+ $rs = null;
+
+ // Check parameter ranges
+ if($symsize < 0 || $symsize > 8) return $rs;
+ if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
+ if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
+ if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
+ if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
+
+ $rs = new QRrsItem();
+ $rs->mm = $symsize;
+ $rs->nn = (1<<$symsize)-1;
+ $rs->pad = $pad;
+
+ $rs->alpha_to = array_fill(0, $rs->nn+1, 0);
+ $rs->index_of = array_fill(0, $rs->nn+1, 0);
+
+ // PHP style macro replacement ;)
+ $NN =& $rs->nn;
+ $A0 =& $NN;
+
+ // Generate Galois field lookup tables
+ $rs->index_of[0] = $A0; // log(zero) = -inf
+ $rs->alpha_to[$A0] = 0; // alpha**-inf = 0
+ $sr = 1;
+
+ for($i=0; $i<$rs->nn; $i++) {
+ $rs->index_of[$sr] = $i;
+ $rs->alpha_to[$i] = $sr;
+ $sr <<= 1;
+ if($sr & (1<<$symsize)) {
+ $sr ^= $gfpoly;
+ }
+ $sr &= $rs->nn;
+ }
+
+ if($sr != 1){
+ // field generator polynomial is not primitive!
+ $rs = NULL;
+ return $rs;
+ }
+
+ /* Form RS code generator polynomial from its roots */
+ $rs->genpoly = array_fill(0, $nroots+1, 0);
+
+ $rs->fcr = $fcr;
+ $rs->prim = $prim;
+ $rs->nroots = $nroots;
+ $rs->gfpoly = $gfpoly;
+
+ /* Find prim-th root of 1, used in decoding */
+ for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
+ ; // intentional empty-body loop!
+
+ $rs->iprim = (int)($iprim / $prim);
+ $rs->genpoly[0] = 1;
+
+ for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
+ $rs->genpoly[$i+1] = 1;
+
+ // Multiply rs->genpoly[] by @**(root + x)
+ for ($j = $i; $j > 0; $j--) {
+ if ($rs->genpoly[$j] != 0) {
+ $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
+ } else {
+ $rs->genpoly[$j] = $rs->genpoly[$j-1];
+ }
+ }
+ // rs->genpoly[0] can never be zero
+ $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
+ }
+
+ // convert rs->genpoly[] to index form for quicker encoding
+ for ($i = 0; $i <= $nroots; $i++)
+ $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
+
+ return $rs;
+ }
+
+ //----------------------------------------------------------------------
+ public function encode_rs_char($data, &$parity)
+ {
+ $MM =& $this->mm;
+ $NN =& $this->nn;
+ $ALPHA_TO =& $this->alpha_to;
+ $INDEX_OF =& $this->index_of;
+ $GENPOLY =& $this->genpoly;
+ $NROOTS =& $this->nroots;
+ $FCR =& $this->fcr;
+ $PRIM =& $this->prim;
+ $IPRIM =& $this->iprim;
+ $PAD =& $this->pad;
+ $A0 =& $NN;
+
+ $parity = array_fill(0, $NROOTS, 0);
+
+ for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
+
+ $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
+ if($feedback != $A0) {
+ // feedback term is non-zero
+
+ // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+ // always be for the polynomials constructed by init_rs()
+ $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
+
+ for($j=1;$j<$NROOTS;$j++) {
+ $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
+ }
+ }
+
+ // Shift
+ array_shift($parity);
+ if($feedback != $A0) {
+ array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
+ } else {
+ array_push($parity, 0);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php
new file mode 100644
index 00000000..c1d01f22
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php
@@ -0,0 +1,25 @@
+encode_rs_char($data, $ecc);
+
+ $this->dataLength = $dl;
+ $this->data = $data;
+ $this->eccLength = $el;
+ $this->ecc = $ecc;
+ }
+};
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php
new file mode 100755
index 00000000..d6843260
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php
@@ -0,0 +1,586 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRspec {
+
+ public static $capacity = array(
+ array( 0, 0, 0, array( 0, 0, 0, 0)),
+ array( 21, 26, 0, array( 7, 10, 13, 17)), // 1
+ array( 25, 44, 7, array( 10, 16, 22, 28)),
+ array( 29, 70, 7, array( 15, 26, 36, 44)),
+ array( 33, 100, 7, array( 20, 36, 52, 64)),
+ array( 37, 134, 7, array( 26, 48, 72, 88)), // 5
+ array( 41, 172, 7, array( 36, 64, 96, 112)),
+ array( 45, 196, 0, array( 40, 72, 108, 130)),
+ array( 49, 242, 0, array( 48, 88, 132, 156)),
+ array( 53, 292, 0, array( 60, 110, 160, 192)),
+ array( 57, 346, 0, array( 72, 130, 192, 224)), //10
+ array( 61, 404, 0, array( 80, 150, 224, 264)),
+ array( 65, 466, 0, array( 96, 176, 260, 308)),
+ array( 69, 532, 0, array( 104, 198, 288, 352)),
+ array( 73, 581, 3, array( 120, 216, 320, 384)),
+ array( 77, 655, 3, array( 132, 240, 360, 432)), //15
+ array( 81, 733, 3, array( 144, 280, 408, 480)),
+ array( 85, 815, 3, array( 168, 308, 448, 532)),
+ array( 89, 901, 3, array( 180, 338, 504, 588)),
+ array( 93, 991, 3, array( 196, 364, 546, 650)),
+ array( 97, 1085, 3, array( 224, 416, 600, 700)), //20
+ array(101, 1156, 4, array( 224, 442, 644, 750)),
+ array(105, 1258, 4, array( 252, 476, 690, 816)),
+ array(109, 1364, 4, array( 270, 504, 750, 900)),
+ array(113, 1474, 4, array( 300, 560, 810, 960)),
+ array(117, 1588, 4, array( 312, 588, 870, 1050)), //25
+ array(121, 1706, 4, array( 336, 644, 952, 1110)),
+ array(125, 1828, 4, array( 360, 700, 1020, 1200)),
+ array(129, 1921, 3, array( 390, 728, 1050, 1260)),
+ array(133, 2051, 3, array( 420, 784, 1140, 1350)),
+ array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30
+ array(141, 2323, 3, array( 480, 868, 1290, 1530)),
+ array(145, 2465, 3, array( 510, 924, 1350, 1620)),
+ array(149, 2611, 3, array( 540, 980, 1440, 1710)),
+ array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
+ array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
+ array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
+ array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
+ array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
+ array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
+ array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
+ );
+
+ //----------------------------------------------------------------------
+ public static function getDataLength($version, $level)
+ {
+ return self::$capacity[$version][Constants::QRCAP_WORDS] - self::$capacity[$version][Constants::QRCAP_EC][$level];
+ }
+
+ //----------------------------------------------------------------------
+ public static function getECCLength($version, $level)
+ {
+ return self::$capacity[$version][Constants::QRCAP_EC][$level];
+ }
+
+ //----------------------------------------------------------------------
+ public static function getWidth($version)
+ {
+ return self::$capacity[$version][Constants::QRCAP_WIDTH];
+ }
+
+ //----------------------------------------------------------------------
+ public static function getRemainder($version)
+ {
+ return self::$capacity[$version][Constants::QRCAP_REMINDER];
+ }
+
+ //----------------------------------------------------------------------
+ public static function getMinimumVersion($size, $level)
+ {
+
+ for($i=1; $i<= Constants::QRSPEC_VERSION_MAX; $i++) {
+ $words = self::$capacity[$i][Constants::QRCAP_WORDS] - self::$capacity[$i][Constants::QRCAP_EC][$level];
+ if($words >= $size)
+ return $i;
+ }
+
+ return -1;
+ }
+
+ //######################################################################
+
+ public static $lengthTableBits = array(
+ array(10, 12, 14),
+ array( 9, 11, 13),
+ array( 8, 16, 16),
+ array( 8, 10, 12)
+ );
+
+ //----------------------------------------------------------------------
+ public static function lengthIndicator($mode, $version)
+ {
+ if ($mode == Constants::QR_MODE_STRUCTURE)
+ return 0;
+
+ if ($version <= 9) {
+ $l = 0;
+ } else if ($version <= 26) {
+ $l = 1;
+ } else {
+ $l = 2;
+ }
+
+ return self::$lengthTableBits[$mode][$l];
+ }
+
+ //----------------------------------------------------------------------
+ public static function maximumWords($mode, $version)
+ {
+ if($mode == Constants::QR_MODE_STRUCTURE)
+ return 3;
+
+ if($version <= 9) {
+ $l = 0;
+ } else if($version <= 26) {
+ $l = 1;
+ } else {
+ $l = 2;
+ }
+
+ $bits = self::$lengthTableBits[$mode][$l];
+ $words = (1 << $bits) - 1;
+
+ if($mode == Constants::QR_MODE_KANJI) {
+ $words *= 2; // the number of bytes is required
+ }
+
+ return $words;
+ }
+
+ // Error correction code -----------------------------------------------
+ // Table of the error correction code (Reed-Solomon block)
+ // See Table 12-16 (pp.30-36), JIS X0510:2004.
+
+ public static $eccTable = array(
+ array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
+ array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1
+ array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
+ array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
+ array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
+ array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5
+ array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
+ array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
+ array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
+ array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
+ array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10
+ array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
+ array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
+ array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
+ array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
+ array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15
+ array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
+ array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
+ array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
+ array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
+ array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20
+ array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
+ array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
+ array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
+ array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
+ array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25
+ array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
+ array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
+ array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
+ array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
+ array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
+ array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
+ array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
+ array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
+ array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
+ array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
+ array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
+ array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
+ array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
+ array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
+ array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40
+ );
+
+ //----------------------------------------------------------------------
+ // CACHEABLE!!!
+
+ public static function getEccSpec($version, $level, array &$spec)
+ {
+ if (count($spec) < 5) {
+ $spec = array(0,0,0,0,0);
+ }
+
+ $b1 = self::$eccTable[$version][$level][0];
+ $b2 = self::$eccTable[$version][$level][1];
+ $data = self::getDataLength($version, $level);
+ $ecc = self::getECCLength($version, $level);
+
+ if($b2 == 0) {
+ $spec[0] = $b1;
+ $spec[1] = (int)($data / $b1);
+ $spec[2] = (int)($ecc / $b1);
+ $spec[3] = 0;
+ $spec[4] = 0;
+ } else {
+ $spec[0] = $b1;
+ $spec[1] = (int)($data / ($b1 + $b2));
+ $spec[2] = (int)($ecc / ($b1 + $b2));
+ $spec[3] = $b2;
+ $spec[4] = $spec[1] + 1;
+ }
+ }
+
+ // Alignment pattern ---------------------------------------------------
+
+ // Positions of alignment patterns.
+ // This array includes only the second and the third position of the
+ // alignment patterns. Rest of them can be calculated from the distance
+ // between them.
+
+ // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
+
+ public static $alignmentPattern = array(
+ array( 0, 0),
+ array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5
+ array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
+ array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
+ array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
+ array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
+ array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
+ array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
+ array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
+ );
+
+
+ /** --------------------------------------------------------------------
+ * Put an alignment marker.
+ * @param frame
+ * @param width
+ * @param ox,oy center coordinate of the pattern
+ */
+ public static function putAlignmentMarker(array &$frame, $ox, $oy)
+ {
+ $finder = array(
+ "\xa1\xa1\xa1\xa1\xa1",
+ "\xa1\xa0\xa0\xa0\xa1",
+ "\xa1\xa0\xa1\xa0\xa1",
+ "\xa1\xa0\xa0\xa0\xa1",
+ "\xa1\xa1\xa1\xa1\xa1"
+ );
+
+ $yStart = $oy-2;
+ $xStart = $ox-2;
+
+ for($y=0; $y<5; $y++) {
+ QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public static function putAlignmentPattern($version, &$frame, $width)
+ {
+ if($version < 2)
+ return;
+
+ $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
+ if($d < 0) {
+ $w = 2;
+ } else {
+ $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
+ }
+
+ if($w * $w - 3 == 1) {
+ $x = self::$alignmentPattern[$version][0];
+ $y = self::$alignmentPattern[$version][0];
+ self::putAlignmentMarker($frame, $x, $y);
+ return;
+ }
+
+ $cx = self::$alignmentPattern[$version][0];
+ for($x=1; $x<$w - 1; $x++) {
+ self::putAlignmentMarker($frame, 6, $cx);
+ self::putAlignmentMarker($frame, $cx, 6);
+ $cx += $d;
+ }
+
+ $cy = self::$alignmentPattern[$version][0];
+ for($y=0; $y<$w-1; $y++) {
+ $cx = self::$alignmentPattern[$version][0];
+ for($x=0; $x<$w-1; $x++) {
+ self::putAlignmentMarker($frame, $cx, $cy);
+ $cx += $d;
+ }
+ $cy += $d;
+ }
+ }
+
+ // Version information pattern -----------------------------------------
+
+ // Version information pattern (BCH coded).
+ // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
+
+ // size: [Constants::QRSPEC_VERSION_MAX - 6]
+
+ public static $versionPattern = array(
+ 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
+ 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
+ 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
+ 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
+ 0x27541, 0x28c69
+ );
+
+ //----------------------------------------------------------------------
+ public static function getVersionPattern($version)
+ {
+ if($version < 7 || $version > Constants::QRSPEC_VERSION_MAX)
+ return 0;
+
+ return self::$versionPattern[$version -7];
+ }
+
+ // Format information --------------------------------------------------
+ // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
+
+ public static $formatInfo = array(
+ array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
+ array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
+ array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
+ array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
+ );
+
+ public static function getFormatInfo($mask, $level)
+ {
+ if($mask < 0 || $mask > 7)
+ return 0;
+
+ if($level < 0 || $level > 3)
+ return 0;
+
+ return self::$formatInfo[$level][$mask];
+ }
+
+ // Frame ---------------------------------------------------------------
+ // Cache of initial frames.
+
+ public static $frames = array();
+
+ /** --------------------------------------------------------------------
+ * Put a finder pattern.
+ * @param frame
+ * @param width
+ * @param ox,oy upper-left coordinate of the pattern
+ */
+ public static function putFinderPattern(&$frame, $ox, $oy)
+ {
+ $finder = array(
+ "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
+ "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
+ "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+ "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+ "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
+ "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
+ "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
+ );
+
+ for($y=0; $y<7; $y++) {
+ QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public static function createFrame($version)
+ {
+ $width = self::$capacity[$version][Constants::QRCAP_WIDTH];
+ $frameLine = str_repeat ("\0", $width);
+ $frame = array_fill(0, $width, $frameLine);
+
+ // Finder pattern
+ self::putFinderPattern($frame, 0, 0);
+ self::putFinderPattern($frame, $width - 7, 0);
+ self::putFinderPattern($frame, 0, $width - 7);
+
+ // Separator
+ $yOffset = $width - 7;
+
+ for($y=0; $y<7; $y++) {
+ $frame[$y][7] = "\xc0";
+ $frame[$y][$width - 8] = "\xc0";
+ $frame[$yOffset][7] = "\xc0";
+ $yOffset++;
+ }
+
+ $setPattern = str_repeat("\xc0", 8);
+
+ QRstr::set($frame, 0, 7, $setPattern);
+ QRstr::set($frame, $width-8, 7, $setPattern);
+ QRstr::set($frame, 0, $width - 8, $setPattern);
+
+ // Format info
+ $setPattern = str_repeat("\x84", 9);
+ QRstr::set($frame, 0, 8, $setPattern);
+ QRstr::set($frame, $width - 8, 8, $setPattern, 8);
+
+ $yOffset = $width - 8;
+
+ for($y=0; $y<8; $y++,$yOffset++) {
+ $frame[$y][8] = "\x84";
+ $frame[$yOffset][8] = "\x84";
+ }
+
+ // Timing pattern
+
+ for($i=1; $i<$width-15; $i++) {
+ $frame[6][7+$i] = chr(0x90 | ($i & 1));
+ $frame[7+$i][6] = chr(0x90 | ($i & 1));
+ }
+
+ // Alignment pattern
+ self::putAlignmentPattern($version, $frame, $width);
+
+ // Version information
+ if($version >= 7) {
+ $vinf = self::getVersionPattern($version);
+
+ $v = $vinf;
+
+ for($x=0; $x<6; $x++) {
+ for($y=0; $y<3; $y++) {
+ $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
+ $v = $v >> 1;
+ }
+ }
+
+ $v = $vinf;
+ for($y=0; $y<6; $y++) {
+ for($x=0; $x<3; $x++) {
+ $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
+ $v = $v >> 1;
+ }
+ }
+ }
+
+ // and a little bit...
+ $frame[$width - 8][8] = "\x81";
+
+ return $frame;
+ }
+
+ //----------------------------------------------------------------------
+ public static function debug($frame, $binary_mode = false)
+ {
+ if ($binary_mode) {
+
+ foreach ($frame as &$frameLine) {
+ $frameLine = join(' ', explode('0', $frameLine));
+ $frameLine = join('██', explode('1', $frameLine));
+ }
+
+ ?>
+
+
';
+ echo join("
", $frame);
+ echo '
';
+
+ } else {
+
+ foreach ($frame as &$frameLine) {
+ $frameLine = join(' ', explode("\xc0", $frameLine));
+ $frameLine = join('▒', explode("\xc1", $frameLine));
+ $frameLine = join(' ', explode("\xa0", $frameLine));
+ $frameLine = join('▒', explode("\xa1", $frameLine));
+ $frameLine = join('◇', explode("\x84", $frameLine)); //format 0
+ $frameLine = join('◆', explode("\x85", $frameLine)); //format 1
+ $frameLine = join('☢', explode("\x81", $frameLine)); //special bit
+ $frameLine = join(' ', explode("\x90", $frameLine)); //clock 0
+ $frameLine = join('◷', explode("\x91", $frameLine)); //clock 1
+ $frameLine = join(' ', explode("\x88", $frameLine)); //version
+ $frameLine = join('▒', explode("\x89", $frameLine)); //version
+ $frameLine = join('♦', explode("\x01", $frameLine));
+ $frameLine = join('⋅', explode("\0", $frameLine));
+ }
+
+ ?>
+
+ ";
+ echo join("
", $frame);
+ echo "";
+
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public static function serial($frame)
+ {
+ return gzcompress(join("\n", $frame), 9);
+ }
+
+ //----------------------------------------------------------------------
+ public static function unserial($code)
+ {
+ return explode("\n", gzuncompress($code));
+ }
+
+ //----------------------------------------------------------------------
+ public static function newFrame($version)
+ {
+ if($version < 1 || $version > Constants::QRSPEC_VERSION_MAX)
+ return null;
+
+ if(!isset(self::$frames[$version])) {
+
+ $fileName = Constants::QR_CACHE_DIR.'frame_'.$version.'.dat';
+
+ if (Constants::QR_CACHEABLE) {
+ if (file_exists($fileName)) {
+ self::$frames[$version] = self::unserial(file_get_contents($fileName));
+ } else {
+ self::$frames[$version] = self::createFrame($version);
+ file_put_contents($fileName, self::serial(self::$frames[$version]));
+ }
+ } else {
+ self::$frames[$version] = self::createFrame($version);
+ }
+ }
+
+ if(is_null(self::$frames[$version]))
+ return null;
+
+ return self::$frames[$version];
+ }
+
+ //----------------------------------------------------------------------
+ public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; }
+ public static function rsBlockNum1($spec) { return $spec[0]; }
+ public static function rsDataCodes1($spec) { return $spec[1]; }
+ public static function rsEccCodes1($spec) { return $spec[2]; }
+ public static function rsBlockNum2($spec) { return $spec[3]; }
+ public static function rsDataCodes2($spec) { return $spec[4]; }
+ public static function rsEccCodes2($spec) { return $spec[2]; }
+ public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
+ public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; }
+
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php
new file mode 100755
index 00000000..805140a9
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php
@@ -0,0 +1,316 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+use Exception;
+
+class QRsplit {
+
+ public $dataStr = '';
+ public $input;
+ public $modeHint;
+
+ //----------------------------------------------------------------------
+ public function __construct($dataStr, $input, $modeHint)
+ {
+ $this->dataStr = $dataStr;
+ $this->input = $input;
+ $this->modeHint = $modeHint;
+ }
+
+ //----------------------------------------------------------------------
+ public static function isdigitat($str, $pos)
+ {
+ if ($pos >= strlen($str))
+ return false;
+
+ return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
+ }
+
+ //----------------------------------------------------------------------
+ public static function isalnumat($str, $pos)
+ {
+ if ($pos >= strlen($str))
+ return false;
+
+ return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
+ }
+
+ //----------------------------------------------------------------------
+ public function identifyMode($pos)
+ {
+ if ($pos >= strlen($this->dataStr))
+ return Constants::QR_MODE_NUL;
+
+ $c = $this->dataStr[$pos];
+
+ if(self::isdigitat($this->dataStr, $pos)) {
+ return Constants::QR_MODE_NUM;
+ } else if(self::isalnumat($this->dataStr, $pos)) {
+ return Constants::QR_MODE_AN;
+ } else if($this->modeHint == Constants::QR_MODE_KANJI) {
+
+ if ($pos+1 < strlen($this->dataStr))
+ {
+ $d = $this->dataStr[$pos+1];
+ $word = (ord($c) << 8) | ord($d);
+ if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
+ return Constants::QR_MODE_KANJI;
+ }
+ }
+ }
+
+ return Constants::QR_MODE_8;
+ }
+
+ //----------------------------------------------------------------------
+ public function eatNum()
+ {
+ $ln = QRspec::lengthIndicator(Constants::QR_MODE_NUM, $this->input->getVersion());
+
+ $p = 0;
+ while(self::isdigitat($this->dataStr, $p)) {
+ $p++;
+ }
+
+ $run = $p;
+ $mode = $this->identifyMode($p);
+
+ if($mode == Constants::QR_MODE_8) {
+ $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ + QRinput::estimateBitsMode8(1) // + 4 + l8
+ - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
+ if($dif > 0) {
+ return $this->eat8();
+ }
+ }
+ if($mode == Constants::QR_MODE_AN) {
+ $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ + QRinput::estimateBitsModeAn(1) // + 4 + la
+ - QRinput::estimateBitsModeAn($run + 1);// - 4 - la
+ if($dif > 0) {
+ return $this->eatAn();
+ }
+ }
+
+ $ret = $this->input->append(Constants::QR_MODE_NUM, $run, str_split($this->dataStr));
+ if($ret < 0)
+ return -1;
+
+ return $run;
+ }
+
+ //----------------------------------------------------------------------
+ public function eatAn()
+ {
+ $la = QRspec::lengthIndicator(Constants::QR_MODE_AN, $this->input->getVersion());
+ $ln = QRspec::lengthIndicator(Constants::QR_MODE_NUM, $this->input->getVersion());
+
+ $p = 0;
+
+ while(self::isalnumat($this->dataStr, $p)) {
+ if(self::isdigitat($this->dataStr, $p)) {
+ $q = $p;
+ while(self::isdigitat($this->dataStr, $q)) {
+ $q++;
+ }
+
+ $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
+ + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
+ - QRinput::estimateBitsModeAn($q); // - 4 - la
+
+ if($dif < 0) {
+ break;
+ } else {
+ $p = $q;
+ }
+ } else {
+ $p++;
+ }
+ }
+
+ $run = $p;
+
+ if(!self::isalnumat($this->dataStr, $p)) {
+ $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
+ + QRinput::estimateBitsMode8(1) // + 4 + l8
+ - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
+ if($dif > 0) {
+ return $this->eat8();
+ }
+ }
+
+ $ret = $this->input->append(Constants::QR_MODE_AN, $run, str_split($this->dataStr));
+ if($ret < 0)
+ return -1;
+
+ return $run;
+ }
+
+ //----------------------------------------------------------------------
+ public function eatKanji()
+ {
+ $p = 0;
+
+ while($this->identifyMode($p) == Constants::QR_MODE_KANJI) {
+ $p += 2;
+ }
+
+ $ret = $this->input->append(Constants::QR_MODE_KANJI, $p, str_split($this->dataStr));
+ if($ret < 0)
+ return -1;
+
+ return $ret;
+ }
+
+ //----------------------------------------------------------------------
+ public function eat8()
+ {
+ $la = QRspec::lengthIndicator(Constants::QR_MODE_AN, $this->input->getVersion());
+ $ln = QRspec::lengthIndicator(Constants::QR_MODE_NUM, $this->input->getVersion());
+
+ $p = 1;
+ $dataStrLen = strlen($this->dataStr);
+
+ while($p < $dataStrLen) {
+
+ $mode = $this->identifyMode($p);
+ if($mode == Constants::QR_MODE_KANJI) {
+ break;
+ }
+ if($mode == Constants::QR_MODE_NUM) {
+ $q = $p;
+ while(self::isdigitat($this->dataStr, $q)) {
+ $q++;
+ }
+ $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
+ - QRinput::estimateBitsMode8($q); // - 4 - l8
+ if($dif < 0) {
+ break;
+ } else {
+ $p = $q;
+ }
+ } else if($mode == Constants::QR_MODE_AN) {
+ $q = $p;
+ while(self::isalnumat($this->dataStr, $q)) {
+ $q++;
+ }
+ $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
+ - QRinput::estimateBitsMode8($q); // - 4 - l8
+ if($dif < 0) {
+ break;
+ } else {
+ $p = $q;
+ }
+ } else {
+ $p++;
+ }
+ }
+
+ $run = $p;
+ $ret = $this->input->append(Constants::QR_MODE_8, $run, str_split($this->dataStr));
+
+ if($ret < 0)
+ return -1;
+
+ return $run;
+ }
+
+ //----------------------------------------------------------------------
+ public function splitString()
+ {
+ while (strlen($this->dataStr) > 0)
+ {
+ if($this->dataStr == '')
+ return 0;
+
+ $mode = $this->identifyMode(0);
+
+ switch ($mode) {
+ case Constants::QR_MODE_NUM: $length = $this->eatNum(); break;
+ case Constants::QR_MODE_AN: $length = $this->eatAn(); break;
+ case Constants::QR_MODE_KANJI:
+ if ($hint == Constants::QR_MODE_KANJI)
+ $length = $this->eatKanji();
+ else $length = $this->eat8();
+ break;
+ default: $length = $this->eat8(); break;
+
+ }
+
+ if($length == 0) return 0;
+ if($length < 0) return -1;
+
+ $this->dataStr = substr($this->dataStr, $length);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public function toUpper()
+ {
+ $stringLen = strlen($this->dataStr);
+ $p = 0;
+
+ while ($p<$stringLen) {
+ $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
+ if($mode == Constants::QR_MODE_KANJI) {
+ $p += 2;
+ } else {
+ if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
+ $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
+ }
+ $p++;
+ }
+ }
+
+ return $this->dataStr;
+ }
+
+ //----------------------------------------------------------------------
+ public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
+ {
+ if(is_null($string) || $string == '\0' || $string == '') {
+ throw new Exception('empty string!!!');
+ }
+
+ $split = new QRsplit($string, $input, $modeHint);
+
+ if(!$casesensitive)
+ $split->toUpper();
+
+ return $split->splitString();
+ }
+}
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php
new file mode 100644
index 00000000..64c4bd5c
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php
@@ -0,0 +1,35 @@
+
+ *
+ * PHP QR Code is distributed under LGPL 3
+ * Copyright (C) 2010 Dominik Dzienia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRstr {
+ public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
+ $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
+ }
+}
\ No newline at end of file
diff --git a/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php
new file mode 100755
index 00000000..7c75a6e2
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php
@@ -0,0 +1,171 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+namespace PHPQRCode;
+
+class QRtools {
+
+ //----------------------------------------------------------------------
+ public static function binarize($frame)
+ {
+ $len = count($frame);
+ foreach ($frame as &$frameLine) {
+
+ for($i=0; $i<$len; $i++) {
+ $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
+ }
+ }
+
+ return $frame;
+ }
+
+ //----------------------------------------------------------------------
+ public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
+ {
+ $barcode_array = array();
+
+ if (!is_array($mode))
+ $mode = explode(',', $mode);
+
+ $eccLevel = 'L';
+
+ if (count($mode) > 1) {
+ $eccLevel = $mode[1];
+ }
+
+ $qrTab = QRcode::text($code, false, $eccLevel);
+ $size = count($qrTab);
+
+ $barcode_array['num_rows'] = $size;
+ $barcode_array['num_cols'] = $size;
+ $barcode_array['bcode'] = array();
+
+ foreach ($qrTab as $line) {
+ $arrAdd = array();
+ foreach(str_split($line) as $char)
+ $arrAdd[] = ($char=='1')?1:0;
+ $barcode_array['bcode'][] = $arrAdd;
+ }
+
+ return $barcode_array;
+ }
+
+ //----------------------------------------------------------------------
+ public static function clearCache()
+ {
+ self::$frames = array();
+ }
+
+ //----------------------------------------------------------------------
+ public static function buildCache()
+ {
+ QRtools::markTime('before_build_cache');
+
+ $mask = new QRmask();
+ for ($a=1; $a <= Constants::QRSPEC_VERSION_MAX; $a++) {
+ $frame = QRspec::newFrame($a);
+ if (Constants::QR_IMAGE) {
+ $fileName = Constants::QR_CACHE_DIR.'frame_'.$a.'.png';
+ QRimage::png(self::binarize($frame), $fileName, 1, 0);
+ }
+
+ $width = count($frame);
+ $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
+ for ($maskNo=0; $maskNo<8; $maskNo++)
+ $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
+ }
+
+ QRtools::markTime('after_build_cache');
+ }
+
+ //----------------------------------------------------------------------
+ public static function log($outfile, $err)
+ {
+ if (Constants::QR_LOG_DIR !== false) {
+ if ($err != '') {
+ if ($outfile !== false) {
+ file_put_contents(Constants::QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
+ } else {
+ file_put_contents(Constants::QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
+ }
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public static function dumpMask($frame)
+ {
+ $width = count($frame);
+ for($y=0;$y<$width;$y++) {
+ for($x=0;$x<$width;$x++) {
+ echo ord($frame[$y][$x]).',';
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ public static function markTime($markerId)
+ {
+ list($usec, $sec) = explode(" ", microtime());
+ $time = ((float)$usec + (float)$sec);
+
+ if (!isset($GLOBALS['qr_time_bench']))
+ $GLOBALS['qr_time_bench'] = array();
+
+ $GLOBALS['qr_time_bench'][$markerId] = $time;
+ }
+
+ //----------------------------------------------------------------------
+ public static function timeBenchmark()
+ {
+ self::markTime('finish');
+
+ $lastTime = 0;
+ $startTime = 0;
+ $p = 0;
+
+ echo '
+ BENCHMARK |
+ ';
+
+ foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
+ if ($p > 0) {
+ echo 'till '.$markerId.': | '.number_format($thisTime-$lastTime, 6).'s |
';
+ } else {
+ $startTime = $thisTime;
+ }
+
+ $p++;
+ $lastTime = $thisTime;
+ }
+
+ echo '
+ TOTAL: | '.number_format($lastTime-$startTime, 6).'s |
+
+
';
+ }
+
+}
+
+QRtools::markTime('start');
diff --git a/vendor/aferrandini/phpqrcode/readme.md b/vendor/aferrandini/phpqrcode/readme.md
new file mode 100755
index 00000000..e8f2f5ab
--- /dev/null
+++ b/vendor/aferrandini/phpqrcode/readme.md
@@ -0,0 +1,37 @@
+# PHP QRCode Library
+
+To install this library please follow the next steps:
+
+## Install the library using `composer`:
+
+Add the required module to your `composer.json` file:
+
+ {
+ "require": {
+ ...
+ "aferrandini/phpqrcode": "1.0.1"
+ ...
+ }
+ }
+
+Then run the command `composer update`.
+
+
+## Usage
+
+Sample code:
+
+ \PHPQRCode\QRcode::png("Test", "/tmp/qrcode.png", 'L', 4, 2);
+
+This code will generate a PNG file on '/tmp/qrcode.png' with a QRCode that contains the word 'Test'.
+
+## Acknowledgements
+
+This library is an import of PHP QR Code by Dominik Dzienia that you can find at http://phpqrcode.sourceforge.net
+
+Based on C libqrencode library (ver. 3.1.1), Copyright (C) 2006-2010 by Kentaro Fukuchi
+http://megaui.net/fukuchi/works/qrencode/index.en.html
+
+QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other countries.
+
+Reed-Solomon code encoder is written by Phil Karn, KA9Q. Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
diff --git a/vendor/autoload.php b/vendor/autoload.php
new file mode 100644
index 00000000..099ee6b9
--- /dev/null
+++ b/vendor/autoload.php
@@ -0,0 +1,7 @@
+ http://christianriesen.com
+
+Acknowledgements
+----------------
+
+Base32 is mostly based on the work of https://github.com/NTICompass/PHP-Base32
+
diff --git a/vendor/christian-riesen/base32/build.xml b/vendor/christian-riesen/base32/build.xml
new file mode 100644
index 00000000..c06a49f9
--- /dev/null
+++ b/vendor/christian-riesen/base32/build.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/christian-riesen/base32/composer.json b/vendor/christian-riesen/base32/composer.json
new file mode 100644
index 00000000..0c61fbf7
--- /dev/null
+++ b/vendor/christian-riesen/base32/composer.json
@@ -0,0 +1,33 @@
+{
+ "name": "christian-riesen/base32",
+ "type": "library",
+ "description": "Base32 encoder/decoder according to RFC 4648",
+ "keywords": ["base32","encode","decode","rfc4648"],
+ "homepage": "https://github.com/ChristianRiesen/base32",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Christian Riesen",
+ "email": "chris.riesen@gmail.com",
+ "homepage": "http://christianriesen.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*",
+ "satooshi/php-coveralls": "0.*"
+ },
+ "autoload": {
+ "psr-4": {
+ "Base32\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ }
+}
diff --git a/vendor/christian-riesen/base32/phpunit.xml.dist b/vendor/christian-riesen/base32/phpunit.xml.dist
new file mode 100644
index 00000000..3e2def6f
--- /dev/null
+++ b/vendor/christian-riesen/base32/phpunit.xml.dist
@@ -0,0 +1,32 @@
+
+
+
+
+ tests/
+
+
+
+
+
+ src/
+
+
+
+
+
+
+
+
+
diff --git a/vendor/christian-riesen/base32/src/Base32.php b/vendor/christian-riesen/base32/src/Base32.php
new file mode 100644
index 00000000..bf790182
--- /dev/null
+++ b/vendor/christian-riesen/base32/src/Base32.php
@@ -0,0 +1,146 @@
+
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+class Base32
+{
+ /**
+ * Alphabet for encoding and decoding base32
+ *
+ * @var array
+ */
+ private static $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=';
+
+ /**
+ * Creates an array from a binary string into a given chunk size
+ *
+ * @param string $binaryString String to chunk
+ * @param integer $bits Number of bits per chunk
+ * @return array
+ */
+ private static function chunk($binaryString, $bits)
+ {
+ $binaryString = chunk_split($binaryString, $bits, ' ');
+
+ if (substr($binaryString, (strlen($binaryString)) - 1) == ' ') {
+ $binaryString = substr($binaryString, 0, strlen($binaryString)-1);
+ }
+
+ return explode(' ', $binaryString);
+ }
+
+ /**
+ * Encodes into base32
+ *
+ * @param string $string Clear text string
+ * @return string Base32 encoded string
+ */
+ public static function encode($string)
+ {
+ if (strlen($string) == 0) {
+ // Gives an empty string
+
+ return '';
+ }
+
+ // Convert string to binary
+ $binaryString = '';
+
+ foreach (str_split($string) as $s) {
+ // Return each character as an 8-bit binary string
+ $binaryString .= sprintf('%08b', ord($s));
+ }
+
+ // Break into 5-bit chunks, then break that into an array
+ $binaryArray = self::chunk($binaryString, 5);
+
+ // Pad array to be divisible by 8
+ while (count($binaryArray) % 8 !== 0) {
+ $binaryArray[] = null;
+ }
+
+ $base32String = '';
+
+ // Encode in base32
+ foreach ($binaryArray as $bin) {
+ $char = 32;
+
+ if (!is_null($bin)) {
+ // Pad the binary strings
+ $bin = str_pad($bin, 5, 0, STR_PAD_RIGHT);
+ $char = bindec($bin);
+ }
+
+ // Base32 character
+ $base32String .= self::$alphabet[$char];
+ }
+
+ return $base32String;
+ }
+
+ /**
+ * Decodes base32
+ *
+ * @param string $base32String Base32 encoded string
+ * @return string Clear text string
+ */
+ public static function decode($base32String)
+ {
+ // Only work in upper cases
+ $base32String = strtoupper($base32String);
+
+ // Remove anything that is not base32 alphabet
+ $pattern = '/[^A-Z2-7]/';
+
+ $base32String = preg_replace($pattern, '', $base32String);
+
+ if (strlen($base32String) == 0) {
+ // Gives an empty string
+ return '';
+ }
+
+ $base32Array = str_split($base32String);
+
+ $string = '';
+
+ foreach ($base32Array as $str) {
+ $char = strpos(self::$alphabet, $str);
+
+ // Ignore the padding character
+ if ($char !== 32) {
+ $string .= sprintf('%05b', $char);
+ }
+ }
+
+ while (strlen($string) %8 !== 0) {
+ $string = substr($string, 0, strlen($string)-1);
+ }
+
+ $binaryArray = self::chunk($string, 8);
+
+ $realString = '';
+
+ foreach ($binaryArray as $bin) {
+ // Pad each value to 8 bits
+ $bin = str_pad($bin, 8, 0, STR_PAD_RIGHT);
+ // Convert binary strings to ASCII
+ $realString .= chr(bindec($bin));
+ }
+
+ return $realString;
+ }
+}
diff --git a/vendor/christian-riesen/base32/tests/Base32Test.php b/vendor/christian-riesen/base32/tests/Base32Test.php
new file mode 100644
index 00000000..3e5924ce
--- /dev/null
+++ b/vendor/christian-riesen/base32/tests/Base32Test.php
@@ -0,0 +1,51 @@
+decode()
+ *
+ * Testing test vectors according to RFC 4648
+ * http://www.ietf.org/rfc/rfc4648.txt
+ */
+ public function testDecode()
+ {
+ // RFC test vectors say that empty string returns empty string
+ $this->assertEquals('', Base32::decode(''));
+
+ // these strings are taken from the RFC
+ $this->assertEquals('f', Base32::decode('MY======'));
+ $this->assertEquals('fo', Base32::decode('MZXQ===='));
+ $this->assertEquals('foo', Base32::decode('MZXW6==='));
+ $this->assertEquals('foob', Base32::decode('MZXW6YQ='));
+ $this->assertEquals('fooba', Base32::decode('MZXW6YTB'));
+ $this->assertEquals('foobar', Base32::decode('MZXW6YTBOI======'));
+
+ // Decoding a string made up entirely of invalid characters
+ $this->assertEquals('', Base32::decode('8908908908908908'));
+ }
+
+ /**
+ * Encoder tests, reverse of the decodes
+ */
+ public function testEncode()
+ {
+ // RFC test vectors say that empty string returns empty string
+ $this->assertEquals('', Base32::encode(''));
+
+ // these strings are taken from the RFC
+ $this->assertEquals('MY======', Base32::encode('f'));
+ $this->assertEquals('MZXQ====', Base32::encode('fo'));
+ $this->assertEquals('MZXW6===', Base32::encode('foo'));
+ $this->assertEquals('MZXW6YQ=', Base32::encode('foob'));
+ $this->assertEquals('MZXW6YTB', Base32::encode('fooba'));
+ $this->assertEquals('MZXW6YTBOI======', Base32::encode('foobar'));
+ }
+}
diff --git a/vendor/christian-riesen/base32/tests/bootstrap.php b/vendor/christian-riesen/base32/tests/bootstrap.php
new file mode 100644
index 00000000..12bea5b1
--- /dev/null
+++ b/vendor/christian-riesen/base32/tests/bootstrap.php
@@ -0,0 +1,5 @@
+add("Base32", __DIR__);
+$loader->register();
diff --git a/vendor/christian-riesen/otp/.gitignore b/vendor/christian-riesen/otp/.gitignore
new file mode 100644
index 00000000..bab62331
--- /dev/null
+++ b/vendor/christian-riesen/otp/.gitignore
@@ -0,0 +1,5 @@
+.svn
+/.buildpath
+/.project
+/.settings
+
diff --git a/vendor/christian-riesen/otp/.travis.yml b/vendor/christian-riesen/otp/.travis.yml
new file mode 100644
index 00000000..b863299e
--- /dev/null
+++ b/vendor/christian-riesen/otp/.travis.yml
@@ -0,0 +1,11 @@
+language: php
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+script: phpunit
+
diff --git a/vendor/christian-riesen/otp/LICENSE b/vendor/christian-riesen/otp/LICENSE
new file mode 100644
index 00000000..70894746
--- /dev/null
+++ b/vendor/christian-riesen/otp/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) Christian Riesen http://christianriesen.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/christian-riesen/otp/README.md b/vendor/christian-riesen/otp/README.md
new file mode 100644
index 00000000..c979dbbc
--- /dev/null
+++ b/vendor/christian-riesen/otp/README.md
@@ -0,0 +1,105 @@
+One Time Passwords
+==================
+
+[![Build Status](https://secure.travis-ci.org/ChristianRiesen/otp.png)](http://travis-ci.org/ChristianRiesen/otp)
+
+Did you like this? Flattr it:
+
+[![Flattr otp](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/719284/ChristianRiesenotp-on-GitHub)
+
+Installation
+------------
+
+Use [composer](http://getcomposer.org/) and require the library in your `composer.json`
+
+ {
+ "require": {
+ "christian-riesen/otp": "1.*",
+ }
+ }
+
+Usage
+-----
+
+```php
+checkTotp(Base32::decode($secret), $key)) {
+ // Correct key
+ // IMPORTANT! Note this key as being used
+ // so nobody could launch a replay attack.
+ // Cache that for the next minutes and you
+ // should be good.
+} else {
+ // Wrong key
+}
+
+// Just to create a key for display (testing)
+$key = $otp->totp($secret);
+
+```
+
+Sample script in `example` folder. Requires sessions to work (for secret storage).
+
+Class Otp
+---------
+
+Implements hotp according to [RFC4226](https://tools.ietf.org/html/rfc4226) and totp according to [RFC6238](https://tools.ietf.org/html/rfc6238) (only sha1 algorithm). Once you have a secret, you can use it directly in this class to create the passwords themselves (mainly for debugging use) or use the check functions to safely check the validity of the keys. The `checkTotp` function also includes a helper to battle timedrift.
+
+Class GoogleAuthenticator
+-------------------------
+
+Static function class to generate a correct url for the QR code, so you can easy scan it with your device. Google Authenticator is avaiaible as application for iPhone and Android. This removes the burden to create such an app from the developers of websites by using this set of classes.
+
+There are also older open source versions of the Google Authenticator app for both [iPhone](https://github.com/google/google-authenticator) and [Android](https://github.com/google/google-authenticator-android)
+
+This helper class uses the random_int function from PHP7, or the polyfill method from [paragonie/random_compat](https://packagist.org/packages/paragonie/random_compat) if present and falls back on other (less "secure") random generators.
+
+About
+=====
+
+Requirements
+------------
+
+PHP 5.3.x+
+
+Uses [Base32 class](https://github.com/ChristianRiesen/base32).
+
+If you want to run the tests, PHPUnit 3.6 or up is required.
+
+Author
+------
+
+Christian Riesen http://christianriesen.com
+
+Acknowledgements
+----------------
+
+The classes have been inspired by many different places that were talking about otp and Google Authenticator. Thank you all for your help.
+
+Project setup ideas blantently taken from https://github.com/Seldaek/monolog
+
diff --git a/vendor/christian-riesen/otp/composer.json b/vendor/christian-riesen/otp/composer.json
new file mode 100644
index 00000000..94f16c67
--- /dev/null
+++ b/vendor/christian-riesen/otp/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "christian-riesen/otp",
+ "type": "library",
+ "description": "One Time Passwords, hotp and totp according to RFC4226 and RFC6238",
+ "keywords": ["otp","hotp","totp","googleauthenticator","rfc4226","rfc6238"],
+ "homepage": "https://github.com/ChristianRiesen/otp",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Christian Riesen",
+ "email": "chris.riesen@gmail.com",
+ "homepage": "http://christianriesen.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0",
+ "christian-riesen/base32": ">=1.0"
+ },
+ "suggest": {
+ "paragonie/random_compat": "Optional polyfill for a more secure random generator for pre PHP7 versions"
+ },
+ "autoload": {
+ "psr-0": {
+ "Otp": "src"
+ }
+ }
+}
diff --git a/vendor/christian-riesen/otp/example/index.php b/vendor/christian-riesen/otp/example/index.php
new file mode 100644
index 00000000..4da362c5
--- /dev/null
+++ b/vendor/christian-riesen/otp/example/index.php
@@ -0,0 +1,100 @@
+totp(Base32::decode($secret));
+
+$qrCode = GoogleAuthenticator::getQrCodeUrl('totp', 'otpsample@cr', $secret);
+$keyUri = GoogleAuthenticator::getKeyUri('totp', 'otpsample@cr', $secret);
+
+?>
+
+One Time Passwords Example
+
+
+
+One Time Passwords Example
+
+Secret is . This is saved with the users credentials.
+
+
+
+
+QR Code for totp:
+
+
+This QR Code contains the Key URI:
+
+
+
+Current totp would be
+
+
+
+Because of timedrift, you could technically enter a code before or after it
+would actually be used. This form uses the checkTotp function. To test this,
+open this page, wait until the key changes once or twice (not more) on your
+Google Authenticator, then hit submit. Even though the key is "wrong" because of
+small time differences, you can still use it.
+
+
+
+Output:
+
+
+
+checkTotp(Base32::decode($secret), $key)) {
+ echo 'Key correct!';
+ // Add here something that makes note of this key and will not allow
+ // the use of it, for this user for the next 2 minutes. This way you
+ // prevent a replay attack. Otherwise your OTP is missing one of the
+ // key features it can bring in security to your application!
+ } else {
+ echo 'Wrong key!';
+ }
+
+ } else {
+ echo 'Key not the correct size';
+ }
+}
+
+?>
+
+
+
diff --git a/vendor/christian-riesen/otp/phpunit.xml.dist b/vendor/christian-riesen/otp/phpunit.xml.dist
new file mode 100644
index 00000000..7ffc6c63
--- /dev/null
+++ b/vendor/christian-riesen/otp/phpunit.xml.dist
@@ -0,0 +1,15 @@
+
+
+
+
+
+ tests/Otp/
+
+
+
+
+
+ src/Otp/
+
+
+
diff --git a/vendor/christian-riesen/otp/src/Otp/GoogleAuthenticator.php b/vendor/christian-riesen/otp/src/Otp/GoogleAuthenticator.php
new file mode 100644
index 00000000..23e67ff0
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/Otp/GoogleAuthenticator.php
@@ -0,0 +1,189 @@
+
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+class GoogleAuthenticator
+{
+ protected static $allowedTypes = array('hotp', 'totp');
+
+ protected static $height = 200;
+ protected static $width = 200;
+
+ /**
+ * Returns the Key URI
+ *
+ * Format of encoded url is here:
+ * https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
+ * Should be done in a better fashion
+ *
+ * @param string $type totp or hotp
+ * @param string $label Label to display this as to the user
+ * @param string $secret Base32 encoded secret
+ * @param integer $counter Required by hotp, otherwise ignored
+ * @param array $options Optional fields that will be set if present
+ *
+ * @return string Key URI
+ */
+ public static function getKeyUri($type, $label, $secret, $counter = null, $options = array())
+ {
+ // two types only..
+ if (!in_array($type, self::$allowedTypes)) {
+ throw new \InvalidArgumentException('Type has to be of allowed types list');
+ }
+
+ // Label can't be empty
+ $label = trim($label);
+
+ if (strlen($label) < 1) {
+ throw new \InvalidArgumentException('Label has to be one or more printable characters');
+ }
+
+ if (substr_count($label, ':') > 2) {
+ throw new \InvalidArgumentException('Account name contains illegal colon characters');
+ }
+
+ // Secret needs to be here
+ if (strlen($secret) < 1) {
+ throw new \InvalidArgumentException('No secret present');
+ }
+
+ // check for counter on hotp
+ if ($type == 'hotp' && is_null($counter)) {
+ throw new \InvalidArgumentException('Counter required for hotp');
+ }
+
+ // This is the base, these are at least required
+ $otpauth = 'otpauth://' . $type . '/' . str_replace(array(':', ' '), array('%3A', '%20'), $label) . '?secret=' . rawurlencode($secret);
+
+ if ($type == 'hotp' && !is_null($counter)) {
+ $otpauth .= '&counter=' . intval($counter);
+ }
+
+ // Now check the options array
+
+ // algorithm (currently ignored by Authenticator)
+ // Defaults to SHA1
+ if (array_key_exists('algorithm', $options)) {
+ $otpauth .= '&algorithm=' . rawurlencode($options['algorithm']);
+ }
+
+ // digits (currently ignored by Authenticator)
+ // Defaults to 6
+ if (array_key_exists('digits', $options) && intval($options['digits']) !== 6 && intval($options['digits']) !== 8) {
+ throw new \InvalidArgumentException('Digits can only have the values 6 or 8, ' . $options['digits'] . ' given');
+ } elseif (array_key_exists('digits', $options)) {
+ $otpauth .= '&digits=' . intval($options['digits']);
+ }
+
+ // period, only for totp (currently ignored by Authenticator)
+ // Defaults to 30
+ if ($type == 'totp' && array_key_exists('period', $options)) {
+ $otpauth .= '&period=' . rawurlencode($options['period']);
+ }
+
+ // issuer
+ // Defaults to none
+ if (array_key_exists('issuer', $options)) {
+ $otpauth .= '&issuer=' . rawurlencode($options['issuer']);
+ }
+
+ return $otpauth;
+ }
+
+
+ /**
+ * Returns the QR code url
+ *
+ * Format of encoded url is here:
+ * https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
+ * Should be done in a better fashion
+ *
+ * @param string $type totp or hotp
+ * @param string $label Label to display this as to the user
+ * @param string $secret Base32 encoded secret
+ * @param integer $counter Required by hotp, otherwise ignored
+ * @param array $options Optional fields that will be set if present
+ *
+ * @return string URL to the QR code
+ */
+ public static function getQrCodeUrl($type, $label, $secret, $counter = null, $options = array())
+ {
+ // Width and height can be overwritten
+ $width = self::$width;
+
+ if (array_key_exists('width', $options) && is_numeric($options['width'])) {
+ $width = $options['width'];
+ }
+
+ $height = self::$height;
+
+ if (array_key_exists('height', $options) && is_numeric($options['height'])) {
+ $height = $options['height'];
+ }
+
+ $otpauth = self::getKeyUri($type, $label, $secret, $counter, $options);
+
+ $url = 'https://chart.googleapis.com/chart?chs=' . $width . 'x'
+ . $height . '&cht=qr&chld=M|0&chl=' . urlencode($otpauth);
+
+ return $url;
+ }
+
+ /**
+ * Creates a pseudo random Base32 string
+ *
+ * This could decode into anything. It's located here as a small helper
+ * where code that might need base32 usually also needs something like this.
+ *
+ * @param integer $length Exact length of output string
+ * @return string Base32 encoded random
+ */
+ public static function generateRandom($length = 16)
+ {
+ $keys = array_merge(range('A','Z'), range(2,7)); // No padding char
+
+ $string = '';
+
+ for ($i = 0; $i < $length; $i++) {
+ $string .= $keys[self::getRand()];
+ }
+
+ return $string;
+ }
+
+ /**
+ * Get random number
+ *
+ * @return int Random number between 0 and 31 (including)
+ */
+ private static function getRand()
+ {
+ if (function_exists('random_int')) {
+ // Uses either the PHP7 internal function or the polyfill if present
+ return random_int(0, 31);
+ } elseif (function_exists('openssl_random_pseudo_bytes')) {
+ $bytes = openssl_random_pseudo_bytes(2);
+ $number = hexdec(bin2hex($bytes));
+
+ if ($number > 31) {
+ $number = $number % 32;
+ }
+
+ return $number;
+ } else {
+ return mt_rand(0, 31);
+ }
+ }
+}
diff --git a/vendor/christian-riesen/otp/src/Otp/Otp.php b/vendor/christian-riesen/otp/src/Otp/Otp.php
new file mode 100644
index 00000000..7d954870
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/Otp/Otp.php
@@ -0,0 +1,310 @@
+
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+class Otp implements OtpInterface
+{
+ /**
+ * The digits the code can have
+ *
+ * Either 6 or 8.
+ * Authenticator does only support 6.
+ *
+ * @var integer
+ */
+ protected $digits = 6;
+
+ /**
+ * Time in seconds one counter period is long
+ *
+ * @var integer
+ */
+ protected $period = 30;
+
+ /**
+ * Possible algorithms
+ *
+ * @var array
+ */
+ protected $allowedAlgorithms = array('sha1', 'sha256', 'sha512');
+
+ /**
+ * Currently used algorithm
+ *
+ * @var string
+ */
+ protected $algorithm = 'sha1';
+
+ /* (non-PHPdoc)
+ * @see Otp.OtpInterface::hotp()
+ */
+ public function hotp($secret, $counter)
+ {
+ if (!is_numeric($counter)) {
+ throw new \InvalidArgumentException('Counter must be integer');
+ }
+
+ $hash = hash_hmac(
+ $this->algorithm,
+ $this->getBinaryCounter($counter),
+ $secret,
+ true
+ );
+
+ return str_pad($this->truncate($hash), $this->digits, '0', STR_PAD_LEFT);
+ }
+
+ /* (non-PHPdoc)
+ * @see Otp.OtpInterface::totp()
+ */
+ public function totp($secret, $timecounter = null)
+ {
+ if (is_null($timecounter)) {
+ $timecounter = $this->getTimecounter();
+ }
+
+ return $this->hotp($secret, $timecounter);
+ }
+
+ /* (non-PHPdoc)
+ * @see Otp.OtpInterface::checkHotp()
+ */
+ public function checkHotp($secret, $counter, $key)
+ {
+ return $this->safeCompare($this->hotp($secret, $counter), $key);
+ }
+
+ /* (non-PHPdoc)
+ * @see Otp.OtpInterface::checkTotp()
+ */
+ public function checkTotp($secret, $key, $timedrift = 1)
+ {
+ if (!is_numeric($timedrift) || $timedrift < 0) {
+ throw new \InvalidArgumentException('Invalid timedrift supplied');
+ }
+ // Counter comes from time now
+ // Also we check the current timestamp as well as previous and future ones
+ // according to $timerange
+ $timecounter = $this->getTimecounter();
+
+ $start = $timecounter - ($timedrift);
+ $end = $timecounter + ($timedrift);
+
+ // We first try the current, as it is the most likely to work
+ if ($this->safeCompare($this->totp($secret, $timecounter), $key)) {
+ return true;
+ } elseif ($timedrift == 0) {
+ // When timedrift is 0, this is the end of the checks
+ return false;
+ }
+
+ // Well, that didn't work, so try the others
+ for ($t = $start; $t <= $end; $t = $t + 1) {
+ if ($t == $timecounter) {
+ // Already tried that one
+ continue;
+ }
+
+ if ($this->safeCompare($this->totp($secret, $t), $key)) {
+ return true;
+ }
+ }
+
+ // if none worked, then return false
+ return false;
+ }
+
+ /**
+ * Changing the used algorithm for hashing
+ *
+ * Can only be one of the algorithms in the allowedAlgorithms property.
+ *
+ * @param string $algorithm
+ * @throws \InvalidArgumentException
+ * @return \Otp\Otp
+ */
+
+ /*
+ * This has been disabled since it does not bring the expected results
+ * according to the RFC test vectors for sha256 or sha512.
+ * Until that is fixed, the algorithm simply stays at sha1.
+ * Google Authenticator does not support sha256 and sha512 at the moment.
+ *
+
+ public function setAlgorithm($algorithm)
+ {
+ if (!in_array($algorithm, $this->allowedAlgorithms)) {
+ throw new \InvalidArgumentException('Not an allowed algorithm: ' . $algorithm);
+ }
+
+ $this->algorithm = $algorithm;
+
+ return $this;
+ }
+ // */
+
+ /**
+ * Get the algorithms name (lowercase)
+ *
+ * @return string
+ */
+ public function getAlgorithm()
+ {
+ return $this->algorithm;
+ }
+
+ /**
+ * Setting period lenght for totp
+ *
+ * @param integer $period
+ * @throws \InvalidArgumentException
+ * @return \Otp\Otp
+ */
+ public function setPeriod($period)
+ {
+ if (!is_int($period)) {
+ throw new \InvalidArgumentException('Period must be an integer');
+ }
+
+ $this->period = $period;
+
+ return $this;
+ }
+
+ /**
+ * Returns the set period value
+ *
+ * @return integer
+ */
+ public function getPeriod()
+ {
+ return $this->period;
+ }
+
+ /**
+ * Setting number of otp digits
+ *
+ * @param integer $digits Number of digits for the otp (6 or 8)
+ * @throws \InvalidArgumentException
+ * @return \Otp\Otp
+ */
+ public function setDigits($digits)
+ {
+ if (!in_array($digits, array(6, 8))) {
+ throw new \InvalidArgumentException('Digits must be 6 or 8');
+ }
+
+ $this->digits = $digits;
+
+ return $this;
+ }
+
+ /**
+ * Returns number of digits in the otp
+ *
+ * @return integer
+ */
+ public function getDigits()
+ {
+ return $this->digits;
+ }
+
+ /**
+ * Generates a binary counter for hashing
+ *
+ * Warning: Not 2038 safe. Maybe until then pack supports 64bit.
+ *
+ * @param integer $counter Counter in integer form
+ * @return string Binary string
+ */
+ protected function getBinaryCounter($counter)
+ {
+ return pack('N*', 0) . pack('N*', $counter);
+ }
+
+ /**
+ * Generating time counter
+ *
+ * This is the time divided by 30 by default.
+ *
+ * @return integer Time counter
+ */
+ protected function getTimecounter()
+ {
+ return floor(time() / $this->period);
+ }
+
+ /**
+ * Creates the basic number for otp from hash
+ *
+ * This number is left padded with zeros to the required length by the
+ * calling function.
+ *
+ * @param string $hash hmac hash
+ * @return number
+ */
+ protected function truncate($hash)
+ {
+ $offset = ord($hash[19]) & 0xf;
+
+ return (
+ ((ord($hash[$offset+0]) & 0x7f) << 24 ) |
+ ((ord($hash[$offset+1]) & 0xff) << 16 ) |
+ ((ord($hash[$offset+2]) & 0xff) << 8 ) |
+ (ord($hash[$offset+3]) & 0xff)
+ ) % pow(10, $this->digits);
+ }
+
+ /**
+ * Safely compares two inputs
+ *
+ * Assumed inputs are numbers and strings.
+ * Compares them in a time linear manner. No matter how much you guess
+ * correct of the partial content, it does not change the time it takes to
+ * run the entire comparison.
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return boolean
+ */
+ protected function safeCompare($a, $b)
+ {
+ $sha1a = sha1($a);
+ $sha1b = sha1($b);
+
+ // Now the compare is always the same length. Even considering minute
+ // time differences in sha1 creation, all you know is that a longer
+ // input takes longer to hash, not how long the actual compared value is
+ $result = 0;
+
+ for ($i = 0; $i < 40; $i++) {
+ $result |= ord($sha1a[$i]) ^ ord($sha1b[$i]);
+ }
+
+ return $result == 0;
+ }
+}
+
diff --git a/vendor/christian-riesen/otp/src/Otp/OtpInterface.php b/vendor/christian-riesen/otp/src/Otp/OtpInterface.php
new file mode 100644
index 00000000..7ff34f2f
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/Otp/OtpInterface.php
@@ -0,0 +1,65 @@
+
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+interface OtpInterface
+{
+ /**
+ * Returns OTP using the HOTP algorithm
+ *
+ * @param string $secret
+ * @param integer $counter
+ * @return string One Time Password
+ */
+ function hotp($secret, $counter);
+
+ /**
+ * Returns OTP using the TOTP algorithm
+ *
+ * @param string $secret
+ * @param integer $timecounter Optional: Uses current time if null
+ * @return string One Time Password
+ */
+ function totp($secret, $timecounter = null);
+
+ /**
+ * Checks Hotp against a key
+ *
+ * This is a helper function, but is here to ensure the Totp can be checked
+ * in the same manner.
+ *
+ * @param string $secret
+ * @param integer $counter
+ * @param string $key
+ *
+ * @return boolean If key is correct
+ */
+ function checkHotp($secret, $counter, $key);
+
+ /**
+ * Checks Totp agains a key
+ *
+ *
+ * @param string $secret
+ * @param integer $key
+ * @param integer $timedrift
+ *
+ * @return boolean If key is correct
+ */
+ function checkTotp($secret, $key, $timedrift = 1);
+}
diff --git a/vendor/christian-riesen/otp/tests/Otp/GoogleAuthenticatorTest.php b/vendor/christian-riesen/otp/tests/Otp/GoogleAuthenticatorTest.php
new file mode 100644
index 00000000..219bdaa8
--- /dev/null
+++ b/vendor/christian-riesen/otp/tests/Otp/GoogleAuthenticatorTest.php
@@ -0,0 +1,88 @@
+assertEquals(
+ 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Ftotp%2Fuser%40host.com%3Fsecret%3DMEP3EYVA6XNFNVNM',
+ GoogleAuthenticator::getQrCodeUrl('totp', 'user@host.com', $secret)
+ );
+
+ // hotp (include a counter)
+ $this->assertEquals(
+ 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Fhotp%2Fuser%40host.com%3Fsecret%3DMEP3EYVA6XNFNVNM%26counter%3D1234',
+ GoogleAuthenticator::getQrCodeUrl('hotp', 'user@host.com', $secret, 1234)
+ );
+
+ // totp, this time with a parameter for chaning the size of the QR
+ $this->assertEquals(
+ 'https://chart.googleapis.com/chart?chs=300x300&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Ftotp%2Fuser%40host.com%3Fsecret%3DMEP3EYVA6XNFNVNM',
+ GoogleAuthenticator::getQrCodeUrl('totp', 'user@host.com', $secret, null, array('height' => 300, 'width' => 300))
+ );
+
+ }
+
+ /**
+ * Tests getKeyUri
+ */
+ public function testGetKeyUri()
+ {
+ $secret = 'MEP3EYVA6XNFNVNM'; // testing secret
+
+ // Standard totp case
+ $this->assertEquals(
+ 'otpauth://totp/user@host.com?secret=MEP3EYVA6XNFNVNM',
+ GoogleAuthenticator::getKeyUri('totp', 'user@host.com', $secret)
+ );
+
+ // hotp (include a counter)
+ $this->assertEquals(
+ 'otpauth://hotp/user@host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+ GoogleAuthenticator::getKeyUri('hotp', 'user@host.com', $secret, 1234)
+ );
+
+ // totp/hotp with an issuer in the label
+ $this->assertEquals(
+ 'otpauth://hotp/issuer%3Auser@host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+ GoogleAuthenticator::getKeyUri('hotp', 'issuer:user@host.com', $secret, 1234)
+ );
+
+ // totp/hotp with an issuer and spaces in the label
+ $this->assertEquals(
+ 'otpauth://hotp/an%20issuer%3A%20user@host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+ GoogleAuthenticator::getKeyUri('hotp', 'an issuer: user@host.com', $secret, 1234)
+ );
+
+ // totp/hotp with an issuer as option
+ $this->assertEquals(
+ 'otpauth://hotp/an%20issuer%3Auser@host.com?secret=MEP3EYVA6XNFNVNM&counter=1234&issuer=an%20issuer',
+ GoogleAuthenticator::getKeyUri('hotp', 'an issuer:user@host.com', $secret, 1234, array('issuer' => 'an issuer'))
+ );
+ }
+
+ /**
+ * Tests generateRandom
+ */
+ public function testGenerateRandom()
+ {
+ // contains numbers 2-7 and letters A-Z in large letters, 16 chars long
+ $this->assertRegExp('/[2-7A-Z]{16}/', GoogleAuthenticator::generateRandom());
+
+ // Can be told to make a longer secret
+ $this->assertRegExp('/[2-7A-Z]{18}/', GoogleAuthenticator::generateRandom(18));
+ }
+}
diff --git a/vendor/christian-riesen/otp/tests/Otp/OtpTest.php b/vendor/christian-riesen/otp/tests/Otp/OtpTest.php
new file mode 100644
index 00000000..ccfdddab
--- /dev/null
+++ b/vendor/christian-riesen/otp/tests/Otp/OtpTest.php
@@ -0,0 +1,124 @@
+Otp = new Otp();
+
+ }
+
+ /**
+ * Cleans up the environment after running a test.
+ */
+ protected function tearDown()
+ {
+ $this->Otp = null;
+
+ parent::tearDown();
+ }
+
+ /**
+ * Tests Otp->hotp()
+ *
+ * Using test vectors from RFC
+ * https://tools.ietf.org/html/rfc4226
+ */
+ public function testHotpRfc()
+ {
+ $secret = $this->secret;
+
+ $this->assertEquals('755224', $this->Otp->hotp($secret, 0));
+ $this->assertEquals('287082', $this->Otp->hotp($secret, 1));
+ $this->assertEquals('359152', $this->Otp->hotp($secret, 2));
+ $this->assertEquals('969429', $this->Otp->hotp($secret, 3));
+ $this->assertEquals('338314', $this->Otp->hotp($secret, 4));
+ $this->assertEquals('254676', $this->Otp->hotp($secret, 5));
+ $this->assertEquals('287922', $this->Otp->hotp($secret, 6));
+ $this->assertEquals('162583', $this->Otp->hotp($secret, 7));
+ $this->assertEquals('399871', $this->Otp->hotp($secret, 8));
+ $this->assertEquals('520489', $this->Otp->hotp($secret, 9));
+ }
+
+ /**
+ * Tests TOTP general construction
+ *
+ * Still uses the hotp function, but since totp is a bit more special, has
+ * its own tests
+ * Using test vectors from RFC
+ * https://tools.ietf.org/html/rfc6238
+ */
+ public function testTotpRfc()
+ {
+ $secret = $this->secret;
+
+ // Test vectors are in 8 digits
+ $this->Otp->setDigits(8);
+
+ // The time presented in the test vector has to be first divided through 30
+ // to count as the key
+
+ // SHA 1 grouping
+ $this->assertEquals('94287082', $this->Otp->hotp($secret, floor(59/30)), 'sha1 with time 59');
+ $this->assertEquals('07081804', $this->Otp->hotp($secret, floor(1111111109/30)), 'sha1 with time 1111111109');
+ $this->assertEquals('14050471', $this->Otp->hotp($secret, floor(1111111111/30)), 'sha1 with time 1111111111');
+ $this->assertEquals('89005924', $this->Otp->hotp($secret, floor(1234567890/30)), 'sha1 with time 1234567890');
+ $this->assertEquals('69279037', $this->Otp->hotp($secret, floor(2000000000/30)), 'sha1 with time 2000000000');
+ $this->assertEquals('65353130', $this->Otp->hotp($secret, floor(20000000000/30)), 'sha1 with time 20000000000');
+
+ /*
+ The following tests do NOT pass.
+ Once the otp class can deal with these correctly, they can be used again.
+ They are here for completeness test vectors from the RFC.
+
+ // SHA 256 grouping
+ $this->Otp->setAlgorithm('sha256');
+ $this->assertEquals('46119246', $this->Otp->hotp($secret, floor(59/30)), 'sha256 with time 59');
+ $this->assertEquals('07081804', $this->Otp->hotp($secret, floor(1111111109/30)), 'sha256 with time 1111111109');
+ $this->assertEquals('14050471', $this->Otp->hotp($secret, floor(1111111111/30)), 'sha256 with time 1111111111');
+ $this->assertEquals('89005924', $this->Otp->hotp($secret, floor(1234567890/30)), 'sha256 with time 1234567890');
+ $this->assertEquals('69279037', $this->Otp->hotp($secret, floor(2000000000/30)), 'sha256 with time 2000000000');
+ $this->assertEquals('65353130', $this->Otp->hotp($secret, floor(20000000000/30)), 'sha256 with time 20000000000');
+
+ // SHA 512 grouping
+ $this->Otp->setAlgorithm('sha512');
+ $this->assertEquals('90693936', $this->Otp->hotp($secret, floor(59/30)), 'sha512 with time 59');
+ $this->assertEquals('25091201', $this->Otp->hotp($secret, floor(1111111109/30)), 'sha512 with time 1111111109');
+ $this->assertEquals('99943326', $this->Otp->hotp($secret, floor(1111111111/30)), 'sha512 with time 1111111111');
+ $this->assertEquals('93441116', $this->Otp->hotp($secret, floor(1234567890/30)), 'sha512 with time 1234567890');
+ $this->assertEquals('38618901', $this->Otp->hotp($secret, floor(2000000000/30)), 'sha512 with time 2000000000');
+ $this->assertEquals('47863826', $this->Otp->hotp($secret, floor(20000000000/30)), 'sha512 with time 20000000000');
+ */
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage Counter must be integer
+ */
+ public function testHotpInvalidCounter()
+ {
+ $this->Otp->hotp($this->secret, 'a');
+ }
+
+}
diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php
new file mode 100644
index 00000000..2c72175e
--- /dev/null
+++ b/vendor/composer/ClassLoader.php
@@ -0,0 +1,445 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier
+ * @author Jordi Boggiano
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+ private $classMapAuthoritative = false;
+ private $missingClasses = array();
+ private $apcuPrefix;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath.'\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ $length = $this->prefixLengthsPsr4[$first][$search];
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE
new file mode 100644
index 00000000..f27399a0
--- /dev/null
+++ b/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
new file mode 100644
index 00000000..75207dbe
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,901 @@
+ $vendorDir . '/christian-riesen/base32/src/Base32.php',
+ 'Eluceo\\iCal\\Component' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component.php',
+ 'Eluceo\\iCal\\Component\\Alarm' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php',
+ 'Eluceo\\iCal\\Component\\Calendar' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php',
+ 'Eluceo\\iCal\\Component\\Event' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component/Event.php',
+ 'Eluceo\\iCal\\Component\\Timezone' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php',
+ 'Eluceo\\iCal\\Component\\TimezoneRule' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php',
+ 'Eluceo\\iCal\\ParameterBag' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/ParameterBag.php',
+ 'Eluceo\\iCal\\Property' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property.php',
+ 'Eluceo\\iCal\\PropertyBag' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/PropertyBag.php',
+ 'Eluceo\\iCal\\Property\\ArrayValue' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php',
+ 'Eluceo\\iCal\\Property\\DateTimeProperty' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php',
+ 'Eluceo\\iCal\\Property\\DateTimesProperty' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php',
+ 'Eluceo\\iCal\\Property\\Event\\Attendees' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php',
+ 'Eluceo\\iCal\\Property\\Event\\Description' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php',
+ 'Eluceo\\iCal\\Property\\Event\\Organizer' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php',
+ 'Eluceo\\iCal\\Property\\Event\\RecurrenceId' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php',
+ 'Eluceo\\iCal\\Property\\Event\\RecurrenceRule' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php',
+ 'Eluceo\\iCal\\Property\\StringValue' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php',
+ 'Eluceo\\iCal\\Property\\ValueInterface' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php',
+ 'Eluceo\\iCal\\Util\\ComponentUtil' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php',
+ 'Eluceo\\iCal\\Util\\DateUtil' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php',
+ 'Eluceo\\iCal\\Util\\PropertyValueUtil' => $vendorDir . '/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php',
+ 'Gregwar\\Captcha\\CaptchaBuilder' => $vendorDir . '/gregwar/captcha/CaptchaBuilder.php',
+ 'Gregwar\\Captcha\\CaptchaBuilderInterface' => $vendorDir . '/gregwar/captcha/CaptchaBuilderInterface.php',
+ 'Gregwar\\Captcha\\ImageFileHandler' => $vendorDir . '/gregwar/captcha/ImageFileHandler.php',
+ 'Gregwar\\Captcha\\PhraseBuilder' => $vendorDir . '/gregwar/captcha/PhraseBuilder.php',
+ 'Gregwar\\Captcha\\PhraseBuilderInterface' => $vendorDir . '/gregwar/captcha/PhraseBuilderInterface.php',
+ 'JsonRPC\\Client' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Client.php',
+ 'JsonRPC\\Exception\\AccessDeniedException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php',
+ 'JsonRPC\\Exception\\AuthenticationFailureException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/AuthenticationFailureException.php',
+ 'JsonRPC\\Exception\\ConnectionFailureException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ConnectionFailureException.php',
+ 'JsonRPC\\Exception\\InvalidJsonFormatException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonFormatException.php',
+ 'JsonRPC\\Exception\\InvalidJsonRpcFormatException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonRpcFormatException.php',
+ 'JsonRPC\\Exception\\ResponseEncodingFailureException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseEncodingFailureException.php',
+ 'JsonRPC\\Exception\\ResponseException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php',
+ 'JsonRPC\\Exception\\ServerErrorException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php',
+ 'JsonRPC\\HttpClient' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/HttpClient.php',
+ 'JsonRPC\\MiddlewareHandler' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php',
+ 'JsonRPC\\MiddlewareInterface' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php',
+ 'JsonRPC\\ProcedureHandler' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php',
+ 'JsonRPC\\Request\\BatchRequestParser' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php',
+ 'JsonRPC\\Request\\RequestBuilder' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php',
+ 'JsonRPC\\Request\\RequestParser' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php',
+ 'JsonRPC\\Response\\ResponseBuilder' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php',
+ 'JsonRPC\\Response\\ResponseParser' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php',
+ 'JsonRPC\\Server' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Server.php',
+ 'JsonRPC\\Validator\\HostValidator' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php',
+ 'JsonRPC\\Validator\\JsonEncodingValidator' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Validator/JsonEncodingValidator.php',
+ 'JsonRPC\\Validator\\JsonFormatValidator' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Validator/JsonFormatValidator.php',
+ 'JsonRPC\\Validator\\RpcFormatValidator' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Validator/RpcFormatValidator.php',
+ 'JsonRPC\\Validator\\UserValidator' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Validator/UserValidator.php',
+ 'Kanboard\\Action\\Base' => $baseDir . '/app/Action/Base.php',
+ 'Kanboard\\Action\\CommentCreation' => $baseDir . '/app/Action/CommentCreation.php',
+ 'Kanboard\\Action\\CommentCreationMoveTaskColumn' => $baseDir . '/app/Action/CommentCreationMoveTaskColumn.php',
+ 'Kanboard\\Action\\TaskAssignCategoryColor' => $baseDir . '/app/Action/TaskAssignCategoryColor.php',
+ 'Kanboard\\Action\\TaskAssignCategoryLabel' => $baseDir . '/app/Action/TaskAssignCategoryLabel.php',
+ 'Kanboard\\Action\\TaskAssignCategoryLink' => $baseDir . '/app/Action/TaskAssignCategoryLink.php',
+ 'Kanboard\\Action\\TaskAssignColorCategory' => $baseDir . '/app/Action/TaskAssignColorCategory.php',
+ 'Kanboard\\Action\\TaskAssignColorColumn' => $baseDir . '/app/Action/TaskAssignColorColumn.php',
+ 'Kanboard\\Action\\TaskAssignColorLink' => $baseDir . '/app/Action/TaskAssignColorLink.php',
+ 'Kanboard\\Action\\TaskAssignColorOnDueDate' => $baseDir . '/app/Action/TaskAssignColorOnDueDate.php',
+ 'Kanboard\\Action\\TaskAssignColorPriority' => $baseDir . '/app/Action/TaskAssignColorPriority.php',
+ 'Kanboard\\Action\\TaskAssignColorSwimlane' => $baseDir . '/app/Action/TaskAssignColorSwimlane.php',
+ 'Kanboard\\Action\\TaskAssignColorUser' => $baseDir . '/app/Action/TaskAssignColorUser.php',
+ 'Kanboard\\Action\\TaskAssignCreator' => $baseDir . '/app/Action/TaskAssignCreator.php',
+ 'Kanboard\\Action\\TaskAssignCurrentUser' => $baseDir . '/app/Action/TaskAssignCurrentUser.php',
+ 'Kanboard\\Action\\TaskAssignCurrentUserColumn' => $baseDir . '/app/Action/TaskAssignCurrentUserColumn.php',
+ 'Kanboard\\Action\\TaskAssignDueDateOnCreation' => $baseDir . '/app/Action/TaskAssignDueDateOnCreation.php',
+ 'Kanboard\\Action\\TaskAssignPrioritySwimlane' => $baseDir . '/app/Action/TaskAssignPrioritySwimlane.php',
+ 'Kanboard\\Action\\TaskAssignSpecificUser' => $baseDir . '/app/Action/TaskAssignSpecificUser.php',
+ 'Kanboard\\Action\\TaskAssignUser' => $baseDir . '/app/Action/TaskAssignUser.php',
+ 'Kanboard\\Action\\TaskClose' => $baseDir . '/app/Action/TaskClose.php',
+ 'Kanboard\\Action\\TaskCloseColumn' => $baseDir . '/app/Action/TaskCloseColumn.php',
+ 'Kanboard\\Action\\TaskCloseNoActivity' => $baseDir . '/app/Action/TaskCloseNoActivity.php',
+ 'Kanboard\\Action\\TaskCloseNoActivityColumn' => $baseDir . '/app/Action/TaskCloseNoActivityColumn.php',
+ 'Kanboard\\Action\\TaskCloseNotMovedColumn' => $baseDir . '/app/Action/TaskCloseNotMovedColumn.php',
+ 'Kanboard\\Action\\TaskCreation' => $baseDir . '/app/Action/TaskCreation.php',
+ 'Kanboard\\Action\\TaskDuplicateAnotherProject' => $baseDir . '/app/Action/TaskDuplicateAnotherProject.php',
+ 'Kanboard\\Action\\TaskEmail' => $baseDir . '/app/Action/TaskEmail.php',
+ 'Kanboard\\Action\\TaskEmailNoActivity' => $baseDir . '/app/Action/TaskEmailNoActivity.php',
+ 'Kanboard\\Action\\TaskMoveAnotherProject' => $baseDir . '/app/Action/TaskMoveAnotherProject.php',
+ 'Kanboard\\Action\\TaskMoveColumnAssigned' => $baseDir . '/app/Action/TaskMoveColumnAssigned.php',
+ 'Kanboard\\Action\\TaskMoveColumnCategoryChange' => $baseDir . '/app/Action/TaskMoveColumnCategoryChange.php',
+ 'Kanboard\\Action\\TaskMoveColumnClosed' => $baseDir . '/app/Action/TaskMoveColumnClosed.php',
+ 'Kanboard\\Action\\TaskMoveColumnNotMovedPeriod' => $baseDir . '/app/Action/TaskMoveColumnNotMovedPeriod.php',
+ 'Kanboard\\Action\\TaskMoveColumnUnAssigned' => $baseDir . '/app/Action/TaskMoveColumnUnAssigned.php',
+ 'Kanboard\\Action\\TaskOpen' => $baseDir . '/app/Action/TaskOpen.php',
+ 'Kanboard\\Action\\TaskUpdateStartDate' => $baseDir . '/app/Action/TaskUpdateStartDate.php',
+ 'Kanboard\\Analytic\\AverageLeadCycleTimeAnalytic' => $baseDir . '/app/Analytic/AverageLeadCycleTimeAnalytic.php',
+ 'Kanboard\\Analytic\\AverageTimeSpentColumnAnalytic' => $baseDir . '/app/Analytic/AverageTimeSpentColumnAnalytic.php',
+ 'Kanboard\\Analytic\\EstimatedTimeComparisonAnalytic' => $baseDir . '/app/Analytic/EstimatedTimeComparisonAnalytic.php',
+ 'Kanboard\\Analytic\\TaskDistributionAnalytic' => $baseDir . '/app/Analytic/TaskDistributionAnalytic.php',
+ 'Kanboard\\Analytic\\UserDistributionAnalytic' => $baseDir . '/app/Analytic/UserDistributionAnalytic.php',
+ 'Kanboard\\Api\\Authorization\\ActionAuthorization' => $baseDir . '/app/Api/Authorization/ActionAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\CategoryAuthorization' => $baseDir . '/app/Api/Authorization/CategoryAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ColumnAuthorization' => $baseDir . '/app/Api/Authorization/ColumnAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\CommentAuthorization' => $baseDir . '/app/Api/Authorization/CommentAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ProcedureAuthorization' => $baseDir . '/app/Api/Authorization/ProcedureAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ProjectAuthorization' => $baseDir . '/app/Api/Authorization/ProjectAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\SubtaskAuthorization' => $baseDir . '/app/Api/Authorization/SubtaskAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TagAuthorization' => $baseDir . '/app/Api/Authorization/TagAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskAuthorization' => $baseDir . '/app/Api/Authorization/TaskAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskFileAuthorization' => $baseDir . '/app/Api/Authorization/TaskFileAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskLinkAuthorization' => $baseDir . '/app/Api/Authorization/TaskLinkAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\UserAuthorization' => $baseDir . '/app/Api/Authorization/UserAuthorization.php',
+ 'Kanboard\\Api\\Middleware\\AuthenticationMiddleware' => $baseDir . '/app/Api/Middleware/AuthenticationMiddleware.php',
+ 'Kanboard\\Api\\Procedure\\ActionProcedure' => $baseDir . '/app/Api/Procedure/ActionProcedure.php',
+ 'Kanboard\\Api\\Procedure\\AppProcedure' => $baseDir . '/app/Api/Procedure/AppProcedure.php',
+ 'Kanboard\\Api\\Procedure\\BaseProcedure' => $baseDir . '/app/Api/Procedure/BaseProcedure.php',
+ 'Kanboard\\Api\\Procedure\\BoardProcedure' => $baseDir . '/app/Api/Procedure/BoardProcedure.php',
+ 'Kanboard\\Api\\Procedure\\CategoryProcedure' => $baseDir . '/app/Api/Procedure/CategoryProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ColumnProcedure' => $baseDir . '/app/Api/Procedure/ColumnProcedure.php',
+ 'Kanboard\\Api\\Procedure\\CommentProcedure' => $baseDir . '/app/Api/Procedure/CommentProcedure.php',
+ 'Kanboard\\Api\\Procedure\\GroupMemberProcedure' => $baseDir . '/app/Api/Procedure/GroupMemberProcedure.php',
+ 'Kanboard\\Api\\Procedure\\GroupProcedure' => $baseDir . '/app/Api/Procedure/GroupProcedure.php',
+ 'Kanboard\\Api\\Procedure\\LinkProcedure' => $baseDir . '/app/Api/Procedure/LinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\MeProcedure' => $baseDir . '/app/Api/Procedure/MeProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectFileProcedure' => $baseDir . '/app/Api/Procedure/ProjectFileProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectPermissionProcedure' => $baseDir . '/app/Api/Procedure/ProjectPermissionProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectProcedure' => $baseDir . '/app/Api/Procedure/ProjectProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SubtaskProcedure' => $baseDir . '/app/Api/Procedure/SubtaskProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SubtaskTimeTrackingProcedure' => $baseDir . '/app/Api/Procedure/SubtaskTimeTrackingProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SwimlaneProcedure' => $baseDir . '/app/Api/Procedure/SwimlaneProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TagProcedure' => $baseDir . '/app/Api/Procedure/TagProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskExternalLinkProcedure' => $baseDir . '/app/Api/Procedure/TaskExternalLinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskFileProcedure' => $baseDir . '/app/Api/Procedure/TaskFileProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskLinkProcedure' => $baseDir . '/app/Api/Procedure/TaskLinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskMetadataProcedure' => $baseDir . '/app/Api/Procedure/TaskMetadataProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskProcedure' => $baseDir . '/app/Api/Procedure/TaskProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskTagProcedure' => $baseDir . '/app/Api/Procedure/TaskTagProcedure.php',
+ 'Kanboard\\Api\\Procedure\\UserProcedure' => $baseDir . '/app/Api/Procedure/UserProcedure.php',
+ 'Kanboard\\Auth\\ApiAccessTokenAuth' => $baseDir . '/app/Auth/ApiAccessTokenAuth.php',
+ 'Kanboard\\Auth\\DatabaseAuth' => $baseDir . '/app/Auth/DatabaseAuth.php',
+ 'Kanboard\\Auth\\LdapAuth' => $baseDir . '/app/Auth/LdapAuth.php',
+ 'Kanboard\\Auth\\RememberMeAuth' => $baseDir . '/app/Auth/RememberMeAuth.php',
+ 'Kanboard\\Auth\\ReverseProxyAuth' => $baseDir . '/app/Auth/ReverseProxyAuth.php',
+ 'Kanboard\\Auth\\TotpAuth' => $baseDir . '/app/Auth/TotpAuth.php',
+ 'Kanboard\\Console\\BaseCommand' => $baseDir . '/app/Console/BaseCommand.php',
+ 'Kanboard\\Console\\CronjobCommand' => $baseDir . '/app/Console/CronjobCommand.php',
+ 'Kanboard\\Console\\DatabaseMigrationCommand' => $baseDir . '/app/Console/DatabaseMigrationCommand.php',
+ 'Kanboard\\Console\\DatabaseVersionCommand' => $baseDir . '/app/Console/DatabaseVersionCommand.php',
+ 'Kanboard\\Console\\JobCommand' => $baseDir . '/app/Console/JobCommand.php',
+ 'Kanboard\\Console\\LocaleComparatorCommand' => $baseDir . '/app/Console/LocaleComparatorCommand.php',
+ 'Kanboard\\Console\\LocaleSyncCommand' => $baseDir . '/app/Console/LocaleSyncCommand.php',
+ 'Kanboard\\Console\\PluginInstallCommand' => $baseDir . '/app/Console/PluginInstallCommand.php',
+ 'Kanboard\\Console\\PluginUninstallCommand' => $baseDir . '/app/Console/PluginUninstallCommand.php',
+ 'Kanboard\\Console\\PluginUpgradeCommand' => $baseDir . '/app/Console/PluginUpgradeCommand.php',
+ 'Kanboard\\Console\\ProjectDailyColumnStatsExportCommand' => $baseDir . '/app/Console/ProjectDailyColumnStatsExportCommand.php',
+ 'Kanboard\\Console\\ProjectDailyStatsCalculationCommand' => $baseDir . '/app/Console/ProjectDailyStatsCalculationCommand.php',
+ 'Kanboard\\Console\\ResetPasswordCommand' => $baseDir . '/app/Console/ResetPasswordCommand.php',
+ 'Kanboard\\Console\\ResetTwoFactorCommand' => $baseDir . '/app/Console/ResetTwoFactorCommand.php',
+ 'Kanboard\\Console\\SubtaskExportCommand' => $baseDir . '/app/Console/SubtaskExportCommand.php',
+ 'Kanboard\\Console\\TaskExportCommand' => $baseDir . '/app/Console/TaskExportCommand.php',
+ 'Kanboard\\Console\\TaskOverdueNotificationCommand' => $baseDir . '/app/Console/TaskOverdueNotificationCommand.php',
+ 'Kanboard\\Console\\TaskTriggerCommand' => $baseDir . '/app/Console/TaskTriggerCommand.php',
+ 'Kanboard\\Console\\TransitionExportCommand' => $baseDir . '/app/Console/TransitionExportCommand.php',
+ 'Kanboard\\Console\\WorkerCommand' => $baseDir . '/app/Console/WorkerCommand.php',
+ 'Kanboard\\Controller\\ActionController' => $baseDir . '/app/Controller/ActionController.php',
+ 'Kanboard\\Controller\\ActionCreationController' => $baseDir . '/app/Controller/ActionCreationController.php',
+ 'Kanboard\\Controller\\ActivityController' => $baseDir . '/app/Controller/ActivityController.php',
+ 'Kanboard\\Controller\\AnalyticController' => $baseDir . '/app/Controller/AnalyticController.php',
+ 'Kanboard\\Controller\\AppController' => $baseDir . '/app/Controller/AppController.php',
+ 'Kanboard\\Controller\\AuthController' => $baseDir . '/app/Controller/AuthController.php',
+ 'Kanboard\\Controller\\AvatarFileController' => $baseDir . '/app/Controller/AvatarFileController.php',
+ 'Kanboard\\Controller\\BaseController' => $baseDir . '/app/Controller/BaseController.php',
+ 'Kanboard\\Controller\\BoardAjaxController' => $baseDir . '/app/Controller/BoardAjaxController.php',
+ 'Kanboard\\Controller\\BoardPopoverController' => $baseDir . '/app/Controller/BoardPopoverController.php',
+ 'Kanboard\\Controller\\BoardTooltipController' => $baseDir . '/app/Controller/BoardTooltipController.php',
+ 'Kanboard\\Controller\\BoardViewController' => $baseDir . '/app/Controller/BoardViewController.php',
+ 'Kanboard\\Controller\\CaptchaController' => $baseDir . '/app/Controller/CaptchaController.php',
+ 'Kanboard\\Controller\\CategoryController' => $baseDir . '/app/Controller/CategoryController.php',
+ 'Kanboard\\Controller\\ColumnController' => $baseDir . '/app/Controller/ColumnController.php',
+ 'Kanboard\\Controller\\ColumnMoveRestrictionController' => $baseDir . '/app/Controller/ColumnMoveRestrictionController.php',
+ 'Kanboard\\Controller\\ColumnRestrictionController' => $baseDir . '/app/Controller/ColumnRestrictionController.php',
+ 'Kanboard\\Controller\\CommentController' => $baseDir . '/app/Controller/CommentController.php',
+ 'Kanboard\\Controller\\CommentListController' => $baseDir . '/app/Controller/CommentListController.php',
+ 'Kanboard\\Controller\\CommentMailController' => $baseDir . '/app/Controller/CommentMailController.php',
+ 'Kanboard\\Controller\\ConfigController' => $baseDir . '/app/Controller/ConfigController.php',
+ 'Kanboard\\Controller\\CurrencyController' => $baseDir . '/app/Controller/CurrencyController.php',
+ 'Kanboard\\Controller\\CustomFilterController' => $baseDir . '/app/Controller/CustomFilterController.php',
+ 'Kanboard\\Controller\\DashboardController' => $baseDir . '/app/Controller/DashboardController.php',
+ 'Kanboard\\Controller\\DocumentationController' => $baseDir . '/app/Controller/DocumentationController.php',
+ 'Kanboard\\Controller\\ExportController' => $baseDir . '/app/Controller/ExportController.php',
+ 'Kanboard\\Controller\\ExternalTaskCreationController' => $baseDir . '/app/Controller/ExternalTaskCreationController.php',
+ 'Kanboard\\Controller\\ExternalTaskViewController' => $baseDir . '/app/Controller/ExternalTaskViewController.php',
+ 'Kanboard\\Controller\\FeedController' => $baseDir . '/app/Controller/FeedController.php',
+ 'Kanboard\\Controller\\FileViewerController' => $baseDir . '/app/Controller/FileViewerController.php',
+ 'Kanboard\\Controller\\GroupAjaxController' => $baseDir . '/app/Controller/GroupAjaxController.php',
+ 'Kanboard\\Controller\\GroupCreationController' => $baseDir . '/app/Controller/GroupCreationController.php',
+ 'Kanboard\\Controller\\GroupListController' => $baseDir . '/app/Controller/GroupListController.php',
+ 'Kanboard\\Controller\\GroupModificationController' => $baseDir . '/app/Controller/GroupModificationController.php',
+ 'Kanboard\\Controller\\ICalendarController' => $baseDir . '/app/Controller/ICalendarController.php',
+ 'Kanboard\\Controller\\LinkController' => $baseDir . '/app/Controller/LinkController.php',
+ 'Kanboard\\Controller\\OAuthController' => $baseDir . '/app/Controller/OAuthController.php',
+ 'Kanboard\\Controller\\PasswordResetController' => $baseDir . '/app/Controller/PasswordResetController.php',
+ 'Kanboard\\Controller\\PluginController' => $baseDir . '/app/Controller/PluginController.php',
+ 'Kanboard\\Controller\\ProjectActionDuplicationController' => $baseDir . '/app/Controller/ProjectActionDuplicationController.php',
+ 'Kanboard\\Controller\\ProjectCreationController' => $baseDir . '/app/Controller/ProjectCreationController.php',
+ 'Kanboard\\Controller\\ProjectEditController' => $baseDir . '/app/Controller/ProjectEditController.php',
+ 'Kanboard\\Controller\\ProjectFileController' => $baseDir . '/app/Controller/ProjectFileController.php',
+ 'Kanboard\\Controller\\ProjectListController' => $baseDir . '/app/Controller/ProjectListController.php',
+ 'Kanboard\\Controller\\ProjectOverviewController' => $baseDir . '/app/Controller/ProjectOverviewController.php',
+ 'Kanboard\\Controller\\ProjectPermissionController' => $baseDir . '/app/Controller/ProjectPermissionController.php',
+ 'Kanboard\\Controller\\ProjectRoleController' => $baseDir . '/app/Controller/ProjectRoleController.php',
+ 'Kanboard\\Controller\\ProjectRoleRestrictionController' => $baseDir . '/app/Controller/ProjectRoleRestrictionController.php',
+ 'Kanboard\\Controller\\ProjectStatusController' => $baseDir . '/app/Controller/ProjectStatusController.php',
+ 'Kanboard\\Controller\\ProjectTagController' => $baseDir . '/app/Controller/ProjectTagController.php',
+ 'Kanboard\\Controller\\ProjectUserOverviewController' => $baseDir . '/app/Controller/ProjectUserOverviewController.php',
+ 'Kanboard\\Controller\\ProjectViewController' => $baseDir . '/app/Controller/ProjectViewController.php',
+ 'Kanboard\\Controller\\SearchController' => $baseDir . '/app/Controller/SearchController.php',
+ 'Kanboard\\Controller\\SubtaskController' => $baseDir . '/app/Controller/SubtaskController.php',
+ 'Kanboard\\Controller\\SubtaskConverterController' => $baseDir . '/app/Controller/SubtaskConverterController.php',
+ 'Kanboard\\Controller\\SubtaskRestrictionController' => $baseDir . '/app/Controller/SubtaskRestrictionController.php',
+ 'Kanboard\\Controller\\SubtaskStatusController' => $baseDir . '/app/Controller/SubtaskStatusController.php',
+ 'Kanboard\\Controller\\SwimlaneController' => $baseDir . '/app/Controller/SwimlaneController.php',
+ 'Kanboard\\Controller\\TagController' => $baseDir . '/app/Controller/TagController.php',
+ 'Kanboard\\Controller\\TaskAjaxController' => $baseDir . '/app/Controller/TaskAjaxController.php',
+ 'Kanboard\\Controller\\TaskBulkController' => $baseDir . '/app/Controller/TaskBulkController.php',
+ 'Kanboard\\Controller\\TaskCreationController' => $baseDir . '/app/Controller/TaskCreationController.php',
+ 'Kanboard\\Controller\\TaskDuplicationController' => $baseDir . '/app/Controller/TaskDuplicationController.php',
+ 'Kanboard\\Controller\\TaskExternalLinkController' => $baseDir . '/app/Controller/TaskExternalLinkController.php',
+ 'Kanboard\\Controller\\TaskFileController' => $baseDir . '/app/Controller/TaskFileController.php',
+ 'Kanboard\\Controller\\TaskImportController' => $baseDir . '/app/Controller/TaskImportController.php',
+ 'Kanboard\\Controller\\TaskInternalLinkController' => $baseDir . '/app/Controller/TaskInternalLinkController.php',
+ 'Kanboard\\Controller\\TaskListController' => $baseDir . '/app/Controller/TaskListController.php',
+ 'Kanboard\\Controller\\TaskMailController' => $baseDir . '/app/Controller/TaskMailController.php',
+ 'Kanboard\\Controller\\TaskModificationController' => $baseDir . '/app/Controller/TaskModificationController.php',
+ 'Kanboard\\Controller\\TaskMovePositionController' => $baseDir . '/app/Controller/TaskMovePositionController.php',
+ 'Kanboard\\Controller\\TaskPopoverController' => $baseDir . '/app/Controller/TaskPopoverController.php',
+ 'Kanboard\\Controller\\TaskRecurrenceController' => $baseDir . '/app/Controller/TaskRecurrenceController.php',
+ 'Kanboard\\Controller\\TaskStatusController' => $baseDir . '/app/Controller/TaskStatusController.php',
+ 'Kanboard\\Controller\\TaskSuppressionController' => $baseDir . '/app/Controller/TaskSuppressionController.php',
+ 'Kanboard\\Controller\\TaskViewController' => $baseDir . '/app/Controller/TaskViewController.php',
+ 'Kanboard\\Controller\\TwoFactorController' => $baseDir . '/app/Controller/TwoFactorController.php',
+ 'Kanboard\\Controller\\UserAjaxController' => $baseDir . '/app/Controller/UserAjaxController.php',
+ 'Kanboard\\Controller\\UserApiAccessController' => $baseDir . '/app/Controller/UserApiAccessController.php',
+ 'Kanboard\\Controller\\UserCreationController' => $baseDir . '/app/Controller/UserCreationController.php',
+ 'Kanboard\\Controller\\UserCredentialController' => $baseDir . '/app/Controller/UserCredentialController.php',
+ 'Kanboard\\Controller\\UserImportController' => $baseDir . '/app/Controller/UserImportController.php',
+ 'Kanboard\\Controller\\UserInviteController' => $baseDir . '/app/Controller/UserInviteController.php',
+ 'Kanboard\\Controller\\UserListController' => $baseDir . '/app/Controller/UserListController.php',
+ 'Kanboard\\Controller\\UserModificationController' => $baseDir . '/app/Controller/UserModificationController.php',
+ 'Kanboard\\Controller\\UserStatusController' => $baseDir . '/app/Controller/UserStatusController.php',
+ 'Kanboard\\Controller\\UserViewController' => $baseDir . '/app/Controller/UserViewController.php',
+ 'Kanboard\\Controller\\WebNotificationController' => $baseDir . '/app/Controller/WebNotificationController.php',
+ 'Kanboard\\Core\\Action\\ActionManager' => $baseDir . '/app/Core/Action/ActionManager.php',
+ 'Kanboard\\Core\\Base' => $baseDir . '/app/Core/Base.php',
+ 'Kanboard\\Core\\Cache\\BaseCache' => $baseDir . '/app/Core/Cache/BaseCache.php',
+ 'Kanboard\\Core\\Cache\\CacheInterface' => $baseDir . '/app/Core/Cache/CacheInterface.php',
+ 'Kanboard\\Core\\Cache\\FileCache' => $baseDir . '/app/Core/Cache/FileCache.php',
+ 'Kanboard\\Core\\Cache\\MemoryCache' => $baseDir . '/app/Core/Cache/MemoryCache.php',
+ 'Kanboard\\Core\\Controller\\AccessForbiddenException' => $baseDir . '/app/Core/Controller/AccessForbiddenException.php',
+ 'Kanboard\\Core\\Controller\\BaseException' => $baseDir . '/app/Core/Controller/BaseException.php',
+ 'Kanboard\\Core\\Controller\\BaseMiddleware' => $baseDir . '/app/Core/Controller/BaseMiddleware.php',
+ 'Kanboard\\Core\\Controller\\PageNotFoundException' => $baseDir . '/app/Core/Controller/PageNotFoundException.php',
+ 'Kanboard\\Core\\Controller\\Runner' => $baseDir . '/app/Core/Controller/Runner.php',
+ 'Kanboard\\Core\\Csv' => $baseDir . '/app/Core/Csv.php',
+ 'Kanboard\\Core\\DateParser' => $baseDir . '/app/Core/DateParser.php',
+ 'Kanboard\\Core\\Event\\EventManager' => $baseDir . '/app/Core/Event/EventManager.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkInterface' => $baseDir . '/app/Core/ExternalLink/ExternalLinkInterface.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkManager' => $baseDir . '/app/Core/ExternalLink/ExternalLinkManager.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkProviderInterface' => $baseDir . '/app/Core/ExternalLink/ExternalLinkProviderInterface.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkProviderNotFound' => $baseDir . '/app/Core/ExternalLink/ExternalLinkProviderNotFound.php',
+ 'Kanboard\\Core\\ExternalTask\\AccessForbiddenException' => $baseDir . '/app/Core/ExternalTask/AccessForbiddenException.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskException' => $baseDir . '/app/Core/ExternalTask/ExternalTaskException.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskInterface' => $baseDir . '/app/Core/ExternalTask/ExternalTaskInterface.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskManager' => $baseDir . '/app/Core/ExternalTask/ExternalTaskManager.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskProviderInterface' => $baseDir . '/app/Core/ExternalTask/ExternalTaskProviderInterface.php',
+ 'Kanboard\\Core\\ExternalTask\\NotFoundException' => $baseDir . '/app/Core/ExternalTask/NotFoundException.php',
+ 'Kanboard\\Core\\ExternalTask\\ProviderNotFoundException' => $baseDir . '/app/Core/ExternalTask/ProviderNotFoundException.php',
+ 'Kanboard\\Core\\Filter\\CriteriaInterface' => $baseDir . '/app/Core/Filter/CriteriaInterface.php',
+ 'Kanboard\\Core\\Filter\\FilterInterface' => $baseDir . '/app/Core/Filter/FilterInterface.php',
+ 'Kanboard\\Core\\Filter\\FormatterInterface' => $baseDir . '/app/Core/Filter/FormatterInterface.php',
+ 'Kanboard\\Core\\Filter\\Lexer' => $baseDir . '/app/Core/Filter/Lexer.php',
+ 'Kanboard\\Core\\Filter\\LexerBuilder' => $baseDir . '/app/Core/Filter/LexerBuilder.php',
+ 'Kanboard\\Core\\Filter\\OrCriteria' => $baseDir . '/app/Core/Filter/OrCriteria.php',
+ 'Kanboard\\Core\\Filter\\QueryBuilder' => $baseDir . '/app/Core/Filter/QueryBuilder.php',
+ 'Kanboard\\Core\\Group\\GroupBackendProviderInterface' => $baseDir . '/app/Core/Group/GroupBackendProviderInterface.php',
+ 'Kanboard\\Core\\Group\\GroupManager' => $baseDir . '/app/Core/Group/GroupManager.php',
+ 'Kanboard\\Core\\Group\\GroupProviderInterface' => $baseDir . '/app/Core/Group/GroupProviderInterface.php',
+ 'Kanboard\\Core\\Helper' => $baseDir . '/app/Core/Helper.php',
+ 'Kanboard\\Core\\Http\\Client' => $baseDir . '/app/Core/Http/Client.php',
+ 'Kanboard\\Core\\Http\\OAuth2' => $baseDir . '/app/Core/Http/OAuth2.php',
+ 'Kanboard\\Core\\Http\\RememberMeCookie' => $baseDir . '/app/Core/Http/RememberMeCookie.php',
+ 'Kanboard\\Core\\Http\\Request' => $baseDir . '/app/Core/Http/Request.php',
+ 'Kanboard\\Core\\Http\\Response' => $baseDir . '/app/Core/Http/Response.php',
+ 'Kanboard\\Core\\Http\\Route' => $baseDir . '/app/Core/Http/Route.php',
+ 'Kanboard\\Core\\Http\\Router' => $baseDir . '/app/Core/Http/Router.php',
+ 'Kanboard\\Core\\Ldap\\Client' => $baseDir . '/app/Core/Ldap/Client.php',
+ 'Kanboard\\Core\\Ldap\\ClientException' => $baseDir . '/app/Core/Ldap/ClientException.php',
+ 'Kanboard\\Core\\Ldap\\ConnectionException' => $baseDir . '/app/Core/Ldap/ConnectionException.php',
+ 'Kanboard\\Core\\Ldap\\Entries' => $baseDir . '/app/Core/Ldap/Entries.php',
+ 'Kanboard\\Core\\Ldap\\Entry' => $baseDir . '/app/Core/Ldap/Entry.php',
+ 'Kanboard\\Core\\Ldap\\Group' => $baseDir . '/app/Core/Ldap/Group.php',
+ 'Kanboard\\Core\\Ldap\\Query' => $baseDir . '/app/Core/Ldap/Query.php',
+ 'Kanboard\\Core\\Ldap\\User' => $baseDir . '/app/Core/Ldap/User.php',
+ 'Kanboard\\Core\\Mail\\Client' => $baseDir . '/app/Core/Mail/Client.php',
+ 'Kanboard\\Core\\Mail\\ClientInterface' => $baseDir . '/app/Core/Mail/ClientInterface.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Mail' => $baseDir . '/app/Core/Mail/Transport/Mail.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Sendmail' => $baseDir . '/app/Core/Mail/Transport/Sendmail.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Smtp' => $baseDir . '/app/Core/Mail/Transport/Smtp.php',
+ 'Kanboard\\Core\\Markdown' => $baseDir . '/app/Core/Markdown.php',
+ 'Kanboard\\Core\\Notification\\NotificationInterface' => $baseDir . '/app/Core/Notification/NotificationInterface.php',
+ 'Kanboard\\Core\\ObjectStorage\\FileStorage' => $baseDir . '/app/Core/ObjectStorage/FileStorage.php',
+ 'Kanboard\\Core\\ObjectStorage\\ObjectStorageException' => $baseDir . '/app/Core/ObjectStorage/ObjectStorageException.php',
+ 'Kanboard\\Core\\ObjectStorage\\ObjectStorageInterface' => $baseDir . '/app/Core/ObjectStorage/ObjectStorageInterface.php',
+ 'Kanboard\\Core\\Paginator' => $baseDir . '/app/Core/Paginator.php',
+ 'Kanboard\\Core\\Plugin\\Base' => $baseDir . '/app/Core/Plugin/Base.php',
+ 'Kanboard\\Core\\Plugin\\Directory' => $baseDir . '/app/Core/Plugin/Directory.php',
+ 'Kanboard\\Core\\Plugin\\Hook' => $baseDir . '/app/Core/Plugin/Hook.php',
+ 'Kanboard\\Core\\Plugin\\Installer' => $baseDir . '/app/Core/Plugin/Installer.php',
+ 'Kanboard\\Core\\Plugin\\Loader' => $baseDir . '/app/Core/Plugin/Loader.php',
+ 'Kanboard\\Core\\Plugin\\PluginException' => $baseDir . '/app/Core/Plugin/PluginException.php',
+ 'Kanboard\\Core\\Plugin\\PluginInstallerException' => $baseDir . '/app/Core/Plugin/PluginInstallerException.php',
+ 'Kanboard\\Core\\Plugin\\SchemaHandler' => $baseDir . '/app/Core/Plugin/SchemaHandler.php',
+ 'Kanboard\\Core\\Plugin\\Version' => $baseDir . '/app/Core/Plugin/Version.php',
+ 'Kanboard\\Core\\Queue\\JobHandler' => $baseDir . '/app/Core/Queue/JobHandler.php',
+ 'Kanboard\\Core\\Queue\\QueueManager' => $baseDir . '/app/Core/Queue/QueueManager.php',
+ 'Kanboard\\Core\\Security\\AccessMap' => $baseDir . '/app/Core/Security/AccessMap.php',
+ 'Kanboard\\Core\\Security\\AuthenticationManager' => $baseDir . '/app/Core/Security/AuthenticationManager.php',
+ 'Kanboard\\Core\\Security\\AuthenticationProviderInterface' => $baseDir . '/app/Core/Security/AuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Authorization' => $baseDir . '/app/Core/Security/Authorization.php',
+ 'Kanboard\\Core\\Security\\OAuthAuthenticationProviderInterface' => $baseDir . '/app/Core/Security/OAuthAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PasswordAuthenticationProviderInterface' => $baseDir . '/app/Core/Security/PasswordAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PostAuthenticationProviderInterface' => $baseDir . '/app/Core/Security/PostAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PreAuthenticationProviderInterface' => $baseDir . '/app/Core/Security/PreAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Role' => $baseDir . '/app/Core/Security/Role.php',
+ 'Kanboard\\Core\\Security\\SessionCheckProviderInterface' => $baseDir . '/app/Core/Security/SessionCheckProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Token' => $baseDir . '/app/Core/Security/Token.php',
+ 'Kanboard\\Core\\Session\\FlashMessage' => $baseDir . '/app/Core/Session/FlashMessage.php',
+ 'Kanboard\\Core\\Session\\SessionManager' => $baseDir . '/app/Core/Session/SessionManager.php',
+ 'Kanboard\\Core\\Session\\SessionStorage' => $baseDir . '/app/Core/Session/SessionStorage.php',
+ 'Kanboard\\Core\\Template' => $baseDir . '/app/Core/Template.php',
+ 'Kanboard\\Core\\Thumbnail' => $baseDir . '/app/Core/Thumbnail.php',
+ 'Kanboard\\Core\\Tool' => $baseDir . '/app/Core/Tool.php',
+ 'Kanboard\\Core\\Translator' => $baseDir . '/app/Core/Translator.php',
+ 'Kanboard\\Core\\User\\Avatar\\AvatarManager' => $baseDir . '/app/Core/User/Avatar/AvatarManager.php',
+ 'Kanboard\\Core\\User\\Avatar\\AvatarProviderInterface' => $baseDir . '/app/Core/User/Avatar/AvatarProviderInterface.php',
+ 'Kanboard\\Core\\User\\GroupSync' => $baseDir . '/app/Core/User/GroupSync.php',
+ 'Kanboard\\Core\\User\\UserProfile' => $baseDir . '/app/Core/User/UserProfile.php',
+ 'Kanboard\\Core\\User\\UserProperty' => $baseDir . '/app/Core/User/UserProperty.php',
+ 'Kanboard\\Core\\User\\UserProviderInterface' => $baseDir . '/app/Core/User/UserProviderInterface.php',
+ 'Kanboard\\Core\\User\\UserSession' => $baseDir . '/app/Core/User/UserSession.php',
+ 'Kanboard\\Core\\User\\UserSync' => $baseDir . '/app/Core/User/UserSync.php',
+ 'Kanboard\\Decorator\\ColumnMoveRestrictionCacheDecorator' => $baseDir . '/app/Decorator/ColumnMoveRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\ColumnRestrictionCacheDecorator' => $baseDir . '/app/Decorator/ColumnRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\MetadataCacheDecorator' => $baseDir . '/app/Decorator/MetadataCacheDecorator.php',
+ 'Kanboard\\Decorator\\ProjectRoleRestrictionCacheDecorator' => $baseDir . '/app/Decorator/ProjectRoleRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\UserCacheDecorator' => $baseDir . '/app/Decorator/UserCacheDecorator.php',
+ 'Kanboard\\EventBuilder\\BaseEventBuilder' => $baseDir . '/app/EventBuilder/BaseEventBuilder.php',
+ 'Kanboard\\EventBuilder\\CommentEventBuilder' => $baseDir . '/app/EventBuilder/CommentEventBuilder.php',
+ 'Kanboard\\EventBuilder\\EventIteratorBuilder' => $baseDir . '/app/EventBuilder/EventIteratorBuilder.php',
+ 'Kanboard\\EventBuilder\\ProjectFileEventBuilder' => $baseDir . '/app/EventBuilder/ProjectFileEventBuilder.php',
+ 'Kanboard\\EventBuilder\\SubtaskEventBuilder' => $baseDir . '/app/EventBuilder/SubtaskEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskEventBuilder' => $baseDir . '/app/EventBuilder/TaskEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskFileEventBuilder' => $baseDir . '/app/EventBuilder/TaskFileEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskLinkEventBuilder' => $baseDir . '/app/EventBuilder/TaskLinkEventBuilder.php',
+ 'Kanboard\\Event\\AuthFailureEvent' => $baseDir . '/app/Event/AuthFailureEvent.php',
+ 'Kanboard\\Event\\AuthSuccessEvent' => $baseDir . '/app/Event/AuthSuccessEvent.php',
+ 'Kanboard\\Event\\CommentEvent' => $baseDir . '/app/Event/CommentEvent.php',
+ 'Kanboard\\Event\\GenericEvent' => $baseDir . '/app/Event/GenericEvent.php',
+ 'Kanboard\\Event\\ProjectFileEvent' => $baseDir . '/app/Event/ProjectFileEvent.php',
+ 'Kanboard\\Event\\SubtaskEvent' => $baseDir . '/app/Event/SubtaskEvent.php',
+ 'Kanboard\\Event\\TaskEvent' => $baseDir . '/app/Event/TaskEvent.php',
+ 'Kanboard\\Event\\TaskFileEvent' => $baseDir . '/app/Event/TaskFileEvent.php',
+ 'Kanboard\\Event\\TaskLinkEvent' => $baseDir . '/app/Event/TaskLinkEvent.php',
+ 'Kanboard\\Event\\TaskListEvent' => $baseDir . '/app/Event/TaskListEvent.php',
+ 'Kanboard\\Event\\UserProfileSyncEvent' => $baseDir . '/app/Event/UserProfileSyncEvent.php',
+ 'Kanboard\\Export\\SubtaskExport' => $baseDir . '/app/Export/SubtaskExport.php',
+ 'Kanboard\\Export\\TaskExport' => $baseDir . '/app/Export/TaskExport.php',
+ 'Kanboard\\Export\\TransitionExport' => $baseDir . '/app/Export/TransitionExport.php',
+ 'Kanboard\\ExternalLink\\AttachmentLink' => $baseDir . '/app/ExternalLink/AttachmentLink.php',
+ 'Kanboard\\ExternalLink\\AttachmentLinkProvider' => $baseDir . '/app/ExternalLink/AttachmentLinkProvider.php',
+ 'Kanboard\\ExternalLink\\BaseLink' => $baseDir . '/app/ExternalLink/BaseLink.php',
+ 'Kanboard\\ExternalLink\\BaseLinkProvider' => $baseDir . '/app/ExternalLink/BaseLinkProvider.php',
+ 'Kanboard\\ExternalLink\\FileLink' => $baseDir . '/app/ExternalLink/FileLink.php',
+ 'Kanboard\\ExternalLink\\FileLinkProvider' => $baseDir . '/app/ExternalLink/FileLinkProvider.php',
+ 'Kanboard\\ExternalLink\\WebLink' => $baseDir . '/app/ExternalLink/WebLink.php',
+ 'Kanboard\\ExternalLink\\WebLinkProvider' => $baseDir . '/app/ExternalLink/WebLinkProvider.php',
+ 'Kanboard\\Filter\\BaseComparisonFilter' => $baseDir . '/app/Filter/BaseComparisonFilter.php',
+ 'Kanboard\\Filter\\BaseDateFilter' => $baseDir . '/app/Filter/BaseDateFilter.php',
+ 'Kanboard\\Filter\\BaseFilter' => $baseDir . '/app/Filter/BaseFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityCreationDateFilter' => $baseDir . '/app/Filter/ProjectActivityCreationDateFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityCreatorFilter' => $baseDir . '/app/Filter/ProjectActivityCreatorFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectIdFilter' => $baseDir . '/app/Filter/ProjectActivityProjectIdFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectIdsFilter' => $baseDir . '/app/Filter/ProjectActivityProjectIdsFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectNameFilter' => $baseDir . '/app/Filter/ProjectActivityProjectNameFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskIdFilter' => $baseDir . '/app/Filter/ProjectActivityTaskIdFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskStatusFilter' => $baseDir . '/app/Filter/ProjectActivityTaskStatusFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskTitleFilter' => $baseDir . '/app/Filter/ProjectActivityTaskTitleFilter.php',
+ 'Kanboard\\Filter\\ProjectGroupRoleProjectFilter' => $baseDir . '/app/Filter/ProjectGroupRoleProjectFilter.php',
+ 'Kanboard\\Filter\\ProjectGroupRoleUsernameFilter' => $baseDir . '/app/Filter/ProjectGroupRoleUsernameFilter.php',
+ 'Kanboard\\Filter\\ProjectIdsFilter' => $baseDir . '/app/Filter/ProjectIdsFilter.php',
+ 'Kanboard\\Filter\\ProjectStatusFilter' => $baseDir . '/app/Filter/ProjectStatusFilter.php',
+ 'Kanboard\\Filter\\ProjectTypeFilter' => $baseDir . '/app/Filter/ProjectTypeFilter.php',
+ 'Kanboard\\Filter\\ProjectUserRoleProjectFilter' => $baseDir . '/app/Filter/ProjectUserRoleProjectFilter.php',
+ 'Kanboard\\Filter\\ProjectUserRoleUsernameFilter' => $baseDir . '/app/Filter/ProjectUserRoleUsernameFilter.php',
+ 'Kanboard\\Filter\\TaskAssigneeFilter' => $baseDir . '/app/Filter/TaskAssigneeFilter.php',
+ 'Kanboard\\Filter\\TaskCategoryFilter' => $baseDir . '/app/Filter/TaskCategoryFilter.php',
+ 'Kanboard\\Filter\\TaskColorFilter' => $baseDir . '/app/Filter/TaskColorFilter.php',
+ 'Kanboard\\Filter\\TaskColumnFilter' => $baseDir . '/app/Filter/TaskColumnFilter.php',
+ 'Kanboard\\Filter\\TaskCommentFilter' => $baseDir . '/app/Filter/TaskCommentFilter.php',
+ 'Kanboard\\Filter\\TaskCompletionDateFilter' => $baseDir . '/app/Filter/TaskCompletionDateFilter.php',
+ 'Kanboard\\Filter\\TaskCreationDateFilter' => $baseDir . '/app/Filter/TaskCreationDateFilter.php',
+ 'Kanboard\\Filter\\TaskCreatorFilter' => $baseDir . '/app/Filter/TaskCreatorFilter.php',
+ 'Kanboard\\Filter\\TaskDescriptionFilter' => $baseDir . '/app/Filter/TaskDescriptionFilter.php',
+ 'Kanboard\\Filter\\TaskDueDateFilter' => $baseDir . '/app/Filter/TaskDueDateFilter.php',
+ 'Kanboard\\Filter\\TaskDueDateRangeFilter' => $baseDir . '/app/Filter/TaskDueDateRangeFilter.php',
+ 'Kanboard\\Filter\\TaskIdExclusionFilter' => $baseDir . '/app/Filter/TaskIdExclusionFilter.php',
+ 'Kanboard\\Filter\\TaskIdFilter' => $baseDir . '/app/Filter/TaskIdFilter.php',
+ 'Kanboard\\Filter\\TaskLinkFilter' => $baseDir . '/app/Filter/TaskLinkFilter.php',
+ 'Kanboard\\Filter\\TaskModificationDateFilter' => $baseDir . '/app/Filter/TaskModificationDateFilter.php',
+ 'Kanboard\\Filter\\TaskMovedDateFilter' => $baseDir . '/app/Filter/TaskMovedDateFilter.php',
+ 'Kanboard\\Filter\\TaskPriorityFilter' => $baseDir . '/app/Filter/TaskPriorityFilter.php',
+ 'Kanboard\\Filter\\TaskProjectFilter' => $baseDir . '/app/Filter/TaskProjectFilter.php',
+ 'Kanboard\\Filter\\TaskProjectsFilter' => $baseDir . '/app/Filter/TaskProjectsFilter.php',
+ 'Kanboard\\Filter\\TaskReferenceFilter' => $baseDir . '/app/Filter/TaskReferenceFilter.php',
+ 'Kanboard\\Filter\\TaskScoreFilter' => $baseDir . '/app/Filter/TaskScoreFilter.php',
+ 'Kanboard\\Filter\\TaskStartDateFilter' => $baseDir . '/app/Filter/TaskStartDateFilter.php',
+ 'Kanboard\\Filter\\TaskStartsWithIdFilter' => $baseDir . '/app/Filter/TaskStartsWithIdFilter.php',
+ 'Kanboard\\Filter\\TaskStatusFilter' => $baseDir . '/app/Filter/TaskStatusFilter.php',
+ 'Kanboard\\Filter\\TaskSubtaskAssigneeFilter' => $baseDir . '/app/Filter/TaskSubtaskAssigneeFilter.php',
+ 'Kanboard\\Filter\\TaskSwimlaneFilter' => $baseDir . '/app/Filter/TaskSwimlaneFilter.php',
+ 'Kanboard\\Filter\\TaskTagFilter' => $baseDir . '/app/Filter/TaskTagFilter.php',
+ 'Kanboard\\Filter\\TaskTitleFilter' => $baseDir . '/app/Filter/TaskTitleFilter.php',
+ 'Kanboard\\Filter\\UserNameFilter' => $baseDir . '/app/Filter/UserNameFilter.php',
+ 'Kanboard\\Formatter\\BaseFormatter' => $baseDir . '/app/Formatter/BaseFormatter.php',
+ 'Kanboard\\Formatter\\BaseTaskCalendarFormatter' => $baseDir . '/app/Formatter/BaseTaskCalendarFormatter.php',
+ 'Kanboard\\Formatter\\BoardColumnFormatter' => $baseDir . '/app/Formatter/BoardColumnFormatter.php',
+ 'Kanboard\\Formatter\\BoardFormatter' => $baseDir . '/app/Formatter/BoardFormatter.php',
+ 'Kanboard\\Formatter\\BoardSwimlaneFormatter' => $baseDir . '/app/Formatter/BoardSwimlaneFormatter.php',
+ 'Kanboard\\Formatter\\BoardTaskFormatter' => $baseDir . '/app/Formatter/BoardTaskFormatter.php',
+ 'Kanboard\\Formatter\\GroupAutoCompleteFormatter' => $baseDir . '/app/Formatter/GroupAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\ProjectActivityEventFormatter' => $baseDir . '/app/Formatter/ProjectActivityEventFormatter.php',
+ 'Kanboard\\Formatter\\ProjectApiFormatter' => $baseDir . '/app/Formatter/ProjectApiApiFormatter.php',
+ 'Kanboard\\Formatter\\ProjectsApiFormatter' => $baseDir . '/app/Formatter/ProjectsApiFormatter.php',
+ 'Kanboard\\Formatter\\SubtaskListFormatter' => $baseDir . '/app/Formatter/SubtaskListFormatter.php',
+ 'Kanboard\\Formatter\\SubtaskTimeTrackingCalendarFormatter' => $baseDir . '/app/Formatter/SubtaskTimeTrackingCalendarFormatter.php',
+ 'Kanboard\\Formatter\\TaskApiFormatter' => $baseDir . '/app/Formatter/TaskApiFormatter.php',
+ 'Kanboard\\Formatter\\TaskAutoCompleteFormatter' => $baseDir . '/app/Formatter/TaskAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\TaskICalFormatter' => $baseDir . '/app/Formatter/TaskICalFormatter.php',
+ 'Kanboard\\Formatter\\TaskListFormatter' => $baseDir . '/app/Formatter/TaskListFormatter.php',
+ 'Kanboard\\Formatter\\TaskListSubtaskAssigneeFormatter' => $baseDir . '/app/Formatter/TaskListSubtaskAssigneeFormatter.php',
+ 'Kanboard\\Formatter\\TaskListSubtaskFormatter' => $baseDir . '/app/Formatter/TaskListSubtaskFormatter.php',
+ 'Kanboard\\Formatter\\TaskSuggestMenuFormatter' => $baseDir . '/app/Formatter/TaskSuggestMenuFormatter.php',
+ 'Kanboard\\Formatter\\TasksApiFormatter' => $baseDir . '/app/Formatter/TasksApiFormatter.php',
+ 'Kanboard\\Formatter\\UserAutoCompleteFormatter' => $baseDir . '/app/Formatter/UserAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\UserMentionFormatter' => $baseDir . '/app/Formatter/UserMentionFormatter.php',
+ 'Kanboard\\Group\\DatabaseBackendGroupProvider' => $baseDir . '/app/Group/DatabaseBackendGroupProvider.php',
+ 'Kanboard\\Group\\DatabaseGroupProvider' => $baseDir . '/app/Group/DatabaseGroupProvider.php',
+ 'Kanboard\\Group\\LdapBackendGroupProvider' => $baseDir . '/app/Group/LdapBackendGroupProvider.php',
+ 'Kanboard\\Group\\LdapGroupProvider' => $baseDir . '/app/Group/LdapGroupProvider.php',
+ 'Kanboard\\Helper\\AppHelper' => $baseDir . '/app/Helper/AppHelper.php',
+ 'Kanboard\\Helper\\AssetHelper' => $baseDir . '/app/Helper/AssetHelper.php',
+ 'Kanboard\\Helper\\AvatarHelper' => $baseDir . '/app/Helper/AvatarHelper.php',
+ 'Kanboard\\Helper\\BoardHelper' => $baseDir . '/app/Helper/BoardHelper.php',
+ 'Kanboard\\Helper\\CommentHelper' => $baseDir . '/app/Helper/CommentHelper.php',
+ 'Kanboard\\Helper\\DateHelper' => $baseDir . '/app/Helper/DateHelper.php',
+ 'Kanboard\\Helper\\FileHelper' => $baseDir . '/app/Helper/FileHelper.php',
+ 'Kanboard\\Helper\\FormHelper' => $baseDir . '/app/Helper/FormHelper.php',
+ 'Kanboard\\Helper\\HookHelper' => $baseDir . '/app/Helper/HookHelper.php',
+ 'Kanboard\\Helper\\ICalHelper' => $baseDir . '/app/Helper/ICalHelper.php',
+ 'Kanboard\\Helper\\LayoutHelper' => $baseDir . '/app/Helper/LayoutHelper.php',
+ 'Kanboard\\Helper\\MailHelper' => $baseDir . '/app/Helper/MailHelper.php',
+ 'Kanboard\\Helper\\ModalHelper' => $baseDir . '/app/Helper/ModalHelper.php',
+ 'Kanboard\\Helper\\ModelHelper' => $baseDir . '/app/Helper/ModelHelper.php',
+ 'Kanboard\\Helper\\ProjectActivityHelper' => $baseDir . '/app/Helper/ProjectActivityHelper.php',
+ 'Kanboard\\Helper\\ProjectHeaderHelper' => $baseDir . '/app/Helper/ProjectHeaderHelper.php',
+ 'Kanboard\\Helper\\ProjectRoleHelper' => $baseDir . '/app/Helper/ProjectRoleHelper.php',
+ 'Kanboard\\Helper\\SubtaskHelper' => $baseDir . '/app/Helper/SubtaskHelper.php',
+ 'Kanboard\\Helper\\TaskHelper' => $baseDir . '/app/Helper/TaskHelper.php',
+ 'Kanboard\\Helper\\TextHelper' => $baseDir . '/app/Helper/TextHelper.php',
+ 'Kanboard\\Helper\\UrlHelper' => $baseDir . '/app/Helper/UrlHelper.php',
+ 'Kanboard\\Helper\\UserHelper' => $baseDir . '/app/Helper/UserHelper.php',
+ 'Kanboard\\Import\\TaskImport' => $baseDir . '/app/Import/TaskImport.php',
+ 'Kanboard\\Import\\UserImport' => $baseDir . '/app/Import/UserImport.php',
+ 'Kanboard\\Job\\BaseJob' => $baseDir . '/app/Job/BaseJob.php',
+ 'Kanboard\\Job\\CommentEventJob' => $baseDir . '/app/Job/CommentEventJob.php',
+ 'Kanboard\\Job\\EmailJob' => $baseDir . '/app/Job/EmailJob.php',
+ 'Kanboard\\Job\\HttpAsyncJob' => $baseDir . '/app/Job/HttpAsyncJob.php',
+ 'Kanboard\\Job\\NotificationJob' => $baseDir . '/app/Job/NotificationJob.php',
+ 'Kanboard\\Job\\ProjectFileEventJob' => $baseDir . '/app/Job/ProjectFileEventJob.php',
+ 'Kanboard\\Job\\ProjectMetricJob' => $baseDir . '/app/Job/ProjectMetricJob.php',
+ 'Kanboard\\Job\\SubtaskEventJob' => $baseDir . '/app/Job/SubtaskEventJob.php',
+ 'Kanboard\\Job\\TaskEventJob' => $baseDir . '/app/Job/TaskEventJob.php',
+ 'Kanboard\\Job\\TaskFileEventJob' => $baseDir . '/app/Job/TaskFileEventJob.php',
+ 'Kanboard\\Job\\TaskLinkEventJob' => $baseDir . '/app/Job/TaskLinkEventJob.php',
+ 'Kanboard\\Job\\UserMentionJob' => $baseDir . '/app/Job/UserMentionJob.php',
+ 'Kanboard\\Middleware\\ApplicationAuthorizationMiddleware' => $baseDir . '/app/Middleware/ApplicationAuthorizationMiddleware.php',
+ 'Kanboard\\Middleware\\AuthenticationMiddleware' => $baseDir . '/app/Middleware/AuthenticationMiddleware.php',
+ 'Kanboard\\Middleware\\BootstrapMiddleware' => $baseDir . '/app/Middleware/BootstrapMiddleware.php',
+ 'Kanboard\\Middleware\\PostAuthenticationMiddleware' => $baseDir . '/app/Middleware/PostAuthenticationMiddleware.php',
+ 'Kanboard\\Middleware\\ProjectAuthorizationMiddleware' => $baseDir . '/app/Middleware/ProjectAuthorizationMiddleware.php',
+ 'Kanboard\\Model\\ActionModel' => $baseDir . '/app/Model/ActionModel.php',
+ 'Kanboard\\Model\\ActionParameterModel' => $baseDir . '/app/Model/ActionParameterModel.php',
+ 'Kanboard\\Model\\AvatarFileModel' => $baseDir . '/app/Model/AvatarFileModel.php',
+ 'Kanboard\\Model\\BoardModel' => $baseDir . '/app/Model/BoardModel.php',
+ 'Kanboard\\Model\\CategoryModel' => $baseDir . '/app/Model/CategoryModel.php',
+ 'Kanboard\\Model\\ColorModel' => $baseDir . '/app/Model/ColorModel.php',
+ 'Kanboard\\Model\\ColumnModel' => $baseDir . '/app/Model/ColumnModel.php',
+ 'Kanboard\\Model\\ColumnMoveRestrictionModel' => $baseDir . '/app/Model/ColumnMoveRestrictionModel.php',
+ 'Kanboard\\Model\\ColumnRestrictionModel' => $baseDir . '/app/Model/ColumnRestrictionModel.php',
+ 'Kanboard\\Model\\CommentModel' => $baseDir . '/app/Model/CommentModel.php',
+ 'Kanboard\\Model\\ConfigModel' => $baseDir . '/app/Model/ConfigModel.php',
+ 'Kanboard\\Model\\CurrencyModel' => $baseDir . '/app/Model/CurrencyModel.php',
+ 'Kanboard\\Model\\CustomFilterModel' => $baseDir . '/app/Model/CustomFilterModel.php',
+ 'Kanboard\\Model\\FileModel' => $baseDir . '/app/Model/FileModel.php',
+ 'Kanboard\\Model\\GroupMemberModel' => $baseDir . '/app/Model/GroupMemberModel.php',
+ 'Kanboard\\Model\\GroupModel' => $baseDir . '/app/Model/GroupModel.php',
+ 'Kanboard\\Model\\InviteModel' => $baseDir . '/app/Model/InviteModel.php',
+ 'Kanboard\\Model\\LanguageModel' => $baseDir . '/app/Model/LanguageModel.php',
+ 'Kanboard\\Model\\LastLoginModel' => $baseDir . '/app/Model/LastLoginModel.php',
+ 'Kanboard\\Model\\LinkModel' => $baseDir . '/app/Model/LinkModel.php',
+ 'Kanboard\\Model\\MetadataModel' => $baseDir . '/app/Model/MetadataModel.php',
+ 'Kanboard\\Model\\NotificationModel' => $baseDir . '/app/Model/NotificationModel.php',
+ 'Kanboard\\Model\\NotificationTypeModel' => $baseDir . '/app/Model/NotificationTypeModel.php',
+ 'Kanboard\\Model\\PasswordResetModel' => $baseDir . '/app/Model/PasswordResetModel.php',
+ 'Kanboard\\Model\\ProjectActivityModel' => $baseDir . '/app/Model/ProjectActivityModel.php',
+ 'Kanboard\\Model\\ProjectDailyColumnStatsModel' => $baseDir . '/app/Model/ProjectDailyColumnStatsModel.php',
+ 'Kanboard\\Model\\ProjectDailyStatsModel' => $baseDir . '/app/Model/ProjectDailyStatsModel.php',
+ 'Kanboard\\Model\\ProjectDuplicationModel' => $baseDir . '/app/Model/ProjectDuplicationModel.php',
+ 'Kanboard\\Model\\ProjectFileModel' => $baseDir . '/app/Model/ProjectFileModel.php',
+ 'Kanboard\\Model\\ProjectGroupRoleModel' => $baseDir . '/app/Model/ProjectGroupRoleModel.php',
+ 'Kanboard\\Model\\ProjectMetadataModel' => $baseDir . '/app/Model/ProjectMetadataModel.php',
+ 'Kanboard\\Model\\ProjectModel' => $baseDir . '/app/Model/ProjectModel.php',
+ 'Kanboard\\Model\\ProjectNotificationModel' => $baseDir . '/app/Model/ProjectNotificationModel.php',
+ 'Kanboard\\Model\\ProjectNotificationTypeModel' => $baseDir . '/app/Model/ProjectNotificationTypeModel.php',
+ 'Kanboard\\Model\\ProjectPermissionModel' => $baseDir . '/app/Model/ProjectPermissionModel.php',
+ 'Kanboard\\Model\\ProjectRoleModel' => $baseDir . '/app/Model/ProjectRoleModel.php',
+ 'Kanboard\\Model\\ProjectRoleRestrictionModel' => $baseDir . '/app/Model/ProjectRoleRestrictionModel.php',
+ 'Kanboard\\Model\\ProjectTaskDuplicationModel' => $baseDir . '/app/Model/ProjectTaskDuplicationModel.php',
+ 'Kanboard\\Model\\ProjectTaskPriorityModel' => $baseDir . '/app/Model/ProjectTaskPriorityModel.php',
+ 'Kanboard\\Model\\ProjectUserRoleModel' => $baseDir . '/app/Model/ProjectUserRoleModel.php',
+ 'Kanboard\\Model\\RememberMeSessionModel' => $baseDir . '/app/Model/RememberMeSessionModel.php',
+ 'Kanboard\\Model\\SettingModel' => $baseDir . '/app/Model/SettingModel.php',
+ 'Kanboard\\Model\\SubtaskModel' => $baseDir . '/app/Model/SubtaskModel.php',
+ 'Kanboard\\Model\\SubtaskPositionModel' => $baseDir . '/app/Model/SubtaskPositionModel.php',
+ 'Kanboard\\Model\\SubtaskStatusModel' => $baseDir . '/app/Model/SubtaskStatusModel.php',
+ 'Kanboard\\Model\\SubtaskTaskConversionModel' => $baseDir . '/app/Model/SubtaskTaskConversionModel.php',
+ 'Kanboard\\Model\\SubtaskTimeTrackingModel' => $baseDir . '/app/Model/SubtaskTimeTrackingModel.php',
+ 'Kanboard\\Model\\SwimlaneModel' => $baseDir . '/app/Model/SwimlaneModel.php',
+ 'Kanboard\\Model\\TagDuplicationModel' => $baseDir . '/app/Model/TagDuplicationModel.php',
+ 'Kanboard\\Model\\TagModel' => $baseDir . '/app/Model/TagModel.php',
+ 'Kanboard\\Model\\TaskAnalyticModel' => $baseDir . '/app/Model/TaskAnalyticModel.php',
+ 'Kanboard\\Model\\TaskCreationModel' => $baseDir . '/app/Model/TaskCreationModel.php',
+ 'Kanboard\\Model\\TaskDuplicationModel' => $baseDir . '/app/Model/TaskDuplicationModel.php',
+ 'Kanboard\\Model\\TaskExternalLinkModel' => $baseDir . '/app/Model/TaskExternalLinkModel.php',
+ 'Kanboard\\Model\\TaskFileModel' => $baseDir . '/app/Model/TaskFileModel.php',
+ 'Kanboard\\Model\\TaskFinderModel' => $baseDir . '/app/Model/TaskFinderModel.php',
+ 'Kanboard\\Model\\TaskLinkModel' => $baseDir . '/app/Model/TaskLinkModel.php',
+ 'Kanboard\\Model\\TaskMetadataModel' => $baseDir . '/app/Model/TaskMetadataModel.php',
+ 'Kanboard\\Model\\TaskModel' => $baseDir . '/app/Model/TaskModel.php',
+ 'Kanboard\\Model\\TaskModificationModel' => $baseDir . '/app/Model/TaskModificationModel.php',
+ 'Kanboard\\Model\\TaskPositionModel' => $baseDir . '/app/Model/TaskPositionModel.php',
+ 'Kanboard\\Model\\TaskProjectDuplicationModel' => $baseDir . '/app/Model/TaskProjectDuplicationModel.php',
+ 'Kanboard\\Model\\TaskProjectMoveModel' => $baseDir . '/app/Model/TaskProjectMoveModel.php',
+ 'Kanboard\\Model\\TaskRecurrenceModel' => $baseDir . '/app/Model/TaskRecurrenceModel.php',
+ 'Kanboard\\Model\\TaskStatusModel' => $baseDir . '/app/Model/TaskStatusModel.php',
+ 'Kanboard\\Model\\TaskTagModel' => $baseDir . '/app/Model/TaskTagModel.php',
+ 'Kanboard\\Model\\TimezoneModel' => $baseDir . '/app/Model/TimezoneModel.php',
+ 'Kanboard\\Model\\TransitionModel' => $baseDir . '/app/Model/TransitionModel.php',
+ 'Kanboard\\Model\\UserLockingModel' => $baseDir . '/app/Model/UserLockingModel.php',
+ 'Kanboard\\Model\\UserMetadataModel' => $baseDir . '/app/Model/UserMetadataModel.php',
+ 'Kanboard\\Model\\UserModel' => $baseDir . '/app/Model/UserModel.php',
+ 'Kanboard\\Model\\UserNotificationFilterModel' => $baseDir . '/app/Model/UserNotificationFilterModel.php',
+ 'Kanboard\\Model\\UserNotificationModel' => $baseDir . '/app/Model/UserNotificationModel.php',
+ 'Kanboard\\Model\\UserNotificationTypeModel' => $baseDir . '/app/Model/UserNotificationTypeModel.php',
+ 'Kanboard\\Model\\UserUnreadNotificationModel' => $baseDir . '/app/Model/UserUnreadNotificationModel.php',
+ 'Kanboard\\Notification\\ActivityStreamNotification' => $baseDir . '/app/Notification/ActivityStreamNotification.php',
+ 'Kanboard\\Notification\\MailNotification' => $baseDir . '/app/Notification/MailNotification.php',
+ 'Kanboard\\Notification\\WebNotification' => $baseDir . '/app/Notification/WebNotification.php',
+ 'Kanboard\\Notification\\WebhookNotification' => $baseDir . '/app/Notification/WebhookNotification.php',
+ 'Kanboard\\Pagination\\DashboardPagination' => $baseDir . '/app/Pagination/DashboardPagination.php',
+ 'Kanboard\\Pagination\\ProjectPagination' => $baseDir . '/app/Pagination/ProjectPagination.php',
+ 'Kanboard\\Pagination\\SubtaskPagination' => $baseDir . '/app/Pagination/SubtaskPagination.php',
+ 'Kanboard\\Pagination\\TaskPagination' => $baseDir . '/app/Pagination/TaskPagination.php',
+ 'Kanboard\\Pagination\\UserPagination' => $baseDir . '/app/Pagination/UserPagination.php',
+ 'Kanboard\\ServiceProvider\\ActionProvider' => $baseDir . '/app/ServiceProvider/ActionProvider.php',
+ 'Kanboard\\ServiceProvider\\ApiProvider' => $baseDir . '/app/ServiceProvider/ApiProvider.php',
+ 'Kanboard\\ServiceProvider\\AuthenticationProvider' => $baseDir . '/app/ServiceProvider/AuthenticationProvider.php',
+ 'Kanboard\\ServiceProvider\\AvatarProvider' => $baseDir . '/app/ServiceProvider/AvatarProvider.php',
+ 'Kanboard\\ServiceProvider\\CacheProvider' => $baseDir . '/app/ServiceProvider/CacheProvider.php',
+ 'Kanboard\\ServiceProvider\\ClassProvider' => $baseDir . '/app/ServiceProvider/ClassProvider.php',
+ 'Kanboard\\ServiceProvider\\CommandProvider' => $baseDir . '/app/ServiceProvider/CommandProvider.php',
+ 'Kanboard\\ServiceProvider\\DatabaseProvider' => $baseDir . '/app/ServiceProvider/DatabaseProvider.php',
+ 'Kanboard\\ServiceProvider\\EventDispatcherProvider' => $baseDir . '/app/ServiceProvider/EventDispatcherProvider.php',
+ 'Kanboard\\ServiceProvider\\ExternalLinkProvider' => $baseDir . '/app/ServiceProvider/ExternalLinkProvider.php',
+ 'Kanboard\\ServiceProvider\\ExternalTaskProvider' => $baseDir . '/app/ServiceProvider/ExternalTaskProvider.php',
+ 'Kanboard\\ServiceProvider\\FilterProvider' => $baseDir . '/app/ServiceProvider/FilterProvider.php',
+ 'Kanboard\\ServiceProvider\\FormatterProvider' => $baseDir . '/app/ServiceProvider/FormatterProvider.php',
+ 'Kanboard\\ServiceProvider\\GroupProvider' => $baseDir . '/app/ServiceProvider/GroupProvider.php',
+ 'Kanboard\\ServiceProvider\\HelperProvider' => $baseDir . '/app/ServiceProvider/HelperProvider.php',
+ 'Kanboard\\ServiceProvider\\JobProvider' => $baseDir . '/app/ServiceProvider/JobProvider.php',
+ 'Kanboard\\ServiceProvider\\LoggingProvider' => $baseDir . '/app/ServiceProvider/LoggingProvider.php',
+ 'Kanboard\\ServiceProvider\\MailProvider' => $baseDir . '/app/ServiceProvider/MailProvider.php',
+ 'Kanboard\\ServiceProvider\\NotificationProvider' => $baseDir . '/app/ServiceProvider/NotificationProvider.php',
+ 'Kanboard\\ServiceProvider\\ObjectStorageProvider' => $baseDir . '/app/ServiceProvider/ObjectStorageProvider.php',
+ 'Kanboard\\ServiceProvider\\PluginProvider' => $baseDir . '/app/ServiceProvider/PluginProvider.php',
+ 'Kanboard\\ServiceProvider\\QueueProvider' => $baseDir . '/app/ServiceProvider/QueueProvider.php',
+ 'Kanboard\\ServiceProvider\\RouteProvider' => $baseDir . '/app/ServiceProvider/RouteProvider.php',
+ 'Kanboard\\ServiceProvider\\SessionProvider' => $baseDir . '/app/ServiceProvider/SessionProvider.php',
+ 'Kanboard\\Subscriber\\AuthSubscriber' => $baseDir . '/app/Subscriber/AuthSubscriber.php',
+ 'Kanboard\\Subscriber\\BaseSubscriber' => $baseDir . '/app/Subscriber/BaseSubscriber.php',
+ 'Kanboard\\Subscriber\\BootstrapSubscriber' => $baseDir . '/app/Subscriber/BootstrapSubscriber.php',
+ 'Kanboard\\Subscriber\\LdapUserPhotoSubscriber' => $baseDir . '/app/Subscriber/LdapUserPhotoSubscriber.php',
+ 'Kanboard\\Subscriber\\NotificationSubscriber' => $baseDir . '/app/Subscriber/NotificationSubscriber.php',
+ 'Kanboard\\Subscriber\\ProjectDailySummarySubscriber' => $baseDir . '/app/Subscriber/ProjectDailySummarySubscriber.php',
+ 'Kanboard\\Subscriber\\ProjectModificationDateSubscriber' => $baseDir . '/app/Subscriber/ProjectModificationDateSubscriber.php',
+ 'Kanboard\\Subscriber\\RecurringTaskSubscriber' => $baseDir . '/app/Subscriber/RecurringTaskSubscriber.php',
+ 'Kanboard\\Subscriber\\TransitionSubscriber' => $baseDir . '/app/Subscriber/TransitionSubscriber.php',
+ 'Kanboard\\User\\Avatar\\AvatarFileProvider' => $baseDir . '/app/User/Avatar/AvatarFileProvider.php',
+ 'Kanboard\\User\\Avatar\\LetterAvatarProvider' => $baseDir . '/app/User/Avatar/LetterAvatarProvider.php',
+ 'Kanboard\\User\\DatabaseUserProvider' => $baseDir . '/app/User/DatabaseUserProvider.php',
+ 'Kanboard\\User\\LdapUserProvider' => $baseDir . '/app/User/LdapUserProvider.php',
+ 'Kanboard\\User\\OAuthUserProvider' => $baseDir . '/app/User/OAuthUserProvider.php',
+ 'Kanboard\\User\\ReverseProxyUserProvider' => $baseDir . '/app/User/ReverseProxyUserProvider.php',
+ 'Kanboard\\Validator\\ActionValidator' => $baseDir . '/app/Validator/ActionValidator.php',
+ 'Kanboard\\Validator\\AuthValidator' => $baseDir . '/app/Validator/AuthValidator.php',
+ 'Kanboard\\Validator\\BaseValidator' => $baseDir . '/app/Validator/BaseValidator.php',
+ 'Kanboard\\Validator\\CategoryValidator' => $baseDir . '/app/Validator/CategoryValidator.php',
+ 'Kanboard\\Validator\\ColumnMoveRestrictionValidator' => $baseDir . '/app/Validator/ColumnMoveRestrictionValidator.php',
+ 'Kanboard\\Validator\\ColumnRestrictionValidator' => $baseDir . '/app/Validator/ColumnRestrictionValidator.php',
+ 'Kanboard\\Validator\\ColumnValidator' => $baseDir . '/app/Validator/ColumnValidator.php',
+ 'Kanboard\\Validator\\CommentValidator' => $baseDir . '/app/Validator/CommentValidator.php',
+ 'Kanboard\\Validator\\CurrencyValidator' => $baseDir . '/app/Validator/CurrencyValidator.php',
+ 'Kanboard\\Validator\\CustomFilterValidator' => $baseDir . '/app/Validator/CustomFilterValidator.php',
+ 'Kanboard\\Validator\\ExternalLinkValidator' => $baseDir . '/app/Validator/ExternalLinkValidator.php',
+ 'Kanboard\\Validator\\GroupValidator' => $baseDir . '/app/Validator/GroupValidator.php',
+ 'Kanboard\\Validator\\LinkValidator' => $baseDir . '/app/Validator/LinkValidator.php',
+ 'Kanboard\\Validator\\PasswordResetValidator' => $baseDir . '/app/Validator/PasswordResetValidator.php',
+ 'Kanboard\\Validator\\ProjectRoleValidator' => $baseDir . '/app/Validator/ProjectRoleValidator.php',
+ 'Kanboard\\Validator\\ProjectValidator' => $baseDir . '/app/Validator/ProjectValidator.php',
+ 'Kanboard\\Validator\\SubtaskValidator' => $baseDir . '/app/Validator/SubtaskValidator.php',
+ 'Kanboard\\Validator\\SwimlaneValidator' => $baseDir . '/app/Validator/SwimlaneValidator.php',
+ 'Kanboard\\Validator\\TagValidator' => $baseDir . '/app/Validator/TagValidator.php',
+ 'Kanboard\\Validator\\TaskLinkValidator' => $baseDir . '/app/Validator/TaskLinkValidator.php',
+ 'Kanboard\\Validator\\TaskValidator' => $baseDir . '/app/Validator/TaskValidator.php',
+ 'Kanboard\\Validator\\UserValidator' => $baseDir . '/app/Validator/UserValidator.php',
+ 'Otp\\GoogleAuthenticator' => $vendorDir . '/christian-riesen/otp/src/Otp/GoogleAuthenticator.php',
+ 'Otp\\Otp' => $vendorDir . '/christian-riesen/otp/src/Otp/Otp.php',
+ 'Otp\\OtpInterface' => $vendorDir . '/christian-riesen/otp/src/Otp/OtpInterface.php',
+ 'PHPQRCode' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode.php',
+ 'PHPQRCode\\Autoloader' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/Autoloader.php',
+ 'PHPQRCode\\Constants' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/Constants.php',
+ 'PHPQRCode\\FrameFiller' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/FrameFiller.php',
+ 'PHPQRCode\\QRbitstream' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php',
+ 'PHPQRCode\\QRcode' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php',
+ 'PHPQRCode\\QRencode' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php',
+ 'PHPQRCode\\QRimage' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php',
+ 'PHPQRCode\\QRinput' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php',
+ 'PHPQRCode\\QRinputItem' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php',
+ 'PHPQRCode\\QRmask' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php',
+ 'PHPQRCode\\QRrawcode' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php',
+ 'PHPQRCode\\QRrs' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php',
+ 'PHPQRCode\\QRrsItem' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php',
+ 'PHPQRCode\\QRrsblock' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php',
+ 'PHPQRCode\\QRspec' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php',
+ 'PHPQRCode\\QRsplit' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php',
+ 'PHPQRCode\\QRstr' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php',
+ 'PHPQRCode\\QRtools' => $vendorDir . '/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php',
+ 'Parsedown' => $vendorDir . '/erusev/parsedown/Parsedown.php',
+ 'ParsedownTest' => $vendorDir . '/erusev/parsedown/test/ParsedownTest.php',
+ 'PicoDb\\Builder\\BaseBuilder' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Builder/BaseBuilder.php',
+ 'PicoDb\\Builder\\ConditionBuilder' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php',
+ 'PicoDb\\Builder\\InsertBuilder' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php',
+ 'PicoDb\\Builder\\OrConditionBuilder' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php',
+ 'PicoDb\\Builder\\UpdateBuilder' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php',
+ 'PicoDb\\Database' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Database.php',
+ 'PicoDb\\DriverFactory' => $vendorDir . '/fguillot/picodb/lib/PicoDb/DriverFactory.php',
+ 'PicoDb\\Driver\\Base' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Base.php',
+ 'PicoDb\\Driver\\Mssql' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Mssql.php',
+ 'PicoDb\\Driver\\Mysql' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Mysql.php',
+ 'PicoDb\\Driver\\Postgres' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Postgres.php',
+ 'PicoDb\\Driver\\Sqlite' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php',
+ 'PicoDb\\Hashtable' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Hashtable.php',
+ 'PicoDb\\LargeObject' => $vendorDir . '/fguillot/picodb/lib/PicoDb/LargeObject.php',
+ 'PicoDb\\SQLException' => $vendorDir . '/fguillot/picodb/lib/PicoDb/SQLException.php',
+ 'PicoDb\\Schema' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Schema.php',
+ 'PicoDb\\StatementHandler' => $vendorDir . '/fguillot/picodb/lib/PicoDb/StatementHandler.php',
+ 'PicoDb\\Table' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Table.php',
+ 'PicoDb\\UrlParser' => $vendorDir . '/fguillot/picodb/lib/PicoDb/UrlParser.php',
+ 'PicoFeed\\Base' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Base.php',
+ 'PicoFeed\\Client\\Client' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/Client.php',
+ 'PicoFeed\\Client\\ClientException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php',
+ 'PicoFeed\\Client\\Curl' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/Curl.php',
+ 'PicoFeed\\Client\\ForbiddenException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php',
+ 'PicoFeed\\Client\\HttpHeaders' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/HttpHeaders.php',
+ 'PicoFeed\\Client\\InvalidCertificateException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php',
+ 'PicoFeed\\Client\\InvalidUrlException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/InvalidUrlException.php',
+ 'PicoFeed\\Client\\MaxRedirectException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/MaxRedirectException.php',
+ 'PicoFeed\\Client\\MaxSizeException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/MaxSizeException.php',
+ 'PicoFeed\\Client\\Stream' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/Stream.php',
+ 'PicoFeed\\Client\\TimeoutException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php',
+ 'PicoFeed\\Client\\UnauthorizedException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/UnauthorizedException.php',
+ 'PicoFeed\\Client\\Url' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Client/Url.php',
+ 'PicoFeed\\Config\\Config' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Config/Config.php',
+ 'PicoFeed\\Encoding\\Encoding' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php',
+ 'PicoFeed\\Filter\\Attribute' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Filter/Attribute.php',
+ 'PicoFeed\\Filter\\Filter' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php',
+ 'PicoFeed\\Filter\\Html' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Filter/Html.php',
+ 'PicoFeed\\Filter\\Tag' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php',
+ 'PicoFeed\\Generator\\ContentGeneratorInterface' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php',
+ 'PicoFeed\\Generator\\FileContentGenerator' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php',
+ 'PicoFeed\\Generator\\YoutubeContentGenerator' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php',
+ 'PicoFeed\\Logging\\Logger' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php',
+ 'PicoFeed\\Parser\\Atom' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php',
+ 'PicoFeed\\Parser\\DateParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php',
+ 'PicoFeed\\Parser\\Feed' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php',
+ 'PicoFeed\\Parser\\Item' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Item.php',
+ 'PicoFeed\\Parser\\MalformedXmlException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php',
+ 'PicoFeed\\Parser\\Parser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Parser.php',
+ 'PicoFeed\\Parser\\ParserException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php',
+ 'PicoFeed\\Parser\\ParserInterface' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/ParserInterface.php',
+ 'PicoFeed\\Parser\\Rss10' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss10.php',
+ 'PicoFeed\\Parser\\Rss20' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php',
+ 'PicoFeed\\Parser\\Rss91' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php',
+ 'PicoFeed\\Parser\\Rss92' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss92.php',
+ 'PicoFeed\\Parser\\XmlEntityException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/XmlEntityException.php',
+ 'PicoFeed\\Parser\\XmlParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Parser/XmlParser.php',
+ 'PicoFeed\\PicoFeedException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php',
+ 'PicoFeed\\Processor\\ContentFilterProcessor' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php',
+ 'PicoFeed\\Processor\\ContentGeneratorProcessor' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php',
+ 'PicoFeed\\Processor\\ItemPostProcessor' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php',
+ 'PicoFeed\\Processor\\ItemProcessorInterface' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php',
+ 'PicoFeed\\Processor\\ScraperProcessor' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php',
+ 'PicoFeed\\Reader\\Favicon' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php',
+ 'PicoFeed\\Reader\\Reader' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php',
+ 'PicoFeed\\Reader\\ReaderException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php',
+ 'PicoFeed\\Reader\\SubscriptionNotFoundException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php',
+ 'PicoFeed\\Reader\\UnsupportedFeedFormatException' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php',
+ 'PicoFeed\\Scraper\\CandidateParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php',
+ 'PicoFeed\\Scraper\\ParserInterface' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php',
+ 'PicoFeed\\Scraper\\RuleLoader' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Scraper/RuleLoader.php',
+ 'PicoFeed\\Scraper\\RuleParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php',
+ 'PicoFeed\\Scraper\\Scraper' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php',
+ 'PicoFeed\\Serialization\\Subscription' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php',
+ 'PicoFeed\\Serialization\\SubscriptionList' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php',
+ 'PicoFeed\\Serialization\\SubscriptionListBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php',
+ 'PicoFeed\\Serialization\\SubscriptionListParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php',
+ 'PicoFeed\\Serialization\\SubscriptionParser' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php',
+ 'PicoFeed\\Syndication\\AtomFeedBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php',
+ 'PicoFeed\\Syndication\\AtomHelper' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php',
+ 'PicoFeed\\Syndication\\AtomItemBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php',
+ 'PicoFeed\\Syndication\\FeedBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php',
+ 'PicoFeed\\Syndication\\ItemBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php',
+ 'PicoFeed\\Syndication\\Rss20FeedBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php',
+ 'PicoFeed\\Syndication\\Rss20Helper' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php',
+ 'PicoFeed\\Syndication\\Rss20ItemBuilder' => $vendorDir . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php',
+ 'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php',
+ 'Pimple\\ServiceProviderInterface' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php',
+ 'Pimple\\Tests\\Fixtures\\Invokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php',
+ 'Pimple\\Tests\\Fixtures\\NonInvokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php',
+ 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php',
+ 'Pimple\\Tests\\Fixtures\\Service' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php',
+ 'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php',
+ 'Pimple\\Tests\\PimpleTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php',
+ 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
+ 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php',
+ 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php',
+ 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php',
+ 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php',
+ 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
+ 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
+ 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
+ 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
+ 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
+ 'SimpleLogger\\Base' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/Base.php',
+ 'SimpleLogger\\File' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/File.php',
+ 'SimpleLogger\\Logger' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/Logger.php',
+ 'SimpleLogger\\Stderr' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/Stderr.php',
+ 'SimpleLogger\\Stdout' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/Stdout.php',
+ 'SimpleLogger\\Syslog' => $vendorDir . '/fguillot/simpleLogger/src/SimpleLogger/Syslog.php',
+ 'SimpleQueue\\Adapter\\AmqpQueueAdapter' => $vendorDir . '/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\AwsSqsQueueAdapter' => $vendorDir . '/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\BeanstalkQueueAdapter' => $vendorDir . '/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\DisqueQueueAdapter' => $vendorDir . '/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\MemoryQueueAdapter' => $vendorDir . '/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php',
+ 'SimpleQueue\\Exception\\NotSupportedException' => $vendorDir . '/fguillot/simple-queue/src/Exception/NotSupportedException.php',
+ 'SimpleQueue\\Job' => $vendorDir . '/fguillot/simple-queue/src/Job.php',
+ 'SimpleQueue\\Queue' => $vendorDir . '/fguillot/simple-queue/src/Queue.php',
+ 'SimpleQueue\\QueueAdapterInterface' => $vendorDir . '/fguillot/simple-queue/src/QueueAdapterInterface.php',
+ 'SimpleValidator\\Validator' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validator.php',
+ 'SimpleValidator\\Validators\\Alpha' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php',
+ 'SimpleValidator\\Validators\\AlphaNumeric' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php',
+ 'SimpleValidator\\Validators\\Base' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php',
+ 'SimpleValidator\\Validators\\Date' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php',
+ 'SimpleValidator\\Validators\\Email' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php',
+ 'SimpleValidator\\Validators\\Equals' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php',
+ 'SimpleValidator\\Validators\\Exists' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php',
+ 'SimpleValidator\\Validators\\GreaterThan' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php',
+ 'SimpleValidator\\Validators\\InArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php',
+ 'SimpleValidator\\Validators\\Integer' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php',
+ 'SimpleValidator\\Validators\\Ip' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php',
+ 'SimpleValidator\\Validators\\Length' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php',
+ 'SimpleValidator\\Validators\\MaxLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php',
+ 'SimpleValidator\\Validators\\MinLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php',
+ 'SimpleValidator\\Validators\\NotEmpty' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php',
+ 'SimpleValidator\\Validators\\NotEquals' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php',
+ 'SimpleValidator\\Validators\\NotInArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php',
+ 'SimpleValidator\\Validators\\Numeric' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php',
+ 'SimpleValidator\\Validators\\Range' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php',
+ 'SimpleValidator\\Validators\\Required' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php',
+ 'SimpleValidator\\Validators\\Unique' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php',
+ 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php',
+ 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php',
+ 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php',
+ 'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php',
+ 'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php',
+ 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php',
+ 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php',
+ 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => $vendorDir . '/symfony/console/Event/ConsoleExceptionEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php',
+ 'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php',
+ 'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php',
+ 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php',
+ 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php',
+ 'Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php',
+ 'Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
+ 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\DialogHelper' => $vendorDir . '/symfony/console/Helper/DialogHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php',
+ 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php',
+ 'Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php',
+ 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => $vendorDir . '/symfony/console/Helper/ProgressHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php',
+ 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php',
+ 'Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php',
+ 'Symfony\\Component\\Console\\Helper\\TableHelper' => $vendorDir . '/symfony/console/Helper/TableHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php',
+ 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php',
+ 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php',
+ 'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php',
+ 'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php',
+ 'Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php',
+ 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php',
+ 'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php',
+ 'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php',
+ 'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php',
+ 'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php',
+ 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php',
+ 'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php',
+ 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php',
+ 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php',
+ 'Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php',
+ 'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php',
+ 'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php',
+ 'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php',
+ 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php',
+ 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php',
+ 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php',
+ 'Symfony\\Component\\Console\\Shell' => $vendorDir . '/symfony/console/Shell.php',
+ 'Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php',
+ 'Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php',
+ 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php',
+ 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php',
+ 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php',
+ 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php',
+ 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php',
+ 'Symfony\\Component\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher/Event.php',
+ 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/EventDispatcherInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/EventSubscriberInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/GenericEvent.php',
+ 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ImmutableEventDispatcher.php',
+ 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
+ 'ZendXml\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zendxml/library/ZendXml/Exception/ExceptionInterface.php',
+ 'ZendXml\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zendxml/library/ZendXml/Exception/InvalidArgumentException.php',
+ 'ZendXml\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zendxml/library/ZendXml/Exception/RuntimeException.php',
+ 'ZendXml\\Security' => $vendorDir . '/zendframework/zendxml/library/ZendXml/Security.php',
+);
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
new file mode 100644
index 00000000..e7fae22d
--- /dev/null
+++ b/vendor/composer/autoload_files.php
@@ -0,0 +1,15 @@
+ $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+ '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
+ '8cd2fca4db21bffce1ad0612f7caeec4' => $vendorDir . '/ramsey/array_column/src/array_column.php',
+ '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
+ 'f51af1d1e172536bcdb5baf6f649449d' => $baseDir . '/app/functions.php',
+ 'da6e17f7b0fa11d4819751ff2afd0bac' => $baseDir . '/app/Library/password.php',
+);
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
new file mode 100644
index 00000000..c2ba047d
--- /dev/null
+++ b/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,20 @@
+ array($vendorDir . '/zendframework/zendxml/library'),
+ 'SimpleValidator' => array($vendorDir . '/fguillot/simple-validator/src'),
+ 'SimpleLogger' => array($vendorDir . '/fguillot/simpleLogger/src'),
+ 'Pimple' => array($vendorDir . '/pimple/pimple/src'),
+ 'PicoFeed' => array($vendorDir . '/miniflux/picofeed/lib'),
+ 'PicoDb' => array($vendorDir . '/fguillot/picodb/lib'),
+ 'Parsedown' => array($vendorDir . '/erusev/parsedown'),
+ 'PHPQRCode' => array($vendorDir . '/aferrandini/phpqrcode/lib'),
+ 'Otp' => array($vendorDir . '/christian-riesen/otp/src'),
+ 'JsonRPC' => array($vendorDir . '/fguillot/json-rpc/src'),
+ 'Eluceo\\iCal' => array($vendorDir . '/eluceo/ical/src'),
+);
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
new file mode 100644
index 00000000..7367aa46
--- /dev/null
+++ b/vendor/composer/autoload_psr4.php
@@ -0,0 +1,17 @@
+ array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
+ 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
+ 'SimpleQueue\\' => array($vendorDir . '/fguillot/simple-queue/src'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'Kanboard\\' => array($baseDir . '/app'),
+ 'Gregwar\\Captcha\\' => array($vendorDir . '/gregwar/captcha'),
+ 'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'),
+);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
new file mode 100644
index 00000000..2f490fe8
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,70 @@
+= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+ if ($useStaticLoader) {
+ require_once __DIR__ . '/autoload_static.php';
+
+ call_user_func(\Composer\Autoload\ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::getInitializer($loader));
+ } else {
+ $map = require __DIR__ . '/autoload_namespaces.php';
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $map = require __DIR__ . '/autoload_psr4.php';
+ foreach ($map as $namespace => $path) {
+ $loader->setPsr4($namespace, $path);
+ }
+
+ $classMap = require __DIR__ . '/autoload_classmap.php';
+ if ($classMap) {
+ $loader->addClassMap($classMap);
+ }
+ }
+
+ $loader->register(true);
+
+ if ($useStaticLoader) {
+ $includeFiles = Composer\Autoload\ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::$files;
+ } else {
+ $includeFiles = require __DIR__ . '/autoload_files.php';
+ }
+ foreach ($includeFiles as $fileIdentifier => $file) {
+ composerRequire6edea6294a88689e3f5c56484bb70c9b($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
+
+function composerRequire6edea6294a88689e3f5c56484bb70c9b($fileIdentifier, $file)
+{
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ require $file;
+
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+ }
+}
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
new file mode 100644
index 00000000..626fed60
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,1049 @@
+ __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
+ '8cd2fca4db21bffce1ad0612f7caeec4' => __DIR__ . '/..' . '/ramsey/array_column/src/array_column.php',
+ '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
+ 'f51af1d1e172536bcdb5baf6f649449d' => __DIR__ . '/../..' . '/app/functions.php',
+ 'da6e17f7b0fa11d4819751ff2afd0bac' => __DIR__ . '/../..' . '/app/Library/password.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'S' =>
+ array (
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Component\\EventDispatcher\\' => 34,
+ 'Symfony\\Component\\Console\\' => 26,
+ 'SimpleQueue\\' => 12,
+ ),
+ 'P' =>
+ array (
+ 'Psr\\Log\\' => 8,
+ ),
+ 'K' =>
+ array (
+ 'Kanboard\\' => 9,
+ ),
+ 'G' =>
+ array (
+ 'Gregwar\\Captcha\\' => 16,
+ ),
+ 'B' =>
+ array (
+ 'Base32\\' => 7,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Symfony\\Polyfill\\Mbstring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+ ),
+ 'Symfony\\Component\\EventDispatcher\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
+ ),
+ 'Symfony\\Component\\Console\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/console',
+ ),
+ 'SimpleQueue\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/fguillot/simple-queue/src',
+ ),
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+ ),
+ 'Kanboard\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/app',
+ ),
+ 'Gregwar\\Captcha\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/gregwar/captcha',
+ ),
+ 'Base32\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/christian-riesen/base32/src',
+ ),
+ );
+
+ public static $prefixesPsr0 = array (
+ 'Z' =>
+ array (
+ 'ZendXml\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/zendframework/zendxml/library',
+ ),
+ ),
+ 'S' =>
+ array (
+ 'SimpleValidator' =>
+ array (
+ 0 => __DIR__ . '/..' . '/fguillot/simple-validator/src',
+ ),
+ 'SimpleLogger' =>
+ array (
+ 0 => __DIR__ . '/..' . '/fguillot/simpleLogger/src',
+ ),
+ ),
+ 'P' =>
+ array (
+ 'Pimple' =>
+ array (
+ 0 => __DIR__ . '/..' . '/pimple/pimple/src',
+ ),
+ 'PicoFeed' =>
+ array (
+ 0 => __DIR__ . '/..' . '/miniflux/picofeed/lib',
+ ),
+ 'PicoDb' =>
+ array (
+ 0 => __DIR__ . '/..' . '/fguillot/picodb/lib',
+ ),
+ 'Parsedown' =>
+ array (
+ 0 => __DIR__ . '/..' . '/erusev/parsedown',
+ ),
+ 'PHPQRCode' =>
+ array (
+ 0 => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib',
+ ),
+ ),
+ 'O' =>
+ array (
+ 'Otp' =>
+ array (
+ 0 => __DIR__ . '/..' . '/christian-riesen/otp/src',
+ ),
+ ),
+ 'J' =>
+ array (
+ 'JsonRPC' =>
+ array (
+ 0 => __DIR__ . '/..' . '/fguillot/json-rpc/src',
+ ),
+ ),
+ 'E' =>
+ array (
+ 'Eluceo\\iCal' =>
+ array (
+ 0 => __DIR__ . '/..' . '/eluceo/ical/src',
+ ),
+ ),
+ );
+
+ public static $classMap = array (
+ 'Base32\\Base32' => __DIR__ . '/..' . '/christian-riesen/base32/src/Base32.php',
+ 'Eluceo\\iCal\\Component' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component.php',
+ 'Eluceo\\iCal\\Component\\Alarm' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php',
+ 'Eluceo\\iCal\\Component\\Calendar' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php',
+ 'Eluceo\\iCal\\Component\\Event' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component/Event.php',
+ 'Eluceo\\iCal\\Component\\Timezone' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php',
+ 'Eluceo\\iCal\\Component\\TimezoneRule' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php',
+ 'Eluceo\\iCal\\ParameterBag' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/ParameterBag.php',
+ 'Eluceo\\iCal\\Property' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property.php',
+ 'Eluceo\\iCal\\PropertyBag' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/PropertyBag.php',
+ 'Eluceo\\iCal\\Property\\ArrayValue' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php',
+ 'Eluceo\\iCal\\Property\\DateTimeProperty' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php',
+ 'Eluceo\\iCal\\Property\\DateTimesProperty' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php',
+ 'Eluceo\\iCal\\Property\\Event\\Attendees' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php',
+ 'Eluceo\\iCal\\Property\\Event\\Description' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php',
+ 'Eluceo\\iCal\\Property\\Event\\Organizer' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php',
+ 'Eluceo\\iCal\\Property\\Event\\RecurrenceId' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php',
+ 'Eluceo\\iCal\\Property\\Event\\RecurrenceRule' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php',
+ 'Eluceo\\iCal\\Property\\StringValue' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php',
+ 'Eluceo\\iCal\\Property\\ValueInterface' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php',
+ 'Eluceo\\iCal\\Util\\ComponentUtil' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php',
+ 'Eluceo\\iCal\\Util\\DateUtil' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php',
+ 'Eluceo\\iCal\\Util\\PropertyValueUtil' => __DIR__ . '/..' . '/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php',
+ 'Gregwar\\Captcha\\CaptchaBuilder' => __DIR__ . '/..' . '/gregwar/captcha/CaptchaBuilder.php',
+ 'Gregwar\\Captcha\\CaptchaBuilderInterface' => __DIR__ . '/..' . '/gregwar/captcha/CaptchaBuilderInterface.php',
+ 'Gregwar\\Captcha\\ImageFileHandler' => __DIR__ . '/..' . '/gregwar/captcha/ImageFileHandler.php',
+ 'Gregwar\\Captcha\\PhraseBuilder' => __DIR__ . '/..' . '/gregwar/captcha/PhraseBuilder.php',
+ 'Gregwar\\Captcha\\PhraseBuilderInterface' => __DIR__ . '/..' . '/gregwar/captcha/PhraseBuilderInterface.php',
+ 'JsonRPC\\Client' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Client.php',
+ 'JsonRPC\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php',
+ 'JsonRPC\\Exception\\AuthenticationFailureException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/AuthenticationFailureException.php',
+ 'JsonRPC\\Exception\\ConnectionFailureException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ConnectionFailureException.php',
+ 'JsonRPC\\Exception\\InvalidJsonFormatException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonFormatException.php',
+ 'JsonRPC\\Exception\\InvalidJsonRpcFormatException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonRpcFormatException.php',
+ 'JsonRPC\\Exception\\ResponseEncodingFailureException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseEncodingFailureException.php',
+ 'JsonRPC\\Exception\\ResponseException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php',
+ 'JsonRPC\\Exception\\ServerErrorException' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php',
+ 'JsonRPC\\HttpClient' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/HttpClient.php',
+ 'JsonRPC\\MiddlewareHandler' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php',
+ 'JsonRPC\\MiddlewareInterface' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php',
+ 'JsonRPC\\ProcedureHandler' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php',
+ 'JsonRPC\\Request\\BatchRequestParser' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php',
+ 'JsonRPC\\Request\\RequestBuilder' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php',
+ 'JsonRPC\\Request\\RequestParser' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php',
+ 'JsonRPC\\Response\\ResponseBuilder' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php',
+ 'JsonRPC\\Response\\ResponseParser' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php',
+ 'JsonRPC\\Server' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Server.php',
+ 'JsonRPC\\Validator\\HostValidator' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php',
+ 'JsonRPC\\Validator\\JsonEncodingValidator' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Validator/JsonEncodingValidator.php',
+ 'JsonRPC\\Validator\\JsonFormatValidator' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Validator/JsonFormatValidator.php',
+ 'JsonRPC\\Validator\\RpcFormatValidator' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Validator/RpcFormatValidator.php',
+ 'JsonRPC\\Validator\\UserValidator' => __DIR__ . '/..' . '/fguillot/json-rpc/src/JsonRPC/Validator/UserValidator.php',
+ 'Kanboard\\Action\\Base' => __DIR__ . '/../..' . '/app/Action/Base.php',
+ 'Kanboard\\Action\\CommentCreation' => __DIR__ . '/../..' . '/app/Action/CommentCreation.php',
+ 'Kanboard\\Action\\CommentCreationMoveTaskColumn' => __DIR__ . '/../..' . '/app/Action/CommentCreationMoveTaskColumn.php',
+ 'Kanboard\\Action\\TaskAssignCategoryColor' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryColor.php',
+ 'Kanboard\\Action\\TaskAssignCategoryLabel' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryLabel.php',
+ 'Kanboard\\Action\\TaskAssignCategoryLink' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryLink.php',
+ 'Kanboard\\Action\\TaskAssignColorCategory' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorCategory.php',
+ 'Kanboard\\Action\\TaskAssignColorColumn' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorColumn.php',
+ 'Kanboard\\Action\\TaskAssignColorLink' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorLink.php',
+ 'Kanboard\\Action\\TaskAssignColorOnDueDate' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorOnDueDate.php',
+ 'Kanboard\\Action\\TaskAssignColorPriority' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorPriority.php',
+ 'Kanboard\\Action\\TaskAssignColorSwimlane' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorSwimlane.php',
+ 'Kanboard\\Action\\TaskAssignColorUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorUser.php',
+ 'Kanboard\\Action\\TaskAssignCreator' => __DIR__ . '/../..' . '/app/Action/TaskAssignCreator.php',
+ 'Kanboard\\Action\\TaskAssignCurrentUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignCurrentUser.php',
+ 'Kanboard\\Action\\TaskAssignCurrentUserColumn' => __DIR__ . '/../..' . '/app/Action/TaskAssignCurrentUserColumn.php',
+ 'Kanboard\\Action\\TaskAssignDueDateOnCreation' => __DIR__ . '/../..' . '/app/Action/TaskAssignDueDateOnCreation.php',
+ 'Kanboard\\Action\\TaskAssignPrioritySwimlane' => __DIR__ . '/../..' . '/app/Action/TaskAssignPrioritySwimlane.php',
+ 'Kanboard\\Action\\TaskAssignSpecificUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignSpecificUser.php',
+ 'Kanboard\\Action\\TaskAssignUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignUser.php',
+ 'Kanboard\\Action\\TaskClose' => __DIR__ . '/../..' . '/app/Action/TaskClose.php',
+ 'Kanboard\\Action\\TaskCloseColumn' => __DIR__ . '/../..' . '/app/Action/TaskCloseColumn.php',
+ 'Kanboard\\Action\\TaskCloseNoActivity' => __DIR__ . '/../..' . '/app/Action/TaskCloseNoActivity.php',
+ 'Kanboard\\Action\\TaskCloseNoActivityColumn' => __DIR__ . '/../..' . '/app/Action/TaskCloseNoActivityColumn.php',
+ 'Kanboard\\Action\\TaskCloseNotMovedColumn' => __DIR__ . '/../..' . '/app/Action/TaskCloseNotMovedColumn.php',
+ 'Kanboard\\Action\\TaskCreation' => __DIR__ . '/../..' . '/app/Action/TaskCreation.php',
+ 'Kanboard\\Action\\TaskDuplicateAnotherProject' => __DIR__ . '/../..' . '/app/Action/TaskDuplicateAnotherProject.php',
+ 'Kanboard\\Action\\TaskEmail' => __DIR__ . '/../..' . '/app/Action/TaskEmail.php',
+ 'Kanboard\\Action\\TaskEmailNoActivity' => __DIR__ . '/../..' . '/app/Action/TaskEmailNoActivity.php',
+ 'Kanboard\\Action\\TaskMoveAnotherProject' => __DIR__ . '/../..' . '/app/Action/TaskMoveAnotherProject.php',
+ 'Kanboard\\Action\\TaskMoveColumnAssigned' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnAssigned.php',
+ 'Kanboard\\Action\\TaskMoveColumnCategoryChange' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnCategoryChange.php',
+ 'Kanboard\\Action\\TaskMoveColumnClosed' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnClosed.php',
+ 'Kanboard\\Action\\TaskMoveColumnNotMovedPeriod' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnNotMovedPeriod.php',
+ 'Kanboard\\Action\\TaskMoveColumnUnAssigned' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnUnAssigned.php',
+ 'Kanboard\\Action\\TaskOpen' => __DIR__ . '/../..' . '/app/Action/TaskOpen.php',
+ 'Kanboard\\Action\\TaskUpdateStartDate' => __DIR__ . '/../..' . '/app/Action/TaskUpdateStartDate.php',
+ 'Kanboard\\Analytic\\AverageLeadCycleTimeAnalytic' => __DIR__ . '/../..' . '/app/Analytic/AverageLeadCycleTimeAnalytic.php',
+ 'Kanboard\\Analytic\\AverageTimeSpentColumnAnalytic' => __DIR__ . '/../..' . '/app/Analytic/AverageTimeSpentColumnAnalytic.php',
+ 'Kanboard\\Analytic\\EstimatedTimeComparisonAnalytic' => __DIR__ . '/../..' . '/app/Analytic/EstimatedTimeComparisonAnalytic.php',
+ 'Kanboard\\Analytic\\TaskDistributionAnalytic' => __DIR__ . '/../..' . '/app/Analytic/TaskDistributionAnalytic.php',
+ 'Kanboard\\Analytic\\UserDistributionAnalytic' => __DIR__ . '/../..' . '/app/Analytic/UserDistributionAnalytic.php',
+ 'Kanboard\\Api\\Authorization\\ActionAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/ActionAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\CategoryAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/CategoryAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ColumnAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/ColumnAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\CommentAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/CommentAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ProcedureAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/ProcedureAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\ProjectAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/ProjectAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\SubtaskAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/SubtaskAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TagAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/TagAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/TaskAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskFileAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/TaskFileAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\TaskLinkAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/TaskLinkAuthorization.php',
+ 'Kanboard\\Api\\Authorization\\UserAuthorization' => __DIR__ . '/../..' . '/app/Api/Authorization/UserAuthorization.php',
+ 'Kanboard\\Api\\Middleware\\AuthenticationMiddleware' => __DIR__ . '/../..' . '/app/Api/Middleware/AuthenticationMiddleware.php',
+ 'Kanboard\\Api\\Procedure\\ActionProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/ActionProcedure.php',
+ 'Kanboard\\Api\\Procedure\\AppProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/AppProcedure.php',
+ 'Kanboard\\Api\\Procedure\\BaseProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/BaseProcedure.php',
+ 'Kanboard\\Api\\Procedure\\BoardProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/BoardProcedure.php',
+ 'Kanboard\\Api\\Procedure\\CategoryProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/CategoryProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ColumnProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/ColumnProcedure.php',
+ 'Kanboard\\Api\\Procedure\\CommentProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/CommentProcedure.php',
+ 'Kanboard\\Api\\Procedure\\GroupMemberProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/GroupMemberProcedure.php',
+ 'Kanboard\\Api\\Procedure\\GroupProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/GroupProcedure.php',
+ 'Kanboard\\Api\\Procedure\\LinkProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/LinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\MeProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/MeProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectFileProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/ProjectFileProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectPermissionProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/ProjectPermissionProcedure.php',
+ 'Kanboard\\Api\\Procedure\\ProjectProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/ProjectProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SubtaskProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/SubtaskProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SubtaskTimeTrackingProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/SubtaskTimeTrackingProcedure.php',
+ 'Kanboard\\Api\\Procedure\\SwimlaneProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/SwimlaneProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TagProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TagProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskExternalLinkProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskExternalLinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskFileProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskFileProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskLinkProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskLinkProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskMetadataProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskMetadataProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskProcedure.php',
+ 'Kanboard\\Api\\Procedure\\TaskTagProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/TaskTagProcedure.php',
+ 'Kanboard\\Api\\Procedure\\UserProcedure' => __DIR__ . '/../..' . '/app/Api/Procedure/UserProcedure.php',
+ 'Kanboard\\Auth\\ApiAccessTokenAuth' => __DIR__ . '/../..' . '/app/Auth/ApiAccessTokenAuth.php',
+ 'Kanboard\\Auth\\DatabaseAuth' => __DIR__ . '/../..' . '/app/Auth/DatabaseAuth.php',
+ 'Kanboard\\Auth\\LdapAuth' => __DIR__ . '/../..' . '/app/Auth/LdapAuth.php',
+ 'Kanboard\\Auth\\RememberMeAuth' => __DIR__ . '/../..' . '/app/Auth/RememberMeAuth.php',
+ 'Kanboard\\Auth\\ReverseProxyAuth' => __DIR__ . '/../..' . '/app/Auth/ReverseProxyAuth.php',
+ 'Kanboard\\Auth\\TotpAuth' => __DIR__ . '/../..' . '/app/Auth/TotpAuth.php',
+ 'Kanboard\\Console\\BaseCommand' => __DIR__ . '/../..' . '/app/Console/BaseCommand.php',
+ 'Kanboard\\Console\\CronjobCommand' => __DIR__ . '/../..' . '/app/Console/CronjobCommand.php',
+ 'Kanboard\\Console\\DatabaseMigrationCommand' => __DIR__ . '/../..' . '/app/Console/DatabaseMigrationCommand.php',
+ 'Kanboard\\Console\\DatabaseVersionCommand' => __DIR__ . '/../..' . '/app/Console/DatabaseVersionCommand.php',
+ 'Kanboard\\Console\\JobCommand' => __DIR__ . '/../..' . '/app/Console/JobCommand.php',
+ 'Kanboard\\Console\\LocaleComparatorCommand' => __DIR__ . '/../..' . '/app/Console/LocaleComparatorCommand.php',
+ 'Kanboard\\Console\\LocaleSyncCommand' => __DIR__ . '/../..' . '/app/Console/LocaleSyncCommand.php',
+ 'Kanboard\\Console\\PluginInstallCommand' => __DIR__ . '/../..' . '/app/Console/PluginInstallCommand.php',
+ 'Kanboard\\Console\\PluginUninstallCommand' => __DIR__ . '/../..' . '/app/Console/PluginUninstallCommand.php',
+ 'Kanboard\\Console\\PluginUpgradeCommand' => __DIR__ . '/../..' . '/app/Console/PluginUpgradeCommand.php',
+ 'Kanboard\\Console\\ProjectDailyColumnStatsExportCommand' => __DIR__ . '/../..' . '/app/Console/ProjectDailyColumnStatsExportCommand.php',
+ 'Kanboard\\Console\\ProjectDailyStatsCalculationCommand' => __DIR__ . '/../..' . '/app/Console/ProjectDailyStatsCalculationCommand.php',
+ 'Kanboard\\Console\\ResetPasswordCommand' => __DIR__ . '/../..' . '/app/Console/ResetPasswordCommand.php',
+ 'Kanboard\\Console\\ResetTwoFactorCommand' => __DIR__ . '/../..' . '/app/Console/ResetTwoFactorCommand.php',
+ 'Kanboard\\Console\\SubtaskExportCommand' => __DIR__ . '/../..' . '/app/Console/SubtaskExportCommand.php',
+ 'Kanboard\\Console\\TaskExportCommand' => __DIR__ . '/../..' . '/app/Console/TaskExportCommand.php',
+ 'Kanboard\\Console\\TaskOverdueNotificationCommand' => __DIR__ . '/../..' . '/app/Console/TaskOverdueNotificationCommand.php',
+ 'Kanboard\\Console\\TaskTriggerCommand' => __DIR__ . '/../..' . '/app/Console/TaskTriggerCommand.php',
+ 'Kanboard\\Console\\TransitionExportCommand' => __DIR__ . '/../..' . '/app/Console/TransitionExportCommand.php',
+ 'Kanboard\\Console\\WorkerCommand' => __DIR__ . '/../..' . '/app/Console/WorkerCommand.php',
+ 'Kanboard\\Controller\\ActionController' => __DIR__ . '/../..' . '/app/Controller/ActionController.php',
+ 'Kanboard\\Controller\\ActionCreationController' => __DIR__ . '/../..' . '/app/Controller/ActionCreationController.php',
+ 'Kanboard\\Controller\\ActivityController' => __DIR__ . '/../..' . '/app/Controller/ActivityController.php',
+ 'Kanboard\\Controller\\AnalyticController' => __DIR__ . '/../..' . '/app/Controller/AnalyticController.php',
+ 'Kanboard\\Controller\\AppController' => __DIR__ . '/../..' . '/app/Controller/AppController.php',
+ 'Kanboard\\Controller\\AuthController' => __DIR__ . '/../..' . '/app/Controller/AuthController.php',
+ 'Kanboard\\Controller\\AvatarFileController' => __DIR__ . '/../..' . '/app/Controller/AvatarFileController.php',
+ 'Kanboard\\Controller\\BaseController' => __DIR__ . '/../..' . '/app/Controller/BaseController.php',
+ 'Kanboard\\Controller\\BoardAjaxController' => __DIR__ . '/../..' . '/app/Controller/BoardAjaxController.php',
+ 'Kanboard\\Controller\\BoardPopoverController' => __DIR__ . '/../..' . '/app/Controller/BoardPopoverController.php',
+ 'Kanboard\\Controller\\BoardTooltipController' => __DIR__ . '/../..' . '/app/Controller/BoardTooltipController.php',
+ 'Kanboard\\Controller\\BoardViewController' => __DIR__ . '/../..' . '/app/Controller/BoardViewController.php',
+ 'Kanboard\\Controller\\CaptchaController' => __DIR__ . '/../..' . '/app/Controller/CaptchaController.php',
+ 'Kanboard\\Controller\\CategoryController' => __DIR__ . '/../..' . '/app/Controller/CategoryController.php',
+ 'Kanboard\\Controller\\ColumnController' => __DIR__ . '/../..' . '/app/Controller/ColumnController.php',
+ 'Kanboard\\Controller\\ColumnMoveRestrictionController' => __DIR__ . '/../..' . '/app/Controller/ColumnMoveRestrictionController.php',
+ 'Kanboard\\Controller\\ColumnRestrictionController' => __DIR__ . '/../..' . '/app/Controller/ColumnRestrictionController.php',
+ 'Kanboard\\Controller\\CommentController' => __DIR__ . '/../..' . '/app/Controller/CommentController.php',
+ 'Kanboard\\Controller\\CommentListController' => __DIR__ . '/../..' . '/app/Controller/CommentListController.php',
+ 'Kanboard\\Controller\\CommentMailController' => __DIR__ . '/../..' . '/app/Controller/CommentMailController.php',
+ 'Kanboard\\Controller\\ConfigController' => __DIR__ . '/../..' . '/app/Controller/ConfigController.php',
+ 'Kanboard\\Controller\\CurrencyController' => __DIR__ . '/../..' . '/app/Controller/CurrencyController.php',
+ 'Kanboard\\Controller\\CustomFilterController' => __DIR__ . '/../..' . '/app/Controller/CustomFilterController.php',
+ 'Kanboard\\Controller\\DashboardController' => __DIR__ . '/../..' . '/app/Controller/DashboardController.php',
+ 'Kanboard\\Controller\\DocumentationController' => __DIR__ . '/../..' . '/app/Controller/DocumentationController.php',
+ 'Kanboard\\Controller\\ExportController' => __DIR__ . '/../..' . '/app/Controller/ExportController.php',
+ 'Kanboard\\Controller\\ExternalTaskCreationController' => __DIR__ . '/../..' . '/app/Controller/ExternalTaskCreationController.php',
+ 'Kanboard\\Controller\\ExternalTaskViewController' => __DIR__ . '/../..' . '/app/Controller/ExternalTaskViewController.php',
+ 'Kanboard\\Controller\\FeedController' => __DIR__ . '/../..' . '/app/Controller/FeedController.php',
+ 'Kanboard\\Controller\\FileViewerController' => __DIR__ . '/../..' . '/app/Controller/FileViewerController.php',
+ 'Kanboard\\Controller\\GroupAjaxController' => __DIR__ . '/../..' . '/app/Controller/GroupAjaxController.php',
+ 'Kanboard\\Controller\\GroupCreationController' => __DIR__ . '/../..' . '/app/Controller/GroupCreationController.php',
+ 'Kanboard\\Controller\\GroupListController' => __DIR__ . '/../..' . '/app/Controller/GroupListController.php',
+ 'Kanboard\\Controller\\GroupModificationController' => __DIR__ . '/../..' . '/app/Controller/GroupModificationController.php',
+ 'Kanboard\\Controller\\ICalendarController' => __DIR__ . '/../..' . '/app/Controller/ICalendarController.php',
+ 'Kanboard\\Controller\\LinkController' => __DIR__ . '/../..' . '/app/Controller/LinkController.php',
+ 'Kanboard\\Controller\\OAuthController' => __DIR__ . '/../..' . '/app/Controller/OAuthController.php',
+ 'Kanboard\\Controller\\PasswordResetController' => __DIR__ . '/../..' . '/app/Controller/PasswordResetController.php',
+ 'Kanboard\\Controller\\PluginController' => __DIR__ . '/../..' . '/app/Controller/PluginController.php',
+ 'Kanboard\\Controller\\ProjectActionDuplicationController' => __DIR__ . '/../..' . '/app/Controller/ProjectActionDuplicationController.php',
+ 'Kanboard\\Controller\\ProjectCreationController' => __DIR__ . '/../..' . '/app/Controller/ProjectCreationController.php',
+ 'Kanboard\\Controller\\ProjectEditController' => __DIR__ . '/../..' . '/app/Controller/ProjectEditController.php',
+ 'Kanboard\\Controller\\ProjectFileController' => __DIR__ . '/../..' . '/app/Controller/ProjectFileController.php',
+ 'Kanboard\\Controller\\ProjectListController' => __DIR__ . '/../..' . '/app/Controller/ProjectListController.php',
+ 'Kanboard\\Controller\\ProjectOverviewController' => __DIR__ . '/../..' . '/app/Controller/ProjectOverviewController.php',
+ 'Kanboard\\Controller\\ProjectPermissionController' => __DIR__ . '/../..' . '/app/Controller/ProjectPermissionController.php',
+ 'Kanboard\\Controller\\ProjectRoleController' => __DIR__ . '/../..' . '/app/Controller/ProjectRoleController.php',
+ 'Kanboard\\Controller\\ProjectRoleRestrictionController' => __DIR__ . '/../..' . '/app/Controller/ProjectRoleRestrictionController.php',
+ 'Kanboard\\Controller\\ProjectStatusController' => __DIR__ . '/../..' . '/app/Controller/ProjectStatusController.php',
+ 'Kanboard\\Controller\\ProjectTagController' => __DIR__ . '/../..' . '/app/Controller/ProjectTagController.php',
+ 'Kanboard\\Controller\\ProjectUserOverviewController' => __DIR__ . '/../..' . '/app/Controller/ProjectUserOverviewController.php',
+ 'Kanboard\\Controller\\ProjectViewController' => __DIR__ . '/../..' . '/app/Controller/ProjectViewController.php',
+ 'Kanboard\\Controller\\SearchController' => __DIR__ . '/../..' . '/app/Controller/SearchController.php',
+ 'Kanboard\\Controller\\SubtaskController' => __DIR__ . '/../..' . '/app/Controller/SubtaskController.php',
+ 'Kanboard\\Controller\\SubtaskConverterController' => __DIR__ . '/../..' . '/app/Controller/SubtaskConverterController.php',
+ 'Kanboard\\Controller\\SubtaskRestrictionController' => __DIR__ . '/../..' . '/app/Controller/SubtaskRestrictionController.php',
+ 'Kanboard\\Controller\\SubtaskStatusController' => __DIR__ . '/../..' . '/app/Controller/SubtaskStatusController.php',
+ 'Kanboard\\Controller\\SwimlaneController' => __DIR__ . '/../..' . '/app/Controller/SwimlaneController.php',
+ 'Kanboard\\Controller\\TagController' => __DIR__ . '/../..' . '/app/Controller/TagController.php',
+ 'Kanboard\\Controller\\TaskAjaxController' => __DIR__ . '/../..' . '/app/Controller/TaskAjaxController.php',
+ 'Kanboard\\Controller\\TaskBulkController' => __DIR__ . '/../..' . '/app/Controller/TaskBulkController.php',
+ 'Kanboard\\Controller\\TaskCreationController' => __DIR__ . '/../..' . '/app/Controller/TaskCreationController.php',
+ 'Kanboard\\Controller\\TaskDuplicationController' => __DIR__ . '/../..' . '/app/Controller/TaskDuplicationController.php',
+ 'Kanboard\\Controller\\TaskExternalLinkController' => __DIR__ . '/../..' . '/app/Controller/TaskExternalLinkController.php',
+ 'Kanboard\\Controller\\TaskFileController' => __DIR__ . '/../..' . '/app/Controller/TaskFileController.php',
+ 'Kanboard\\Controller\\TaskImportController' => __DIR__ . '/../..' . '/app/Controller/TaskImportController.php',
+ 'Kanboard\\Controller\\TaskInternalLinkController' => __DIR__ . '/../..' . '/app/Controller/TaskInternalLinkController.php',
+ 'Kanboard\\Controller\\TaskListController' => __DIR__ . '/../..' . '/app/Controller/TaskListController.php',
+ 'Kanboard\\Controller\\TaskMailController' => __DIR__ . '/../..' . '/app/Controller/TaskMailController.php',
+ 'Kanboard\\Controller\\TaskModificationController' => __DIR__ . '/../..' . '/app/Controller/TaskModificationController.php',
+ 'Kanboard\\Controller\\TaskMovePositionController' => __DIR__ . '/../..' . '/app/Controller/TaskMovePositionController.php',
+ 'Kanboard\\Controller\\TaskPopoverController' => __DIR__ . '/../..' . '/app/Controller/TaskPopoverController.php',
+ 'Kanboard\\Controller\\TaskRecurrenceController' => __DIR__ . '/../..' . '/app/Controller/TaskRecurrenceController.php',
+ 'Kanboard\\Controller\\TaskStatusController' => __DIR__ . '/../..' . '/app/Controller/TaskStatusController.php',
+ 'Kanboard\\Controller\\TaskSuppressionController' => __DIR__ . '/../..' . '/app/Controller/TaskSuppressionController.php',
+ 'Kanboard\\Controller\\TaskViewController' => __DIR__ . '/../..' . '/app/Controller/TaskViewController.php',
+ 'Kanboard\\Controller\\TwoFactorController' => __DIR__ . '/../..' . '/app/Controller/TwoFactorController.php',
+ 'Kanboard\\Controller\\UserAjaxController' => __DIR__ . '/../..' . '/app/Controller/UserAjaxController.php',
+ 'Kanboard\\Controller\\UserApiAccessController' => __DIR__ . '/../..' . '/app/Controller/UserApiAccessController.php',
+ 'Kanboard\\Controller\\UserCreationController' => __DIR__ . '/../..' . '/app/Controller/UserCreationController.php',
+ 'Kanboard\\Controller\\UserCredentialController' => __DIR__ . '/../..' . '/app/Controller/UserCredentialController.php',
+ 'Kanboard\\Controller\\UserImportController' => __DIR__ . '/../..' . '/app/Controller/UserImportController.php',
+ 'Kanboard\\Controller\\UserInviteController' => __DIR__ . '/../..' . '/app/Controller/UserInviteController.php',
+ 'Kanboard\\Controller\\UserListController' => __DIR__ . '/../..' . '/app/Controller/UserListController.php',
+ 'Kanboard\\Controller\\UserModificationController' => __DIR__ . '/../..' . '/app/Controller/UserModificationController.php',
+ 'Kanboard\\Controller\\UserStatusController' => __DIR__ . '/../..' . '/app/Controller/UserStatusController.php',
+ 'Kanboard\\Controller\\UserViewController' => __DIR__ . '/../..' . '/app/Controller/UserViewController.php',
+ 'Kanboard\\Controller\\WebNotificationController' => __DIR__ . '/../..' . '/app/Controller/WebNotificationController.php',
+ 'Kanboard\\Core\\Action\\ActionManager' => __DIR__ . '/../..' . '/app/Core/Action/ActionManager.php',
+ 'Kanboard\\Core\\Base' => __DIR__ . '/../..' . '/app/Core/Base.php',
+ 'Kanboard\\Core\\Cache\\BaseCache' => __DIR__ . '/../..' . '/app/Core/Cache/BaseCache.php',
+ 'Kanboard\\Core\\Cache\\CacheInterface' => __DIR__ . '/../..' . '/app/Core/Cache/CacheInterface.php',
+ 'Kanboard\\Core\\Cache\\FileCache' => __DIR__ . '/../..' . '/app/Core/Cache/FileCache.php',
+ 'Kanboard\\Core\\Cache\\MemoryCache' => __DIR__ . '/../..' . '/app/Core/Cache/MemoryCache.php',
+ 'Kanboard\\Core\\Controller\\AccessForbiddenException' => __DIR__ . '/../..' . '/app/Core/Controller/AccessForbiddenException.php',
+ 'Kanboard\\Core\\Controller\\BaseException' => __DIR__ . '/../..' . '/app/Core/Controller/BaseException.php',
+ 'Kanboard\\Core\\Controller\\BaseMiddleware' => __DIR__ . '/../..' . '/app/Core/Controller/BaseMiddleware.php',
+ 'Kanboard\\Core\\Controller\\PageNotFoundException' => __DIR__ . '/../..' . '/app/Core/Controller/PageNotFoundException.php',
+ 'Kanboard\\Core\\Controller\\Runner' => __DIR__ . '/../..' . '/app/Core/Controller/Runner.php',
+ 'Kanboard\\Core\\Csv' => __DIR__ . '/../..' . '/app/Core/Csv.php',
+ 'Kanboard\\Core\\DateParser' => __DIR__ . '/../..' . '/app/Core/DateParser.php',
+ 'Kanboard\\Core\\Event\\EventManager' => __DIR__ . '/../..' . '/app/Core/Event/EventManager.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkInterface' => __DIR__ . '/../..' . '/app/Core/ExternalLink/ExternalLinkInterface.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkManager' => __DIR__ . '/../..' . '/app/Core/ExternalLink/ExternalLinkManager.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkProviderInterface' => __DIR__ . '/../..' . '/app/Core/ExternalLink/ExternalLinkProviderInterface.php',
+ 'Kanboard\\Core\\ExternalLink\\ExternalLinkProviderNotFound' => __DIR__ . '/../..' . '/app/Core/ExternalLink/ExternalLinkProviderNotFound.php',
+ 'Kanboard\\Core\\ExternalTask\\AccessForbiddenException' => __DIR__ . '/../..' . '/app/Core/ExternalTask/AccessForbiddenException.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskException' => __DIR__ . '/../..' . '/app/Core/ExternalTask/ExternalTaskException.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskInterface' => __DIR__ . '/../..' . '/app/Core/ExternalTask/ExternalTaskInterface.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskManager' => __DIR__ . '/../..' . '/app/Core/ExternalTask/ExternalTaskManager.php',
+ 'Kanboard\\Core\\ExternalTask\\ExternalTaskProviderInterface' => __DIR__ . '/../..' . '/app/Core/ExternalTask/ExternalTaskProviderInterface.php',
+ 'Kanboard\\Core\\ExternalTask\\NotFoundException' => __DIR__ . '/../..' . '/app/Core/ExternalTask/NotFoundException.php',
+ 'Kanboard\\Core\\ExternalTask\\ProviderNotFoundException' => __DIR__ . '/../..' . '/app/Core/ExternalTask/ProviderNotFoundException.php',
+ 'Kanboard\\Core\\Filter\\CriteriaInterface' => __DIR__ . '/../..' . '/app/Core/Filter/CriteriaInterface.php',
+ 'Kanboard\\Core\\Filter\\FilterInterface' => __DIR__ . '/../..' . '/app/Core/Filter/FilterInterface.php',
+ 'Kanboard\\Core\\Filter\\FormatterInterface' => __DIR__ . '/../..' . '/app/Core/Filter/FormatterInterface.php',
+ 'Kanboard\\Core\\Filter\\Lexer' => __DIR__ . '/../..' . '/app/Core/Filter/Lexer.php',
+ 'Kanboard\\Core\\Filter\\LexerBuilder' => __DIR__ . '/../..' . '/app/Core/Filter/LexerBuilder.php',
+ 'Kanboard\\Core\\Filter\\OrCriteria' => __DIR__ . '/../..' . '/app/Core/Filter/OrCriteria.php',
+ 'Kanboard\\Core\\Filter\\QueryBuilder' => __DIR__ . '/../..' . '/app/Core/Filter/QueryBuilder.php',
+ 'Kanboard\\Core\\Group\\GroupBackendProviderInterface' => __DIR__ . '/../..' . '/app/Core/Group/GroupBackendProviderInterface.php',
+ 'Kanboard\\Core\\Group\\GroupManager' => __DIR__ . '/../..' . '/app/Core/Group/GroupManager.php',
+ 'Kanboard\\Core\\Group\\GroupProviderInterface' => __DIR__ . '/../..' . '/app/Core/Group/GroupProviderInterface.php',
+ 'Kanboard\\Core\\Helper' => __DIR__ . '/../..' . '/app/Core/Helper.php',
+ 'Kanboard\\Core\\Http\\Client' => __DIR__ . '/../..' . '/app/Core/Http/Client.php',
+ 'Kanboard\\Core\\Http\\OAuth2' => __DIR__ . '/../..' . '/app/Core/Http/OAuth2.php',
+ 'Kanboard\\Core\\Http\\RememberMeCookie' => __DIR__ . '/../..' . '/app/Core/Http/RememberMeCookie.php',
+ 'Kanboard\\Core\\Http\\Request' => __DIR__ . '/../..' . '/app/Core/Http/Request.php',
+ 'Kanboard\\Core\\Http\\Response' => __DIR__ . '/../..' . '/app/Core/Http/Response.php',
+ 'Kanboard\\Core\\Http\\Route' => __DIR__ . '/../..' . '/app/Core/Http/Route.php',
+ 'Kanboard\\Core\\Http\\Router' => __DIR__ . '/../..' . '/app/Core/Http/Router.php',
+ 'Kanboard\\Core\\Ldap\\Client' => __DIR__ . '/../..' . '/app/Core/Ldap/Client.php',
+ 'Kanboard\\Core\\Ldap\\ClientException' => __DIR__ . '/../..' . '/app/Core/Ldap/ClientException.php',
+ 'Kanboard\\Core\\Ldap\\ConnectionException' => __DIR__ . '/../..' . '/app/Core/Ldap/ConnectionException.php',
+ 'Kanboard\\Core\\Ldap\\Entries' => __DIR__ . '/../..' . '/app/Core/Ldap/Entries.php',
+ 'Kanboard\\Core\\Ldap\\Entry' => __DIR__ . '/../..' . '/app/Core/Ldap/Entry.php',
+ 'Kanboard\\Core\\Ldap\\Group' => __DIR__ . '/../..' . '/app/Core/Ldap/Group.php',
+ 'Kanboard\\Core\\Ldap\\Query' => __DIR__ . '/../..' . '/app/Core/Ldap/Query.php',
+ 'Kanboard\\Core\\Ldap\\User' => __DIR__ . '/../..' . '/app/Core/Ldap/User.php',
+ 'Kanboard\\Core\\Mail\\Client' => __DIR__ . '/../..' . '/app/Core/Mail/Client.php',
+ 'Kanboard\\Core\\Mail\\ClientInterface' => __DIR__ . '/../..' . '/app/Core/Mail/ClientInterface.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Mail' => __DIR__ . '/../..' . '/app/Core/Mail/Transport/Mail.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Sendmail' => __DIR__ . '/../..' . '/app/Core/Mail/Transport/Sendmail.php',
+ 'Kanboard\\Core\\Mail\\Transport\\Smtp' => __DIR__ . '/../..' . '/app/Core/Mail/Transport/Smtp.php',
+ 'Kanboard\\Core\\Markdown' => __DIR__ . '/../..' . '/app/Core/Markdown.php',
+ 'Kanboard\\Core\\Notification\\NotificationInterface' => __DIR__ . '/../..' . '/app/Core/Notification/NotificationInterface.php',
+ 'Kanboard\\Core\\ObjectStorage\\FileStorage' => __DIR__ . '/../..' . '/app/Core/ObjectStorage/FileStorage.php',
+ 'Kanboard\\Core\\ObjectStorage\\ObjectStorageException' => __DIR__ . '/../..' . '/app/Core/ObjectStorage/ObjectStorageException.php',
+ 'Kanboard\\Core\\ObjectStorage\\ObjectStorageInterface' => __DIR__ . '/../..' . '/app/Core/ObjectStorage/ObjectStorageInterface.php',
+ 'Kanboard\\Core\\Paginator' => __DIR__ . '/../..' . '/app/Core/Paginator.php',
+ 'Kanboard\\Core\\Plugin\\Base' => __DIR__ . '/../..' . '/app/Core/Plugin/Base.php',
+ 'Kanboard\\Core\\Plugin\\Directory' => __DIR__ . '/../..' . '/app/Core/Plugin/Directory.php',
+ 'Kanboard\\Core\\Plugin\\Hook' => __DIR__ . '/../..' . '/app/Core/Plugin/Hook.php',
+ 'Kanboard\\Core\\Plugin\\Installer' => __DIR__ . '/../..' . '/app/Core/Plugin/Installer.php',
+ 'Kanboard\\Core\\Plugin\\Loader' => __DIR__ . '/../..' . '/app/Core/Plugin/Loader.php',
+ 'Kanboard\\Core\\Plugin\\PluginException' => __DIR__ . '/../..' . '/app/Core/Plugin/PluginException.php',
+ 'Kanboard\\Core\\Plugin\\PluginInstallerException' => __DIR__ . '/../..' . '/app/Core/Plugin/PluginInstallerException.php',
+ 'Kanboard\\Core\\Plugin\\SchemaHandler' => __DIR__ . '/../..' . '/app/Core/Plugin/SchemaHandler.php',
+ 'Kanboard\\Core\\Plugin\\Version' => __DIR__ . '/../..' . '/app/Core/Plugin/Version.php',
+ 'Kanboard\\Core\\Queue\\JobHandler' => __DIR__ . '/../..' . '/app/Core/Queue/JobHandler.php',
+ 'Kanboard\\Core\\Queue\\QueueManager' => __DIR__ . '/../..' . '/app/Core/Queue/QueueManager.php',
+ 'Kanboard\\Core\\Security\\AccessMap' => __DIR__ . '/../..' . '/app/Core/Security/AccessMap.php',
+ 'Kanboard\\Core\\Security\\AuthenticationManager' => __DIR__ . '/../..' . '/app/Core/Security/AuthenticationManager.php',
+ 'Kanboard\\Core\\Security\\AuthenticationProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/AuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Authorization' => __DIR__ . '/../..' . '/app/Core/Security/Authorization.php',
+ 'Kanboard\\Core\\Security\\OAuthAuthenticationProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/OAuthAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PasswordAuthenticationProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/PasswordAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PostAuthenticationProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/PostAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\PreAuthenticationProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/PreAuthenticationProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Role' => __DIR__ . '/../..' . '/app/Core/Security/Role.php',
+ 'Kanboard\\Core\\Security\\SessionCheckProviderInterface' => __DIR__ . '/../..' . '/app/Core/Security/SessionCheckProviderInterface.php',
+ 'Kanboard\\Core\\Security\\Token' => __DIR__ . '/../..' . '/app/Core/Security/Token.php',
+ 'Kanboard\\Core\\Session\\FlashMessage' => __DIR__ . '/../..' . '/app/Core/Session/FlashMessage.php',
+ 'Kanboard\\Core\\Session\\SessionManager' => __DIR__ . '/../..' . '/app/Core/Session/SessionManager.php',
+ 'Kanboard\\Core\\Session\\SessionStorage' => __DIR__ . '/../..' . '/app/Core/Session/SessionStorage.php',
+ 'Kanboard\\Core\\Template' => __DIR__ . '/../..' . '/app/Core/Template.php',
+ 'Kanboard\\Core\\Thumbnail' => __DIR__ . '/../..' . '/app/Core/Thumbnail.php',
+ 'Kanboard\\Core\\Tool' => __DIR__ . '/../..' . '/app/Core/Tool.php',
+ 'Kanboard\\Core\\Translator' => __DIR__ . '/../..' . '/app/Core/Translator.php',
+ 'Kanboard\\Core\\User\\Avatar\\AvatarManager' => __DIR__ . '/../..' . '/app/Core/User/Avatar/AvatarManager.php',
+ 'Kanboard\\Core\\User\\Avatar\\AvatarProviderInterface' => __DIR__ . '/../..' . '/app/Core/User/Avatar/AvatarProviderInterface.php',
+ 'Kanboard\\Core\\User\\GroupSync' => __DIR__ . '/../..' . '/app/Core/User/GroupSync.php',
+ 'Kanboard\\Core\\User\\UserProfile' => __DIR__ . '/../..' . '/app/Core/User/UserProfile.php',
+ 'Kanboard\\Core\\User\\UserProperty' => __DIR__ . '/../..' . '/app/Core/User/UserProperty.php',
+ 'Kanboard\\Core\\User\\UserProviderInterface' => __DIR__ . '/../..' . '/app/Core/User/UserProviderInterface.php',
+ 'Kanboard\\Core\\User\\UserSession' => __DIR__ . '/../..' . '/app/Core/User/UserSession.php',
+ 'Kanboard\\Core\\User\\UserSync' => __DIR__ . '/../..' . '/app/Core/User/UserSync.php',
+ 'Kanboard\\Decorator\\ColumnMoveRestrictionCacheDecorator' => __DIR__ . '/../..' . '/app/Decorator/ColumnMoveRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\ColumnRestrictionCacheDecorator' => __DIR__ . '/../..' . '/app/Decorator/ColumnRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\MetadataCacheDecorator' => __DIR__ . '/../..' . '/app/Decorator/MetadataCacheDecorator.php',
+ 'Kanboard\\Decorator\\ProjectRoleRestrictionCacheDecorator' => __DIR__ . '/../..' . '/app/Decorator/ProjectRoleRestrictionCacheDecorator.php',
+ 'Kanboard\\Decorator\\UserCacheDecorator' => __DIR__ . '/../..' . '/app/Decorator/UserCacheDecorator.php',
+ 'Kanboard\\EventBuilder\\BaseEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/BaseEventBuilder.php',
+ 'Kanboard\\EventBuilder\\CommentEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/CommentEventBuilder.php',
+ 'Kanboard\\EventBuilder\\EventIteratorBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/EventIteratorBuilder.php',
+ 'Kanboard\\EventBuilder\\ProjectFileEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/ProjectFileEventBuilder.php',
+ 'Kanboard\\EventBuilder\\SubtaskEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/SubtaskEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/TaskEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskFileEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/TaskFileEventBuilder.php',
+ 'Kanboard\\EventBuilder\\TaskLinkEventBuilder' => __DIR__ . '/../..' . '/app/EventBuilder/TaskLinkEventBuilder.php',
+ 'Kanboard\\Event\\AuthFailureEvent' => __DIR__ . '/../..' . '/app/Event/AuthFailureEvent.php',
+ 'Kanboard\\Event\\AuthSuccessEvent' => __DIR__ . '/../..' . '/app/Event/AuthSuccessEvent.php',
+ 'Kanboard\\Event\\CommentEvent' => __DIR__ . '/../..' . '/app/Event/CommentEvent.php',
+ 'Kanboard\\Event\\GenericEvent' => __DIR__ . '/../..' . '/app/Event/GenericEvent.php',
+ 'Kanboard\\Event\\ProjectFileEvent' => __DIR__ . '/../..' . '/app/Event/ProjectFileEvent.php',
+ 'Kanboard\\Event\\SubtaskEvent' => __DIR__ . '/../..' . '/app/Event/SubtaskEvent.php',
+ 'Kanboard\\Event\\TaskEvent' => __DIR__ . '/../..' . '/app/Event/TaskEvent.php',
+ 'Kanboard\\Event\\TaskFileEvent' => __DIR__ . '/../..' . '/app/Event/TaskFileEvent.php',
+ 'Kanboard\\Event\\TaskLinkEvent' => __DIR__ . '/../..' . '/app/Event/TaskLinkEvent.php',
+ 'Kanboard\\Event\\TaskListEvent' => __DIR__ . '/../..' . '/app/Event/TaskListEvent.php',
+ 'Kanboard\\Event\\UserProfileSyncEvent' => __DIR__ . '/../..' . '/app/Event/UserProfileSyncEvent.php',
+ 'Kanboard\\Export\\SubtaskExport' => __DIR__ . '/../..' . '/app/Export/SubtaskExport.php',
+ 'Kanboard\\Export\\TaskExport' => __DIR__ . '/../..' . '/app/Export/TaskExport.php',
+ 'Kanboard\\Export\\TransitionExport' => __DIR__ . '/../..' . '/app/Export/TransitionExport.php',
+ 'Kanboard\\ExternalLink\\AttachmentLink' => __DIR__ . '/../..' . '/app/ExternalLink/AttachmentLink.php',
+ 'Kanboard\\ExternalLink\\AttachmentLinkProvider' => __DIR__ . '/../..' . '/app/ExternalLink/AttachmentLinkProvider.php',
+ 'Kanboard\\ExternalLink\\BaseLink' => __DIR__ . '/../..' . '/app/ExternalLink/BaseLink.php',
+ 'Kanboard\\ExternalLink\\BaseLinkProvider' => __DIR__ . '/../..' . '/app/ExternalLink/BaseLinkProvider.php',
+ 'Kanboard\\ExternalLink\\FileLink' => __DIR__ . '/../..' . '/app/ExternalLink/FileLink.php',
+ 'Kanboard\\ExternalLink\\FileLinkProvider' => __DIR__ . '/../..' . '/app/ExternalLink/FileLinkProvider.php',
+ 'Kanboard\\ExternalLink\\WebLink' => __DIR__ . '/../..' . '/app/ExternalLink/WebLink.php',
+ 'Kanboard\\ExternalLink\\WebLinkProvider' => __DIR__ . '/../..' . '/app/ExternalLink/WebLinkProvider.php',
+ 'Kanboard\\Filter\\BaseComparisonFilter' => __DIR__ . '/../..' . '/app/Filter/BaseComparisonFilter.php',
+ 'Kanboard\\Filter\\BaseDateFilter' => __DIR__ . '/../..' . '/app/Filter/BaseDateFilter.php',
+ 'Kanboard\\Filter\\BaseFilter' => __DIR__ . '/../..' . '/app/Filter/BaseFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityCreationDateFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityCreationDateFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityCreatorFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityCreatorFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectIdFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityProjectIdFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectIdsFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityProjectIdsFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityProjectNameFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityProjectNameFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskIdFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityTaskIdFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskStatusFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityTaskStatusFilter.php',
+ 'Kanboard\\Filter\\ProjectActivityTaskTitleFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectActivityTaskTitleFilter.php',
+ 'Kanboard\\Filter\\ProjectGroupRoleProjectFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectGroupRoleProjectFilter.php',
+ 'Kanboard\\Filter\\ProjectGroupRoleUsernameFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectGroupRoleUsernameFilter.php',
+ 'Kanboard\\Filter\\ProjectIdsFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectIdsFilter.php',
+ 'Kanboard\\Filter\\ProjectStatusFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectStatusFilter.php',
+ 'Kanboard\\Filter\\ProjectTypeFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectTypeFilter.php',
+ 'Kanboard\\Filter\\ProjectUserRoleProjectFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectUserRoleProjectFilter.php',
+ 'Kanboard\\Filter\\ProjectUserRoleUsernameFilter' => __DIR__ . '/../..' . '/app/Filter/ProjectUserRoleUsernameFilter.php',
+ 'Kanboard\\Filter\\TaskAssigneeFilter' => __DIR__ . '/../..' . '/app/Filter/TaskAssigneeFilter.php',
+ 'Kanboard\\Filter\\TaskCategoryFilter' => __DIR__ . '/../..' . '/app/Filter/TaskCategoryFilter.php',
+ 'Kanboard\\Filter\\TaskColorFilter' => __DIR__ . '/../..' . '/app/Filter/TaskColorFilter.php',
+ 'Kanboard\\Filter\\TaskColumnFilter' => __DIR__ . '/../..' . '/app/Filter/TaskColumnFilter.php',
+ 'Kanboard\\Filter\\TaskCommentFilter' => __DIR__ . '/../..' . '/app/Filter/TaskCommentFilter.php',
+ 'Kanboard\\Filter\\TaskCompletionDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskCompletionDateFilter.php',
+ 'Kanboard\\Filter\\TaskCreationDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskCreationDateFilter.php',
+ 'Kanboard\\Filter\\TaskCreatorFilter' => __DIR__ . '/../..' . '/app/Filter/TaskCreatorFilter.php',
+ 'Kanboard\\Filter\\TaskDescriptionFilter' => __DIR__ . '/../..' . '/app/Filter/TaskDescriptionFilter.php',
+ 'Kanboard\\Filter\\TaskDueDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskDueDateFilter.php',
+ 'Kanboard\\Filter\\TaskDueDateRangeFilter' => __DIR__ . '/../..' . '/app/Filter/TaskDueDateRangeFilter.php',
+ 'Kanboard\\Filter\\TaskIdExclusionFilter' => __DIR__ . '/../..' . '/app/Filter/TaskIdExclusionFilter.php',
+ 'Kanboard\\Filter\\TaskIdFilter' => __DIR__ . '/../..' . '/app/Filter/TaskIdFilter.php',
+ 'Kanboard\\Filter\\TaskLinkFilter' => __DIR__ . '/../..' . '/app/Filter/TaskLinkFilter.php',
+ 'Kanboard\\Filter\\TaskModificationDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskModificationDateFilter.php',
+ 'Kanboard\\Filter\\TaskMovedDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskMovedDateFilter.php',
+ 'Kanboard\\Filter\\TaskPriorityFilter' => __DIR__ . '/../..' . '/app/Filter/TaskPriorityFilter.php',
+ 'Kanboard\\Filter\\TaskProjectFilter' => __DIR__ . '/../..' . '/app/Filter/TaskProjectFilter.php',
+ 'Kanboard\\Filter\\TaskProjectsFilter' => __DIR__ . '/../..' . '/app/Filter/TaskProjectsFilter.php',
+ 'Kanboard\\Filter\\TaskReferenceFilter' => __DIR__ . '/../..' . '/app/Filter/TaskReferenceFilter.php',
+ 'Kanboard\\Filter\\TaskScoreFilter' => __DIR__ . '/../..' . '/app/Filter/TaskScoreFilter.php',
+ 'Kanboard\\Filter\\TaskStartDateFilter' => __DIR__ . '/../..' . '/app/Filter/TaskStartDateFilter.php',
+ 'Kanboard\\Filter\\TaskStartsWithIdFilter' => __DIR__ . '/../..' . '/app/Filter/TaskStartsWithIdFilter.php',
+ 'Kanboard\\Filter\\TaskStatusFilter' => __DIR__ . '/../..' . '/app/Filter/TaskStatusFilter.php',
+ 'Kanboard\\Filter\\TaskSubtaskAssigneeFilter' => __DIR__ . '/../..' . '/app/Filter/TaskSubtaskAssigneeFilter.php',
+ 'Kanboard\\Filter\\TaskSwimlaneFilter' => __DIR__ . '/../..' . '/app/Filter/TaskSwimlaneFilter.php',
+ 'Kanboard\\Filter\\TaskTagFilter' => __DIR__ . '/../..' . '/app/Filter/TaskTagFilter.php',
+ 'Kanboard\\Filter\\TaskTitleFilter' => __DIR__ . '/../..' . '/app/Filter/TaskTitleFilter.php',
+ 'Kanboard\\Filter\\UserNameFilter' => __DIR__ . '/../..' . '/app/Filter/UserNameFilter.php',
+ 'Kanboard\\Formatter\\BaseFormatter' => __DIR__ . '/../..' . '/app/Formatter/BaseFormatter.php',
+ 'Kanboard\\Formatter\\BaseTaskCalendarFormatter' => __DIR__ . '/../..' . '/app/Formatter/BaseTaskCalendarFormatter.php',
+ 'Kanboard\\Formatter\\BoardColumnFormatter' => __DIR__ . '/../..' . '/app/Formatter/BoardColumnFormatter.php',
+ 'Kanboard\\Formatter\\BoardFormatter' => __DIR__ . '/../..' . '/app/Formatter/BoardFormatter.php',
+ 'Kanboard\\Formatter\\BoardSwimlaneFormatter' => __DIR__ . '/../..' . '/app/Formatter/BoardSwimlaneFormatter.php',
+ 'Kanboard\\Formatter\\BoardTaskFormatter' => __DIR__ . '/../..' . '/app/Formatter/BoardTaskFormatter.php',
+ 'Kanboard\\Formatter\\GroupAutoCompleteFormatter' => __DIR__ . '/../..' . '/app/Formatter/GroupAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\ProjectActivityEventFormatter' => __DIR__ . '/../..' . '/app/Formatter/ProjectActivityEventFormatter.php',
+ 'Kanboard\\Formatter\\ProjectApiFormatter' => __DIR__ . '/../..' . '/app/Formatter/ProjectApiApiFormatter.php',
+ 'Kanboard\\Formatter\\ProjectsApiFormatter' => __DIR__ . '/../..' . '/app/Formatter/ProjectsApiFormatter.php',
+ 'Kanboard\\Formatter\\SubtaskListFormatter' => __DIR__ . '/../..' . '/app/Formatter/SubtaskListFormatter.php',
+ 'Kanboard\\Formatter\\SubtaskTimeTrackingCalendarFormatter' => __DIR__ . '/../..' . '/app/Formatter/SubtaskTimeTrackingCalendarFormatter.php',
+ 'Kanboard\\Formatter\\TaskApiFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskApiFormatter.php',
+ 'Kanboard\\Formatter\\TaskAutoCompleteFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\TaskICalFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskICalFormatter.php',
+ 'Kanboard\\Formatter\\TaskListFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskListFormatter.php',
+ 'Kanboard\\Formatter\\TaskListSubtaskAssigneeFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskListSubtaskAssigneeFormatter.php',
+ 'Kanboard\\Formatter\\TaskListSubtaskFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskListSubtaskFormatter.php',
+ 'Kanboard\\Formatter\\TaskSuggestMenuFormatter' => __DIR__ . '/../..' . '/app/Formatter/TaskSuggestMenuFormatter.php',
+ 'Kanboard\\Formatter\\TasksApiFormatter' => __DIR__ . '/../..' . '/app/Formatter/TasksApiFormatter.php',
+ 'Kanboard\\Formatter\\UserAutoCompleteFormatter' => __DIR__ . '/../..' . '/app/Formatter/UserAutoCompleteFormatter.php',
+ 'Kanboard\\Formatter\\UserMentionFormatter' => __DIR__ . '/../..' . '/app/Formatter/UserMentionFormatter.php',
+ 'Kanboard\\Group\\DatabaseBackendGroupProvider' => __DIR__ . '/../..' . '/app/Group/DatabaseBackendGroupProvider.php',
+ 'Kanboard\\Group\\DatabaseGroupProvider' => __DIR__ . '/../..' . '/app/Group/DatabaseGroupProvider.php',
+ 'Kanboard\\Group\\LdapBackendGroupProvider' => __DIR__ . '/../..' . '/app/Group/LdapBackendGroupProvider.php',
+ 'Kanboard\\Group\\LdapGroupProvider' => __DIR__ . '/../..' . '/app/Group/LdapGroupProvider.php',
+ 'Kanboard\\Helper\\AppHelper' => __DIR__ . '/../..' . '/app/Helper/AppHelper.php',
+ 'Kanboard\\Helper\\AssetHelper' => __DIR__ . '/../..' . '/app/Helper/AssetHelper.php',
+ 'Kanboard\\Helper\\AvatarHelper' => __DIR__ . '/../..' . '/app/Helper/AvatarHelper.php',
+ 'Kanboard\\Helper\\BoardHelper' => __DIR__ . '/../..' . '/app/Helper/BoardHelper.php',
+ 'Kanboard\\Helper\\CommentHelper' => __DIR__ . '/../..' . '/app/Helper/CommentHelper.php',
+ 'Kanboard\\Helper\\DateHelper' => __DIR__ . '/../..' . '/app/Helper/DateHelper.php',
+ 'Kanboard\\Helper\\FileHelper' => __DIR__ . '/../..' . '/app/Helper/FileHelper.php',
+ 'Kanboard\\Helper\\FormHelper' => __DIR__ . '/../..' . '/app/Helper/FormHelper.php',
+ 'Kanboard\\Helper\\HookHelper' => __DIR__ . '/../..' . '/app/Helper/HookHelper.php',
+ 'Kanboard\\Helper\\ICalHelper' => __DIR__ . '/../..' . '/app/Helper/ICalHelper.php',
+ 'Kanboard\\Helper\\LayoutHelper' => __DIR__ . '/../..' . '/app/Helper/LayoutHelper.php',
+ 'Kanboard\\Helper\\MailHelper' => __DIR__ . '/../..' . '/app/Helper/MailHelper.php',
+ 'Kanboard\\Helper\\ModalHelper' => __DIR__ . '/../..' . '/app/Helper/ModalHelper.php',
+ 'Kanboard\\Helper\\ModelHelper' => __DIR__ . '/../..' . '/app/Helper/ModelHelper.php',
+ 'Kanboard\\Helper\\ProjectActivityHelper' => __DIR__ . '/../..' . '/app/Helper/ProjectActivityHelper.php',
+ 'Kanboard\\Helper\\ProjectHeaderHelper' => __DIR__ . '/../..' . '/app/Helper/ProjectHeaderHelper.php',
+ 'Kanboard\\Helper\\ProjectRoleHelper' => __DIR__ . '/../..' . '/app/Helper/ProjectRoleHelper.php',
+ 'Kanboard\\Helper\\SubtaskHelper' => __DIR__ . '/../..' . '/app/Helper/SubtaskHelper.php',
+ 'Kanboard\\Helper\\TaskHelper' => __DIR__ . '/../..' . '/app/Helper/TaskHelper.php',
+ 'Kanboard\\Helper\\TextHelper' => __DIR__ . '/../..' . '/app/Helper/TextHelper.php',
+ 'Kanboard\\Helper\\UrlHelper' => __DIR__ . '/../..' . '/app/Helper/UrlHelper.php',
+ 'Kanboard\\Helper\\UserHelper' => __DIR__ . '/../..' . '/app/Helper/UserHelper.php',
+ 'Kanboard\\Import\\TaskImport' => __DIR__ . '/../..' . '/app/Import/TaskImport.php',
+ 'Kanboard\\Import\\UserImport' => __DIR__ . '/../..' . '/app/Import/UserImport.php',
+ 'Kanboard\\Job\\BaseJob' => __DIR__ . '/../..' . '/app/Job/BaseJob.php',
+ 'Kanboard\\Job\\CommentEventJob' => __DIR__ . '/../..' . '/app/Job/CommentEventJob.php',
+ 'Kanboard\\Job\\EmailJob' => __DIR__ . '/../..' . '/app/Job/EmailJob.php',
+ 'Kanboard\\Job\\HttpAsyncJob' => __DIR__ . '/../..' . '/app/Job/HttpAsyncJob.php',
+ 'Kanboard\\Job\\NotificationJob' => __DIR__ . '/../..' . '/app/Job/NotificationJob.php',
+ 'Kanboard\\Job\\ProjectFileEventJob' => __DIR__ . '/../..' . '/app/Job/ProjectFileEventJob.php',
+ 'Kanboard\\Job\\ProjectMetricJob' => __DIR__ . '/../..' . '/app/Job/ProjectMetricJob.php',
+ 'Kanboard\\Job\\SubtaskEventJob' => __DIR__ . '/../..' . '/app/Job/SubtaskEventJob.php',
+ 'Kanboard\\Job\\TaskEventJob' => __DIR__ . '/../..' . '/app/Job/TaskEventJob.php',
+ 'Kanboard\\Job\\TaskFileEventJob' => __DIR__ . '/../..' . '/app/Job/TaskFileEventJob.php',
+ 'Kanboard\\Job\\TaskLinkEventJob' => __DIR__ . '/../..' . '/app/Job/TaskLinkEventJob.php',
+ 'Kanboard\\Job\\UserMentionJob' => __DIR__ . '/../..' . '/app/Job/UserMentionJob.php',
+ 'Kanboard\\Middleware\\ApplicationAuthorizationMiddleware' => __DIR__ . '/../..' . '/app/Middleware/ApplicationAuthorizationMiddleware.php',
+ 'Kanboard\\Middleware\\AuthenticationMiddleware' => __DIR__ . '/../..' . '/app/Middleware/AuthenticationMiddleware.php',
+ 'Kanboard\\Middleware\\BootstrapMiddleware' => __DIR__ . '/../..' . '/app/Middleware/BootstrapMiddleware.php',
+ 'Kanboard\\Middleware\\PostAuthenticationMiddleware' => __DIR__ . '/../..' . '/app/Middleware/PostAuthenticationMiddleware.php',
+ 'Kanboard\\Middleware\\ProjectAuthorizationMiddleware' => __DIR__ . '/../..' . '/app/Middleware/ProjectAuthorizationMiddleware.php',
+ 'Kanboard\\Model\\ActionModel' => __DIR__ . '/../..' . '/app/Model/ActionModel.php',
+ 'Kanboard\\Model\\ActionParameterModel' => __DIR__ . '/../..' . '/app/Model/ActionParameterModel.php',
+ 'Kanboard\\Model\\AvatarFileModel' => __DIR__ . '/../..' . '/app/Model/AvatarFileModel.php',
+ 'Kanboard\\Model\\BoardModel' => __DIR__ . '/../..' . '/app/Model/BoardModel.php',
+ 'Kanboard\\Model\\CategoryModel' => __DIR__ . '/../..' . '/app/Model/CategoryModel.php',
+ 'Kanboard\\Model\\ColorModel' => __DIR__ . '/../..' . '/app/Model/ColorModel.php',
+ 'Kanboard\\Model\\ColumnModel' => __DIR__ . '/../..' . '/app/Model/ColumnModel.php',
+ 'Kanboard\\Model\\ColumnMoveRestrictionModel' => __DIR__ . '/../..' . '/app/Model/ColumnMoveRestrictionModel.php',
+ 'Kanboard\\Model\\ColumnRestrictionModel' => __DIR__ . '/../..' . '/app/Model/ColumnRestrictionModel.php',
+ 'Kanboard\\Model\\CommentModel' => __DIR__ . '/../..' . '/app/Model/CommentModel.php',
+ 'Kanboard\\Model\\ConfigModel' => __DIR__ . '/../..' . '/app/Model/ConfigModel.php',
+ 'Kanboard\\Model\\CurrencyModel' => __DIR__ . '/../..' . '/app/Model/CurrencyModel.php',
+ 'Kanboard\\Model\\CustomFilterModel' => __DIR__ . '/../..' . '/app/Model/CustomFilterModel.php',
+ 'Kanboard\\Model\\FileModel' => __DIR__ . '/../..' . '/app/Model/FileModel.php',
+ 'Kanboard\\Model\\GroupMemberModel' => __DIR__ . '/../..' . '/app/Model/GroupMemberModel.php',
+ 'Kanboard\\Model\\GroupModel' => __DIR__ . '/../..' . '/app/Model/GroupModel.php',
+ 'Kanboard\\Model\\InviteModel' => __DIR__ . '/../..' . '/app/Model/InviteModel.php',
+ 'Kanboard\\Model\\LanguageModel' => __DIR__ . '/../..' . '/app/Model/LanguageModel.php',
+ 'Kanboard\\Model\\LastLoginModel' => __DIR__ . '/../..' . '/app/Model/LastLoginModel.php',
+ 'Kanboard\\Model\\LinkModel' => __DIR__ . '/../..' . '/app/Model/LinkModel.php',
+ 'Kanboard\\Model\\MetadataModel' => __DIR__ . '/../..' . '/app/Model/MetadataModel.php',
+ 'Kanboard\\Model\\NotificationModel' => __DIR__ . '/../..' . '/app/Model/NotificationModel.php',
+ 'Kanboard\\Model\\NotificationTypeModel' => __DIR__ . '/../..' . '/app/Model/NotificationTypeModel.php',
+ 'Kanboard\\Model\\PasswordResetModel' => __DIR__ . '/../..' . '/app/Model/PasswordResetModel.php',
+ 'Kanboard\\Model\\ProjectActivityModel' => __DIR__ . '/../..' . '/app/Model/ProjectActivityModel.php',
+ 'Kanboard\\Model\\ProjectDailyColumnStatsModel' => __DIR__ . '/../..' . '/app/Model/ProjectDailyColumnStatsModel.php',
+ 'Kanboard\\Model\\ProjectDailyStatsModel' => __DIR__ . '/../..' . '/app/Model/ProjectDailyStatsModel.php',
+ 'Kanboard\\Model\\ProjectDuplicationModel' => __DIR__ . '/../..' . '/app/Model/ProjectDuplicationModel.php',
+ 'Kanboard\\Model\\ProjectFileModel' => __DIR__ . '/../..' . '/app/Model/ProjectFileModel.php',
+ 'Kanboard\\Model\\ProjectGroupRoleModel' => __DIR__ . '/../..' . '/app/Model/ProjectGroupRoleModel.php',
+ 'Kanboard\\Model\\ProjectMetadataModel' => __DIR__ . '/../..' . '/app/Model/ProjectMetadataModel.php',
+ 'Kanboard\\Model\\ProjectModel' => __DIR__ . '/../..' . '/app/Model/ProjectModel.php',
+ 'Kanboard\\Model\\ProjectNotificationModel' => __DIR__ . '/../..' . '/app/Model/ProjectNotificationModel.php',
+ 'Kanboard\\Model\\ProjectNotificationTypeModel' => __DIR__ . '/../..' . '/app/Model/ProjectNotificationTypeModel.php',
+ 'Kanboard\\Model\\ProjectPermissionModel' => __DIR__ . '/../..' . '/app/Model/ProjectPermissionModel.php',
+ 'Kanboard\\Model\\ProjectRoleModel' => __DIR__ . '/../..' . '/app/Model/ProjectRoleModel.php',
+ 'Kanboard\\Model\\ProjectRoleRestrictionModel' => __DIR__ . '/../..' . '/app/Model/ProjectRoleRestrictionModel.php',
+ 'Kanboard\\Model\\ProjectTaskDuplicationModel' => __DIR__ . '/../..' . '/app/Model/ProjectTaskDuplicationModel.php',
+ 'Kanboard\\Model\\ProjectTaskPriorityModel' => __DIR__ . '/../..' . '/app/Model/ProjectTaskPriorityModel.php',
+ 'Kanboard\\Model\\ProjectUserRoleModel' => __DIR__ . '/../..' . '/app/Model/ProjectUserRoleModel.php',
+ 'Kanboard\\Model\\RememberMeSessionModel' => __DIR__ . '/../..' . '/app/Model/RememberMeSessionModel.php',
+ 'Kanboard\\Model\\SettingModel' => __DIR__ . '/../..' . '/app/Model/SettingModel.php',
+ 'Kanboard\\Model\\SubtaskModel' => __DIR__ . '/../..' . '/app/Model/SubtaskModel.php',
+ 'Kanboard\\Model\\SubtaskPositionModel' => __DIR__ . '/../..' . '/app/Model/SubtaskPositionModel.php',
+ 'Kanboard\\Model\\SubtaskStatusModel' => __DIR__ . '/../..' . '/app/Model/SubtaskStatusModel.php',
+ 'Kanboard\\Model\\SubtaskTaskConversionModel' => __DIR__ . '/../..' . '/app/Model/SubtaskTaskConversionModel.php',
+ 'Kanboard\\Model\\SubtaskTimeTrackingModel' => __DIR__ . '/../..' . '/app/Model/SubtaskTimeTrackingModel.php',
+ 'Kanboard\\Model\\SwimlaneModel' => __DIR__ . '/../..' . '/app/Model/SwimlaneModel.php',
+ 'Kanboard\\Model\\TagDuplicationModel' => __DIR__ . '/../..' . '/app/Model/TagDuplicationModel.php',
+ 'Kanboard\\Model\\TagModel' => __DIR__ . '/../..' . '/app/Model/TagModel.php',
+ 'Kanboard\\Model\\TaskAnalyticModel' => __DIR__ . '/../..' . '/app/Model/TaskAnalyticModel.php',
+ 'Kanboard\\Model\\TaskCreationModel' => __DIR__ . '/../..' . '/app/Model/TaskCreationModel.php',
+ 'Kanboard\\Model\\TaskDuplicationModel' => __DIR__ . '/../..' . '/app/Model/TaskDuplicationModel.php',
+ 'Kanboard\\Model\\TaskExternalLinkModel' => __DIR__ . '/../..' . '/app/Model/TaskExternalLinkModel.php',
+ 'Kanboard\\Model\\TaskFileModel' => __DIR__ . '/../..' . '/app/Model/TaskFileModel.php',
+ 'Kanboard\\Model\\TaskFinderModel' => __DIR__ . '/../..' . '/app/Model/TaskFinderModel.php',
+ 'Kanboard\\Model\\TaskLinkModel' => __DIR__ . '/../..' . '/app/Model/TaskLinkModel.php',
+ 'Kanboard\\Model\\TaskMetadataModel' => __DIR__ . '/../..' . '/app/Model/TaskMetadataModel.php',
+ 'Kanboard\\Model\\TaskModel' => __DIR__ . '/../..' . '/app/Model/TaskModel.php',
+ 'Kanboard\\Model\\TaskModificationModel' => __DIR__ . '/../..' . '/app/Model/TaskModificationModel.php',
+ 'Kanboard\\Model\\TaskPositionModel' => __DIR__ . '/../..' . '/app/Model/TaskPositionModel.php',
+ 'Kanboard\\Model\\TaskProjectDuplicationModel' => __DIR__ . '/../..' . '/app/Model/TaskProjectDuplicationModel.php',
+ 'Kanboard\\Model\\TaskProjectMoveModel' => __DIR__ . '/../..' . '/app/Model/TaskProjectMoveModel.php',
+ 'Kanboard\\Model\\TaskRecurrenceModel' => __DIR__ . '/../..' . '/app/Model/TaskRecurrenceModel.php',
+ 'Kanboard\\Model\\TaskStatusModel' => __DIR__ . '/../..' . '/app/Model/TaskStatusModel.php',
+ 'Kanboard\\Model\\TaskTagModel' => __DIR__ . '/../..' . '/app/Model/TaskTagModel.php',
+ 'Kanboard\\Model\\TimezoneModel' => __DIR__ . '/../..' . '/app/Model/TimezoneModel.php',
+ 'Kanboard\\Model\\TransitionModel' => __DIR__ . '/../..' . '/app/Model/TransitionModel.php',
+ 'Kanboard\\Model\\UserLockingModel' => __DIR__ . '/../..' . '/app/Model/UserLockingModel.php',
+ 'Kanboard\\Model\\UserMetadataModel' => __DIR__ . '/../..' . '/app/Model/UserMetadataModel.php',
+ 'Kanboard\\Model\\UserModel' => __DIR__ . '/../..' . '/app/Model/UserModel.php',
+ 'Kanboard\\Model\\UserNotificationFilterModel' => __DIR__ . '/../..' . '/app/Model/UserNotificationFilterModel.php',
+ 'Kanboard\\Model\\UserNotificationModel' => __DIR__ . '/../..' . '/app/Model/UserNotificationModel.php',
+ 'Kanboard\\Model\\UserNotificationTypeModel' => __DIR__ . '/../..' . '/app/Model/UserNotificationTypeModel.php',
+ 'Kanboard\\Model\\UserUnreadNotificationModel' => __DIR__ . '/../..' . '/app/Model/UserUnreadNotificationModel.php',
+ 'Kanboard\\Notification\\ActivityStreamNotification' => __DIR__ . '/../..' . '/app/Notification/ActivityStreamNotification.php',
+ 'Kanboard\\Notification\\MailNotification' => __DIR__ . '/../..' . '/app/Notification/MailNotification.php',
+ 'Kanboard\\Notification\\WebNotification' => __DIR__ . '/../..' . '/app/Notification/WebNotification.php',
+ 'Kanboard\\Notification\\WebhookNotification' => __DIR__ . '/../..' . '/app/Notification/WebhookNotification.php',
+ 'Kanboard\\Pagination\\DashboardPagination' => __DIR__ . '/../..' . '/app/Pagination/DashboardPagination.php',
+ 'Kanboard\\Pagination\\ProjectPagination' => __DIR__ . '/../..' . '/app/Pagination/ProjectPagination.php',
+ 'Kanboard\\Pagination\\SubtaskPagination' => __DIR__ . '/../..' . '/app/Pagination/SubtaskPagination.php',
+ 'Kanboard\\Pagination\\TaskPagination' => __DIR__ . '/../..' . '/app/Pagination/TaskPagination.php',
+ 'Kanboard\\Pagination\\UserPagination' => __DIR__ . '/../..' . '/app/Pagination/UserPagination.php',
+ 'Kanboard\\ServiceProvider\\ActionProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ActionProvider.php',
+ 'Kanboard\\ServiceProvider\\ApiProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ApiProvider.php',
+ 'Kanboard\\ServiceProvider\\AuthenticationProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/AuthenticationProvider.php',
+ 'Kanboard\\ServiceProvider\\AvatarProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/AvatarProvider.php',
+ 'Kanboard\\ServiceProvider\\CacheProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/CacheProvider.php',
+ 'Kanboard\\ServiceProvider\\ClassProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ClassProvider.php',
+ 'Kanboard\\ServiceProvider\\CommandProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/CommandProvider.php',
+ 'Kanboard\\ServiceProvider\\DatabaseProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/DatabaseProvider.php',
+ 'Kanboard\\ServiceProvider\\EventDispatcherProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/EventDispatcherProvider.php',
+ 'Kanboard\\ServiceProvider\\ExternalLinkProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ExternalLinkProvider.php',
+ 'Kanboard\\ServiceProvider\\ExternalTaskProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ExternalTaskProvider.php',
+ 'Kanboard\\ServiceProvider\\FilterProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/FilterProvider.php',
+ 'Kanboard\\ServiceProvider\\FormatterProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/FormatterProvider.php',
+ 'Kanboard\\ServiceProvider\\GroupProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/GroupProvider.php',
+ 'Kanboard\\ServiceProvider\\HelperProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/HelperProvider.php',
+ 'Kanboard\\ServiceProvider\\JobProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/JobProvider.php',
+ 'Kanboard\\ServiceProvider\\LoggingProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/LoggingProvider.php',
+ 'Kanboard\\ServiceProvider\\MailProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/MailProvider.php',
+ 'Kanboard\\ServiceProvider\\NotificationProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/NotificationProvider.php',
+ 'Kanboard\\ServiceProvider\\ObjectStorageProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/ObjectStorageProvider.php',
+ 'Kanboard\\ServiceProvider\\PluginProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/PluginProvider.php',
+ 'Kanboard\\ServiceProvider\\QueueProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/QueueProvider.php',
+ 'Kanboard\\ServiceProvider\\RouteProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/RouteProvider.php',
+ 'Kanboard\\ServiceProvider\\SessionProvider' => __DIR__ . '/../..' . '/app/ServiceProvider/SessionProvider.php',
+ 'Kanboard\\Subscriber\\AuthSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/AuthSubscriber.php',
+ 'Kanboard\\Subscriber\\BaseSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/BaseSubscriber.php',
+ 'Kanboard\\Subscriber\\BootstrapSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/BootstrapSubscriber.php',
+ 'Kanboard\\Subscriber\\LdapUserPhotoSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/LdapUserPhotoSubscriber.php',
+ 'Kanboard\\Subscriber\\NotificationSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/NotificationSubscriber.php',
+ 'Kanboard\\Subscriber\\ProjectDailySummarySubscriber' => __DIR__ . '/../..' . '/app/Subscriber/ProjectDailySummarySubscriber.php',
+ 'Kanboard\\Subscriber\\ProjectModificationDateSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/ProjectModificationDateSubscriber.php',
+ 'Kanboard\\Subscriber\\RecurringTaskSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/RecurringTaskSubscriber.php',
+ 'Kanboard\\Subscriber\\TransitionSubscriber' => __DIR__ . '/../..' . '/app/Subscriber/TransitionSubscriber.php',
+ 'Kanboard\\User\\Avatar\\AvatarFileProvider' => __DIR__ . '/../..' . '/app/User/Avatar/AvatarFileProvider.php',
+ 'Kanboard\\User\\Avatar\\LetterAvatarProvider' => __DIR__ . '/../..' . '/app/User/Avatar/LetterAvatarProvider.php',
+ 'Kanboard\\User\\DatabaseUserProvider' => __DIR__ . '/../..' . '/app/User/DatabaseUserProvider.php',
+ 'Kanboard\\User\\LdapUserProvider' => __DIR__ . '/../..' . '/app/User/LdapUserProvider.php',
+ 'Kanboard\\User\\OAuthUserProvider' => __DIR__ . '/../..' . '/app/User/OAuthUserProvider.php',
+ 'Kanboard\\User\\ReverseProxyUserProvider' => __DIR__ . '/../..' . '/app/User/ReverseProxyUserProvider.php',
+ 'Kanboard\\Validator\\ActionValidator' => __DIR__ . '/../..' . '/app/Validator/ActionValidator.php',
+ 'Kanboard\\Validator\\AuthValidator' => __DIR__ . '/../..' . '/app/Validator/AuthValidator.php',
+ 'Kanboard\\Validator\\BaseValidator' => __DIR__ . '/../..' . '/app/Validator/BaseValidator.php',
+ 'Kanboard\\Validator\\CategoryValidator' => __DIR__ . '/../..' . '/app/Validator/CategoryValidator.php',
+ 'Kanboard\\Validator\\ColumnMoveRestrictionValidator' => __DIR__ . '/../..' . '/app/Validator/ColumnMoveRestrictionValidator.php',
+ 'Kanboard\\Validator\\ColumnRestrictionValidator' => __DIR__ . '/../..' . '/app/Validator/ColumnRestrictionValidator.php',
+ 'Kanboard\\Validator\\ColumnValidator' => __DIR__ . '/../..' . '/app/Validator/ColumnValidator.php',
+ 'Kanboard\\Validator\\CommentValidator' => __DIR__ . '/../..' . '/app/Validator/CommentValidator.php',
+ 'Kanboard\\Validator\\CurrencyValidator' => __DIR__ . '/../..' . '/app/Validator/CurrencyValidator.php',
+ 'Kanboard\\Validator\\CustomFilterValidator' => __DIR__ . '/../..' . '/app/Validator/CustomFilterValidator.php',
+ 'Kanboard\\Validator\\ExternalLinkValidator' => __DIR__ . '/../..' . '/app/Validator/ExternalLinkValidator.php',
+ 'Kanboard\\Validator\\GroupValidator' => __DIR__ . '/../..' . '/app/Validator/GroupValidator.php',
+ 'Kanboard\\Validator\\LinkValidator' => __DIR__ . '/../..' . '/app/Validator/LinkValidator.php',
+ 'Kanboard\\Validator\\PasswordResetValidator' => __DIR__ . '/../..' . '/app/Validator/PasswordResetValidator.php',
+ 'Kanboard\\Validator\\ProjectRoleValidator' => __DIR__ . '/../..' . '/app/Validator/ProjectRoleValidator.php',
+ 'Kanboard\\Validator\\ProjectValidator' => __DIR__ . '/../..' . '/app/Validator/ProjectValidator.php',
+ 'Kanboard\\Validator\\SubtaskValidator' => __DIR__ . '/../..' . '/app/Validator/SubtaskValidator.php',
+ 'Kanboard\\Validator\\SwimlaneValidator' => __DIR__ . '/../..' . '/app/Validator/SwimlaneValidator.php',
+ 'Kanboard\\Validator\\TagValidator' => __DIR__ . '/../..' . '/app/Validator/TagValidator.php',
+ 'Kanboard\\Validator\\TaskLinkValidator' => __DIR__ . '/../..' . '/app/Validator/TaskLinkValidator.php',
+ 'Kanboard\\Validator\\TaskValidator' => __DIR__ . '/../..' . '/app/Validator/TaskValidator.php',
+ 'Kanboard\\Validator\\UserValidator' => __DIR__ . '/../..' . '/app/Validator/UserValidator.php',
+ 'Otp\\GoogleAuthenticator' => __DIR__ . '/..' . '/christian-riesen/otp/src/Otp/GoogleAuthenticator.php',
+ 'Otp\\Otp' => __DIR__ . '/..' . '/christian-riesen/otp/src/Otp/Otp.php',
+ 'Otp\\OtpInterface' => __DIR__ . '/..' . '/christian-riesen/otp/src/Otp/OtpInterface.php',
+ 'PHPQRCode' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode.php',
+ 'PHPQRCode\\Autoloader' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/Autoloader.php',
+ 'PHPQRCode\\Constants' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/Constants.php',
+ 'PHPQRCode\\FrameFiller' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/FrameFiller.php',
+ 'PHPQRCode\\QRbitstream' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRbitstream.php',
+ 'PHPQRCode\\QRcode' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRcode.php',
+ 'PHPQRCode\\QRencode' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRencode.php',
+ 'PHPQRCode\\QRimage' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRimage.php',
+ 'PHPQRCode\\QRinput' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRinput.php',
+ 'PHPQRCode\\QRinputItem' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRinputItem.php',
+ 'PHPQRCode\\QRmask' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRmask.php',
+ 'PHPQRCode\\QRrawcode' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrawcode.php',
+ 'PHPQRCode\\QRrs' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrs.php',
+ 'PHPQRCode\\QRrsItem' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrsItem.php',
+ 'PHPQRCode\\QRrsblock' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRrsblock.php',
+ 'PHPQRCode\\QRspec' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRspec.php',
+ 'PHPQRCode\\QRsplit' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRsplit.php',
+ 'PHPQRCode\\QRstr' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRstr.php',
+ 'PHPQRCode\\QRtools' => __DIR__ . '/..' . '/aferrandini/phpqrcode/lib/PHPQRCode/QRtools.php',
+ 'Parsedown' => __DIR__ . '/..' . '/erusev/parsedown/Parsedown.php',
+ 'ParsedownTest' => __DIR__ . '/..' . '/erusev/parsedown/test/ParsedownTest.php',
+ 'PicoDb\\Builder\\BaseBuilder' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Builder/BaseBuilder.php',
+ 'PicoDb\\Builder\\ConditionBuilder' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php',
+ 'PicoDb\\Builder\\InsertBuilder' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php',
+ 'PicoDb\\Builder\\OrConditionBuilder' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php',
+ 'PicoDb\\Builder\\UpdateBuilder' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php',
+ 'PicoDb\\Database' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Database.php',
+ 'PicoDb\\DriverFactory' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/DriverFactory.php',
+ 'PicoDb\\Driver\\Base' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Driver/Base.php',
+ 'PicoDb\\Driver\\Mssql' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Driver/Mssql.php',
+ 'PicoDb\\Driver\\Mysql' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Driver/Mysql.php',
+ 'PicoDb\\Driver\\Postgres' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Driver/Postgres.php',
+ 'PicoDb\\Driver\\Sqlite' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php',
+ 'PicoDb\\Hashtable' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Hashtable.php',
+ 'PicoDb\\LargeObject' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/LargeObject.php',
+ 'PicoDb\\SQLException' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/SQLException.php',
+ 'PicoDb\\Schema' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Schema.php',
+ 'PicoDb\\StatementHandler' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/StatementHandler.php',
+ 'PicoDb\\Table' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/Table.php',
+ 'PicoDb\\UrlParser' => __DIR__ . '/..' . '/fguillot/picodb/lib/PicoDb/UrlParser.php',
+ 'PicoFeed\\Base' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Base.php',
+ 'PicoFeed\\Client\\Client' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/Client.php',
+ 'PicoFeed\\Client\\ClientException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php',
+ 'PicoFeed\\Client\\Curl' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/Curl.php',
+ 'PicoFeed\\Client\\ForbiddenException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php',
+ 'PicoFeed\\Client\\HttpHeaders' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/HttpHeaders.php',
+ 'PicoFeed\\Client\\InvalidCertificateException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php',
+ 'PicoFeed\\Client\\InvalidUrlException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/InvalidUrlException.php',
+ 'PicoFeed\\Client\\MaxRedirectException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/MaxRedirectException.php',
+ 'PicoFeed\\Client\\MaxSizeException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/MaxSizeException.php',
+ 'PicoFeed\\Client\\Stream' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/Stream.php',
+ 'PicoFeed\\Client\\TimeoutException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php',
+ 'PicoFeed\\Client\\UnauthorizedException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/UnauthorizedException.php',
+ 'PicoFeed\\Client\\Url' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Client/Url.php',
+ 'PicoFeed\\Config\\Config' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Config/Config.php',
+ 'PicoFeed\\Encoding\\Encoding' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php',
+ 'PicoFeed\\Filter\\Attribute' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Filter/Attribute.php',
+ 'PicoFeed\\Filter\\Filter' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php',
+ 'PicoFeed\\Filter\\Html' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Filter/Html.php',
+ 'PicoFeed\\Filter\\Tag' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php',
+ 'PicoFeed\\Generator\\ContentGeneratorInterface' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php',
+ 'PicoFeed\\Generator\\FileContentGenerator' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php',
+ 'PicoFeed\\Generator\\YoutubeContentGenerator' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php',
+ 'PicoFeed\\Logging\\Logger' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php',
+ 'PicoFeed\\Parser\\Atom' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php',
+ 'PicoFeed\\Parser\\DateParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php',
+ 'PicoFeed\\Parser\\Feed' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php',
+ 'PicoFeed\\Parser\\Item' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Item.php',
+ 'PicoFeed\\Parser\\MalformedXmlException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php',
+ 'PicoFeed\\Parser\\Parser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Parser.php',
+ 'PicoFeed\\Parser\\ParserException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php',
+ 'PicoFeed\\Parser\\ParserInterface' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/ParserInterface.php',
+ 'PicoFeed\\Parser\\Rss10' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss10.php',
+ 'PicoFeed\\Parser\\Rss20' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php',
+ 'PicoFeed\\Parser\\Rss91' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php',
+ 'PicoFeed\\Parser\\Rss92' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/Rss92.php',
+ 'PicoFeed\\Parser\\XmlEntityException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/XmlEntityException.php',
+ 'PicoFeed\\Parser\\XmlParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Parser/XmlParser.php',
+ 'PicoFeed\\PicoFeedException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php',
+ 'PicoFeed\\Processor\\ContentFilterProcessor' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php',
+ 'PicoFeed\\Processor\\ContentGeneratorProcessor' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php',
+ 'PicoFeed\\Processor\\ItemPostProcessor' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php',
+ 'PicoFeed\\Processor\\ItemProcessorInterface' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php',
+ 'PicoFeed\\Processor\\ScraperProcessor' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php',
+ 'PicoFeed\\Reader\\Favicon' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php',
+ 'PicoFeed\\Reader\\Reader' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php',
+ 'PicoFeed\\Reader\\ReaderException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php',
+ 'PicoFeed\\Reader\\SubscriptionNotFoundException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php',
+ 'PicoFeed\\Reader\\UnsupportedFeedFormatException' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php',
+ 'PicoFeed\\Scraper\\CandidateParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php',
+ 'PicoFeed\\Scraper\\ParserInterface' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php',
+ 'PicoFeed\\Scraper\\RuleLoader' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Scraper/RuleLoader.php',
+ 'PicoFeed\\Scraper\\RuleParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php',
+ 'PicoFeed\\Scraper\\Scraper' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php',
+ 'PicoFeed\\Serialization\\Subscription' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php',
+ 'PicoFeed\\Serialization\\SubscriptionList' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php',
+ 'PicoFeed\\Serialization\\SubscriptionListBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php',
+ 'PicoFeed\\Serialization\\SubscriptionListParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php',
+ 'PicoFeed\\Serialization\\SubscriptionParser' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php',
+ 'PicoFeed\\Syndication\\AtomFeedBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php',
+ 'PicoFeed\\Syndication\\AtomHelper' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php',
+ 'PicoFeed\\Syndication\\AtomItemBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php',
+ 'PicoFeed\\Syndication\\FeedBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php',
+ 'PicoFeed\\Syndication\\ItemBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php',
+ 'PicoFeed\\Syndication\\Rss20FeedBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php',
+ 'PicoFeed\\Syndication\\Rss20Helper' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php',
+ 'PicoFeed\\Syndication\\Rss20ItemBuilder' => __DIR__ . '/..' . '/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php',
+ 'Pimple\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Container.php',
+ 'Pimple\\ServiceProviderInterface' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php',
+ 'Pimple\\Tests\\Fixtures\\Invokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php',
+ 'Pimple\\Tests\\Fixtures\\NonInvokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php',
+ 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php',
+ 'Pimple\\Tests\\Fixtures\\Service' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php',
+ 'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php',
+ 'Pimple\\Tests\\PimpleTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php',
+ 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
+ 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
+ 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php',
+ 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php',
+ 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php',
+ 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php',
+ 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php',
+ 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php',
+ 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
+ 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
+ 'SimpleLogger\\Base' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/Base.php',
+ 'SimpleLogger\\File' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/File.php',
+ 'SimpleLogger\\Logger' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/Logger.php',
+ 'SimpleLogger\\Stderr' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/Stderr.php',
+ 'SimpleLogger\\Stdout' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/Stdout.php',
+ 'SimpleLogger\\Syslog' => __DIR__ . '/..' . '/fguillot/simpleLogger/src/SimpleLogger/Syslog.php',
+ 'SimpleQueue\\Adapter\\AmqpQueueAdapter' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\AwsSqsQueueAdapter' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\BeanstalkQueueAdapter' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\DisqueQueueAdapter' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php',
+ 'SimpleQueue\\Adapter\\MemoryQueueAdapter' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php',
+ 'SimpleQueue\\Exception\\NotSupportedException' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Exception/NotSupportedException.php',
+ 'SimpleQueue\\Job' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Job.php',
+ 'SimpleQueue\\Queue' => __DIR__ . '/..' . '/fguillot/simple-queue/src/Queue.php',
+ 'SimpleQueue\\QueueAdapterInterface' => __DIR__ . '/..' . '/fguillot/simple-queue/src/QueueAdapterInterface.php',
+ 'SimpleValidator\\Validator' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validator.php',
+ 'SimpleValidator\\Validators\\Alpha' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php',
+ 'SimpleValidator\\Validators\\AlphaNumeric' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php',
+ 'SimpleValidator\\Validators\\Base' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php',
+ 'SimpleValidator\\Validators\\Date' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php',
+ 'SimpleValidator\\Validators\\Email' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php',
+ 'SimpleValidator\\Validators\\Equals' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php',
+ 'SimpleValidator\\Validators\\Exists' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php',
+ 'SimpleValidator\\Validators\\GreaterThan' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php',
+ 'SimpleValidator\\Validators\\InArray' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php',
+ 'SimpleValidator\\Validators\\Integer' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php',
+ 'SimpleValidator\\Validators\\Ip' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php',
+ 'SimpleValidator\\Validators\\Length' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php',
+ 'SimpleValidator\\Validators\\MaxLength' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php',
+ 'SimpleValidator\\Validators\\MinLength' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php',
+ 'SimpleValidator\\Validators\\NotEmpty' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php',
+ 'SimpleValidator\\Validators\\NotEquals' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php',
+ 'SimpleValidator\\Validators\\NotInArray' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php',
+ 'SimpleValidator\\Validators\\Numeric' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php',
+ 'SimpleValidator\\Validators\\Range' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php',
+ 'SimpleValidator\\Validators\\Required' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php',
+ 'SimpleValidator\\Validators\\Unique' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php',
+ 'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php',
+ 'Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php',
+ 'Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php',
+ 'Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php',
+ 'Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php',
+ 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php',
+ 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php',
+ 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php',
+ 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleExceptionEvent.php',
+ 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php',
+ 'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php',
+ 'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php',
+ 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php',
+ 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php',
+ 'Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php',
+ 'Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
+ 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
+ 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\DialogHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DialogHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php',
+ 'Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php',
+ 'Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php',
+ 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php',
+ 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php',
+ 'Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php',
+ 'Symfony\\Component\\Console\\Helper\\TableHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TableHelper.php',
+ 'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php',
+ 'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php',
+ 'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php',
+ 'Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php',
+ 'Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php',
+ 'Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php',
+ 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php',
+ 'Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php',
+ 'Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php',
+ 'Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php',
+ 'Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php',
+ 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php',
+ 'Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php',
+ 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php',
+ 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php',
+ 'Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php',
+ 'Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php',
+ 'Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php',
+ 'Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php',
+ 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php',
+ 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php',
+ 'Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php',
+ 'Symfony\\Component\\Console\\Shell' => __DIR__ . '/..' . '/symfony/console/Shell.php',
+ 'Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php',
+ 'Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php',
+ 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php',
+ 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php',
+ 'Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php',
+ 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php',
+ 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php',
+ 'Symfony\\Component\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher/Event.php',
+ 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php',
+ 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcherInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventSubscriberInterface.php',
+ 'Symfony\\Component\\EventDispatcher\\GenericEvent' => __DIR__ . '/..' . '/symfony/event-dispatcher/GenericEvent.php',
+ 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ImmutableEventDispatcher.php',
+ 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
+ 'ZendXml\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/zendframework/zendxml/library/ZendXml/Exception/ExceptionInterface.php',
+ 'ZendXml\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/zendframework/zendxml/library/ZendXml/Exception/InvalidArgumentException.php',
+ 'ZendXml\\Exception\\RuntimeException' => __DIR__ . '/..' . '/zendframework/zendxml/library/ZendXml/Exception/RuntimeException.php',
+ 'ZendXml\\Security' => __DIR__ . '/..' . '/zendframework/zendxml/library/ZendXml/Security.php',
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::$prefixDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 00000000..12b9857f
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,1051 @@
+[
+ {
+ "name": "aferrandini/phpqrcode",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/aferrandini/PHPQRCode.git",
+ "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/aferrandini/PHPQRCode/zipball/3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
+ "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2013-07-08T09:39:08+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "PHPQRCode": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ariel Ferrandini",
+ "email": "arielferrandini@gmail.com",
+ "homepage": "http://www.ferrandini.com/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHPQRCode porting and changed for PHP 5.3 compatibility",
+ "homepage": "https://github.com/aferrandini/PHPQRCode",
+ "keywords": [
+ "barcode",
+ "php",
+ "qrcode"
+ ]
+ },
+ {
+ "name": "christian-riesen/base32",
+ "version": "1.3.1",
+ "version_normalized": "1.3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ChristianRiesen/base32.git",
+ "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
+ "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*",
+ "satooshi/php-coveralls": "0.*"
+ },
+ "time": "2016-05-05T11:49:03+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Base32\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Christian Riesen",
+ "email": "chris.riesen@gmail.com",
+ "homepage": "http://christianriesen.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Base32 encoder/decoder according to RFC 4648",
+ "homepage": "https://github.com/ChristianRiesen/base32",
+ "keywords": [
+ "base32",
+ "decode",
+ "encode",
+ "rfc4648"
+ ]
+ },
+ {
+ "name": "christian-riesen/otp",
+ "version": "1.4.3",
+ "version_normalized": "1.4.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ChristianRiesen/otp.git",
+ "reference": "20a539ce6280eb029030f4e7caefd5709a75e1ad"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ChristianRiesen/otp/zipball/20a539ce6280eb029030f4e7caefd5709a75e1ad",
+ "reference": "20a539ce6280eb029030f4e7caefd5709a75e1ad",
+ "shasum": ""
+ },
+ "require": {
+ "christian-riesen/base32": ">=1.0",
+ "php": ">=5.3.0"
+ },
+ "suggest": {
+ "paragonie/random_compat": "Optional polyfill for a more secure random generator for pre PHP7 versions"
+ },
+ "time": "2015-10-08T08:17:59+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Otp": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Christian Riesen",
+ "email": "chris.riesen@gmail.com",
+ "homepage": "http://christianriesen.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "One Time Passwords, hotp and totp according to RFC4226 and RFC6238",
+ "homepage": "https://github.com/ChristianRiesen/otp",
+ "keywords": [
+ "googleauthenticator",
+ "hotp",
+ "otp",
+ "rfc4226",
+ "rfc6238",
+ "totp"
+ ]
+ },
+ {
+ "name": "eluceo/ical",
+ "version": "0.10.1",
+ "version_normalized": "0.10.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/markuspoerschke/iCal.git",
+ "reference": "2dd99c12c0aa961c541380ab0c113135e14af33e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/markuspoerschke/iCal/zipball/2dd99c12c0aa961c541380ab0c113135e14af33e",
+ "reference": "2dd99c12c0aa961c541380ab0c113135e14af33e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.3"
+ },
+ "time": "2016-06-09T09:08:55+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Eluceo\\iCal": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Maciej Łebkowski",
+ "email": "m.lebkowski@gmail.com",
+ "role": "Contributor"
+ },
+ {
+ "name": "Markus Poerschke",
+ "email": "markus@eluceo.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "The eluceo/iCal package offers a abstraction layer for creating iCalendars. You can easily create iCal files by using PHP object instead of typing your *.ics file by hand. The output will follow RFC 2445 as best as possible.",
+ "homepage": "https://github.com/markuspoerschke/iCal",
+ "keywords": [
+ "calendar",
+ "iCalendar",
+ "ical",
+ "ics",
+ "php calendar"
+ ]
+ },
+ {
+ "name": "erusev/parsedown",
+ "version": "1.6.0",
+ "version_normalized": "1.6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/erusev/parsedown.git",
+ "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
+ "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
+ "shasum": ""
+ },
+ "time": "2015-10-04T16:44:32+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Parsedown": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Emanuil Rusev",
+ "email": "hello@erusev.com",
+ "homepage": "http://erusev.com"
+ }
+ ],
+ "description": "Parser for Markdown.",
+ "homepage": "http://parsedown.org",
+ "keywords": [
+ "markdown",
+ "parser"
+ ]
+ },
+ {
+ "name": "fguillot/json-rpc",
+ "version": "v1.2.1",
+ "version_normalized": "1.2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/JsonRPC.git",
+ "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/d491bb549bfa11aff4c37abcea2ffb28c9523f69",
+ "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.8.*"
+ },
+ "time": "2016-06-25T23:11:10+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "JsonRPC": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "Simple Json-RPC client/server library that just works",
+ "homepage": "https://github.com/fguillot/JsonRPC"
+ },
+ {
+ "name": "fguillot/picodb",
+ "version": "v1.0.14",
+ "version_normalized": "1.0.14.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/picoDb.git",
+ "reference": "86a831302ab10af800c83dbe4b3b01c88d5433f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/picoDb/zipball/86a831302ab10af800c83dbe4b3b01c88d5433f1",
+ "reference": "86a831302ab10af800c83dbe4b3b01c88d5433f1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.8.*"
+ },
+ "time": "2016-07-16T22:59:59+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "PicoDb": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot",
+ "homepage": "https://github.com/fguillot/"
+ }
+ ],
+ "description": "Minimalist database query builder",
+ "homepage": "https://github.com/fguillot/picoDb"
+ },
+ {
+ "name": "fguillot/simple-queue",
+ "version": "v1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/simple-queue.git",
+ "reference": "ce7801c507f9501bcca455129fb04c3d2107d5ff"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/simple-queue/zipball/ce7801c507f9501bcca455129fb04c3d2107d5ff",
+ "reference": "ce7801c507f9501bcca455129fb04c3d2107d5ff",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "~3.0",
+ "mariano/disque-php": "~2.0",
+ "pda/pheanstalk": "~3.0",
+ "php-amqplib/php-amqplib": "2.6.*",
+ "phpunit/phpunit": "5.3.*"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Required to use the AWS SQS queue driver (~3.0).",
+ "mariano/disque-php": "Required to use the Disque queue driver (~2.0).",
+ "pda/pheanstalk": "Required to use the Beanstalk queue driver (~3.0).",
+ "php-amqplib/php-amqplib": "Required to use the RabbitMQ queue driver (2.6.*)."
+ },
+ "time": "2016-06-05T21:34:56+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "SimpleQueue\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "Abstraction layer for multiple queue systems",
+ "homepage": "https://github.com/fguillot/simple-queue"
+ },
+ {
+ "name": "fguillot/simple-validator",
+ "version": "v1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/simpleValidator.git",
+ "reference": "23b0a99c5f11ad74d05f8845feaafbcfd9223eda"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/simpleValidator/zipball/23b0a99c5f11ad74d05f8845feaafbcfd9223eda",
+ "reference": "23b0a99c5f11ad74d05f8845feaafbcfd9223eda",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2016-06-26T15:09:26+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "SimpleValidator": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "Simple validator library",
+ "homepage": "https://github.com/fguillot/simpleValidator"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "version_normalized": "1.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2016-10-10T12:19:37+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "fguillot/simpleLogger",
+ "version": "v1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/simpleLogger.git",
+ "reference": "c6831841193bb265b7900ecc8b6a8918371a7c98"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/simpleLogger/zipball/c6831841193bb265b7900ecc8b6a8918371a7c98",
+ "reference": "c6831841193bb265b7900ecc8b6a8918371a7c98",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/log": "~1.0"
+ },
+ "time": "2016-05-07T18:01:57+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "SimpleLogger": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "PHP library to write logs (compatible with PSR-3)",
+ "homepage": "https://github.com/fguillot/simpleLogger"
+ },
+ {
+ "name": "gregwar/captcha",
+ "version": "v1.1.1",
+ "version_normalized": "1.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Gregwar/Captcha.git",
+ "reference": "1240ab993ca713680573b2d4166900da5f758623"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Gregwar/Captcha/zipball/1240ab993ca713680573b2d4166900da5f758623",
+ "reference": "1240ab993ca713680573b2d4166900da5f758623",
+ "shasum": ""
+ },
+ "require": {
+ "ext-gd": "*",
+ "php": ">=5.3.0"
+ },
+ "time": "2015-09-11T15:23:20+00:00",
+ "type": "captcha",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Gregwar\\Captcha\\": "/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Grégoire Passault",
+ "email": "g.passault@gmail.com",
+ "homepage": "http://www.gregwar.com/"
+ },
+ {
+ "name": "Jeremy Livingston",
+ "email": "jeremy.j.livingston@gmail.com"
+ }
+ ],
+ "description": "Captcha generator",
+ "homepage": "https://github.com/Gregwar/Captcha",
+ "keywords": [
+ "bot",
+ "captcha",
+ "spam"
+ ]
+ },
+ {
+ "name": "zendframework/zendxml",
+ "version": "1.0.2",
+ "version_normalized": "1.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/zendframework/ZendXml.git",
+ "reference": "7b64507bc35d841c9c5802d67f6f87ef8e1a58c9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/zendframework/ZendXml/zipball/7b64507bc35d841c9c5802d67f6f87ef8e1a58c9",
+ "reference": "7b64507bc35d841c9c5802d67f6f87ef8e1a58c9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.3 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^3.7 || ^4.0",
+ "squizlabs/php_codesniffer": "^1.5"
+ },
+ "time": "2016-02-04T21:02:08+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "ZendXml\\": "library/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Utility library for XML usage, best practices, and security in PHP",
+ "homepage": "http://packages.zendframework.com/",
+ "keywords": [
+ "security",
+ "xml",
+ "zf2"
+ ]
+ },
+ {
+ "name": "miniflux/picofeed",
+ "version": "v0.1.34",
+ "version_normalized": "0.1.34.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/miniflux/picoFeed.git",
+ "reference": "5c8a731d4e7a3589e562e4fdaa98bcb57fa8a2ea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/miniflux/picoFeed/zipball/5c8a731d4e7a3589e562e4fdaa98bcb57fa8a2ea",
+ "reference": "5c8a731d4e7a3589e562e4fdaa98bcb57fa8a2ea",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-iconv": "*",
+ "ext-libxml": "*",
+ "ext-simplexml": "*",
+ "ext-xml": "*",
+ "php": ">=5.3.0",
+ "zendframework/zendxml": "^1.0"
+ },
+ "require-dev": {
+ "phpdocumentor/reflection-docblock": "2.0.4",
+ "phpunit/phpunit": "4.8.26",
+ "symfony/yaml": "2.8.7"
+ },
+ "suggest": {
+ "ext-curl": "PicoFeed will use cURL if present"
+ },
+ "time": "2017-06-12T00:22:06+00:00",
+ "bin": [
+ "picofeed"
+ ],
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "PicoFeed": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "Modern library to handle RSS/Atom feeds",
+ "homepage": "https://github.com/miniflux/picoFeed"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v2.0.2",
+ "version_normalized": "2.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf",
+ "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "time": "2016-04-03T06:00:07+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "lib/random.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "pseudorandom",
+ "random"
+ ]
+ },
+ {
+ "name": "pimple/pimple",
+ "version": "v3.0.2",
+ "version_normalized": "3.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2015-09-11T15:10:35+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Pimple": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "http://pimple.sensiolabs.org",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ]
+ },
+ {
+ "name": "ramsey/array_column",
+ "version": "1.1.3",
+ "version_normalized": "1.1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/array_column.git",
+ "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/array_column/zipball/f8e52eb28e67eb50e613b451dd916abcf783c1db",
+ "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db",
+ "shasum": ""
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.8.*",
+ "phpunit/phpunit": "~4.5",
+ "satooshi/php-coveralls": "0.6.*",
+ "squizlabs/php_codesniffer": "~2.2"
+ },
+ "time": "2015-03-20T22:07:39+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/array_column.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "homepage": "http://benramsey.com"
+ }
+ ],
+ "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.",
+ "homepage": "https://github.com/ramsey/array_column",
+ "keywords": [
+ "array",
+ "array_column",
+ "column"
+ ]
+ },
+ {
+ "name": "swiftmailer/swiftmailer",
+ "version": "v5.4.5",
+ "version_normalized": "5.4.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/swiftmailer/swiftmailer.git",
+ "reference": "cd142238a339459b10da3d8234220963f392540c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/cd142238a339459b10da3d8234220963f392540c",
+ "reference": "cd142238a339459b10da3d8234220963f392540c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "mockery/mockery": "~0.9.1",
+ "symfony/phpunit-bridge": "~3.2"
+ },
+ "time": "2016-12-29T10:02:40+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "lib/swift_required.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Chris Corbyn"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Swiftmailer, free feature-rich PHP mailer",
+ "homepage": "http://swiftmailer.org",
+ "keywords": [
+ "email",
+ "mail",
+ "mailer"
+ ]
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.4.0",
+ "version_normalized": "1.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "f29dca382a6485c3cbe6379f0c61230167681937"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937",
+ "reference": "f29dca382a6485c3cbe6379f0c61230167681937",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2017-06-09T14:24:12+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ]
+ },
+ {
+ "name": "symfony/console",
+ "version": "v2.8.7",
+ "version_normalized": "2.8.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
+ "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.1|~3.0.0",
+ "symfony/process": "~2.1|~3.0.0"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
+ },
+ "time": "2016-06-06T15:06:25+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v2.7.14",
+ "version_normalized": "2.7.14.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "d3e09ed1224503791f31b913d22196f65f9afed5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d3e09ed1224503791f31b913d22196f65f9afed5",
+ "reference": "d3e09ed1224503791f31b913d22196f65f9afed5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.0,>=2.0.5",
+ "symfony/dependency-injection": "~2.6",
+ "symfony/expression-language": "~2.6",
+ "symfony/stopwatch": "~2.3"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "time": "2016-06-06T11:03:51+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com"
+ }
+]
diff --git a/vendor/eluceo/ical/.gitignore b/vendor/eluceo/ical/.gitignore
new file mode 100644
index 00000000..4e06e7d4
--- /dev/null
+++ b/vendor/eluceo/ical/.gitignore
@@ -0,0 +1,3 @@
+vendor
+composer.lock
+bin
diff --git a/vendor/eluceo/ical/.php_cs b/vendor/eluceo/ical/.php_cs
new file mode 100644
index 00000000..1d54d34a
--- /dev/null
+++ b/vendor/eluceo/ical/.php_cs
@@ -0,0 +1,26 @@
+
+
+This source file is subject to the MIT license that is bundled
+with this source code in the file LICENSE.
+EOF
+);
+
+$finder = Symfony\CS\Finder\DefaultFinder::create();
+$finder->in(__DIR__ . '/src');
+
+return Symfony\CS\Config\Config::create()
+ ->fixers(array(
+ 'header_comment',
+ 'concat_with_spaces',
+ 'align_equals',
+ 'align_double_arrow',
+ 'unused_use',
+ 'long_array_syntax',
+ ))
+ ->finder($finder)
+;
diff --git a/vendor/eluceo/ical/.scrutinizer.yml b/vendor/eluceo/ical/.scrutinizer.yml
new file mode 100644
index 00000000..d3b381a2
--- /dev/null
+++ b/vendor/eluceo/ical/.scrutinizer.yml
@@ -0,0 +1,20 @@
+filter:
+ excluded_paths:
+ - tests/*
+
+tools:
+ php_cs_fixer: true
+ php_code_sniffer:
+ config:
+ standard: PSR2
+ php_mess_detector: true
+ php_analyzer: true
+ sensiolabs_security_checker: true
+ external_code_coverage:
+ timeout: 300
+ runs: 1
+
+checks:
+ php:
+ code_rating: true
+ duplication: true
diff --git a/vendor/eluceo/ical/.travis.yml b/vendor/eluceo/ical/.travis.yml
new file mode 100644
index 00000000..cbe31ac9
--- /dev/null
+++ b/vendor/eluceo/ical/.travis.yml
@@ -0,0 +1,19 @@
+language: php
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+
+before_script:
+ - composer self-update
+ - composer install
+
+script: ./bin/phpunit --coverage-clover=coverage.clover
+
+after_script:
+ - wget https://scrutinizer-ci.com/ocular.phar
+ - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
diff --git a/vendor/eluceo/ical/CHANGELOG.md b/vendor/eluceo/ical/CHANGELOG.md
new file mode 100644
index 00000000..84320d98
--- /dev/null
+++ b/vendor/eluceo/ical/CHANGELOG.md
@@ -0,0 +1,31 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+
+## [0.10.1] - 2016-05-09
+### Fixed
+- Problem with GEO property when importing into Google Calendar [#74](https://github.com/markuspoerschke/iCal/pull/74)
+
+## [0.10.0] - 2016-04-26
+### Changed
+- Use 'escapeValue' to escape the new line character. [#60](https://github.com/markuspoerschke/iCal/pull/60)
+- Order components by type when building ical file. [#65](https://github.com/markuspoerschke/iCal/pull/65)
+
+### Added
+- X-ALT-DESC for HTML types with new descriptionHTML field. [#55](https://github.com/markuspoerschke/iCal/pull/55)
+- Added a property and setter for calendar color. [#68](https://github.com/markuspoerschke/iCal/pull/68)
+- Write also GEO property if geo location is given. [#66](https://github.com/markuspoerschke/iCal/pull/66)
+
+## [0.9.0] - 2015-11-13
+### Added
+- CHANGELOG.md based on [’Keep a CHANGELOG’](https://github.com/olivierlacan/keep-a-changelog)
+- Support event properties EXDATE and RECURRENCE-ID [#50](https://github.com/markuspoerschke/iCal/pull/53)
+
+### Changed
+- Allow new lines in event descriptions [#53](https://github.com/markuspoerschke/iCal/pull/53)
+- **Breaking Change:** Changed signature of the ```Event::setOrganizer``` method. Now there is is only one parameter that must be an instance of ```Property\Organizer```.
+- Updated install section in README.md [#54](https://github.com/markuspoerschke/iCal/pull/53)
+
+[Unreleased]: https://github.com/markuspoerschke/iCal/compare/0.10.1...HEAD
+[0.10.1]: https://github.com/markuspoerschke/iCal/compare/0.10.0...0.10.1
+[0.10.0]: https://github.com/markuspoerschke/iCal/compare/0.9.0...0.10.0
+[0.9.0]: https://github.com/markuspoerschke/iCal/compare/0.8.0...0.9.0
diff --git a/vendor/eluceo/ical/LICENSE b/vendor/eluceo/ical/LICENSE
new file mode 100644
index 00000000..92be8d06
--- /dev/null
+++ b/vendor/eluceo/ical/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012-2015 Markus Poerschke
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/eluceo/ical/README.md b/vendor/eluceo/ical/README.md
new file mode 100644
index 00000000..521d537d
--- /dev/null
+++ b/vendor/eluceo/ical/README.md
@@ -0,0 +1,158 @@
+# eluceo — iCal
+
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/markuspoerschke/iCal/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/markuspoerschke/iCal/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/markuspoerschke/iCal/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/markuspoerschke/iCal/?branch=master) [![Build Status](https://travis-ci.org/markuspoerschke/iCal.svg?branch=master)](https://travis-ci.org/markuspoerschke/iCal)
+
+This package offers a abstraction layer for creating iCalendars. The output will
+follow [RFC 5545](http://www.ietf.org/rfc/rfc5545.txt) as best as possible.
+
+The following components are supported at this time:
+
+* VCALENDAR
+* VEVENT
+* VALARM
+* VTIMEZONE
+
+## Installation
+
+You can install this package by using [Composer](http://getcomposer.org), running this command:
+
+```sh
+composer require eluceo/ical
+```
+Link to Packagist: https://packagist.org/packages/eluceo/ical
+
+## Usage
+
+### Basic Usage
+
+#### 1. Create a Calendar object
+
+```PHP
+$vCalendar = new \Eluceo\iCal\Component\Calendar('www.example.com');
+```
+
+#### 2. Create an Event object
+
+```PHP
+$vEvent = new \Eluceo\iCal\Component\Event();
+```
+
+#### 3. Add your information to the Event
+
+```PHP
+$vEvent
+ ->setDtStart(new \DateTime('2012-12-24'))
+ ->setDtEnd(new \DateTime('2012-12-24'))
+ ->setNoTime(true)
+ ->setSummary('Christmas')
+;
+```
+
+#### 4. Add Event to Calendar
+
+```PHP
+$vCalendar->addComponent($vEvent);
+```
+
+#### 5. Set HTTP-headers
+
+```PHP
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+```
+
+#### 6. Send output
+
+```PHP
+echo $vCalendar->render();
+```
+
+### Timezone support
+
+This package supports three different types of handling timezones:
+
+#### 1. UTC (default)
+
+In the default setting, UTC/GMT will be used as Timezone. The time will be formated as following:
+
+```
+DTSTART:20121224T180000Z
+```
+
+#### 2. Use explicit timezone
+
+You can use an explicit timezone by calling `$vEvent->setUseTimezone(true);`. The timezone of your
+`\DateTime` object will be used. In this case the non-standard field "X-WR-TIMEZONE" will be used.
+Be awre that this is a simple solution which is not supported by all calendar clients.
+The output will be as following:
+
+```
+DTSTART;TZID=Europe/Berlin:20121224T180000
+```
+
+#### 3. Use explicit timezone with definition
+
+You can use an explicit timezone and define it using `Timezone()` and `TimezoneRule()` (see example5.php).
+The timezone of your `\DateTime` object will be used. The output will be as following:
+
+```
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+DTSTART:19810329T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+DTSTART:19961027T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+END:VTIMEZONE
+...
+DTSTART;TZID=Europe/Berlin:20121224T180000
+```
+
+#### 4. Use locale time
+
+You can use local time by calling `$vEvent->setUseUtc(false);`. The output will be:
+
+```
+DTSTART:20121224T180000
+```
+
+## Running the tests
+
+To setup and run tests:
+
+- go to the root directory of this project
+- download composer: `wget https://getcomposer.org/composer.phar`
+- install dev dependencies: `php composer.phar install --dev`
+- run `./bin/phpunit`
+
+## License
+
+This package is released under the __MIT license__.
+
+Copyright (c) 2012-2015 Markus Poerschke
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/eluceo/ical/UPGRADE.md b/vendor/eluceo/ical/UPGRADE.md
new file mode 100644
index 00000000..951209dd
--- /dev/null
+++ b/vendor/eluceo/ical/UPGRADE.md
@@ -0,0 +1,9 @@
+# v0.8.0 -> v0.9.0
+
+- The signature of the ```Event::setOrganizer``` method was changed:
+Now there is is only one parameter that must be an instance of ```Property\Organizer```.
+
+# v0.7.0 -> v0.8.0
+
+- The signature of the ```Event::setOrganizer``` method was changed: Now there are
+two parameters name and email instead of an already formatted string.
diff --git a/vendor/eluceo/ical/composer.json b/vendor/eluceo/ical/composer.json
new file mode 100644
index 00000000..b2477c28
--- /dev/null
+++ b/vendor/eluceo/ical/composer.json
@@ -0,0 +1,43 @@
+{
+ "name": "eluceo/ical",
+ "description": "The eluceo/iCal package offers a abstraction layer for creating iCalendars. You can easily create iCal files by using PHP object instead of typing your *.ics file by hand. The output will follow RFC 2445 as best as possible.",
+ "license": "MIT",
+ "homepage": "https://github.com/markuspoerschke/iCal",
+ "authors": [
+ {
+ "name": "Markus Poerschke",
+ "email": "markus@eluceo.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Maciej Łebkowski",
+ "email": "m.lebkowski@gmail.com",
+ "role": "Contributor"
+ }
+ ],
+ "keywords": [
+ "ical",
+ "php calendar",
+ "icalendar",
+ "ics",
+ "calendar"
+ ],
+ "support": {
+ "issues": "https://github.com/markuspoerschke/iCal/issues",
+ "source": "https://github.com/markuspoerschke/iCal"
+ },
+ "autoload": {
+ "psr-0": {
+ "Eluceo\\iCal": "src/"
+ }
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.3"
+ },
+ "config": {
+ "bin-dir": "bin"
+ }
+}
diff --git a/vendor/eluceo/ical/examples/example1.php b/vendor/eluceo/ical/examples/example1.php
new file mode 100644
index 00000000..4d1d32c4
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example1.php
@@ -0,0 +1,30 @@
+setDtStart(new \DateTime('2012-12-24'));
+$vEvent->setDtEnd(new \DateTime('2012-12-24'));
+$vEvent->setNoTime(true);
+$vEvent->setSummary('Christmas');
+
+// Adding Timezone (optional)
+$vEvent->setUseTimezone(true);
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example2.php b/vendor/eluceo/ical/examples/example2.php
new file mode 100644
index 00000000..bafcf033
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example2.php
@@ -0,0 +1,31 @@
+setDtStart(new \DateTime('2012-12-24'));
+$vEvent->setDtEnd(new \DateTime('2012-12-24'));
+$vEvent->setNoTime(true);
+$vEvent->setSummary('Summary with some german "umlauten" and a backslash \\: Kinder mögen Äpfel pflücken.');
+$vEvent->setCategories(['holidays']);
+
+// Adding Timezone (optional)
+$vEvent->setUseTimezone(true);
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example3.php b/vendor/eluceo/ical/examples/example3.php
new file mode 100644
index 00000000..290ff2dc
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example3.php
@@ -0,0 +1,36 @@
+setDtStart(new \DateTime('2012-12-31'));
+$vEvent->setDtEnd(new \DateTime('2012-12-31'));
+$vEvent->setNoTime(true);
+$vEvent->setSummary('New Year’s Eve');
+
+// Set recurrence rule
+$recurrenceRule = new \Eluceo\iCal\Property\Event\RecurrenceRule();
+$recurrenceRule->setFreq(\Eluceo\iCal\Property\Event\RecurrenceRule::FREQ_YEARLY);
+$recurrenceRule->setInterval(1);
+$vEvent->setRecurrenceRule($recurrenceRule);
+
+// Adding Timezone (optional)
+$vEvent->setUseTimezone(true);
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example4.php b/vendor/eluceo/ical/examples/example4.php
new file mode 100644
index 00000000..7b87144c
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example4.php
@@ -0,0 +1,35 @@
+setDtStart(new \DateTime('2012-11-11 13:00:00'));
+$vEvent->setDtEnd(new \DateTime('2012-11-11 14:30:00'));
+$vEvent->setSummary('Weekly lunch with Markus');
+
+// Set recurrence rule
+$recurrenceRule = new \Eluceo\iCal\Property\Event\RecurrenceRule();
+$recurrenceRule->setFreq(\Eluceo\iCal\Property\Event\RecurrenceRule::FREQ_WEEKLY);
+$recurrenceRule->setInterval(1);
+$vEvent->setRecurrenceRule($recurrenceRule);
+
+// Adding Timezone (optional)
+$vEvent->setUseTimezone(true);
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example5.php b/vendor/eluceo/ical/examples/example5.php
new file mode 100644
index 00000000..a7da6e27
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example5.php
@@ -0,0 +1,66 @@
+setTzName('CEST');
+$vTimezoneRuleDst->setDtStart(new \DateTime('1981-03-29 02:00:00', $dtz));
+$vTimezoneRuleDst->setTzOffsetFrom('+0100');
+$vTimezoneRuleDst->setTzOffsetTo('+0200');
+$dstRecurrenceRule = new \Eluceo\iCal\Property\Event\RecurrenceRule();
+$dstRecurrenceRule->setFreq(\Eluceo\iCal\Property\Event\RecurrenceRule::FREQ_YEARLY);
+$dstRecurrenceRule->setByMonth(3);
+$dstRecurrenceRule->setByDay('-1SU');
+$vTimezoneRuleDst->setRecurrenceRule($dstRecurrenceRule);
+
+// 3. Create timezone rule object for Standard Time
+$vTimezoneRuleStd = new \Eluceo\iCal\Component\TimezoneRule(\Eluceo\iCal\Component\TimezoneRule::TYPE_STANDARD);
+$vTimezoneRuleStd->setTzName('CET');
+$vTimezoneRuleStd->setDtStart(new \DateTime('1996-10-27 03:00:00', $dtz));
+$vTimezoneRuleStd->setTzOffsetFrom('+0200');
+$vTimezoneRuleStd->setTzOffsetTo('+0100');
+$stdRecurrenceRule = new \Eluceo\iCal\Property\Event\RecurrenceRule();
+$stdRecurrenceRule->setFreq(\Eluceo\iCal\Property\Event\RecurrenceRule::FREQ_YEARLY);
+$stdRecurrenceRule->setByMonth(10);
+$stdRecurrenceRule->setByDay('-1SU');
+$vTimezoneRuleStd->setRecurrenceRule($stdRecurrenceRule);
+
+// 4. Create timezone definition and add rules
+$vTimezone = new \Eluceo\iCal\Component\Timezone($tz);
+$vTimezone->addComponent($vTimezoneRuleDst);
+$vTimezone->addComponent($vTimezoneRuleStd);
+$vCalendar->setTimezone($vTimezone);
+
+// 5. Create an event
+$vEvent = new \Eluceo\iCal\Component\Event();
+$vEvent->setDtStart(new \DateTime('2012-12-24', $dtz));
+$vEvent->setDtEnd(new \DateTime('2012-12-24', $dtz));
+$vEvent->setSummary('Summary with some german "umlauten" and a backslash \\: Kinder mögen Äpfel pflücken.');
+
+// 6. Adding Timezone
+$vEvent->setUseTimezone(true);
+
+// 7. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 8. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 9. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example6.php b/vendor/eluceo/ical/examples/example6.php
new file mode 100644
index 00000000..10400993
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example6.php
@@ -0,0 +1,30 @@
+setDtStart(new \DateTime('2012-12-24'));
+$vEvent->setDtEnd(new \DateTime('2012-12-24'));
+$vEvent->setNoTime(true);
+$vEvent->setSummary('Christmas');
+
+// add some location information for apple devices
+$vEvent->setLocation("Infinite Loop\nCupertino CA 95014", 'Infinite Loop', '37.332095,-122.030743');
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/examples/example7.php b/vendor/eluceo/ical/examples/example7.php
new file mode 100644
index 00000000..1f8013e7
--- /dev/null
+++ b/vendor/eluceo/ical/examples/example7.php
@@ -0,0 +1,33 @@
+setDtStart(new \DateTime('2012-12-24'));
+$vEvent->setDtEnd(new \DateTime('2012-12-24'));
+$vEvent->setNoTime(true);
+$vEvent->setSummary('Christmas');
+$vEvent->setDescription('Happy Christmas!');
+$vEvent->setDescriptionHTML('Happy Christmas!');
+
+
+// add some location information for apple devices
+$vEvent->setLocation("Infinite Loop\nCupertino CA 95014", 'Infinite Loop', '37.332095,-122.030743');
+
+// 3. Add event to calendar
+$vCalendar->addComponent($vEvent);
+
+// 4. Set headers
+header('Content-Type: text/calendar; charset=utf-8');
+header('Content-Disposition: attachment; filename="cal.ics"');
+
+// 5. Output
+echo $vCalendar->render();
diff --git a/vendor/eluceo/ical/phpunit.xml.dist b/vendor/eluceo/ical/phpunit.xml.dist
new file mode 100644
index 00000000..13e18c0e
--- /dev/null
+++ b/vendor/eluceo/ical/phpunit.xml.dist
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+ ./tests/Eluceo/iCal/
+
+
+
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component.php
new file mode 100644
index 00000000..76c9b2d9
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component.php
@@ -0,0 +1,172 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal;
+
+use Eluceo\iCal\Util\ComponentUtil;
+
+/**
+ * Abstract Calender Component.
+ */
+abstract class Component
+{
+ /**
+ * Array of Components.
+ *
+ * @var Component[]
+ */
+ protected $components = array();
+
+ /**
+ * The order in which the components will be rendered during build.
+ *
+ * Not defined components will be appended at the end.
+ *
+ * @var array
+ */
+ private $componentsBuildOrder = array('VTIMEZONE', 'DAYLIGHT', 'STANDARD');
+
+ /**
+ * The type of the concrete Component.
+ *
+ * @abstract
+ *
+ * @return string
+ */
+ abstract public function getType();
+
+ /**
+ * Building the PropertyBag.
+ *
+ * @abstract
+ *
+ * @return PropertyBag
+ */
+ abstract public function buildPropertyBag();
+
+ /**
+ * Adds a Component.
+ *
+ * If $key is given, the component at $key will be replaced else the component will be append.
+ *
+ * @param Component $component The Component that will be added
+ * @param null $key The key of the Component
+ */
+ public function addComponent(Component $component, $key = null)
+ {
+ if (null == $key) {
+ $this->components[] = $component;
+ } else {
+ $this->components[$key] = $component;
+ }
+ }
+
+ /**
+ * Renders an array containing the lines of the iCal file.
+ *
+ * @return array
+ */
+ public function build()
+ {
+ $lines = array();
+
+ $lines[] = sprintf('BEGIN:%s', $this->getType());
+
+ /** @var $property Property */
+ foreach ($this->buildPropertyBag() as $property) {
+ foreach ($property->toLines() as $l) {
+ $lines[] = $l;
+ }
+ }
+
+ $this->buildComponents($lines);
+
+ $lines[] = sprintf('END:%s', $this->getType());
+
+ $ret = array();
+
+ foreach ($lines as $line) {
+ foreach (ComponentUtil::fold($line) as $l) {
+ $ret[] = $l;
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Renders the output.
+ *
+ * @return string
+ */
+ public function render()
+ {
+ return implode("\r\n", $this->build());
+ }
+
+ /**
+ * Renders the output when treating the class as a string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->render();
+ }
+
+ /**
+ * @param $lines
+ *
+ * @return array
+ */
+ private function buildComponents(array &$lines)
+ {
+ $componentsByType = array();
+
+ /** @var $component Component */
+ foreach ($this->components as $component) {
+ $type = $component->getType();
+ if (!isset($componentsByType[$type])) {
+ $componentsByType[$type] = array();
+ }
+ $componentsByType[$type][] = $component;
+ }
+
+ // render ordered components
+ foreach ($this->componentsBuildOrder as $type) {
+ if (!isset($componentsByType[$type])) {
+ continue;
+ }
+ foreach ($componentsByType[$type] as $component) {
+ $this->addComponentLines($lines, $component);
+ }
+ unset($componentsByType[$type]);
+ }
+
+ // render all other
+ foreach ($componentsByType as $components) {
+ foreach ($components as $component) {
+ $this->addComponentLines($lines, $component);
+ }
+ }
+ }
+
+ /**
+ * @param array $lines
+ * @param Component $component
+ */
+ private function addComponentLines(array &$lines, Component $component)
+ {
+ foreach ($component->build() as $l) {
+ $lines[] = $l;
+ }
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php
new file mode 100644
index 00000000..9e0f0c1b
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Alarm.php
@@ -0,0 +1,151 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Component;
+
+use Eluceo\iCal\Component;
+use Eluceo\iCal\PropertyBag;
+use Eluceo\iCal\Property;
+
+/**
+ * Implementation of the VALARM component.
+ */
+class Alarm extends Component
+{
+ /**
+ * Alarm ACTION property.
+ *
+ * According to RFC 5545: 3.8.6.1. Action
+ *
+ * @link http://tools.ietf.org/html/rfc5545#section-3.8.6.1
+ */
+ const ACTION_AUDIO = 'AUDIO';
+ const ACTION_DISPLAY = 'DISPLAY';
+ const ACTION_EMAIL = 'EMAIL';
+
+ protected $action;
+ protected $repeat;
+ protected $duration;
+ protected $description;
+ protected $attendee;
+ protected $trigger;
+
+ public function getType()
+ {
+ return 'VALARM';
+ }
+
+ public function getAction()
+ {
+ return $this->action;
+ }
+
+ public function getRepeat()
+ {
+ return $this->repeat;
+ }
+
+ public function getDuration()
+ {
+ return $this->duration;
+ }
+
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ public function getAttendee()
+ {
+ return $this->attendee;
+ }
+
+ public function getTrigger()
+ {
+ return $this->trigger;
+ }
+
+ public function setAction($action)
+ {
+ $this->action = $action;
+
+ return $this;
+ }
+
+ public function setRepeat($repeat)
+ {
+ $this->repeat = $repeat;
+
+ return $this;
+ }
+
+ public function setDuration($duration)
+ {
+ $this->duration = $duration;
+
+ return $this;
+ }
+
+ public function setDescription($description)
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ public function setAttendee($attendee)
+ {
+ $this->attendee = $attendee;
+
+ return $this;
+ }
+
+ public function setTrigger($trigger)
+ {
+ $this->trigger = $trigger;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildPropertyBag()
+ {
+ $propertyBag = new PropertyBag();
+
+ if (null != $this->trigger) {
+ $propertyBag->set('TRIGGER', $this->trigger);
+ }
+
+ if (null != $this->action) {
+ $propertyBag->set('ACTION', $this->action);
+ }
+
+ if (null != $this->repeat) {
+ $propertyBag->set('REPEAT', $this->repeat);
+ }
+
+ if (null != $this->duration) {
+ $propertyBag->set('DURATION', $this->duration);
+ }
+
+ if (null != $this->description) {
+ $propertyBag->set('DESCRIPTION', $this->description);
+ }
+
+ if (null != $this->attendee) {
+ $propertyBag->set('ATTENDEE', $this->attendee);
+ }
+
+ return $propertyBag;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php
new file mode 100644
index 00000000..db3dd98d
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Calendar.php
@@ -0,0 +1,323 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Component;
+
+use Eluceo\iCal\Component;
+use Eluceo\iCal\PropertyBag;
+
+class Calendar extends Component
+{
+ /**
+ * Methods for calendar components.
+ *
+ * According to RFP 5545: 3.7.2. Method
+ *
+ * @link http://tools.ietf.org/html/rfc5545#section-3.7.2
+ *
+ * And then according to RFC 2446: 3 APPLICATION PROTOCOL ELEMENTS
+ * @link https://www.ietf.org/rfc/rfc2446.txt
+ */
+ const METHOD_PUBLISH = 'PUBLISH';
+ const METHOD_REQUEST = 'REQUEST';
+ const METHOD_REPLY = 'REPLY';
+ const METHOD_ADD = 'ADD';
+ const METHOD_CANCEL = 'CANCEL';
+ const METHOD_REFRESH = 'REFRESH';
+ const METHOD_COUNTER = 'COUNTER';
+ const METHOD_DECLINECOUNTER = 'DECLINECOUNTER';
+
+ /**
+ * This property defines the calendar scale used for the calendar information specified in the iCalendar object.
+ *
+ * According to RFC 5545: 3.7.1. Calendar Scale
+ *
+ * @link http://tools.ietf.org/html/rfc5545#section-3.7
+ */
+ const CALSCALE_GREGORIAN = 'GREGORIAN';
+
+ /**
+ * The Product Identifier.
+ *
+ * According to RFC 2445: 4.7.3 Product Identifier
+ *
+ * This property specifies the identifier for the product that created the Calendar object.
+ *
+ * @link http://www.ietf.org/rfc/rfc2445.txt
+ *
+ * @var string
+ */
+ protected $prodId = null;
+ protected $method = null;
+ protected $name = null;
+ protected $description = null;
+ protected $timezone = null;
+
+ /**
+ * This property defines the calendar scale used for the
+ * calendar information specified in the iCalendar object.
+ *
+ * Also identifies the calendar type of a non-Gregorian recurring appointment.
+ *
+ * @var string
+ *
+ * @see http://tools.ietf.org/html/rfc5545#section-3.7
+ * @see http://msdn.microsoft.com/en-us/library/ee237520(v=exchg.80).aspx
+ */
+ protected $calendarScale = null;
+
+ /**
+ * Specifies whether or not the iCalendar file only contains one appointment.
+ *
+ * @var bool
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ee203486(v=exchg.80).aspx
+ */
+ protected $forceInspectOrOpen = false;
+
+ /**
+ * Specifies a globally unique identifier for the calendar.
+ *
+ * @var string
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ee179588(v=exchg.80).aspx
+ */
+ protected $calId = null;
+
+ /**
+ * Specifies a suggested iCalendar file download frequency for clients and
+ * servers with sync capabilities.
+ *
+ * @var string
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ee178699(v=exchg.80).aspx
+ */
+ protected $publishedTTL = 'P1W';
+
+ /**
+ * Specifies a color for the calendar in calendar for Apple/Outlook.
+ *
+ * @var string
+ *
+ * @see http://msdn.microsoft.com/en-us/library/ee179588(v=exchg.80).aspx
+ */
+ protected $calendarColor = null;
+
+ public function __construct($prodId)
+ {
+ if (empty($prodId)) {
+ throw new \UnexpectedValueException('PRODID cannot be empty');
+ }
+
+ $this->prodId = $prodId;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getType()
+ {
+ return 'VCALENDAR';
+ }
+
+ /**
+ * @param $method
+ *
+ * @return $this
+ */
+ public function setMethod($method)
+ {
+ $this->method = $method;
+
+ return $this;
+ }
+
+ /**
+ * @param $name
+ *
+ * @return $this
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * @param $description
+ *
+ * @return $this
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ /**
+ * @param $timezone
+ *
+ * @return $this
+ */
+ public function setTimezone($timezone)
+ {
+ $this->timezone = $timezone;
+
+ return $this;
+ }
+
+ /**
+ * @param $calendarColor
+ *
+ * @return $this
+ */
+ public function setCalendarColor($calendarColor)
+ {
+ $this->calendarColor = $calendarColor;
+
+ return $this;
+ }
+
+ /**
+ * @param $calendarScale
+ *
+ * @return $this
+ */
+ public function setCalendarScale($calendarScale)
+ {
+ $this->calendarScale = $calendarScale;
+
+ return $this;
+ }
+
+ /**
+ * @param bool $forceInspectOrOpen
+ *
+ * @return $this
+ */
+ public function setForceInspectOrOpen($forceInspectOrOpen)
+ {
+ $this->forceInspectOrOpen = $forceInspectOrOpen;
+
+ return $this;
+ }
+
+ /**
+ * @param string $calId
+ *
+ * @return $this
+ */
+ public function setCalId($calId)
+ {
+ $this->calId = $calId;
+
+ return $this;
+ }
+
+ /**
+ * @param string $ttl
+ *
+ * @return $this
+ */
+ public function setPublishedTTL($ttl)
+ {
+ $this->publishedTTL = $ttl;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildPropertyBag()
+ {
+ $propertyBag = new PropertyBag();
+ $propertyBag->set('VERSION', '2.0');
+ $propertyBag->set('PRODID', $this->prodId);
+
+ if ($this->method) {
+ $propertyBag->set('METHOD', $this->method);
+ }
+
+ if ($this->calendarColor) {
+ $propertyBag->set('X-APPLE-CALENDAR-COLOR', $this->calendarColor);
+ $propertyBag->set('X-OUTLOOK-COLOR', $this->calendarColor);
+ $propertyBag->set('X-FUNAMBOL-COLOR', $this->calendarColor);
+ }
+
+ if ($this->calendarScale) {
+ $propertyBag->set('CALSCALE', $this->calendarScale);
+ $propertyBag->set('X-MICROSOFT-CALSCALE', $this->calendarScale);
+ }
+
+ if ($this->name) {
+ $propertyBag->set('X-WR-CALNAME', $this->name);
+ }
+
+ if ($this->description) {
+ $propertyBag->set('X-WR-CALDESC', $this->description);
+ }
+
+ if ($this->timezone) {
+ if ($this->timezone instanceof Timezone) {
+ $propertyBag->set('X-WR-TIMEZONE', $this->timezone->getZoneIdentifier());
+ $this->addComponent($this->timezone);
+ } else {
+ $propertyBag->set('X-WR-TIMEZONE', $this->timezone);
+ $this->addComponent(new Timezone($this->timezone));
+ }
+ }
+
+ if ($this->forceInspectOrOpen) {
+ $propertyBag->set('X-MS-OLK-FORCEINSPECTOROPEN', $this->forceInspectOrOpen);
+ }
+
+ if ($this->calId) {
+ $propertyBag->set('X-WR-RELCALID', $this->calId);
+ }
+
+ if ($this->publishedTTL) {
+ $propertyBag->set('X-PUBLISHED-TTL', $this->publishedTTL);
+ }
+
+ return $propertyBag;
+ }
+
+ /**
+ * Adds an Event to the Calendar.
+ *
+ * Wrapper for addComponent()
+ *
+ * @see Eluceo\iCal::addComponent
+ * @deprecated Please, use public method addComponent() from abstract Component class
+ *
+ * @param Event $event
+ */
+ public function addEvent(Event $event)
+ {
+ $this->addComponent($event);
+ }
+
+ /**
+ * @return null|string
+ */
+ public function getProdId()
+ {
+ return $this->prodId;
+ }
+
+ public function getMethod()
+ {
+ return $this->method;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component/Event.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Event.php
new file mode 100644
index 00000000..e93d506c
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Event.php
@@ -0,0 +1,783 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Component;
+
+use Eluceo\iCal\Component;
+use Eluceo\iCal\Property;
+use Eluceo\iCal\Property\DateTimeProperty;
+use Eluceo\iCal\Property\Event\Attendees;
+use Eluceo\iCal\Property\Event\Organizer;
+use Eluceo\iCal\Property\Event\RecurrenceRule;
+use Eluceo\iCal\Property\Event\Description;
+use Eluceo\iCal\PropertyBag;
+use Eluceo\iCal\Property\Event\RecurrenceId;
+use Eluceo\iCal\Property\DateTimesProperty;
+
+/**
+ * Implementation of the EVENT component.
+ */
+class Event extends Component
+{
+ const TIME_TRANSPARENCY_OPAQUE = 'OPAQUE';
+ const TIME_TRANSPARENCY_TRANSPARENT = 'TRANSPARENT';
+
+ const STATUS_TENTATIVE = 'TENTATIVE';
+ const STATUS_CONFIRMED = 'CONFIRMED';
+ const STATUS_CANCELLED = 'CANCELLED';
+
+ /**
+ * @var string
+ */
+ protected $uniqueId;
+
+ /**
+ * The property indicates the date/time that the instance of
+ * the iCalendar object was created.
+ *
+ * The value MUST be specified in the UTC time format.
+ *
+ * @var \DateTime
+ */
+ protected $dtStamp;
+
+ /**
+ * @var \DateTime
+ */
+ protected $dtStart;
+
+ /**
+ * Preferentially chosen over the duration if both are set.
+ *
+ * @var \DateTime
+ */
+ protected $dtEnd;
+
+ /**
+ * @var \DateInterval
+ */
+ protected $duration;
+
+ /**
+ * @var bool
+ */
+ protected $noTime = false;
+
+ /**
+ * @var string
+ */
+ protected $url;
+
+ /**
+ * @var string
+ */
+ protected $location;
+
+ /**
+ * @var string
+ */
+ protected $locationTitle;
+
+ /**
+ * @var string
+ */
+ protected $locationGeo;
+
+ /**
+ * @var string
+ */
+ protected $summary;
+
+ /**
+ * @var Organizer
+ */
+ protected $organizer;
+
+ /**
+ * @see http://www.ietf.org/rfc/rfc2445.txt 4.8.2.7 Time Transparency
+ *
+ * @var string
+ */
+ protected $transparency = self::TIME_TRANSPARENCY_OPAQUE;
+
+ /**
+ * If set to true the timezone will be added to the event.
+ *
+ * @var bool
+ */
+ protected $useTimezone = false;
+
+ /**
+ * @var int
+ */
+ protected $sequence = 0;
+
+ /**
+ * @var Attendees
+ */
+ protected $attendees;
+
+ /**
+ * @var string
+ */
+ protected $description;
+
+ /**
+ * @var string
+ */
+ protected $descriptionHTML;
+
+ /**
+ * @var string
+ */
+ protected $status;
+
+ /**
+ * @var RecurrenceRule
+ */
+ protected $recurrenceRule;
+
+ /**
+ * This property specifies the date and time that the calendar
+ * information was created.
+ *
+ * The value MUST be specified in the UTC time format.
+ *
+ * @var \DateTime
+ */
+ protected $created;
+
+ /**
+ * The property specifies the date and time that the information
+ * associated with the calendar component was last revised.
+ *
+ * The value MUST be specified in the UTC time format.
+ *
+ * @var \DateTime
+ */
+ protected $modified;
+
+ /**
+ * Indicates if the UTC time should be used or not.
+ *
+ * @var bool
+ */
+ protected $useUtc = true;
+
+ /**
+ * @var bool
+ */
+ protected $cancelled;
+
+ /**
+ * This property is used to specify categories or subtypes
+ * of the calendar component. The categories are useful in searching
+ * for a calendar component of a particular type and category.
+ *
+ * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.2
+ *
+ * @var array
+ */
+ protected $categories;
+
+ /**
+ * https://tools.ietf.org/html/rfc5545#section-3.8.1.3.
+ *
+ * @var bool
+ */
+ protected $isPrivate = false;
+
+ /**
+ * Dates to be excluded from a series of events.
+ *
+ * @var \DateTime[]
+ */
+ protected $exDates = array();
+
+ /**
+ * @var RecurrenceId
+ */
+ protected $recurrenceId;
+
+ public function __construct($uniqueId = null)
+ {
+ if (null == $uniqueId) {
+ $uniqueId = uniqid();
+ }
+
+ $this->uniqueId = $uniqueId;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getType()
+ {
+ return 'VEVENT';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildPropertyBag()
+ {
+ $propertyBag = new PropertyBag();
+
+ // mandatory information
+ $propertyBag->set('UID', $this->uniqueId);
+
+ $propertyBag->add(new DateTimeProperty('DTSTART', $this->dtStart, $this->noTime, $this->useTimezone, $this->useUtc));
+ $propertyBag->set('SEQUENCE', $this->sequence);
+ $propertyBag->set('TRANSP', $this->transparency);
+
+ if ($this->status) {
+ $propertyBag->set('STATUS', $this->status);
+ }
+
+ // An event can have a 'dtend' or 'duration', but not both.
+ if (null != $this->dtEnd) {
+ $propertyBag->add(new DateTimeProperty('DTEND', $this->dtEnd, $this->noTime, $this->useTimezone, $this->useUtc));
+ } elseif (null != $this->duration) {
+ $propertyBag->set('DURATION', $this->duration->format('P%dDT%hH%iM%sS'));
+ }
+
+ // optional information
+ if (null != $this->url) {
+ $propertyBag->set('URL', $this->url);
+ }
+
+ if (null != $this->location) {
+ $propertyBag->set('LOCATION', $this->location);
+
+ if (null != $this->locationGeo) {
+ $propertyBag->add(
+ new Property(
+ 'X-APPLE-STRUCTURED-LOCATION',
+ 'geo:' . $this->locationGeo,
+ array(
+ 'VALUE' => 'URI',
+ 'X-ADDRESS' => $this->location,
+ 'X-APPLE-RADIUS' => 49,
+ 'X-TITLE' => $this->locationTitle,
+ )
+ )
+ );
+ $propertyBag->set('GEO', str_replace(',', ';', $this->locationGeo));
+ }
+ }
+
+ if (null != $this->summary) {
+ $propertyBag->set('SUMMARY', $this->summary);
+ }
+
+ if (null != $this->attendees) {
+ $propertyBag->add($this->attendees);
+ }
+
+ $propertyBag->set('CLASS', $this->isPrivate ? 'PRIVATE' : 'PUBLIC');
+
+ if (null != $this->description) {
+ $propertyBag->set('DESCRIPTION', new Description($this->description));
+ }
+
+ if (null != $this->descriptionHTML) {
+ $propertyBag->add(
+ new Property(
+ 'X-ALT-DESC',
+ $this->descriptionHTML,
+ array(
+ 'FMTTYPE' => 'text/html',
+ )
+ )
+ );
+ }
+
+ if (null != $this->recurrenceRule) {
+ $propertyBag->set('RRULE', $this->recurrenceRule);
+ }
+
+ if (null != $this->recurrenceId) {
+ $this->recurrenceId->applyTimeSettings($this->noTime, $this->useTimezone, $this->useUtc);
+ $propertyBag->add($this->recurrenceId);
+ }
+
+ if (!empty($this->exDates)) {
+ $propertyBag->add(new DateTimesProperty('EXDATE', $this->exDates, $this->noTime, $this->useTimezone, $this->useUtc));
+ }
+
+ if ($this->cancelled) {
+ $propertyBag->set('STATUS', 'CANCELLED');
+ }
+
+ if (null != $this->organizer) {
+ $propertyBag->add($this->organizer);
+ }
+
+ if ($this->noTime) {
+ $propertyBag->set('X-MICROSOFT-CDO-ALLDAYEVENT', 'TRUE');
+ }
+
+ if (null != $this->categories) {
+ $propertyBag->set('CATEGORIES', $this->categories);
+ }
+
+ $propertyBag->add(
+ new DateTimeProperty('DTSTAMP', $this->dtStamp ?: new \DateTime(), false, false, true)
+ );
+
+ if ($this->created) {
+ $propertyBag->add(new DateTimeProperty('CREATED', $this->created, false, false, true));
+ }
+
+ if ($this->modified) {
+ $propertyBag->add(new DateTimeProperty('LAST-MODIFIED', $this->modified, false, false, true));
+ }
+
+ return $propertyBag;
+ }
+
+ /**
+ * @param $dtEnd
+ *
+ * @return $this
+ */
+ public function setDtEnd($dtEnd)
+ {
+ $this->dtEnd = $dtEnd;
+
+ return $this;
+ }
+
+ public function getDtEnd()
+ {
+ return $this->dtEnd;
+ }
+
+ public function setDtStart($dtStart)
+ {
+ $this->dtStart = $dtStart;
+
+ return $this;
+ }
+
+ /**
+ * @param $dtStamp
+ *
+ * @return $this
+ */
+ public function setDtStamp($dtStamp)
+ {
+ $this->dtStamp = $dtStamp;
+
+ return $this;
+ }
+
+ /**
+ * @param $duration
+ *
+ * @return $this
+ */
+ public function setDuration($duration)
+ {
+ $this->duration = $duration;
+
+ return $this;
+ }
+
+ /**
+ * @param $location
+ * @param string $title
+ * @param null $geo
+ *
+ * @return $this
+ */
+ public function setLocation($location, $title = '', $geo = null)
+ {
+ $this->location = $location;
+ $this->locationTitle = $title;
+ $this->locationGeo = $geo;
+
+ return $this;
+ }
+
+ /**
+ * @param $noTime
+ *
+ * @return $this
+ */
+ public function setNoTime($noTime)
+ {
+ $this->noTime = $noTime;
+
+ return $this;
+ }
+
+ /**
+ * @param int $sequence
+ *
+ * @return $this
+ */
+ public function setSequence($sequence)
+ {
+ $this->sequence = $sequence;
+
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSequence()
+ {
+ return $this->sequence;
+ }
+
+ /**
+ * @param Organizer $organizer
+ *
+ * @return $this
+ */
+ public function setOrganizer(Organizer $organizer)
+ {
+ $this->organizer = $organizer;
+
+ return $this;
+ }
+
+ /**
+ * @param $summary
+ *
+ * @return $this
+ */
+ public function setSummary($summary)
+ {
+ $this->summary = $summary;
+
+ return $this;
+ }
+
+ /**
+ * @param $uniqueId
+ *
+ * @return $this
+ */
+ public function setUniqueId($uniqueId)
+ {
+ $this->uniqueId = $uniqueId;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUniqueId()
+ {
+ return $this->uniqueId;
+ }
+
+ /**
+ * @param $url
+ *
+ * @return $this
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+
+ return $this;
+ }
+
+ /**
+ * @param $useTimezone
+ *
+ * @return $this
+ */
+ public function setUseTimezone($useTimezone)
+ {
+ $this->useTimezone = $useTimezone;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getUseTimezone()
+ {
+ return $this->useTimezone;
+ }
+
+ /**
+ * @param Attendees $attendees
+ *
+ * @return $this
+ */
+ public function setAttendees(Attendees $attendees)
+ {
+ $this->attendees = $attendees;
+
+ return $this;
+ }
+
+ /**
+ * @param string $attendee
+ * @param array $params
+ *
+ * @return $this
+ */
+ public function addAttendee($attendee, $params = array())
+ {
+ if (!isset($this->attendees)) {
+ $this->attendees = new Attendees();
+ }
+ $this->attendees->add($attendee, $params);
+
+ return $this;
+ }
+
+ /**
+ * @return Attendees
+ */
+ public function getAttendees()
+ {
+ return $this->attendees;
+ }
+
+ /**
+ * @param $description
+ *
+ * @return $this
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ /**
+ * @param $descriptionHTML
+ *
+ * @return $this
+ */
+ public function setDescriptionHTML($descriptionHTML)
+ {
+ $this->descriptionHTML = $descriptionHTML;
+
+ return $this;
+ }
+
+ /**
+ * @param bool $useUtc
+ *
+ * @return $this
+ */
+ public function setUseUtc($useUtc = true)
+ {
+ $this->useUtc = $useUtc;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDescriptionHTML()
+ {
+ return $this->descriptionHTML;
+ }
+
+ /**
+ * @param $status
+ *
+ * @return $this
+ */
+ public function setCancelled($status)
+ {
+ $this->cancelled = (bool) $status;
+
+ return $this;
+ }
+
+ /**
+ * @param $transparency
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setTimeTransparency($transparency)
+ {
+ $transparency = strtoupper($transparency);
+ if ($transparency === self::TIME_TRANSPARENCY_OPAQUE
+ || $transparency === self::TIME_TRANSPARENCY_TRANSPARENT
+ ) {
+ $this->transparency = $transparency;
+ } else {
+ throw new \InvalidArgumentException('Invalid value for transparancy');
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param $status
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setStatus($status)
+ {
+ $status = strtoupper($status);
+ if ($status == self::STATUS_CANCELLED
+ || $status == self::STATUS_CONFIRMED
+ || $status == self::STATUS_TENTATIVE
+ ) {
+ $this->status = $status;
+ } else {
+ throw new \InvalidArgumentException('Invalid value for status');
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param RecurrenceRule $recurrenceRule
+ *
+ * @return $this
+ */
+ public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
+ {
+ $this->recurrenceRule = $recurrenceRule;
+
+ return $this;
+ }
+
+ /**
+ * @return RecurrenceRule
+ */
+ public function getRecurrenceRule()
+ {
+ return $this->recurrenceRule;
+ }
+
+ /**
+ * @param $dtStamp
+ *
+ * @return $this
+ */
+ public function setCreated($dtStamp)
+ {
+ $this->created = $dtStamp;
+
+ return $this;
+ }
+
+ /**
+ * @param $dtStamp
+ *
+ * @return $this
+ */
+ public function setModified($dtStamp)
+ {
+ $this->modified = $dtStamp;
+
+ return $this;
+ }
+
+ /**
+ * @param $categories
+ *
+ * @return $this
+ */
+ public function setCategories($categories)
+ {
+ $this->categories = $categories;
+
+ return $this;
+ }
+
+ /**
+ * Sets the event privacy.
+ *
+ * @param bool $flag
+ *
+ * @return $this
+ */
+ public function setIsPrivate($flag)
+ {
+ $this->isPrivate = (bool) $flag;
+
+ return $this;
+ }
+
+ /**
+ * @param \DateTime $dateTime
+ *
+ * @return \Eluceo\iCal\Component\Event
+ */
+ public function addExDate(\DateTime $dateTime)
+ {
+ $this->exDates[] = $dateTime;
+
+ return $this;
+ }
+
+ /**
+ * @return \DateTime[]
+ */
+ public function getExDates()
+ {
+ return $this->exDates;
+ }
+
+ /**
+ * @param \DateTime[]
+ *
+ * @return \Eluceo\iCal\Component\Event
+ */
+ public function setExDates(array $exDates)
+ {
+ $this->exDates = $exDates;
+
+ return $this;
+ }
+
+ /**
+ * @return \Eluceo\iCal\Property\Event\RecurrenceId
+ */
+ public function getRecurrenceId()
+ {
+ return $this->recurrenceId;
+ }
+
+ /**
+ * @param RecurrenceId $recurrenceId
+ *
+ * @return \Eluceo\iCal\Component\Event
+ */
+ public function setRecurrenceId(RecurrenceId $recurrenceId)
+ {
+ $this->recurrenceId = $recurrenceId;
+
+ return $this;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php
new file mode 100644
index 00000000..c820d75b
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component/Timezone.php
@@ -0,0 +1,57 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Component;
+
+use Eluceo\iCal\Component;
+use Eluceo\iCal\PropertyBag;
+
+/**
+ * Implementation of the TIMEZONE component.
+ */
+class Timezone extends Component
+{
+ /**
+ * @var string
+ */
+ protected $timezone;
+
+ public function __construct($timezone)
+ {
+ $this->timezone = $timezone;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getType()
+ {
+ return 'VTIMEZONE';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildPropertyBag()
+ {
+ $propertyBag = new PropertyBag();
+
+ $propertyBag->set('TZID', $this->timezone);
+ $propertyBag->set('X-LIC-LOCATION', $this->timezone);
+
+ return $propertyBag;
+ }
+
+ public function getZoneIdentifier()
+ {
+ return $this->timezone;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php b/vendor/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php
new file mode 100644
index 00000000..97da4911
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Component/TimezoneRule.php
@@ -0,0 +1,215 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Component;
+
+use Eluceo\iCal\Component;
+use Eluceo\iCal\PropertyBag;
+use Eluceo\iCal\Property\Event\RecurrenceRule;
+
+/**
+ * Implementation of Standard Time and Daylight Saving Time observances (or rules)
+ * which define the TIMEZONE component.
+ */
+class TimezoneRule extends Component
+{
+ const TYPE_DAYLIGHT = 'DAYLIGHT';
+ const TYPE_STANDARD = 'STANDARD';
+
+ /**
+ * @var string
+ */
+ protected $type;
+
+ /**
+ * @var string
+ */
+ protected $tzOffsetFrom;
+
+ /**
+ * @var string
+ */
+ protected $tzOffsetTo;
+
+ /**
+ * @var string
+ */
+ protected $tzName;
+
+ /**
+ * @var \DateTime
+ */
+ protected $dtStart;
+
+ /**
+ * @var RecurrenceRule
+ */
+ protected $recurrenceRule;
+
+ /**
+ * create new Timezone Rule object by giving a rule type identifier.
+ *
+ * @param string $ruleType one of DAYLIGHT or STANDARD
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($ruleType)
+ {
+ $ruleType = strtoupper($ruleType);
+ if ($ruleType === self::TYPE_DAYLIGHT || $ruleType === self::TYPE_STANDARD) {
+ $this->type = $ruleType;
+ } else {
+ throw new \InvalidArgumentException('Invalid value for timezone rule type');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildPropertyBag()
+ {
+ $propertyBag = new PropertyBag();
+
+ if ($this->getTzName()) {
+ $propertyBag->set('TZNAME', $this->getTzName());
+ }
+
+ if ($this->getTzOffsetFrom()) {
+ $propertyBag->set('TZOFFSETFROM', $this->getTzOffsetFrom());
+ }
+
+ if ($this->getTzOffsetTo()) {
+ $propertyBag->set('TZOFFSETTO', $this->getTzOffsetTo());
+ }
+
+ if ($this->getDtStart()) {
+ $propertyBag->set('DTSTART', $this->getDtStart());
+ }
+
+ if ($this->recurrenceRule) {
+ $propertyBag->set('RRULE', $this->recurrenceRule);
+ }
+
+ return $propertyBag;
+ }
+
+ /**
+ * @param $offset
+ *
+ * @return $this
+ */
+ public function setTzOffsetFrom($offset)
+ {
+ $this->tzOffsetFrom = $offset;
+
+ return $this;
+ }
+
+ /**
+ * @param $offset
+ *
+ * @return $this
+ */
+ public function setTzOffsetTo($offset)
+ {
+ $this->tzOffsetTo = $offset;
+
+ return $this;
+ }
+
+ /**
+ * @param $name
+ *
+ * @return $this
+ */
+ public function setTzName($name)
+ {
+ $this->tzName = $name;
+
+ return $this;
+ }
+
+ /**
+ * @param \DateTime $dtStart
+ *
+ * @return $this
+ */
+ public function setDtStart(\DateTime $dtStart)
+ {
+ $this->dtStart = $dtStart;
+
+ return $this;
+ }
+
+ /**
+ * @param RecurrenceRule $recurrenceRule
+ *
+ * @return $this
+ */
+ public function setRecurrenceRule(RecurrenceRule $recurrenceRule)
+ {
+ $this->recurrenceRule = $recurrenceRule;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTzOffsetFrom()
+ {
+ return $this->tzOffsetFrom;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTzOffsetTo()
+ {
+ return $this->tzOffsetTo;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTzName()
+ {
+ return $this->tzName;
+ }
+
+ /**
+ * @return RecurrenceRule
+ */
+ public function getRecurrenceRule()
+ {
+ return $this->recurrenceRule;
+ }
+
+ /**
+ * @return mixed return string representation of start date or NULL if no date was given
+ */
+ public function getDtStart()
+ {
+ if ($this->dtStart) {
+ return $this->dtStart->format('Ymd\THis');
+ }
+
+ return;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/ParameterBag.php b/vendor/eluceo/ical/src/Eluceo/iCal/ParameterBag.php
new file mode 100644
index 00000000..9b0c24a1
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/ParameterBag.php
@@ -0,0 +1,108 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal;
+
+class ParameterBag
+{
+ /**
+ * The params.
+ *
+ * @var array
+ */
+ protected $params;
+
+ public function __construct($params = array())
+ {
+ $this->params = $params;
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $value
+ */
+ public function setParam($name, $value)
+ {
+ $this->params[$name] = $value;
+ }
+
+ /**
+ * @param $name
+ */
+ public function getParam($name)
+ {
+ if (array_key_exists($name, $this->params)) {
+ return $this->params[$name];
+ }
+ }
+
+ /**
+ * Checks if there are any params.
+ *
+ * @return bool
+ */
+ public function hasParams()
+ {
+ return count($this->params) > 0;
+ }
+
+ /**
+ * @return string
+ */
+ public function toString()
+ {
+ $line = '';
+ foreach ($this->params as $param => $paramValues) {
+ if (!is_array($paramValues)) {
+ $paramValues = array($paramValues);
+ }
+ foreach ($paramValues as $k => $v) {
+ $paramValues[$k] = $this->escapeParamValue($v);
+ }
+
+ if ('' != $line) {
+ $line .= ';';
+ }
+
+ $line .= $param . '=' . implode(',', $paramValues);
+ }
+
+ return $line;
+ }
+
+ /**
+ * Returns an escaped string for a param value.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public function escapeParamValue($value)
+ {
+ $count = 0;
+ $value = str_replace('\\', '\\\\', $value);
+ $value = str_replace('"', '\"', $value, $count);
+ $value = str_replace("\n", '\\n', $value);
+ if (false !== strpos($value, ';') || false !== strpos($value, ',') || false !== strpos($value, ':') || $count) {
+ $value = '"' . $value . '"';
+ }
+
+ return $value;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property.php
new file mode 100644
index 00000000..1bf2c3f0
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property.php
@@ -0,0 +1,148 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal;
+
+use Eluceo\iCal\Property\ArrayValue;
+use Eluceo\iCal\Property\StringValue;
+use Eluceo\iCal\Property\ValueInterface;
+
+/**
+ * The Property Class represents a property as defined in RFC 2445.
+ *
+ * The content of a line (unfolded) will be rendered in this class
+ */
+class Property
+{
+ /**
+ * The value of the Property.
+ *
+ * @var ValueInterface
+ */
+ protected $value;
+
+ /**
+ * The params of the Property.
+ *
+ * @var ParameterBag
+ */
+ protected $parameterBag;
+
+ /**
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * @param $name
+ * @param $value
+ * @param array $params
+ */
+ public function __construct($name, $value, $params = array())
+ {
+ $this->name = $name;
+ $this->setValue($value);
+ $this->parameterBag = new ParameterBag($params);
+ }
+
+ /**
+ * Renders an unfolded line.
+ *
+ * @return string
+ */
+ public function toLine()
+ {
+ // Property-name
+ $line = $this->getName();
+
+ // Adding params
+ //@todo added check for $this->parameterBag because doctrine/orm proxies won't execute constructor - ok?
+ if ($this->parameterBag && $this->parameterBag->hasParams()) {
+ $line .= ';' . $this->parameterBag->toString();
+ }
+
+ // Property value
+ $line .= ':' . $this->value->getEscapedValue();
+
+ return $line;
+ }
+
+ /**
+ * Get all unfolded lines.
+ *
+ * @return array
+ */
+ public function toLines()
+ {
+ return array($this->toLine());
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setParam($name, $value)
+ {
+ $this->parameterBag->setParam($name, $value);
+
+ return $this;
+ }
+
+ /**
+ * @param $name
+ */
+ public function getParam($name)
+ {
+ return $this->parameterBag->getParam($name);
+ }
+
+ /**
+ * @param mixed $value
+ *
+ * @return $this
+ *
+ * @throws \Exception
+ */
+ public function setValue($value)
+ {
+ if (is_scalar($value)) {
+ $this->value = new StringValue($value);
+ } elseif (is_array($value)) {
+ $this->value = new ArrayValue($value);
+ } else {
+ if (!$value instanceof ValueInterface) {
+ throw new \Exception('The value must implement the ValueInterface.');
+ } else {
+ $this->value = $value;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php
new file mode 100644
index 00000000..314787a0
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/ArrayValue.php
@@ -0,0 +1,43 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property;
+
+use Eluceo\iCal\Util\PropertyValueUtil;
+
+class ArrayValue implements ValueInterface
+{
+ /**
+ * The value.
+ *
+ * @var array
+ */
+ protected $values;
+
+ public function __construct(array $values)
+ {
+ $this->values = $values;
+ }
+
+ public function setValues(array $values)
+ {
+ $this->values = $values;
+
+ return $this;
+ }
+
+ public function getEscapedValue()
+ {
+ return implode(',', array_map(function ($value) {
+ return PropertyValueUtil::escapeValue((string) $value);
+ }, $this->values));
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php
new file mode 100644
index 00000000..d0fd495e
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimeProperty.php
@@ -0,0 +1,38 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property;
+
+use Eluceo\iCal\Property;
+use Eluceo\iCal\Util\DateUtil;
+
+class DateTimeProperty extends Property
+{
+ /**
+ * @param string $name
+ * @param \DateTime $dateTime
+ * @param bool $noTime
+ * @param bool $useTimezone
+ * @param bool $useUtc
+ */
+ public function __construct(
+ $name,
+ \DateTime $dateTime = null,
+ $noTime = false,
+ $useTimezone = false,
+ $useUtc = false
+ ) {
+ $dateString = DateUtil::getDateString($dateTime, $noTime, $useTimezone, $useUtc);
+ $params = DateUtil::getDefaultParams($dateTime, $noTime, $useTimezone);
+
+ parent::__construct($name, $dateString, $params);
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php
new file mode 100644
index 00000000..6242f285
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/DateTimesProperty.php
@@ -0,0 +1,41 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property;
+
+use Eluceo\iCal\Property;
+use Eluceo\iCal\Util\DateUtil;
+
+class DateTimesProperty extends Property
+{
+ /**
+ * @param string $name
+ * @param \DateTime[] $dateTimes
+ * @param bool $noTime
+ * @param bool $useTimezone
+ * @param bool $useUtc
+ */
+ public function __construct(
+ $name,
+ $dateTimes = array(),
+ $noTime = false,
+ $useTimezone = false,
+ $useUtc = false
+ ) {
+ $dates = array();
+ foreach ($dateTimes as $dateTime) {
+ $dates[] = DateUtil::getDateString($dateTime, $noTime, $useTimezone, $useUtc);
+ }
+ $params = DateUtil::getDefaultParams($dateTime, $noTime, $useTimezone);
+
+ parent::__construct($name, $dates, $params);
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php
new file mode 100644
index 00000000..dbb36e7d
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Attendees.php
@@ -0,0 +1,102 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+use Eluceo\iCal\Property;
+
+class Attendees extends Property
+{
+ /** @var Property[] */
+ protected $attendees = array();
+
+ const PROPERTY_NAME = 'ATTENDEES';
+
+ public function __construct()
+ {
+ // Overwrites constructor functionality of Property
+ }
+
+ /**
+ * @param $value
+ * @param array $params
+ *
+ * @return $this
+ */
+ public function add($value, $params = array())
+ {
+ $this->attendees[] = new Property('ATTENDEE', $value, $params);
+
+ return $this;
+ }
+
+ /**
+ * @param Property[] $value
+ *
+ * @return $this
+ */
+ public function setValue($value)
+ {
+ $this->attendees = $value;
+
+ return $this;
+ }
+
+ /**
+ * @return Property[]
+ */
+ public function getValue()
+ {
+ return $this->attendees;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toLines()
+ {
+ $lines = array();
+ foreach ($this->attendees as $attendee) {
+ $lines[] = $attendee->toLine();
+ }
+
+ return $lines;
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $value
+ *
+ * @throws \BadMethodCallException
+ */
+ public function setParam($name, $value)
+ {
+ throw new \BadMethodCallException('Cannot call setParam on Attendees Property');
+ }
+
+ /**
+ * @param $name
+ *
+ * @throws \BadMethodCallException
+ */
+ public function getParam($name)
+ {
+ throw new \BadMethodCallException('Cannot call getParam on Attendees Property');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return self::PROPERTY_NAME;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php
new file mode 100644
index 00000000..b0dbb3c1
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Description.php
@@ -0,0 +1,66 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+use Eluceo\iCal\Property\ValueInterface;
+use Eluceo\iCal\Util\PropertyValueUtil;
+
+/**
+ * Class Description
+ * Alows new line charectars to be in the description.
+ */
+class Description implements ValueInterface
+{
+ /**
+ * The value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * Return the value of the Property as an escaped string.
+ *
+ * Escape values as per RFC 2445. See http://www.kanzaki.com/docs/ical/text.html
+ *
+ * @return string
+ */
+ public function getEscapedValue()
+ {
+ return PropertyValueUtil::escapeValue((string) $this->value);
+ }
+
+ /**
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php
new file mode 100644
index 00000000..a91a75d2
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/Organizer.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+use Eluceo\iCal\Property;
+
+/**
+ * Class Organizer.
+ */
+class Organizer extends Property
+{
+ const PROPERTY_NAME = 'ORGANIZER';
+
+ /**
+ * @param string $value
+ * @param array $params
+ */
+ public function __construct($value, $params = array())
+ {
+ parent::__construct(self::PROPERTY_NAME, $value, $params);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return self::PROPERTY_NAME;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php
new file mode 100644
index 00000000..2a684dda
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceId.php
@@ -0,0 +1,130 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+use Eluceo\iCal\ParameterBag;
+use Eluceo\iCal\Property;
+use Eluceo\iCal\Util\DateUtil;
+use Eluceo\iCal\Property\ValueInterface;
+
+/**
+ * Implementation of Recurrence Id.
+ *
+ * @see http://www.ietf.org/rfc/rfc2445.txt 4.8.4.4 Recurrence ID
+ */
+class RecurrenceId extends Property
+{
+ const PROPERTY_NAME = 'RECURRENCE-ID';
+
+ /**
+ * The effective range of recurrence instances from the instance
+ * specified by the recurrence identifier specified by the property.
+ */
+ const RANGE_THISANDPRIOR = 'THISANDPRIOR';
+ const RANGE_THISANDFUTURE = 'THISANDFUTURE';
+
+ /**
+ * The dateTime to identify a particular instance of a recurring event which is getting modified.
+ *
+ * @var \DateTime
+ */
+ protected $dateTime;
+
+ /**
+ * Specify the effective range of recurrence instances from the instance.
+ *
+ * @var string
+ */
+ protected $range;
+
+ public function __construct(\DateTime $dateTime = null)
+ {
+ $this->parameterBag = new ParameterBag();
+ if (isset($dateTime)) {
+ $this->dateTime = $dateTime;
+ }
+ }
+
+ public function applyTimeSettings($noTime = false, $useTimezone = false, $useUtc = false)
+ {
+ $params = DateUtil::getDefaultParams($this->dateTime, $noTime, $useTimezone, $useUtc);
+ foreach ($params as $name => $value) {
+ $this->parameterBag->setParam($name, $value);
+ }
+
+ if ($this->range) {
+ $this->parameterBag->setParam('RANGE', $this->range);
+ }
+
+ $this->setValue(DateUtil::getDateString($this->dateTime, $noTime, $useTimezone, $useUtc));
+ }
+
+ /**
+ * @return DateTime
+ */
+ public function getDatetime()
+ {
+ return $this->dateTime;
+ }
+
+ /**
+ * @param \DateTime $dateTime
+ *
+ * @return \Eluceo\iCal\Property\Event\RecurrenceId
+ */
+ public function setDatetime(\DateTime $dateTime)
+ {
+ $this->dateTime = $dateTime;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRange()
+ {
+ return $this->range;
+ }
+
+ /**
+ * @param string $range
+ *
+ * @return \Eluceo\iCal\Property\Event\RecurrenceId
+ */
+ public function setRange($range)
+ {
+ $this->range = $range;
+ }
+
+ /**
+ * Get all unfolded lines.
+ *
+ * @return array
+ */
+ public function toLines()
+ {
+ if (!$this->value instanceof ValueInterface) {
+ throw new \Exception('The value must implement the ValueInterface. Call RecurrenceId::applyTimeSettings() before adding RecurrenceId.');
+ } else {
+ return parent::toLines();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return self::PROPERTY_NAME;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php
new file mode 100644
index 00000000..32533449
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/Event/RecurrenceRule.php
@@ -0,0 +1,444 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+use Eluceo\iCal\Property\ValueInterface;
+use Eluceo\iCal\ParameterBag;
+use InvalidArgumentException;
+
+/**
+ * Implementation of Recurrence Rule.
+ *
+ * @see http://www.ietf.org/rfc/rfc2445.txt 3.3.10. Recurrence Rule
+ */
+class RecurrenceRule implements ValueInterface
+{
+ const FREQ_YEARLY = 'YEARLY';
+ const FREQ_MONTHLY = 'MONTHLY';
+ const FREQ_WEEKLY = 'WEEKLY';
+ const FREQ_DAILY = 'DAILY';
+
+ const WEEKDAY_SUNDAY = 'SU';
+ const WEEKDAY_MONDAY = 'MO';
+ const WEEKDAY_TUESDAY = 'TU';
+ const WEEKDAY_WEDNESDAY = 'WE';
+ const WEEKDAY_THURSDAY = 'TH';
+ const WEEKDAY_FRIDAY = 'FR';
+ const WEEKDAY_SATURDAY = 'SA';
+
+ /**
+ * The frequency of an Event.
+ *
+ * @var string
+ */
+ protected $freq = self::FREQ_YEARLY;
+
+ /**
+ * @var null|int
+ */
+ protected $interval = 1;
+
+ /**
+ * @var null|int
+ */
+ protected $count = null;
+
+ /**
+ * @var null|\DateTime
+ */
+ protected $until = null;
+
+ /**
+ * @var null|string
+ */
+ protected $wkst;
+
+ /**
+ * @var null|string
+ */
+ protected $byMonth;
+
+ /**
+ * @var null|string
+ */
+ protected $byWeekNo;
+
+ /**
+ * @var null|string
+ */
+ protected $byYearDay;
+
+ /**
+ * @var null|string
+ */
+ protected $byMonthDay;
+
+ /**
+ * @var null|string
+ */
+ protected $byDay;
+
+ /**
+ * @var null|string
+ */
+ protected $byHour;
+
+ /**
+ * @var null|string
+ */
+ protected $byMinute;
+
+ /**
+ * @var null|string
+ */
+ protected $bySecond;
+
+ /**
+ * Return the value of the Property as an escaped string.
+ *
+ * Escape values as per RFC 2445. See http://www.kanzaki.com/docs/ical/text.html
+ *
+ * @return string
+ */
+ public function getEscapedValue()
+ {
+ return $this->buildParameterBag()->toString();
+ }
+
+ /**
+ * @return ParameterBag
+ */
+ protected function buildParameterBag()
+ {
+ $parameterBag = new ParameterBag();
+
+ $parameterBag->setParam('FREQ', $this->freq);
+
+ if (null !== $this->interval) {
+ $parameterBag->setParam('INTERVAL', $this->interval);
+ }
+
+ if (null !== $this->count) {
+ $parameterBag->setParam('COUNT', $this->count);
+ }
+
+ if (null != $this->until) {
+ $parameterBag->setParam('UNTIL', $this->until->format('Ymd\THis\Z'));
+ }
+
+ if (null !== $this->wkst) {
+ $parameterBag->setParam('WKST', $this->wkst);
+ }
+
+ if (null !== $this->byMonth) {
+ $parameterBag->setParam('BYMONTH', $this->byMonth);
+ }
+
+ if (null !== $this->byWeekNo) {
+ $parameterBag->setParam('BYWEEKNO', $this->byWeekNo);
+ }
+
+ if (null !== $this->byYearDay) {
+ $parameterBag->setParam('BYYEARDAY', $this->byYearDay);
+ }
+
+ if (null !== $this->byMonthDay) {
+ $parameterBag->setParam('BYMONTHDAY', $this->byMonthDay);
+ }
+
+ if (null !== $this->byDay) {
+ $parameterBag->setParam('BYDAY', $this->byDay);
+ }
+
+ if (null !== $this->byHour) {
+ $parameterBag->setParam('BYHOUR', $this->byHour);
+ }
+
+ if (null !== $this->byMinute) {
+ $parameterBag->setParam('BYMINUTE', $this->byMinute);
+ }
+
+ if (null !== $this->bySecond) {
+ $parameterBag->setParam('BYSECOND', $this->bySecond);
+ }
+
+ return $parameterBag;
+ }
+
+ /**
+ * @param int|null $count
+ *
+ * @return $this
+ */
+ public function setCount($count)
+ {
+ $this->count = $count;
+
+ return $this;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getCount()
+ {
+ return $this->count;
+ }
+
+ /**
+ * @param \DateTime|null $until
+ *
+ * @return $this
+ */
+ public function setUntil(\DateTime $until = null)
+ {
+ $this->until = $until;
+
+ return $this;
+ }
+
+ /**
+ * @return \DateTime|null
+ */
+ public function getUntil()
+ {
+ return $this->until;
+ }
+
+ /**
+ * The FREQ rule part identifies the type of recurrence rule. This
+ * rule part MUST be specified in the recurrence rule. Valid values
+ * include.
+ *
+ * SECONDLY, to specify repeating events based on an interval of a second or more;
+ * MINUTELY, to specify repeating events based on an interval of a minute or more;
+ * HOURLY, to specify repeating events based on an interval of an hour or more;
+ * DAILY, to specify repeating events based on an interval of a day or more;
+ * WEEKLY, to specify repeating events based on an interval of a week or more;
+ * MONTHLY, to specify repeating events based on an interval of a month or more;
+ * YEARLY, to specify repeating events based on an interval of a year or more.
+ *
+ * @param string $freq
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setFreq($freq)
+ {
+ if (self::FREQ_YEARLY === $freq || self::FREQ_MONTHLY === $freq
+ || self::FREQ_WEEKLY === $freq
+ || self::FREQ_DAILY === $freq
+ ) {
+ $this->freq = $freq;
+ } else {
+ throw new \InvalidArgumentException("The Frequency {$freq} is not supported.");
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFreq()
+ {
+ return $this->freq;
+ }
+
+ /**
+ * The INTERVAL rule part contains a positive integer representing at
+ * which intervals the recurrence rule repeats.
+ *
+ * @param int|null $interval
+ *
+ * @return $this
+ */
+ public function setInterval($interval)
+ {
+ $this->interval = $interval;
+
+ return $this;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getInterval()
+ {
+ return $this->interval;
+ }
+
+ /**
+ * The WKST rule part specifies the day on which the workweek starts.
+ * Valid values are MO, TU, WE, TH, FR, SA, and SU.
+ *
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function setWkst($value)
+ {
+ $this->wkst = $value;
+
+ return $this;
+ }
+
+ /**
+ * The BYMONTH rule part specifies a COMMA-separated list of months of the year.
+ * Valid values are 1 to 12.
+ *
+ * @param int $month
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setByMonth($month)
+ {
+ if (!is_integer($month) || $month < 0 || $month > 12) {
+ throw new InvalidArgumentException('Invalid value for BYMONTH');
+ }
+
+ $this->byMonth = $month;
+
+ return $this;
+ }
+
+ /**
+ * The BYWEEKNO rule part specifies a COMMA-separated list of ordinals specifying weeks of the year.
+ * Valid values are 1 to 53 or -53 to -1.
+ *
+ * @param int $value
+ *
+ * @return $this
+ */
+ public function setByWeekNo($value)
+ {
+ $this->byWeekNo = $value;
+
+ return $this;
+ }
+
+ /**
+ * The BYYEARDAY rule part specifies a COMMA-separated list of days of the year.
+ * Valid values are 1 to 366 or -366 to -1.
+ *
+ * @param int $day
+ *
+ * @return $this
+ */
+ public function setByYearDay($day)
+ {
+ $this->byYearDay = $day;
+
+ return $this;
+ }
+
+ /**
+ * The BYMONTHDAY rule part specifies a COMMA-separated list of days of the month.
+ * Valid values are 1 to 31 or -31 to -1.
+ *
+ * @param int $day
+ *
+ * @return $this
+ */
+ public function setByMonthDay($day)
+ {
+ $this->byMonthDay = $day;
+
+ return $this;
+ }
+
+ /**
+ * The BYDAY rule part specifies a COMMA-separated list of days of the week;.
+ *
+ * SU indicates Sunday; MO indicates Monday; TU indicates Tuesday;
+ * WE indicates Wednesday; TH indicates Thursday; FR indicates Friday; and SA indicates Saturday.
+ *
+ * Each BYDAY value can also be preceded by a positive (+n) or negative (-n) integer.
+ * If present, this indicates the nth occurrence of a specific day within the MONTHLY or YEARLY "RRULE".
+ *
+ * @param string $day
+ *
+ * @return $this
+ */
+ public function setByDay($day)
+ {
+ $this->byDay = $day;
+
+ return $this;
+ }
+
+ /**
+ * The BYHOUR rule part specifies a COMMA-separated list of hours of the day.
+ * Valid values are 0 to 23.
+ *
+ * @param int $value
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setByHour($value)
+ {
+ if (!is_integer($value) || $value < 0 || $value > 23) {
+ throw new \InvalidArgumentException('Invalid value for BYHOUR');
+ }
+
+ $this->byHour = $value;
+
+ return $this;
+ }
+
+ /**
+ * The BYMINUTE rule part specifies a COMMA-separated list of minutes within an hour.
+ * Valid values are 0 to 59.
+ *
+ * @param int $value
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setByMinute($value)
+ {
+ if (!is_integer($value) || $value < 0 || $value > 59) {
+ throw new \InvalidArgumentException('Invalid value for BYMINUTE');
+ }
+
+ $this->byMinute = $value;
+
+ return $this;
+ }
+
+ /**
+ * The BYSECOND rule part specifies a COMMA-separated list of seconds within a minute.
+ * Valid values are 0 to 60.
+ *
+ * @param int $value
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setBySecond($value)
+ {
+ if (!is_integer($value) || $value < 0 || $value > 60) {
+ throw new \InvalidArgumentException('Invalid value for BYSECOND');
+ }
+
+ $this->bySecond = $value;
+
+ return $this;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php
new file mode 100644
index 00000000..4995723b
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/StringValue.php
@@ -0,0 +1,61 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property;
+
+use Eluceo\iCal\Util\PropertyValueUtil;
+
+class StringValue implements ValueInterface
+{
+ /**
+ * The value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * Return the value of the Property as an escaped string.
+ *
+ * Escape values as per RFC 2445. See http://www.kanzaki.com/docs/ical/text.html
+ *
+ * @return string
+ */
+ public function getEscapedValue()
+ {
+ return PropertyValueUtil::escapeValue((string) $this->value);
+ }
+
+ /**
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php b/vendor/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php
new file mode 100644
index 00000000..cc3d885c
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Property/ValueInterface.php
@@ -0,0 +1,24 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Property;
+
+interface ValueInterface
+{
+ /**
+ * Return the value of the Property as an escaped string.
+ *
+ * Escape values as per RFC 2445. See http://www.kanzaki.com/docs/ical/text.html
+ *
+ * @return string
+ */
+ public function getEscapedValue();
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/PropertyBag.php b/vendor/eluceo/ical/src/Eluceo/iCal/PropertyBag.php
new file mode 100644
index 00000000..7032360b
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/PropertyBag.php
@@ -0,0 +1,79 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal;
+
+class PropertyBag implements \IteratorAggregate
+{
+ /**
+ * @var array
+ */
+ protected $elements = array();
+
+ /**
+ * Creates a new Property with $name, $value and $params.
+ *
+ * @param $name
+ * @param $value
+ * @param array $params
+ *
+ * @return $this
+ */
+ public function set($name, $value, $params = array())
+ {
+ $property = new Property($name, $value, $params);
+ $this->elements[] = $property;
+
+ return $this;
+ }
+
+ /**
+ * @param string $name
+ *
+ * @return null|Property
+ */
+ public function get($name)
+ {
+ // Searching Property in elements-array
+ /** @var $property Property */
+ foreach ($this->elements as $property) {
+ if ($property->getName() == $name) {
+ return $property;
+ }
+ }
+ }
+
+ /**
+ * Adds a Property. If Property already exists an Exception will be thrown.
+ *
+ * @param Property $property
+ *
+ * @return $this
+ *
+ * @throws \Exception
+ */
+ public function add(Property $property)
+ {
+ // Property already exists?
+ if (null !== $this->get($property->getName())) {
+ throw new \Exception("Property with name '{$property->getName()}' already exists");
+ }
+
+ $this->elements[] = $property;
+
+ return $this;
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayObject($this->elements);
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php b/vendor/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php
new file mode 100644
index 00000000..ca6a2be0
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Util/ComponentUtil.php
@@ -0,0 +1,48 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Util;
+
+class ComponentUtil
+{
+ /**
+ * Folds a single line.
+ *
+ * According to RFC 2445, all lines longer than 75 characters will be folded
+ *
+ * @link http://www.ietf.org/rfc/rfc2445.txt
+ *
+ * @param $string
+ *
+ * @return array
+ */
+ public static function fold($string)
+ {
+ $lines = array();
+ $array = preg_split('/(? 75) {
+ $line = ' ' . $char;
+ ++$lineNo;
+ } else {
+ $line .= $char;
+ }
+ $lines[$lineNo] = $line;
+ }
+
+ return $lines;
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php b/vendor/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php
new file mode 100644
index 00000000..3bd3367f
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Util/DateUtil.php
@@ -0,0 +1,69 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Util;
+
+class DateUtil
+{
+ public static function getDefaultParams(\DateTime $dateTime = null, $noTime = false, $useTimezone = false)
+ {
+ $params = array();
+
+ if ($useTimezone) {
+ $timeZone = $dateTime->getTimezone()->getName();
+ $params['TZID'] = $timeZone;
+ }
+
+ if ($noTime) {
+ $params['VALUE'] = 'DATE';
+ }
+
+ return $params;
+ }
+
+ /**
+ * Returns a formatted date string.
+ *
+ * @param \DateTime|null $dateTime The DateTime object
+ * @param bool $noTime Indicates if the time will be added
+ * @param bool $useTimezone
+ * @param bool $useUtc
+ *
+ * @return mixed
+ */
+ public static function getDateString(\DateTime $dateTime = null, $noTime = false, $useTimezone = false, $useUtc = false)
+ {
+ if (empty($dateTime)) {
+ $dateTime = new \DateTime();
+ }
+
+ return $dateTime->format(self::getDateFormat($noTime, $useTimezone, $useUtc));
+ }
+
+ /**
+ * Returns the date format that can be passed to DateTime::format().
+ *
+ * @param bool $noTime Indicates if the time will be added
+ * @param bool $useTimezone
+ * @param bool $useUtc
+ *
+ * @return string
+ */
+ public static function getDateFormat($noTime = false, $useTimezone = false, $useUtc = false)
+ {
+ // Do not use UTC time (Z) if timezone support is enabled.
+ if ($useTimezone || !$useUtc) {
+ return $noTime ? 'Ymd' : 'Ymd\THis';
+ }
+
+ return $noTime ? 'Ymd' : 'Ymd\THis\Z';
+ }
+}
diff --git a/vendor/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php b/vendor/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php
new file mode 100644
index 00000000..40538589
--- /dev/null
+++ b/vendor/eluceo/ical/src/Eluceo/iCal/Util/PropertyValueUtil.php
@@ -0,0 +1,40 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Eluceo\iCal\Util;
+
+class PropertyValueUtil
+{
+ public static function escapeValue($value)
+ {
+ $value = self::escapeValueAllowNewLine($value);
+ $value = str_replace("\n", '\\n', $value);
+
+ return $value;
+ }
+
+ public static function escapeValueAllowNewLine($value)
+ {
+ $value = str_replace('\\', '\\\\', $value);
+ $value = str_replace('"', '\\"', $value);
+ $value = str_replace(',', '\\,', $value);
+ $value = str_replace(';', '\\;', $value);
+ $value = str_replace(array(
+ "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
+ "\x08", "\x09", /* \n*/ "\x0B", "\x0C", "\x0D", "\x0E", "\x0F",
+ "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
+ "\x18", "\x19", "\x1A", "\x1B", "\x1C", "\x1D", "\x1E", "\x1F",
+ "\x7F",
+ ), '', $value);
+
+ return $value;
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Component/CalendarIntegrationTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Component/CalendarIntegrationTest.php
new file mode 100644
index 00000000..eb869af8
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Component/CalendarIntegrationTest.php
@@ -0,0 +1,64 @@
+setDtStart(new \DateTime('2012-12-31', $timeZone));
+ $vEvent->setDtEnd(new \DateTime('2012-12-31', $timeZone));
+ $vEvent->setNoTime(true);
+ $vEvent->setIsPrivate(true);
+ $vEvent->setSummary('New Year’s Eve');
+
+ // Set recurrence rule
+ $recurrenceRule = new \Eluceo\iCal\Property\Event\RecurrenceRule();
+ $recurrenceRule->setFreq(\Eluceo\iCal\Property\Event\RecurrenceRule::FREQ_YEARLY);
+ $recurrenceRule->setInterval(1);
+ $vEvent->setRecurrenceRule($recurrenceRule);
+
+ // Adding Timezone (optional)
+ $vEvent->setUseTimezone(true);
+
+ // 3. Add event to calendar
+ $vCalendar->addComponent($vEvent);
+
+ $lines = array(
+ '/BEGIN:VCALENDAR/',
+ '/VERSION:2\.0/',
+ '/PRODID:www\.example\.com/',
+ '/X-PUBLISHED-TTL:P1W/',
+ '/BEGIN:VEVENT/',
+ '/UID:123456/',
+ '/DTSTART;TZID=Europe\/Berlin;VALUE=DATE:20121231/',
+ '/SEQUENCE:0/',
+ '/TRANSP:OPAQUE/',
+ '/DTEND;TZID=Europe\/Berlin;VALUE=DATE:20121231/',
+ '/SUMMARY:New Year’s Eve/',
+ '/CLASS:PRIVATE/',
+ '/RRULE:FREQ=YEARLY;INTERVAL=1/',
+ '/X-MICROSOFT-CDO-ALLDAYEVENT:TRUE/',
+ '/DTSTAMP:20\d{6}T\d{6}Z/',
+ '/END:VEVENT/',
+ '/END:VCALENDAR/',
+ );
+
+ foreach (explode("\n", $vCalendar->render()) as $key => $line)
+ {
+ $this->assertTrue(isset($lines[$key]), 'Too many lines... ' . $line);
+
+ $this->assertRegExp($lines[$key], $line);
+ }
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/ComponentTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/ComponentTest.php
new file mode 100644
index 00000000..5cac7c5d
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/ComponentTest.php
@@ -0,0 +1,45 @@
+setDtStart(new \DateTime('2014-12-24'));
+ $vEvent->setDtEnd(new \DateTime('2014-12-24'));
+ $vEvent->setDescription($input);
+
+ $vAlarm = new \Eluceo\iCal\Component\Alarm;
+ $vAlarm->setAction(\Eluceo\iCal\Component\Alarm::ACTION_DISPLAY);
+ $vAlarm->setDescription($input);
+ $vAlarm->setTrigger('PT0S', true);
+ $vEvent->addComponent($vAlarm);
+
+ $vCalendar->addComponent($vEvent);
+
+ $output = $vCalendar->render();
+ $output = preg_replace('/\r\n /u', '', $output);
+ $this->assertContains($input, $output);
+ }
+
+ public function testDescriptionWithNewLines()
+ {
+ $input = "new string \n new line \n new line \n new string";
+
+ $vCalendar = new \Eluceo\iCal\Component\Calendar('www.example.com');
+ $vEvent = new \Eluceo\iCal\Component\Event();
+ $vEvent->setDtStart(new \DateTime('2014-12-24'));
+ $vEvent->setDtEnd(new \DateTime('2014-12-24'));
+ $vEvent->setDescription($input);
+
+ $vCalendar->addComponent($vEvent);
+
+ $output = $vCalendar->render();
+ $this->assertContains(str_replace("\n", "\\n", $input), $output);
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/ParameterBagTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/ParameterBagTest.php
new file mode 100644
index 00000000..0fb6e84c
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/ParameterBagTest.php
@@ -0,0 +1,35 @@
+assertEquals(
+ 'test string',
+ $propertyObject->escapeParamValue('test string'),
+ 'No escaping necessary'
+ );
+
+ $this->assertEquals(
+ '"Containing \\"double-quotes\\""',
+ $propertyObject->escapeParamValue('Containing "double-quotes"'),
+ 'Text contains double quotes'
+ );
+
+ $this->assertEquals(
+ '"Containing forbidden chars like a ;"',
+ $propertyObject->escapeParamValue('Containing forbidden chars like a ;'),
+ 'Text with semicolon'
+ );
+
+ $this->assertEquals(
+ '"Containing forbidden chars like a :"',
+ $propertyObject->escapeParamValue('Containing forbidden chars like a :'),
+ 'Text with colon'
+ );
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Property/ArrayValueTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/ArrayValueTest.php
new file mode 100644
index 00000000..1d1b3331
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/ArrayValueTest.php
@@ -0,0 +1,26 @@
+assertEquals($expectedOutput, $arrayValue->getEscapedValue());
+ }
+
+ public function arrayValuesProvider()
+ {
+ return array(
+ array(array(), ''),
+ array(array('Lorem'), 'Lorem'),
+ array(array('Lorem', 'Ipsum'), 'Lorem,Ipsum'),
+ array(array('Lorem', '"doublequotes"'), 'Lorem,\"doublequotes\"'),
+ );
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/DescriptionTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/DescriptionTest.php
new file mode 100644
index 00000000..0ad16bcc
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/DescriptionTest.php
@@ -0,0 +1,17 @@
+assertEquals(
+ str_replace("\n", "\\n", $testString),
+ $description->getEscapedValue()
+ );
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/OrganizerTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/OrganizerTest.php
new file mode 100644
index 00000000..71acdce9
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/OrganizerTest.php
@@ -0,0 +1,63 @@
+
+ */
+
+namespace Eluceo\iCal\Property\Event;
+
+/**
+ * OrganizerTest
+ */
+class OrganizerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testOrganizerValueOnly()
+ {
+ $value = "MAILTO:name.lastname@example.com";
+ $expected = "ORGANIZER:$value";
+
+ $vCalendar = $this->createCalendarWithOrganizer(
+ new \Eluceo\iCal\Property\Event\Organizer($value)
+ );
+
+ foreach (explode("\n", $vCalendar->render()) as $line)
+ {
+ if (preg_match('/^ORGANIZER[:;](.*)$/', $line)) {
+ $this->assertEquals($expected, trim($line));
+ }
+ }
+ }
+
+ public function testOrganizerValueAndParameter()
+ {
+ $value = "MAILTO:name.lastname@example.com";
+ $param = "Name LastName";
+ $expected = "ORGANIZER;CN=$param:$value";
+
+ $vCalendar = $this->createCalendarWithOrganizer(
+ new \Eluceo\iCal\Property\Event\Organizer($value, array('CN' => $param))
+ );
+
+ foreach (explode("\n", $vCalendar->render()) as $line)
+ {
+ if (preg_match('/^ORGANIZER[:;](.*)$/', $line)) {
+ $this->assertEquals($expected, trim($line));
+ }
+ }
+
+ }
+
+ /**
+ * @param Organizer $vOrganizer
+ * @return \Eluceo\iCal\Component\Calendar
+ */
+ private function createCalendarWithOrganizer(\Eluceo\iCal\Property\Event\Organizer $vOrganizer)
+ {
+ $vCalendar = new \Eluceo\iCal\Component\Calendar('www.example.com');
+ $vEvent = new \Eluceo\iCal\Component\Event('123456');
+ $vEvent->setOrganizer($vOrganizer);
+ $vCalendar->addComponent($vEvent);
+ return $vCalendar;
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/RecurrenceRuleTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/RecurrenceRuleTest.php
new file mode 100644
index 00000000..a44b2580
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/Event/RecurrenceRuleTest.php
@@ -0,0 +1,21 @@
+setFreq(RecurrenceRule::FREQ_DAILY);
+ $rule->setInterval(null);
+ $rule->setUntil(new \DateTime('1997-12-24'));
+ $this->assertEquals(
+ 'FREQ=DAILY;UNTIL=19971224T000000Z',
+ $rule->getEscapedValue()
+ );
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/Property/StringValueTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/StringValueTest.php
new file mode 100644
index 00000000..afa70df1
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/Property/StringValueTest.php
@@ -0,0 +1,63 @@
+assertEquals(
+ 'LOREM',
+ $stringValue->getEscapedValue(),
+ 'No escaping necessary'
+ );
+ }
+
+ public function testValueContainsBackslash()
+ {
+ $stringValue = new StringValue('text contains backslash: \\');
+
+ $this->assertEquals(
+ 'text contains backslash: \\\\',
+ $stringValue->getEscapedValue(),
+ 'Text contains backslash'
+ );
+ }
+
+ public function testEscapingDoubleQuotes()
+ {
+ $stringValue = new StringValue('text with "doublequotes" will be escaped');
+
+ $this->assertEquals(
+ 'text with \\"doublequotes\\" will be escaped',
+ $stringValue->getEscapedValue(),
+ 'Escaping double quotes'
+ );
+ }
+
+ public function testEscapingSemicolonAndComma()
+ {
+ $stringValue = new StringValue('text with , and ; will also be escaped');
+
+ $this->assertEquals(
+ 'text with \\, and \\; will also be escaped',
+ $stringValue->getEscapedValue(),
+ 'Escaping ; and ,'
+ );
+ }
+
+ public function testNewLineEscaping()
+ {
+ $stringValue = new StringValue("Text with new\n line");
+
+ $this->assertEquals(
+ 'Text with new\\n line',
+ $stringValue->getEscapedValue(),
+ 'Escape new line to text'
+ );
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyBagTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyBagTest.php
new file mode 100644
index 00000000..a7f8d8ce
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyBagTest.php
@@ -0,0 +1,18 @@
+setExpectedException('\\Exception', "Property with name 'propName' already exists");
+
+ $propertyBag = new PropertyBag();
+ $propertyBag->add(new Property('propName', ''));
+ $propertyBag->add(new Property('propName', ''));
+ }
+}
diff --git a/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyTest.php b/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyTest.php
new file mode 100644
index 00000000..b30f5a3a
--- /dev/null
+++ b/vendor/eluceo/ical/tests/Eluceo/iCal/PropertyTest.php
@@ -0,0 +1,42 @@
+assertEquals(
+ 'DTSTAMP:20131020T153112',
+ $property->toLine()
+ );
+ }
+
+ public function testPropertyWithValueAndParams()
+ {
+ $property = new Property('DTSTAMP', '20131020T153112', array('TZID' => 'Europe/Berlin'));
+ $this->assertEquals(
+ 'DTSTAMP;TZID=Europe/Berlin:20131020T153112',
+ $property->toLine()
+ );
+ }
+
+ public function testPropertyWithEscapedSingleValue()
+ {
+ $property = new Property('SOMEPROP', 'Escape me!"');
+ $this->assertEquals(
+ 'SOMEPROP:Escape me!\\"',
+ $property->toLine()
+ );
+ }
+
+ public function testPropertyWithEscapedValues()
+ {
+ $property = new Property('SOMEPROP', 'Escape me!"', array('TEST' => 'Lorem "test" ipsum'));
+ $this->assertEquals(
+ 'SOMEPROP;TEST="Lorem \\"test\\" ipsum":Escape me!\\"',
+ $property->toLine()
+ );
+ }
+}
diff --git a/vendor/erusev/parsedown/.travis.yml b/vendor/erusev/parsedown/.travis.yml
new file mode 100644
index 00000000..5df49dcb
--- /dev/null
+++ b/vendor/erusev/parsedown/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+php:
+ - 7.0
+ - 5.6
+ - 5.5
+ - 5.4
+ - 5.3
+ - hhvm
+ - hhvm-nightly
+
+matrix:
+ fast_finish: true
+ allow_failures:
+ - php: 7.0
+ - php: hhvm-nightly
diff --git a/vendor/erusev/parsedown/LICENSE.txt b/vendor/erusev/parsedown/LICENSE.txt
new file mode 100644
index 00000000..baca86f5
--- /dev/null
+++ b/vendor/erusev/parsedown/LICENSE.txt
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Emanuil Rusev, erusev.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/Parsedown.php b/vendor/erusev/parsedown/Parsedown.php
new file mode 100755
index 00000000..c8c92a39
--- /dev/null
+++ b/vendor/erusev/parsedown/Parsedown.php
@@ -0,0 +1,1528 @@
+DefinitionData = array();
+
+ # standardize line breaks
+ $text = str_replace(array("\r\n", "\r"), "\n", $text);
+
+ # remove surrounding line breaks
+ $text = trim($text, "\n");
+
+ # split text into lines
+ $lines = explode("\n", $text);
+
+ # iterate through lines to identify blocks
+ $markup = $this->lines($lines);
+
+ # trim line breaks
+ $markup = trim($markup, "\n");
+
+ return $markup;
+ }
+
+ #
+ # Setters
+ #
+
+ function setBreaksEnabled($breaksEnabled)
+ {
+ $this->breaksEnabled = $breaksEnabled;
+
+ return $this;
+ }
+
+ protected $breaksEnabled;
+
+ function setMarkupEscaped($markupEscaped)
+ {
+ $this->markupEscaped = $markupEscaped;
+
+ return $this;
+ }
+
+ protected $markupEscaped;
+
+ function setUrlsLinked($urlsLinked)
+ {
+ $this->urlsLinked = $urlsLinked;
+
+ return $this;
+ }
+
+ protected $urlsLinked = true;
+
+ #
+ # Lines
+ #
+
+ protected $BlockTypes = array(
+ '#' => array('Header'),
+ '*' => array('Rule', 'List'),
+ '+' => array('List'),
+ '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
+ '0' => array('List'),
+ '1' => array('List'),
+ '2' => array('List'),
+ '3' => array('List'),
+ '4' => array('List'),
+ '5' => array('List'),
+ '6' => array('List'),
+ '7' => array('List'),
+ '8' => array('List'),
+ '9' => array('List'),
+ ':' => array('Table'),
+ '<' => array('Comment', 'Markup'),
+ '=' => array('SetextHeader'),
+ '>' => array('Quote'),
+ '[' => array('Reference'),
+ '_' => array('Rule'),
+ '`' => array('FencedCode'),
+ '|' => array('Table'),
+ '~' => array('FencedCode'),
+ );
+
+ # ~
+
+ protected $unmarkedBlockTypes = array(
+ 'Code',
+ );
+
+ #
+ # Blocks
+ #
+
+ private function lines(array $lines)
+ {
+ $CurrentBlock = null;
+
+ foreach ($lines as $line)
+ {
+ if (chop($line) === '')
+ {
+ if (isset($CurrentBlock))
+ {
+ $CurrentBlock['interrupted'] = true;
+ }
+
+ continue;
+ }
+
+ if (strpos($line, "\t") !== false)
+ {
+ $parts = explode("\t", $line);
+
+ $line = $parts[0];
+
+ unset($parts[0]);
+
+ foreach ($parts as $part)
+ {
+ $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
+
+ $line .= str_repeat(' ', $shortage);
+ $line .= $part;
+ }
+ }
+
+ $indent = 0;
+
+ while (isset($line[$indent]) and $line[$indent] === ' ')
+ {
+ $indent ++;
+ }
+
+ $text = $indent > 0 ? substr($line, $indent) : $line;
+
+ # ~
+
+ $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
+
+ # ~
+
+ if (isset($CurrentBlock['continuable']))
+ {
+ $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
+
+ if (isset($Block))
+ {
+ $CurrentBlock = $Block;
+
+ continue;
+ }
+ else
+ {
+ if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
+ {
+ $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
+ }
+ }
+ }
+
+ # ~
+
+ $marker = $text[0];
+
+ # ~
+
+ $blockTypes = $this->unmarkedBlockTypes;
+
+ if (isset($this->BlockTypes[$marker]))
+ {
+ foreach ($this->BlockTypes[$marker] as $blockType)
+ {
+ $blockTypes []= $blockType;
+ }
+ }
+
+ #
+ # ~
+
+ foreach ($blockTypes as $blockType)
+ {
+ $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
+
+ if (isset($Block))
+ {
+ $Block['type'] = $blockType;
+
+ if ( ! isset($Block['identified']))
+ {
+ $Blocks []= $CurrentBlock;
+
+ $Block['identified'] = true;
+ }
+
+ if (method_exists($this, 'block'.$blockType.'Continue'))
+ {
+ $Block['continuable'] = true;
+ }
+
+ $CurrentBlock = $Block;
+
+ continue 2;
+ }
+ }
+
+ # ~
+
+ if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
+ {
+ $CurrentBlock['element']['text'] .= "\n".$text;
+ }
+ else
+ {
+ $Blocks []= $CurrentBlock;
+
+ $CurrentBlock = $this->paragraph($Line);
+
+ $CurrentBlock['identified'] = true;
+ }
+ }
+
+ # ~
+
+ if (isset($CurrentBlock['continuable']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
+ {
+ $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
+ }
+
+ # ~
+
+ $Blocks []= $CurrentBlock;
+
+ unset($Blocks[0]);
+
+ # ~
+
+ $markup = '';
+
+ foreach ($Blocks as $Block)
+ {
+ if (isset($Block['hidden']))
+ {
+ continue;
+ }
+
+ $markup .= "\n";
+ $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
+ }
+
+ $markup .= "\n";
+
+ # ~
+
+ return $markup;
+ }
+
+ #
+ # Code
+
+ protected function blockCode($Line, $Block = null)
+ {
+ if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if ($Line['indent'] >= 4)
+ {
+ $text = substr($Line['body'], 4);
+
+ $Block = array(
+ 'element' => array(
+ 'name' => 'pre',
+ 'handler' => 'element',
+ 'text' => array(
+ 'name' => 'code',
+ 'text' => $text,
+ ),
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockCodeContinue($Line, $Block)
+ {
+ if ($Line['indent'] >= 4)
+ {
+ if (isset($Block['interrupted']))
+ {
+ $Block['element']['text']['text'] .= "\n";
+
+ unset($Block['interrupted']);
+ }
+
+ $Block['element']['text']['text'] .= "\n";
+
+ $text = substr($Line['body'], 4);
+
+ $Block['element']['text']['text'] .= $text;
+
+ return $Block;
+ }
+ }
+
+ protected function blockCodeComplete($Block)
+ {
+ $text = $Block['element']['text']['text'];
+
+ $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+
+ $Block['element']['text']['text'] = $text;
+
+ return $Block;
+ }
+
+ #
+ # Comment
+
+ protected function blockComment($Line)
+ {
+ if ($this->markupEscaped)
+ {
+ return;
+ }
+
+ if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
+ {
+ $Block = array(
+ 'markup' => $Line['body'],
+ );
+
+ if (preg_match('/-->$/', $Line['text']))
+ {
+ $Block['closed'] = true;
+ }
+
+ return $Block;
+ }
+ }
+
+ protected function blockCommentContinue($Line, array $Block)
+ {
+ if (isset($Block['closed']))
+ {
+ return;
+ }
+
+ $Block['markup'] .= "\n" . $Line['body'];
+
+ if (preg_match('/-->$/', $Line['text']))
+ {
+ $Block['closed'] = true;
+ }
+
+ return $Block;
+ }
+
+ #
+ # Fenced Code
+
+ protected function blockFencedCode($Line)
+ {
+ if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
+ {
+ $Element = array(
+ 'name' => 'code',
+ 'text' => '',
+ );
+
+ if (isset($matches[1]))
+ {
+ $class = 'language-'.$matches[1];
+
+ $Element['attributes'] = array(
+ 'class' => $class,
+ );
+ }
+
+ $Block = array(
+ 'char' => $Line['text'][0],
+ 'element' => array(
+ 'name' => 'pre',
+ 'handler' => 'element',
+ 'text' => $Element,
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockFencedCodeContinue($Line, $Block)
+ {
+ if (isset($Block['complete']))
+ {
+ return;
+ }
+
+ if (isset($Block['interrupted']))
+ {
+ $Block['element']['text']['text'] .= "\n";
+
+ unset($Block['interrupted']);
+ }
+
+ if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
+ {
+ $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
+
+ $Block['complete'] = true;
+
+ return $Block;
+ }
+
+ $Block['element']['text']['text'] .= "\n".$Line['body'];;
+
+ return $Block;
+ }
+
+ protected function blockFencedCodeComplete($Block)
+ {
+ $text = $Block['element']['text']['text'];
+
+ $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+
+ $Block['element']['text']['text'] = $text;
+
+ return $Block;
+ }
+
+ #
+ # Header
+
+ protected function blockHeader($Line)
+ {
+ if (isset($Line['text'][1]))
+ {
+ $level = 1;
+
+ while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
+ {
+ $level ++;
+ }
+
+ if ($level > 6)
+ {
+ return;
+ }
+
+ $text = trim($Line['text'], '# ');
+
+ $Block = array(
+ 'element' => array(
+ 'name' => 'h' . min(6, $level),
+ 'text' => $text,
+ 'handler' => 'line',
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ #
+ # List
+
+ protected function blockList($Line)
+ {
+ list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
+
+ if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
+ {
+ $Block = array(
+ 'indent' => $Line['indent'],
+ 'pattern' => $pattern,
+ 'element' => array(
+ 'name' => $name,
+ 'handler' => 'elements',
+ ),
+ );
+
+ $Block['li'] = array(
+ 'name' => 'li',
+ 'handler' => 'li',
+ 'text' => array(
+ $matches[2],
+ ),
+ );
+
+ $Block['element']['text'] []= & $Block['li'];
+
+ return $Block;
+ }
+ }
+
+ protected function blockListContinue($Line, array $Block)
+ {
+ if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
+ {
+ if (isset($Block['interrupted']))
+ {
+ $Block['li']['text'] []= '';
+
+ unset($Block['interrupted']);
+ }
+
+ unset($Block['li']);
+
+ $text = isset($matches[1]) ? $matches[1] : '';
+
+ $Block['li'] = array(
+ 'name' => 'li',
+ 'handler' => 'li',
+ 'text' => array(
+ $text,
+ ),
+ );
+
+ $Block['element']['text'] []= & $Block['li'];
+
+ return $Block;
+ }
+
+ if ($Line['text'][0] === '[' and $this->blockReference($Line))
+ {
+ return $Block;
+ }
+
+ if ( ! isset($Block['interrupted']))
+ {
+ $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
+
+ $Block['li']['text'] []= $text;
+
+ return $Block;
+ }
+
+ if ($Line['indent'] > 0)
+ {
+ $Block['li']['text'] []= '';
+
+ $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
+
+ $Block['li']['text'] []= $text;
+
+ unset($Block['interrupted']);
+
+ return $Block;
+ }
+ }
+
+ #
+ # Quote
+
+ protected function blockQuote($Line)
+ {
+ if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
+ {
+ $Block = array(
+ 'element' => array(
+ 'name' => 'blockquote',
+ 'handler' => 'lines',
+ 'text' => (array) $matches[1],
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockQuoteContinue($Line, array $Block)
+ {
+ if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
+ {
+ if (isset($Block['interrupted']))
+ {
+ $Block['element']['text'] []= '';
+
+ unset($Block['interrupted']);
+ }
+
+ $Block['element']['text'] []= $matches[1];
+
+ return $Block;
+ }
+
+ if ( ! isset($Block['interrupted']))
+ {
+ $Block['element']['text'] []= $Line['text'];
+
+ return $Block;
+ }
+ }
+
+ #
+ # Rule
+
+ protected function blockRule($Line)
+ {
+ if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
+ {
+ $Block = array(
+ 'element' => array(
+ 'name' => 'hr'
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ #
+ # Setext
+
+ protected function blockSetextHeader($Line, array $Block = null)
+ {
+ if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if (chop($Line['text'], $Line['text'][0]) === '')
+ {
+ $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
+
+ return $Block;
+ }
+ }
+
+ #
+ # Markup
+
+ protected function blockMarkup($Line)
+ {
+ if ($this->markupEscaped)
+ {
+ return;
+ }
+
+ if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
+ {
+ $element = strtolower($matches[1]);
+
+ if (in_array($element, $this->textLevelElements))
+ {
+ return;
+ }
+
+ $Block = array(
+ 'name' => $matches[1],
+ 'depth' => 0,
+ 'markup' => $Line['text'],
+ );
+
+ $length = strlen($matches[0]);
+
+ $remainder = substr($Line['text'], $length);
+
+ if (trim($remainder) === '')
+ {
+ if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
+ {
+ $Block['closed'] = true;
+
+ $Block['void'] = true;
+ }
+ }
+ else
+ {
+ if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
+ {
+ return;
+ }
+
+ if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
+ {
+ $Block['closed'] = true;
+ }
+ }
+
+ return $Block;
+ }
+ }
+
+ protected function blockMarkupContinue($Line, array $Block)
+ {
+ if (isset($Block['closed']))
+ {
+ return;
+ }
+
+ if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
+ {
+ $Block['depth'] ++;
+ }
+
+ if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
+ {
+ if ($Block['depth'] > 0)
+ {
+ $Block['depth'] --;
+ }
+ else
+ {
+ $Block['closed'] = true;
+ }
+ }
+
+ if (isset($Block['interrupted']))
+ {
+ $Block['markup'] .= "\n";
+
+ unset($Block['interrupted']);
+ }
+
+ $Block['markup'] .= "\n".$Line['body'];
+
+ return $Block;
+ }
+
+ #
+ # Reference
+
+ protected function blockReference($Line)
+ {
+ if (preg_match('/^\[(.+?)\]:[ ]*(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
+ {
+ $id = strtolower($matches[1]);
+
+ $Data = array(
+ 'url' => $matches[2],
+ 'title' => null,
+ );
+
+ if (isset($matches[3]))
+ {
+ $Data['title'] = $matches[3];
+ }
+
+ $this->DefinitionData['Reference'][$id] = $Data;
+
+ $Block = array(
+ 'hidden' => true,
+ );
+
+ return $Block;
+ }
+ }
+
+ #
+ # Table
+
+ protected function blockTable($Line, array $Block = null)
+ {
+ if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
+ {
+ $alignments = array();
+
+ $divider = $Line['text'];
+
+ $divider = trim($divider);
+ $divider = trim($divider, '|');
+
+ $dividerCells = explode('|', $divider);
+
+ foreach ($dividerCells as $dividerCell)
+ {
+ $dividerCell = trim($dividerCell);
+
+ if ($dividerCell === '')
+ {
+ continue;
+ }
+
+ $alignment = null;
+
+ if ($dividerCell[0] === ':')
+ {
+ $alignment = 'left';
+ }
+
+ if (substr($dividerCell, - 1) === ':')
+ {
+ $alignment = $alignment === 'left' ? 'center' : 'right';
+ }
+
+ $alignments []= $alignment;
+ }
+
+ # ~
+
+ $HeaderElements = array();
+
+ $header = $Block['element']['text'];
+
+ $header = trim($header);
+ $header = trim($header, '|');
+
+ $headerCells = explode('|', $header);
+
+ foreach ($headerCells as $index => $headerCell)
+ {
+ $headerCell = trim($headerCell);
+
+ $HeaderElement = array(
+ 'name' => 'th',
+ 'text' => $headerCell,
+ 'handler' => 'line',
+ );
+
+ if (isset($alignments[$index]))
+ {
+ $alignment = $alignments[$index];
+
+ $HeaderElement['attributes'] = array(
+ 'style' => 'text-align: '.$alignment.';',
+ );
+ }
+
+ $HeaderElements []= $HeaderElement;
+ }
+
+ # ~
+
+ $Block = array(
+ 'alignments' => $alignments,
+ 'identified' => true,
+ 'element' => array(
+ 'name' => 'table',
+ 'handler' => 'elements',
+ ),
+ );
+
+ $Block['element']['text'] []= array(
+ 'name' => 'thead',
+ 'handler' => 'elements',
+ );
+
+ $Block['element']['text'] []= array(
+ 'name' => 'tbody',
+ 'handler' => 'elements',
+ 'text' => array(),
+ );
+
+ $Block['element']['text'][0]['text'] []= array(
+ 'name' => 'tr',
+ 'handler' => 'elements',
+ 'text' => $HeaderElements,
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockTableContinue($Line, array $Block)
+ {
+ if (isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
+ {
+ $Elements = array();
+
+ $row = $Line['text'];
+
+ $row = trim($row);
+ $row = trim($row, '|');
+
+ preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
+
+ foreach ($matches[0] as $index => $cell)
+ {
+ $cell = trim($cell);
+
+ $Element = array(
+ 'name' => 'td',
+ 'handler' => 'line',
+ 'text' => $cell,
+ );
+
+ if (isset($Block['alignments'][$index]))
+ {
+ $Element['attributes'] = array(
+ 'style' => 'text-align: '.$Block['alignments'][$index].';',
+ );
+ }
+
+ $Elements []= $Element;
+ }
+
+ $Element = array(
+ 'name' => 'tr',
+ 'handler' => 'elements',
+ 'text' => $Elements,
+ );
+
+ $Block['element']['text'][1]['text'] []= $Element;
+
+ return $Block;
+ }
+ }
+
+ #
+ # ~
+ #
+
+ protected function paragraph($Line)
+ {
+ $Block = array(
+ 'element' => array(
+ 'name' => 'p',
+ 'text' => $Line['text'],
+ 'handler' => 'line',
+ ),
+ );
+
+ return $Block;
+ }
+
+ #
+ # Inline Elements
+ #
+
+ protected $InlineTypes = array(
+ '"' => array('SpecialCharacter'),
+ '!' => array('Image'),
+ '&' => array('SpecialCharacter'),
+ '*' => array('Emphasis'),
+ ':' => array('Url'),
+ '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
+ '>' => array('SpecialCharacter'),
+ '[' => array('Link'),
+ '_' => array('Emphasis'),
+ '`' => array('Code'),
+ '~' => array('Strikethrough'),
+ '\\' => array('EscapeSequence'),
+ );
+
+ # ~
+
+ protected $inlineMarkerList = '!"*_&[:<>`~\\';
+
+ #
+ # ~
+ #
+
+ public function line($text)
+ {
+ $markup = '';
+
+ # $excerpt is based on the first occurrence of a marker
+
+ while ($excerpt = strpbrk($text, $this->inlineMarkerList))
+ {
+ $marker = $excerpt[0];
+
+ $markerPosition = strpos($text, $marker);
+
+ $Excerpt = array('text' => $excerpt, 'context' => $text);
+
+ foreach ($this->InlineTypes[$marker] as $inlineType)
+ {
+ $Inline = $this->{'inline'.$inlineType}($Excerpt);
+
+ if ( ! isset($Inline))
+ {
+ continue;
+ }
+
+ # makes sure that the inline belongs to "our" marker
+
+ if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
+ {
+ continue;
+ }
+
+ # sets a default inline position
+
+ if ( ! isset($Inline['position']))
+ {
+ $Inline['position'] = $markerPosition;
+ }
+
+ # the text that comes before the inline
+ $unmarkedText = substr($text, 0, $Inline['position']);
+
+ # compile the unmarked text
+ $markup .= $this->unmarkedText($unmarkedText);
+
+ # compile the inline
+ $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
+
+ # remove the examined text
+ $text = substr($text, $Inline['position'] + $Inline['extent']);
+
+ continue 2;
+ }
+
+ # the marker does not belong to an inline
+
+ $unmarkedText = substr($text, 0, $markerPosition + 1);
+
+ $markup .= $this->unmarkedText($unmarkedText);
+
+ $text = substr($text, $markerPosition + 1);
+ }
+
+ $markup .= $this->unmarkedText($text);
+
+ return $markup;
+ }
+
+ #
+ # ~
+ #
+
+ protected function inlineCode($Excerpt)
+ {
+ $marker = $Excerpt['text'][0];
+
+ if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'code',
+ 'text' => $text,
+ ),
+ );
+ }
+ }
+
+ protected function inlineEmailTag($Excerpt)
+ {
+ if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
+ {
+ $url = $matches[1];
+
+ if ( ! isset($matches[2]))
+ {
+ $url = 'mailto:' . $url;
+ }
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $matches[1],
+ 'attributes' => array(
+ 'href' => $url,
+ ),
+ ),
+ );
+ }
+ }
+
+ protected function inlineEmphasis($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]))
+ {
+ return;
+ }
+
+ $marker = $Excerpt['text'][0];
+
+ if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
+ {
+ $emphasis = 'strong';
+ }
+ elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
+ {
+ $emphasis = 'em';
+ }
+ else
+ {
+ return;
+ }
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => $emphasis,
+ 'handler' => 'line',
+ 'text' => $matches[1],
+ ),
+ );
+ }
+
+ protected function inlineEscapeSequence($Excerpt)
+ {
+ if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
+ {
+ return array(
+ 'markup' => $Excerpt['text'][1],
+ 'extent' => 2,
+ );
+ }
+ }
+
+ protected function inlineImage($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
+ {
+ return;
+ }
+
+ $Excerpt['text']= substr($Excerpt['text'], 1);
+
+ $Link = $this->inlineLink($Excerpt);
+
+ if ($Link === null)
+ {
+ return;
+ }
+
+ $Inline = array(
+ 'extent' => $Link['extent'] + 1,
+ 'element' => array(
+ 'name' => 'img',
+ 'attributes' => array(
+ 'src' => $Link['element']['attributes']['href'],
+ 'alt' => $Link['element']['text'],
+ ),
+ ),
+ );
+
+ $Inline['element']['attributes'] += $Link['element']['attributes'];
+
+ unset($Inline['element']['attributes']['href']);
+
+ return $Inline;
+ }
+
+ protected function inlineLink($Excerpt)
+ {
+ $Element = array(
+ 'name' => 'a',
+ 'handler' => 'line',
+ 'text' => null,
+ 'attributes' => array(
+ 'href' => null,
+ 'title' => null,
+ ),
+ );
+
+ $extent = 0;
+
+ $remainder = $Excerpt['text'];
+
+ if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
+ {
+ $Element['text'] = $matches[1];
+
+ $extent += strlen($matches[0]);
+
+ $remainder = substr($remainder, $extent);
+ }
+ else
+ {
+ return;
+ }
+
+ if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
+ {
+ $Element['attributes']['href'] = $matches[1];
+
+ if (isset($matches[2]))
+ {
+ $Element['attributes']['title'] = substr($matches[2], 1, - 1);
+ }
+
+ $extent += strlen($matches[0]);
+ }
+ else
+ {
+ if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
+ {
+ $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
+ $definition = strtolower($definition);
+
+ $extent += strlen($matches[0]);
+ }
+ else
+ {
+ $definition = strtolower($Element['text']);
+ }
+
+ if ( ! isset($this->DefinitionData['Reference'][$definition]))
+ {
+ return;
+ }
+
+ $Definition = $this->DefinitionData['Reference'][$definition];
+
+ $Element['attributes']['href'] = $Definition['url'];
+ $Element['attributes']['title'] = $Definition['title'];
+ }
+
+ $Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']);
+
+ return array(
+ 'extent' => $extent,
+ 'element' => $Element,
+ );
+ }
+
+ protected function inlineMarkup($Excerpt)
+ {
+ if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
+ {
+ return;
+ }
+
+ if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'markup' => $matches[0],
+ 'extent' => strlen($matches[0]),
+ );
+ }
+
+ if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'markup' => $matches[0],
+ 'extent' => strlen($matches[0]),
+ );
+ }
+
+ if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'markup' => $matches[0],
+ 'extent' => strlen($matches[0]),
+ );
+ }
+ }
+
+ protected function inlineSpecialCharacter($Excerpt)
+ {
+ if ($Excerpt['text'][0] === '&' and ! preg_match('/^?\w+;/', $Excerpt['text']))
+ {
+ return array(
+ 'markup' => '&',
+ 'extent' => 1,
+ );
+ }
+
+ $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
+
+ if (isset($SpecialCharacter[$Excerpt['text'][0]]))
+ {
+ return array(
+ 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
+ 'extent' => 1,
+ );
+ }
+ }
+
+ protected function inlineStrikethrough($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]))
+ {
+ return;
+ }
+
+ if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'del',
+ 'text' => $matches[1],
+ 'handler' => 'line',
+ ),
+ );
+ }
+ }
+
+ protected function inlineUrl($Excerpt)
+ {
+ if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
+ {
+ return;
+ }
+
+ if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
+ {
+ $Inline = array(
+ 'extent' => strlen($matches[0][0]),
+ 'position' => $matches[0][1],
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $matches[0][0],
+ 'attributes' => array(
+ 'href' => $matches[0][0],
+ ),
+ ),
+ );
+
+ return $Inline;
+ }
+ }
+
+ protected function inlineUrlTag($Excerpt)
+ {
+ if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
+ {
+ $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]);
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $url,
+ 'attributes' => array(
+ 'href' => $url,
+ ),
+ ),
+ );
+ }
+ }
+
+ # ~
+
+ protected function unmarkedText($text)
+ {
+ if ($this->breaksEnabled)
+ {
+ $text = preg_replace('/[ ]*\n/', "
\n", $text);
+ }
+ else
+ {
+ $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "
\n", $text);
+ $text = str_replace(" \n", "\n", $text);
+ }
+
+ return $text;
+ }
+
+ #
+ # Handlers
+ #
+
+ protected function element(array $Element)
+ {
+ $markup = '<'.$Element['name'];
+
+ if (isset($Element['attributes']))
+ {
+ foreach ($Element['attributes'] as $name => $value)
+ {
+ if ($value === null)
+ {
+ continue;
+ }
+
+ $markup .= ' '.$name.'="'.$value.'"';
+ }
+ }
+
+ if (isset($Element['text']))
+ {
+ $markup .= '>';
+
+ if (isset($Element['handler']))
+ {
+ $markup .= $this->{$Element['handler']}($Element['text']);
+ }
+ else
+ {
+ $markup .= $Element['text'];
+ }
+
+ $markup .= ''.$Element['name'].'>';
+ }
+ else
+ {
+ $markup .= ' />';
+ }
+
+ return $markup;
+ }
+
+ protected function elements(array $Elements)
+ {
+ $markup = '';
+
+ foreach ($Elements as $Element)
+ {
+ $markup .= "\n" . $this->element($Element);
+ }
+
+ $markup .= "\n";
+
+ return $markup;
+ }
+
+ # ~
+
+ protected function li($lines)
+ {
+ $markup = $this->lines($lines);
+
+ $trimmedMarkup = trim($markup);
+
+ if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '')
+ {
+ $markup = $trimmedMarkup;
+ $markup = substr($markup, 3);
+
+ $position = strpos($markup, "
");
+
+ $markup = substr_replace($markup, '', $position, 4);
+ }
+
+ return $markup;
+ }
+
+ #
+ # Deprecated Methods
+ #
+
+ function parse($text)
+ {
+ $markup = $this->text($text);
+
+ return $markup;
+ }
+
+ #
+ # Static Methods
+ #
+
+ static function instance($name = 'default')
+ {
+ if (isset(self::$instances[$name]))
+ {
+ return self::$instances[$name];
+ }
+
+ $instance = new static();
+
+ self::$instances[$name] = $instance;
+
+ return $instance;
+ }
+
+ private static $instances = array();
+
+ #
+ # Fields
+ #
+
+ protected $DefinitionData;
+
+ #
+ # Read-Only
+
+ protected $specialCharacters = array(
+ '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
+ );
+
+ protected $StrongRegex = array(
+ '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
+ '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
+ );
+
+ protected $EmRegex = array(
+ '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
+ '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
+ );
+
+ protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
+
+ protected $voidElements = array(
+ 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
+ );
+
+ protected $textLevelElements = array(
+ 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
+ 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
+ 'i', 'rp', 'del', 'code', 'strike', 'marquee',
+ 'q', 'rt', 'ins', 'font', 'strong',
+ 's', 'tt', 'sub', 'mark',
+ 'u', 'xm', 'sup', 'nobr',
+ 'var', 'ruby',
+ 'wbr', 'span',
+ 'time',
+ );
+}
diff --git a/vendor/erusev/parsedown/README.md b/vendor/erusev/parsedown/README.md
new file mode 100644
index 00000000..6f9f6498
--- /dev/null
+++ b/vendor/erusev/parsedown/README.md
@@ -0,0 +1,57 @@
+## Parsedown
+
+[![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown)
+
+
+Better Markdown Parser in PHP
+
+[Demo](http://parsedown.org/demo) |
+[Benchmarks](http://parsedown.org/speed) |
+[Tests](http://parsedown.org/tests/) |
+[Documentation](https://github.com/erusev/parsedown/wiki/)
+
+### Features
+
+* Super Fast
+* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
+* Extensible
+* Tested in 5.3 to 5.6
+* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
+
+### Installation
+
+Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
+
+### Example
+
+``` php
+$Parsedown = new Parsedown();
+
+echo $Parsedown->text('Hello _Parsedown_!'); # prints: Hello Parsedown!
+```
+
+More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
+
+### Questions
+
+**How does Parsedown work?**
+
+It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line start with a `-` then it perhaps belong to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).
+
+We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.
+
+**Is it compliant with CommonMark?**
+
+It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.
+
+**Who uses it?**
+
+[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://www.versioneye.com/php/erusev:parsedown/references).
+
+**How can I help?**
+
+Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
+
+---
+
+You might also like [Caret](http://caret.io) - our Markdown editor for the desktop.
diff --git a/vendor/erusev/parsedown/composer.json b/vendor/erusev/parsedown/composer.json
new file mode 100644
index 00000000..1439b824
--- /dev/null
+++ b/vendor/erusev/parsedown/composer.json
@@ -0,0 +1,18 @@
+{
+ "name": "erusev/parsedown",
+ "description": "Parser for Markdown.",
+ "keywords": ["markdown", "parser"],
+ "homepage": "http://parsedown.org",
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Emanuil Rusev",
+ "email": "hello@erusev.com",
+ "homepage": "http://erusev.com"
+ }
+ ],
+ "autoload": {
+ "psr-0": {"Parsedown": ""}
+ }
+}
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/phpunit.xml.dist b/vendor/erusev/parsedown/phpunit.xml.dist
new file mode 100644
index 00000000..b2d5e9d4
--- /dev/null
+++ b/vendor/erusev/parsedown/phpunit.xml.dist
@@ -0,0 +1,8 @@
+
+
+
+
+ test/ParsedownTest.php
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/CommonMarkTest.php b/vendor/erusev/parsedown/test/CommonMarkTest.php
new file mode 100644
index 00000000..9b8d1162
--- /dev/null
+++ b/vendor/erusev/parsedown/test/CommonMarkTest.php
@@ -0,0 +1,74 @@
+setUrlsLinked(false);
+
+ $actualHtml = $Parsedown->text($markdown);
+ $actualHtml = $this->normalizeMarkup($actualHtml);
+
+ $this->assertEquals($expectedHtml, $actualHtml);
+ }
+
+ function data()
+ {
+ $spec = file_get_contents(self::SPEC_URL);
+ $spec = strstr($spec, '', true);
+
+ $tests = array();
+ $currentSection = '';
+
+ preg_replace_callback(
+ '/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/m',
+ function($matches) use ( & $tests, & $currentSection, & $testCount) {
+ if (isset($matches[3]) and $matches[3]) {
+ $currentSection = $matches[3];
+ } else {
+ $testCount++;
+ $markdown = $matches[1];
+ $markdown = preg_replace('/→/', "\t", $markdown);
+ $expectedHtml = $matches[2];
+ $expectedHtml = $this->normalizeMarkup($expectedHtml);
+ $tests []= array(
+ $currentSection, # section
+ $markdown, # markdown
+ $expectedHtml, # html
+ );
+ }
+ },
+ $spec
+ );
+
+ return $tests;
+ }
+
+ private function normalizeMarkup($markup)
+ {
+ $markup = preg_replace("/\n+/", "\n", $markup);
+ $markup = preg_replace('/^\s+/m', '', $markup);
+ $markup = preg_replace('/^((?:<[\w]+>)+)\n/m', '$1', $markup);
+ $markup = preg_replace('/\n((?:<\/[\w]+>)+)$/m', '$1', $markup);
+ $markup = trim($markup);
+
+ return $markup;
+ }
+}
diff --git a/vendor/erusev/parsedown/test/ParsedownTest.php b/vendor/erusev/parsedown/test/ParsedownTest.php
new file mode 100644
index 00000000..c922ab1f
--- /dev/null
+++ b/vendor/erusev/parsedown/test/ParsedownTest.php
@@ -0,0 +1,159 @@
+dirs = $this->initDirs();
+ $this->Parsedown = $this->initParsedown();
+
+ parent::__construct($name, $data, $dataName);
+ }
+
+ private $dirs, $Parsedown;
+
+ /**
+ * @return array
+ */
+ protected function initDirs()
+ {
+ $dirs []= dirname(__FILE__).'/data/';
+
+ return $dirs;
+ }
+
+ /**
+ * @return Parsedown
+ */
+ protected function initParsedown()
+ {
+ $Parsedown = new Parsedown();
+
+ return $Parsedown;
+ }
+
+ /**
+ * @dataProvider data
+ * @param $test
+ * @param $dir
+ */
+ function test_($test, $dir)
+ {
+ $markdown = file_get_contents($dir . $test . '.md');
+
+ $expectedMarkup = file_get_contents($dir . $test . '.html');
+
+ $expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
+ $expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
+
+ $actualMarkup = $this->Parsedown->text($markdown);
+
+ $this->assertEquals($expectedMarkup, $actualMarkup);
+ }
+
+ function data()
+ {
+ $data = array();
+
+ foreach ($this->dirs as $dir)
+ {
+ $Folder = new DirectoryIterator($dir);
+
+ foreach ($Folder as $File)
+ {
+ /** @var $File DirectoryIterator */
+
+ if ( ! $File->isFile())
+ {
+ continue;
+ }
+
+ $filename = $File->getFilename();
+
+ $extension = pathinfo($filename, PATHINFO_EXTENSION);
+
+ if ($extension !== 'md')
+ {
+ continue;
+ }
+
+ $basename = $File->getBasename('.md');
+
+ if (file_exists($dir . $basename . '.html'))
+ {
+ $data []= array($basename, $dir);
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ public function test_no_markup()
+ {
+ $markdownWithHtml = <<_content_
+
+sparse:
+
+
+
+paragraph
+
+
+
+comment
+
+
+MARKDOWN_WITH_MARKUP;
+
+ $expectedHtml = <<<div>content</div>
+sparse:
+<div>
+<div class="inner">
+content
+</div>
+</div>
+paragraph
+<style type="text/css">
+p {
+color: red;
+}
+</style>
+comment
+<!-- html comment -->
+EXPECTED_HTML;
+ $parsedownWithNoMarkup = new Parsedown();
+ $parsedownWithNoMarkup->setMarkupEscaped(true);
+ $this->assertEquals($expectedHtml, $parsedownWithNoMarkup->text($markdownWithHtml));
+ }
+
+ public function testLateStaticBinding()
+ {
+ include 'test/TestParsedown.php';
+
+ $parsedown = Parsedown::instance();
+ $this->assertInstanceOf('Parsedown', $parsedown);
+
+ // After instance is already called on Parsedown
+ // subsequent calls with the same arguments return the same instance
+ $sameParsedown = TestParsedown::instance();
+ $this->assertInstanceOf('Parsedown', $sameParsedown);
+ $this->assertSame($parsedown, $sameParsedown);
+
+ $testParsedown = TestParsedown::instance('test late static binding');
+ $this->assertInstanceOf('TestParsedown', $testParsedown);
+
+ $sameInstanceAgain = TestParsedown::instance('test late static binding');
+ $this->assertSame($testParsedown, $sameInstanceAgain);
+ }
+}
diff --git a/vendor/erusev/parsedown/test/TestParsedown.php b/vendor/erusev/parsedown/test/TestParsedown.php
new file mode 100644
index 00000000..7024dfbc
--- /dev/null
+++ b/vendor/erusev/parsedown/test/TestParsedown.php
@@ -0,0 +1,5 @@
+
+
+
+header 1 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+
+
+cell 2.1 |
+cell 2.2 |
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/aesthetic_table.md b/vendor/erusev/parsedown/test/data/aesthetic_table.md
new file mode 100644
index 00000000..5245e6c9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/aesthetic_table.md
@@ -0,0 +1,4 @@
+| header 1 | header 2 |
+| -------- | -------- |
+| cell 1.1 | cell 1.2 |
+| cell 2.1 | cell 2.2 |
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/aligned_table.html b/vendor/erusev/parsedown/test/data/aligned_table.html
new file mode 100644
index 00000000..c4acfcb6
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/aligned_table.html
@@ -0,0 +1,21 @@
+
+
+
+header 1 |
+header 2 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+cell 1.3 |
+
+
+cell 2.1 |
+cell 2.2 |
+cell 2.3 |
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/aligned_table.md b/vendor/erusev/parsedown/test/data/aligned_table.md
new file mode 100644
index 00000000..69a45f90
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/aligned_table.md
@@ -0,0 +1,4 @@
+| header 1 | header 2 | header 2 |
+| :------- | :------: | -------: |
+| cell 1.1 | cell 1.2 | cell 1.3 |
+| cell 2.1 | cell 2.2 | cell 2.3 |
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/atx_heading.html b/vendor/erusev/parsedown/test/data/atx_heading.html
new file mode 100644
index 00000000..751f8739
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/atx_heading.html
@@ -0,0 +1,9 @@
+h1
+h2
+h3
+h4
+h5
+h6
+####### not a heading
+closed h1
+#
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/atx_heading.md b/vendor/erusev/parsedown/test/data/atx_heading.md
new file mode 100644
index 00000000..ad97b44c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/atx_heading.md
@@ -0,0 +1,17 @@
+# h1
+
+## h2
+
+### h3
+
+#### h4
+
+##### h5
+
+###### h6
+
+####### not a heading
+
+# closed h1 #
+
+#
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/automatic_link.html b/vendor/erusev/parsedown/test/data/automatic_link.html
new file mode 100644
index 00000000..50a94ba0
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/automatic_link.html
@@ -0,0 +1 @@
+http://example.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/automatic_link.md b/vendor/erusev/parsedown/test/data/automatic_link.md
new file mode 100644
index 00000000..08d3bf46
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/automatic_link.md
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/block-level_html.html b/vendor/erusev/parsedown/test/data/block-level_html.html
new file mode 100644
index 00000000..6443a4a6
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/block-level_html.html
@@ -0,0 +1,12 @@
+_content_
+paragraph
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/block-level_html.md b/vendor/erusev/parsedown/test/data/block-level_html.md
new file mode 100644
index 00000000..17cbc22d
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/block-level_html.md
@@ -0,0 +1,16 @@
+_content_
+
+paragraph
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/code_block.html b/vendor/erusev/parsedown/test/data/code_block.html
new file mode 100644
index 00000000..889b02d9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/code_block.html
@@ -0,0 +1,8 @@
+<?php
+
+$message = 'Hello World!';
+echo $message;
+
+> not a quote
+- not a list item
+[not a reference]: http://foo.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/code_block.md b/vendor/erusev/parsedown/test/data/code_block.md
new file mode 100644
index 00000000..2cfc953c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/code_block.md
@@ -0,0 +1,10 @@
+ not a quote
+ - not a list item
+ [not a reference]: http://foo.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/code_span.html b/vendor/erusev/parsedown/test/data/code_span.html
new file mode 100644
index 00000000..5c4c231e
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/code_span.html
@@ -0,0 +1,6 @@
+a code span
+this is also a codespan
trailing text
+and look at this one!
+single backtick in a code span: `
+backtick-delimited string in a code span: `foo`
+sth `` sth
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/code_span.md b/vendor/erusev/parsedown/test/data/code_span.md
new file mode 100644
index 00000000..c2f1a744
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/code_span.md
@@ -0,0 +1,11 @@
+a `code span`
+
+`this is also a codespan` trailing text
+
+`and look at this one!`
+
+single backtick in a code span: `` ` ``
+
+backtick-delimited string in a code span: `` `foo` ``
+
+`sth `` sth`
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/compound_blockquote.html b/vendor/erusev/parsedown/test/data/compound_blockquote.html
new file mode 100644
index 00000000..37afb57a
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_blockquote.html
@@ -0,0 +1,9 @@
+
+header
+paragraph
+
+
+paragraph
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/compound_blockquote.md b/vendor/erusev/parsedown/test/data/compound_blockquote.md
new file mode 100644
index 00000000..80c4aed1
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_blockquote.md
@@ -0,0 +1,10 @@
+> header
+> ------
+>
+> paragraph
+>
+> - li
+>
+> ---
+>
+> paragraph
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/compound_emphasis.html b/vendor/erusev/parsedown/test/data/compound_emphasis.html
new file mode 100644
index 00000000..178dd54b
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_emphasis.html
@@ -0,0 +1,2 @@
+code
code
+code
code
code
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/compound_emphasis.md b/vendor/erusev/parsedown/test/data/compound_emphasis.md
new file mode 100644
index 00000000..6fe07f26
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_emphasis.md
@@ -0,0 +1,4 @@
+_`code`_ __`code`__
+
+*`code`**`code`**`code`*
+
diff --git a/vendor/erusev/parsedown/test/data/compound_list.html b/vendor/erusev/parsedown/test/data/compound_list.html
new file mode 100644
index 00000000..f5593c14
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_list.html
@@ -0,0 +1,12 @@
+
+-
+
paragraph
+paragraph
+
+-
+
paragraph
+
+quote
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/compound_list.md b/vendor/erusev/parsedown/test/data/compound_list.md
new file mode 100644
index 00000000..ed7f0c60
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/compound_list.md
@@ -0,0 +1,7 @@
+- paragraph
+
+ paragraph
+
+- paragraph
+
+ > quote
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/deeply_nested_list.html b/vendor/erusev/parsedown/test/data/deeply_nested_list.html
new file mode 100644
index 00000000..d2c7e5ac
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/deeply_nested_list.html
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/deeply_nested_list.md b/vendor/erusev/parsedown/test/data/deeply_nested_list.md
new file mode 100644
index 00000000..76b7552d
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/deeply_nested_list.md
@@ -0,0 +1,6 @@
+- li
+ - li
+ - li
+ - li
+ - li
+- li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/em_strong.html b/vendor/erusev/parsedown/test/data/em_strong.html
new file mode 100644
index 00000000..323d60ae
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/em_strong.html
@@ -0,0 +1,8 @@
+em strong
+em strong strong
+strong em strong
+strong em strong strong
+em strong
+em strong strong
+strong em strong
+strong em strong strong
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/em_strong.md b/vendor/erusev/parsedown/test/data/em_strong.md
new file mode 100644
index 00000000..9abeb3fd
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/em_strong.md
@@ -0,0 +1,15 @@
+___em strong___
+
+___em strong_ strong__
+
+__strong _em strong___
+
+__strong _em strong_ strong__
+
+***em strong***
+
+***em strong* strong**
+
+**strong *em strong***
+
+**strong *em strong* strong**
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/email.html b/vendor/erusev/parsedown/test/data/email.html
new file mode 100644
index 00000000..c40759c9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/email.html
@@ -0,0 +1 @@
+my email is me@example.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/email.md b/vendor/erusev/parsedown/test/data/email.md
new file mode 100644
index 00000000..26b7b6cc
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/email.md
@@ -0,0 +1 @@
+my email is
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/emphasis.html b/vendor/erusev/parsedown/test/data/emphasis.html
new file mode 100644
index 00000000..60ff4bd8
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/emphasis.html
@@ -0,0 +1,8 @@
+underscore, asterisk, one two, three four, a, b
+strong and em and strong and em
+line
+line
+line
+this_is_not_an_emphasis
+an empty emphasis __ ** is not an emphasis
+*mixed *double and single asterisk** spans
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/emphasis.md b/vendor/erusev/parsedown/test/data/emphasis.md
new file mode 100644
index 00000000..85b9d229
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/emphasis.md
@@ -0,0 +1,13 @@
+_underscore_, *asterisk*, _one two_, *three four*, _a_, *b*
+
+**strong** and *em* and **strong** and *em*
+
+_line
+line
+line_
+
+this_is_not_an_emphasis
+
+an empty emphasis __ ** is not an emphasis
+
+*mixed **double and* single asterisk** spans
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/escaping.html b/vendor/erusev/parsedown/test/data/escaping.html
new file mode 100644
index 00000000..ab1c41fd
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/escaping.html
@@ -0,0 +1,6 @@
+escaped *emphasis*.
+escaped \*emphasis\* in a code span
+escaped \*emphasis\* in a code block
+\ ` * _ { } [ ] ( ) > # + - . !
+one_two one_two
+one*two one*two
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/escaping.md b/vendor/erusev/parsedown/test/data/escaping.md
new file mode 100644
index 00000000..9f174e98
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/escaping.md
@@ -0,0 +1,11 @@
+escaped \*emphasis\*.
+
+`escaped \*emphasis\* in a code span`
+
+ escaped \*emphasis\* in a code block
+
+\\ \` \* \_ \{ \} \[ \] \( \) \> \# \+ \- \. \!
+
+_one\_two_ __one\_two__
+
+*one\*two* **one\*two**
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/fenced_code_block.html b/vendor/erusev/parsedown/test/data/fenced_code_block.html
new file mode 100644
index 00000000..8bdabba9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/fenced_code_block.html
@@ -0,0 +1,6 @@
+<?php
+
+$message = 'fenced code block';
+echo $message;
+tilde
+echo 'language identifier';
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/fenced_code_block.md b/vendor/erusev/parsedown/test/data/fenced_code_block.md
new file mode 100644
index 00000000..cbed8ebb
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/fenced_code_block.md
@@ -0,0 +1,14 @@
+```
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/horizontal_rule.md b/vendor/erusev/parsedown/test/data/horizontal_rule.md
new file mode 100644
index 00000000..bf461a92
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/horizontal_rule.md
@@ -0,0 +1,9 @@
+---
+
+- - -
+
+ - - -
+
+***
+
+___
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/html_comment.html b/vendor/erusev/parsedown/test/data/html_comment.html
new file mode 100644
index 00000000..566dc3ad
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/html_comment.html
@@ -0,0 +1,5 @@
+
+paragraph
+
+paragraph
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/html_comment.md b/vendor/erusev/parsedown/test/data/html_comment.md
new file mode 100644
index 00000000..6ddfdb44
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/html_comment.md
@@ -0,0 +1,8 @@
+
+
+paragraph
+
+
+
+paragraph
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/html_entity.html b/vendor/erusev/parsedown/test/data/html_entity.html
new file mode 100644
index 00000000..4d23e3cd
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/html_entity.html
@@ -0,0 +1 @@
+& © {
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/html_entity.md b/vendor/erusev/parsedown/test/data/html_entity.md
new file mode 100644
index 00000000..ff545ea5
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/html_entity.md
@@ -0,0 +1 @@
+& © {
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/image_reference.html b/vendor/erusev/parsedown/test/data/image_reference.html
new file mode 100644
index 00000000..67fbd2c8
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/image_reference.html
@@ -0,0 +1,2 @@
+
+![missing reference]
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/image_reference.md b/vendor/erusev/parsedown/test/data/image_reference.md
new file mode 100644
index 00000000..1e11d947
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/image_reference.md
@@ -0,0 +1,5 @@
+![Markdown Logo][image]
+
+[image]: /md.png
+
+![missing reference]
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/image_title.html b/vendor/erusev/parsedown/test/data/image_title.html
new file mode 100644
index 00000000..957c9505
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/image_title.html
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/image_title.md b/vendor/erusev/parsedown/test/data/image_title.md
new file mode 100644
index 00000000..7ce2849a
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/image_title.md
@@ -0,0 +1,3 @@
+![alt](/md.png "title")
+
+![blank title](/md.png "")
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/implicit_reference.html b/vendor/erusev/parsedown/test/data/implicit_reference.html
new file mode 100644
index 00000000..24b51c1b
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/implicit_reference.html
@@ -0,0 +1,4 @@
+an implicit reference link
+an implicit reference link with an empty link definition
+an implicit reference link followed by another
+an explicit reference link with a title
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/implicit_reference.md b/vendor/erusev/parsedown/test/data/implicit_reference.md
new file mode 100644
index 00000000..f850df96
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/implicit_reference.md
@@ -0,0 +1,13 @@
+an [implicit] reference link
+
+[implicit]: http://example.com
+
+an [implicit][] reference link with an empty link definition
+
+an [implicit][] reference link followed by [another][]
+
+[another]: http://cnn.com
+
+an [explicit][example] reference link with a title
+
+[example]: http://example.com "Example"
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_link.html b/vendor/erusev/parsedown/test/data/inline_link.html
new file mode 100644
index 00000000..5ad564aa
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_link.html
@@ -0,0 +1,6 @@
+link
+link with parentheses in URL
+(link) in parentheses
+link
+
+ and text
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_link.md b/vendor/erusev/parsedown/test/data/inline_link.md
new file mode 100644
index 00000000..6bac0b35
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_link.md
@@ -0,0 +1,11 @@
+[link](http://example.com)
+
+[link](/url-(parentheses)) with parentheses in URL
+
+([link](/index.php)) in parentheses
+
+[`link`](http://example.com)
+
+[![MD Logo](http://parsedown.org/md.png)](http://example.com)
+
+[![MD Logo](http://parsedown.org/md.png) and text](http://example.com)
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_link_title.html b/vendor/erusev/parsedown/test/data/inline_link_title.html
new file mode 100644
index 00000000..ecdfd03d
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_link_title.html
@@ -0,0 +1,6 @@
+single quotes
+double quotes
+single quotes blank
+double quotes blank
+space
+parentheses
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_link_title.md b/vendor/erusev/parsedown/test/data/inline_link_title.md
new file mode 100644
index 00000000..6e1c5af9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_link_title.md
@@ -0,0 +1,11 @@
+[single quotes](http://example.com 'Title')
+
+[double quotes](http://example.com "Title")
+
+[single quotes blank](http://example.com '')
+
+[double quotes blank](http://example.com "")
+
+[space](http://example.com "2 Words")
+
+[parentheses](http://example.com/url-(parentheses) "Title")
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_title.html b/vendor/erusev/parsedown/test/data/inline_title.html
new file mode 100644
index 00000000..bbab93b6
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_title.html
@@ -0,0 +1 @@
+single quotes and double quotes
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/inline_title.md b/vendor/erusev/parsedown/test/data/inline_title.md
new file mode 100644
index 00000000..cb09344a
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/inline_title.md
@@ -0,0 +1 @@
+[single quotes](http://example.com 'Example') and [double quotes](http://example.com "Example")
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/lazy_blockquote.html b/vendor/erusev/parsedown/test/data/lazy_blockquote.html
new file mode 100644
index 00000000..0a2a2aaf
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/lazy_blockquote.html
@@ -0,0 +1,6 @@
+
+quote
+the rest of it
+another paragraph
+the rest of it
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/lazy_blockquote.md b/vendor/erusev/parsedown/test/data/lazy_blockquote.md
new file mode 100644
index 00000000..48f645f9
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/lazy_blockquote.md
@@ -0,0 +1,5 @@
+> quote
+the rest of it
+
+> another paragraph
+the rest of it
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/lazy_list.html b/vendor/erusev/parsedown/test/data/lazy_list.html
new file mode 100644
index 00000000..1a519924
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/lazy_list.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/lazy_list.md b/vendor/erusev/parsedown/test/data/lazy_list.md
new file mode 100644
index 00000000..62ad9d71
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/lazy_list.md
@@ -0,0 +1,2 @@
+- li
+the rest of it
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/line_break.html b/vendor/erusev/parsedown/test/data/line_break.html
new file mode 100644
index 00000000..5f37d854
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/line_break.html
@@ -0,0 +1,2 @@
+line
+line
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/line_break.md b/vendor/erusev/parsedown/test/data/line_break.md
new file mode 100644
index 00000000..04dff43e
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/line_break.md
@@ -0,0 +1,2 @@
+line
+line
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/multiline_list_paragraph.html b/vendor/erusev/parsedown/test/data/multiline_list_paragraph.html
new file mode 100644
index 00000000..3247bd22
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/multiline_list_paragraph.html
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/multiline_list_paragraph.md b/vendor/erusev/parsedown/test/data/multiline_list_paragraph.md
new file mode 100644
index 00000000..f5b42729
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/multiline_list_paragraph.md
@@ -0,0 +1,4 @@
+- li
+
+ line
+ line
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/nested_block-level_html.html b/vendor/erusev/parsedown/test/data/nested_block-level_html.html
new file mode 100644
index 00000000..bfbef54d
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/nested_block-level_html.html
@@ -0,0 +1,10 @@
+
+_parent_
+
+_child_
+
+
+_adopted child_
+
+
+outside
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/nested_block-level_html.md b/vendor/erusev/parsedown/test/data/nested_block-level_html.md
new file mode 100644
index 00000000..5e01e109
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/nested_block-level_html.md
@@ -0,0 +1,11 @@
+
+_parent_
+
+_child_
+
+
+_adopted child_
+
+
+
+_outside_
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/ordered_list.html b/vendor/erusev/parsedown/test/data/ordered_list.html
new file mode 100644
index 00000000..b6c5216c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/ordered_list.html
@@ -0,0 +1,13 @@
+
+- one
+- two
+
+repeating numbers:
+
+- one
+- two
+
+large numbers:
+
+- one
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/ordered_list.md b/vendor/erusev/parsedown/test/data/ordered_list.md
new file mode 100644
index 00000000..b307032c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/ordered_list.md
@@ -0,0 +1,11 @@
+1. one
+2. two
+
+repeating numbers:
+
+1. one
+1. two
+
+large numbers:
+
+123. one
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/paragraph_list.html b/vendor/erusev/parsedown/test/data/paragraph_list.html
new file mode 100644
index 00000000..ced1c43e
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/paragraph_list.html
@@ -0,0 +1,12 @@
+paragraph
+
+paragraph
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/paragraph_list.md b/vendor/erusev/parsedown/test/data/paragraph_list.md
new file mode 100644
index 00000000..b973908c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/paragraph_list.md
@@ -0,0 +1,9 @@
+paragraph
+- li
+- li
+
+paragraph
+
+ * li
+
+ * li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/reference_title.html b/vendor/erusev/parsedown/test/data/reference_title.html
new file mode 100644
index 00000000..8f2be944
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/reference_title.html
@@ -0,0 +1,2 @@
+double quotes and single quotes and parentheses
+[invalid title]: http://example.com example title
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/reference_title.md b/vendor/erusev/parsedown/test/data/reference_title.md
new file mode 100644
index 00000000..43cb2170
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/reference_title.md
@@ -0,0 +1,6 @@
+[double quotes] and [single quotes] and [parentheses]
+
+[double quotes]: http://example.com "example title"
+[single quotes]: http://example.com 'example title'
+[parentheses]: http://example.com (example title)
+[invalid title]: http://example.com example title
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/self-closing_html.html b/vendor/erusev/parsedown/test/data/self-closing_html.html
new file mode 100644
index 00000000..4d072b43
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/self-closing_html.html
@@ -0,0 +1,12 @@
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/self-closing_html.md b/vendor/erusev/parsedown/test/data/self-closing_html.md
new file mode 100644
index 00000000..acb20327
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/self-closing_html.md
@@ -0,0 +1,12 @@
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
+
+paragraph
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/separated_nested_list.html b/vendor/erusev/parsedown/test/data/separated_nested_list.html
new file mode 100644
index 00000000..80a5cae2
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/separated_nested_list.html
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/separated_nested_list.md b/vendor/erusev/parsedown/test/data/separated_nested_list.md
new file mode 100644
index 00000000..d7cd1af7
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/separated_nested_list.md
@@ -0,0 +1,4 @@
+- li
+
+ - li
+ - li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/setext_header.html b/vendor/erusev/parsedown/test/data/setext_header.html
new file mode 100644
index 00000000..60aac081
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/setext_header.html
@@ -0,0 +1,5 @@
+h1
+h2
+single character
+not a header
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/setext_header.md b/vendor/erusev/parsedown/test/data/setext_header.md
new file mode 100644
index 00000000..c43b52c3
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/setext_header.md
@@ -0,0 +1,12 @@
+h1
+==
+
+h2
+--
+
+single character
+-
+
+not a header
+
+------------
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/simple_blockquote.html b/vendor/erusev/parsedown/test/data/simple_blockquote.html
new file mode 100644
index 00000000..8225d57c
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/simple_blockquote.html
@@ -0,0 +1,11 @@
+
+quote
+
+indented:
+
+quote
+
+no space after >
:
+
+quote
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/simple_blockquote.md b/vendor/erusev/parsedown/test/data/simple_blockquote.md
new file mode 100644
index 00000000..22b6b11a
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/simple_blockquote.md
@@ -0,0 +1,7 @@
+> quote
+
+indented:
+ > quote
+
+no space after `>`:
+>quote
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/simple_table.html b/vendor/erusev/parsedown/test/data/simple_table.html
new file mode 100644
index 00000000..237d7efb
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/simple_table.html
@@ -0,0 +1,37 @@
+
+
+
+header 1 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+
+
+cell 2.1 |
+cell 2.2 |
+
+
+
+
+
+
+
+header 1 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+
+
+cell 2.1 |
+cell 2.2 |
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/simple_table.md b/vendor/erusev/parsedown/test/data/simple_table.md
new file mode 100644
index 00000000..466d140e
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/simple_table.md
@@ -0,0 +1,11 @@
+header 1 | header 2
+-------- | --------
+cell 1.1 | cell 1.2
+cell 2.1 | cell 2.2
+
+---
+
+header 1 | header 2
+:------- | --------
+cell 1.1 | cell 1.2
+cell 2.1 | cell 2.2
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/span-level_html.html b/vendor/erusev/parsedown/test/data/span-level_html.html
new file mode 100644
index 00000000..f852a25a
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/span-level_html.html
@@ -0,0 +1,5 @@
+an important link
+broken
+line
+inline tag at the beginning
+http://example.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/span-level_html.md b/vendor/erusev/parsedown/test/data/span-level_html.md
new file mode 100644
index 00000000..f2219655
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/span-level_html.md
@@ -0,0 +1,8 @@
+an important link
+
+broken
+line
+
+inline tag at the beginning
+
+http://example.com
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_dense_list.html b/vendor/erusev/parsedown/test/data/sparse_dense_list.html
new file mode 100644
index 00000000..095bc739
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_dense_list.html
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_dense_list.md b/vendor/erusev/parsedown/test/data/sparse_dense_list.md
new file mode 100644
index 00000000..57684227
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_dense_list.md
@@ -0,0 +1,4 @@
+- li
+
+- li
+- li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_html.html b/vendor/erusev/parsedown/test/data/sparse_html.html
new file mode 100644
index 00000000..9e896274
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_html.html
@@ -0,0 +1,8 @@
+
+line 1
+
+line 2
+line 3
+
+line 4
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_html.md b/vendor/erusev/parsedown/test/data/sparse_html.md
new file mode 100644
index 00000000..9e896274
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_html.md
@@ -0,0 +1,8 @@
+
+line 1
+
+line 2
+line 3
+
+line 4
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_list.html b/vendor/erusev/parsedown/test/data/sparse_list.html
new file mode 100644
index 00000000..452b2b86
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_list.html
@@ -0,0 +1,15 @@
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/sparse_list.md b/vendor/erusev/parsedown/test/data/sparse_list.md
new file mode 100644
index 00000000..362a35f5
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/sparse_list.md
@@ -0,0 +1,9 @@
+- li
+
+- li
+
+---
+
+- li
+
+ - indented li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/special_characters.html b/vendor/erusev/parsedown/test/data/special_characters.html
new file mode 100644
index 00000000..3b652c33
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/special_characters.html
@@ -0,0 +1,6 @@
+AT&T has an ampersand in their name
+this & that
+4 < 5 and 6 > 5
+http://example.com/autolink?a=1&b=2
+inline link
+reference link
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/special_characters.md b/vendor/erusev/parsedown/test/data/special_characters.md
new file mode 100644
index 00000000..111b03b6
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/special_characters.md
@@ -0,0 +1,13 @@
+AT&T has an ampersand in their name
+
+this & that
+
+4 < 5 and 6 > 5
+
+
+
+[inline link](/script?a=1&b=2)
+
+[reference link][1]
+
+[1]: http://example.com/?a=1&b=2
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/strikethrough.html b/vendor/erusev/parsedown/test/data/strikethrough.html
new file mode 100644
index 00000000..2a9da982
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/strikethrough.html
@@ -0,0 +1,3 @@
+strikethrough
+here's one followed by another one
+~~ this ~~ is not one neither is ~this~
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/strikethrough.md b/vendor/erusev/parsedown/test/data/strikethrough.md
new file mode 100644
index 00000000..d169144d
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/strikethrough.md
@@ -0,0 +1,5 @@
+~~strikethrough~~
+
+here's ~~one~~ followed by ~~another one~~
+
+~~ this ~~ is not one neither is ~this~
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/strong_em.html b/vendor/erusev/parsedown/test/data/strong_em.html
new file mode 100644
index 00000000..b709c991
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/strong_em.html
@@ -0,0 +1,6 @@
+em strong em
+strong em em
+em strong em em
+em strong em
+strong em em
+em strong em em
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/strong_em.md b/vendor/erusev/parsedown/test/data/strong_em.md
new file mode 100644
index 00000000..f2aa3c78
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/strong_em.md
@@ -0,0 +1,11 @@
+*em **strong em***
+
+***strong em** em*
+
+*em **strong em** em*
+
+_em __strong em___
+
+___strong em__ em_
+
+_em __strong em__ em_
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/tab-indented_code_block.html b/vendor/erusev/parsedown/test/data/tab-indented_code_block.html
new file mode 100644
index 00000000..7c140de7
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/tab-indented_code_block.html
@@ -0,0 +1,6 @@
+<?php
+
+$message = 'Hello World!';
+echo $message;
+
+echo "following a blank line";
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/tab-indented_code_block.md b/vendor/erusev/parsedown/test/data/tab-indented_code_block.md
new file mode 100644
index 00000000..a405a160
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/tab-indented_code_block.md
@@ -0,0 +1,6 @@
+
+
+
+header 1 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+
+
+| 2.1 |
+| 2.2 |
+
+
+\| 2.1 |
+link |
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/table_inline_markdown.md b/vendor/erusev/parsedown/test/data/table_inline_markdown.md
new file mode 100644
index 00000000..2f3c6200
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/table_inline_markdown.md
@@ -0,0 +1,5 @@
+| _header_ 1 | header 2 |
+| ------------ | ------------ |
+| _cell_ 1.1 | ~~cell~~ 1.2 |
+| `|` 2.1 | \| 2.2 |
+| `\|` 2.1 | [link](/) |
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/text_reference.html b/vendor/erusev/parsedown/test/data/text_reference.html
new file mode 100644
index 00000000..11e4d37f
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/text_reference.html
@@ -0,0 +1,8 @@
+reference link
+one with a semantic name
+[one][404] with no definition
+multiline
+one defined on 2 lines
+one with a mixed case label and an upper case definition
+one with the a label on the next line
+link
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/text_reference.md b/vendor/erusev/parsedown/test/data/text_reference.md
new file mode 100644
index 00000000..1a66a5cf
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/text_reference.md
@@ -0,0 +1,21 @@
+[reference link][1]
+
+[1]: http://example.com
+
+[one][website] with a semantic name
+
+[website]: http://example.com
+
+[one][404] with no definition
+
+[multiline
+one][website] defined on 2 lines
+
+[one][Label] with a mixed case label and an upper case definition
+
+[LABEL]: http://example.com
+
+[one]
+[1] with the a label on the next line
+
+[`link`][website]
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/unordered_list.html b/vendor/erusev/parsedown/test/data/unordered_list.html
new file mode 100644
index 00000000..cd95567b
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/unordered_list.html
@@ -0,0 +1,10 @@
+
+mixed markers:
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/unordered_list.md b/vendor/erusev/parsedown/test/data/unordered_list.md
new file mode 100644
index 00000000..cf62c99f
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/unordered_list.md
@@ -0,0 +1,8 @@
+- li
+- li
+
+mixed markers:
+
+* li
++ li
+- li
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/untidy_table.html b/vendor/erusev/parsedown/test/data/untidy_table.html
new file mode 100644
index 00000000..88e1c2bd
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/untidy_table.html
@@ -0,0 +1,18 @@
+
+
+
+header 1 |
+header 2 |
+
+
+
+
+cell 1.1 |
+cell 1.2 |
+
+
+cell 2.1 |
+cell 2.2 |
+
+
+
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/untidy_table.md b/vendor/erusev/parsedown/test/data/untidy_table.md
new file mode 100644
index 00000000..8524eb18
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/untidy_table.md
@@ -0,0 +1,4 @@
+| header 1 | header 2 |
+| ------------- | ----------- |
+| cell 1.1 | cell 1.2 |
+| cell 2.1 | cell 2.2 |
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/url_autolinking.html b/vendor/erusev/parsedown/test/data/url_autolinking.html
new file mode 100644
index 00000000..58ca94c6
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/url_autolinking.html
@@ -0,0 +1,3 @@
+an autolink http://example.com
+inside of brackets [http://example.com], inside of braces {http://example.com}, inside of parentheses (http://example.com)
+trailing slash http://example.com/ and http://example.com/path/
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/url_autolinking.md b/vendor/erusev/parsedown/test/data/url_autolinking.md
new file mode 100644
index 00000000..840f3540
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/url_autolinking.md
@@ -0,0 +1,5 @@
+an autolink http://example.com
+
+inside of brackets [http://example.com], inside of braces {http://example.com}, inside of parentheses (http://example.com)
+
+trailing slash http://example.com/ and http://example.com/path/
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/whitespace.html b/vendor/erusev/parsedown/test/data/whitespace.html
new file mode 100644
index 00000000..f2dd7a00
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/whitespace.html
@@ -0,0 +1 @@
+code
\ No newline at end of file
diff --git a/vendor/erusev/parsedown/test/data/whitespace.md b/vendor/erusev/parsedown/test/data/whitespace.md
new file mode 100644
index 00000000..4cf926a8
--- /dev/null
+++ b/vendor/erusev/parsedown/test/data/whitespace.md
@@ -0,0 +1,5 @@
+
+
+ code
+
+
\ No newline at end of file
diff --git a/vendor/fguillot/json-rpc/LICENSE b/vendor/fguillot/json-rpc/LICENSE
new file mode 100644
index 00000000..6a362bc1
--- /dev/null
+++ b/vendor/fguillot/json-rpc/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Frederic Guillot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php
new file mode 100644
index 00000000..fed1ce30
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php
@@ -0,0 +1,194 @@
+httpClient = $httpClient ?: new HttpClient($url);
+ $this->returnException = $returnException;
+ }
+
+ /**
+ * Arguments passed are always positional
+ *
+ * @access public
+ * @return $this
+ */
+ public function withPositionalArguments()
+ {
+ $this->isNamedArguments = false;
+ return $this;
+ }
+
+ /**
+ * Get HTTP Client
+ *
+ * @access public
+ * @return HttpClient
+ */
+ public function getHttpClient()
+ {
+ return $this->httpClient;
+ }
+
+ /**
+ * Set username and password
+ *
+ * @access public
+ * @param string $username
+ * @param string $password
+ * @return $this
+ */
+ public function authentication($username, $password)
+ {
+ $this->httpClient
+ ->withUsername($username)
+ ->withPassword($password);
+
+ return $this;
+ }
+
+ /**
+ * Automatic mapping of procedures
+ *
+ * @access public
+ * @param string $method Procedure name
+ * @param array $params Procedure arguments
+ * @return mixed
+ */
+ public function __call($method, array $params)
+ {
+ if ($this->isNamedArguments && count($params) === 1 && is_array($params[0])) {
+ $params = $params[0];
+ }
+
+ return $this->execute($method, $params);
+ }
+
+ /**
+ * Start a batch request
+ *
+ * @access public
+ * @return Client
+ */
+ public function batch()
+ {
+ $this->isBatch = true;
+ $this->batch = array();
+ return $this;
+ }
+
+ /**
+ * Send a batch request
+ *
+ * @access public
+ * @return array
+ */
+ public function send()
+ {
+ $this->isBatch = false;
+ return $this->sendPayload('['.implode(', ', $this->batch).']');
+ }
+
+ /**
+ * Execute a procedure
+ *
+ * @access public
+ * @param string $procedure Procedure name
+ * @param array $params Procedure arguments
+ * @param array $reqattrs
+ * @return mixed
+ */
+ public function execute($procedure, array $params = array(), array $reqattrs = array())
+ {
+ $payload = RequestBuilder::create()
+ ->withProcedure($procedure)
+ ->withParams($params)
+ ->withRequestAttributes($reqattrs)
+ ->build();
+
+ if ($this->isBatch) {
+ $this->batch[] = $payload;
+ return $this;
+ }
+
+ return $this->sendPayload($payload);
+ }
+
+ /**
+ * Send payload
+ *
+ * @access private
+ * @throws Exception
+ * @param string $payload
+ * @return Exception|Client
+ */
+ private function sendPayload($payload)
+ {
+ return ResponseParser::create()
+ ->withReturnException($this->returnException)
+ ->withPayload($this->httpClient->execute($payload))
+ ->parse();
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php
new file mode 100644
index 00000000..8cb9bc2b
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php
@@ -0,0 +1,15 @@
+setData($data);
+ }
+
+ /**
+ * Attach additional information
+ *
+ * @access public
+ * @param mixed $data [optional] A value that contains additional information about the error.
+ * @return \JsonRPC\Exception\ResponseException
+ */
+ public function setData($data = null)
+ {
+ $this->data = $data;
+ return $this;
+ }
+
+ /**
+ * Get additional information
+ *
+ * @access public
+ * @return mixed|null
+ */
+ public function getData()
+ {
+ return $this->data;
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php
new file mode 100644
index 00000000..ab3ea584
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php
@@ -0,0 +1,15 @@
+',
+ 'Content-Type: application/json',
+ 'Accept: application/json',
+ 'Connection: close',
+ );
+
+ /**
+ * Username for authentication
+ *
+ * @access private
+ * @var string
+ */
+ private $username;
+
+ /**
+ * Password for authentication
+ *
+ * @access private
+ * @var string
+ */
+ private $password;
+
+ /**
+ * Enable debug output to the php error log
+ *
+ * @access private
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * Cookies
+ *
+ * @access private
+ * @var array
+ */
+ private $cookies = array();
+
+ /**
+ * SSL certificates verification
+ *
+ * @access private
+ * @var boolean
+ */
+ private $verifySslCertificate = true;
+
+ /**
+ * Callback called before the doing the request
+ *
+ * @access private
+ * @var Closure
+ */
+ private $beforeRequest;
+
+ /**
+ * HttpClient constructor
+ *
+ * @access public
+ * @param string $url
+ */
+ public function __construct($url = '')
+ {
+ $this->url = $url;
+ }
+
+ /**
+ * Set URL
+ *
+ * @access public
+ * @param string $url
+ * @return $this
+ */
+ public function withUrl($url)
+ {
+ $this->url = $url;
+ return $this;
+ }
+
+ /**
+ * Set username
+ *
+ * @access public
+ * @param string $username
+ * @return $this
+ */
+ public function withUsername($username)
+ {
+ $this->username = $username;
+ return $this;
+ }
+
+ /**
+ * Set password
+ *
+ * @access public
+ * @param string $password
+ * @return $this
+ */
+ public function withPassword($password)
+ {
+ $this->password = $password;
+ return $this;
+ }
+
+ /**
+ * Set timeout
+ *
+ * @access public
+ * @param integer $timeout
+ * @return $this
+ */
+ public function withTimeout($timeout)
+ {
+ $this->timeout = $timeout;
+ return $this;
+ }
+
+ /**
+ * Set timeout
+ *
+ * @access public
+ * @param array $headers
+ * @return $this
+ */
+ public function withHeaders(array $headers)
+ {
+ $this->headers = array_merge($this->headers, $headers);
+ return $this;
+ }
+
+ /**
+ * Set cookies
+ *
+ * @access public
+ * @param array $cookies
+ * @param boolean $replace
+ */
+ public function withCookies(array $cookies, $replace = false)
+ {
+ if ($replace) {
+ $this->cookies = $cookies;
+ } else {
+ $this->cookies = array_merge($this->cookies, $cookies);
+ }
+ }
+
+ /**
+ * Enable debug mode
+ *
+ * @access public
+ * @return $this
+ */
+ public function withDebug()
+ {
+ $this->debug = true;
+ return $this;
+ }
+
+ /**
+ * Disable SSL verification
+ *
+ * @access public
+ * @return $this
+ */
+ public function withoutSslVerification()
+ {
+ $this->verifySslCertificate = false;
+ return $this;
+ }
+
+ /**
+ * Assign a callback before the request
+ *
+ * @access public
+ * @param Closure $closure
+ * @return $this
+ */
+ public function withBeforeRequestCallback(Closure $closure)
+ {
+ $this->beforeRequest = $closure;
+ return $this;
+ }
+
+ /**
+ * Get cookies
+ *
+ * @access public
+ * @return array
+ */
+ public function getCookies()
+ {
+ return $this->cookies;
+ }
+
+ /**
+ * Do the HTTP request
+ *
+ * @access public
+ * @throws ConnectionFailureException
+ * @param string $payload
+ * @return array
+ */
+ public function execute($payload)
+ {
+ if (is_callable($this->beforeRequest)) {
+ call_user_func_array($this->beforeRequest, array($this, $payload));
+ }
+
+ $stream = fopen(trim($this->url), 'r', false, $this->buildContext($payload));
+
+ if (! is_resource($stream)) {
+ throw new ConnectionFailureException('Unable to establish a connection');
+ }
+
+ $metadata = stream_get_meta_data($stream);
+ $headers = $metadata['wrapper_data'];
+ $response = json_decode(stream_get_contents($stream), true);
+
+ if ($this->debug) {
+ error_log('==> Request: '.PHP_EOL.(is_string($payload) ? $payload : json_encode($payload, JSON_PRETTY_PRINT)));
+ error_log('==> Headers: '.PHP_EOL.var_export($headers, true));
+ error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT));
+ }
+
+ $this->handleExceptions($headers);
+ $this->parseCookies($headers);
+
+ return $response;
+ }
+
+ /**
+ * Prepare stream context
+ *
+ * @access private
+ * @param string $payload
+ * @return resource
+ */
+ private function buildContext($payload)
+ {
+ $headers = $this->headers;
+
+ if (! empty($this->username) && ! empty($this->password)) {
+ $headers[] = 'Authorization: Basic '.base64_encode($this->username.':'.$this->password);
+ }
+
+ if (! empty($this->cookies)){
+ $cookies = array();
+
+ foreach ($this->cookies as $key => $value) {
+ $cookies[] = $key.'='.$value;
+ }
+
+ $headers[] = 'Cookie: '.implode('; ', $cookies);
+ }
+
+ return stream_context_create(array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'protocol_version' => 1.1,
+ 'timeout' => $this->timeout,
+ 'max_redirects' => 2,
+ 'header' => implode("\r\n", $headers),
+ 'content' => $payload,
+ 'ignore_errors' => true,
+ ),
+ 'ssl' => array(
+ 'verify_peer' => $this->verifySslCertificate,
+ 'verify_peer_name' => $this->verifySslCertificate,
+ )
+ ));
+ }
+
+ /**
+ * Parse cookies from response
+ *
+ * @access private
+ * @param array $headers
+ */
+ private function parseCookies(array $headers)
+ {
+ foreach ($headers as $header) {
+ $pos = stripos($header, 'Set-Cookie:');
+
+ if ($pos !== false) {
+ $cookies = explode(';', substr($header, $pos + 11));
+
+ foreach ($cookies as $cookie) {
+ $item = explode('=', $cookie);
+
+ if (count($item) === 2) {
+ $name = trim($item[0]);
+ $value = $item[1];
+ $this->cookies[$name] = $value;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Throw an exception according the HTTP response
+ *
+ * @access public
+ * @param array $headers
+ * @throws AccessDeniedException
+ * @throws ServerErrorException
+ */
+ public function handleExceptions(array $headers)
+ {
+ $exceptions = array(
+ '401' => '\JsonRPC\Exception\AccessDeniedException',
+ '403' => '\JsonRPC\Exception\AccessDeniedException',
+ '404' => '\JsonRPC\Exception\ConnectionFailureException',
+ '500' => '\JsonRPC\Exception\ServerErrorException',
+ );
+
+ foreach ($headers as $header) {
+ foreach ($exceptions as $code => $exception) {
+ if (strpos($header, 'HTTP/1.0 '.$code) !== false || strpos($header, 'HTTP/1.1 '.$code) !== false) {
+ throw new $exception('Response: '.$header);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php
new file mode 100644
index 00000000..61d5a2d2
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php
@@ -0,0 +1,114 @@
+username = $username;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set password
+ *
+ * @access public
+ * @param string $password
+ * @return $this
+ */
+ public function withPassword($password)
+ {
+ if (! empty($password)) {
+ $this->password = $password;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set procedure name
+ *
+ * @access public
+ * @param string $procedureName
+ * @return $this
+ */
+ public function withProcedure($procedureName)
+ {
+ $this->procedureName = $procedureName;
+ return $this;
+ }
+
+ /**
+ * Add a new middleware
+ *
+ * @access public
+ * @param MiddlewareInterface $middleware
+ * @return MiddlewareHandler
+ */
+ public function withMiddleware(MiddlewareInterface $middleware)
+ {
+ $this->middleware[] = $middleware;
+ return $this;
+ }
+
+ /**
+ * Execute all middleware
+ *
+ * @access public
+ */
+ public function execute()
+ {
+ foreach ($this->middleware as $middleware) {
+ $middleware->execute($this->username, $this->password, $this->procedureName);
+ }
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php
new file mode 100644
index 00000000..ab55261d
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php
@@ -0,0 +1,27 @@
+callbacks[$procedure] = $callback;
+ return $this;
+ }
+
+ /**
+ * Bind a procedure to a class
+ *
+ * @access public
+ * @param string $procedure Procedure name
+ * @param mixed $class Class name or instance
+ * @param string $method Procedure name
+ * @return $this
+ */
+ public function withClassAndMethod($procedure, $class, $method = '')
+ {
+ if ($method === '') {
+ $method = $procedure;
+ }
+
+ $this->classes[$procedure] = array($class, $method);
+ return $this;
+ }
+
+ /**
+ * Bind a class instance
+ *
+ * @access public
+ * @param mixed $instance
+ * @return $this
+ */
+ public function withObject($instance)
+ {
+ $this->instances[] = $instance;
+ return $this;
+ }
+
+ /**
+ * Set a before method to call
+ *
+ * @access public
+ * @param string $methodName
+ * @return $this
+ */
+ public function withBeforeMethod($methodName)
+ {
+ $this->beforeMethodName = $methodName;
+ return $this;
+ }
+
+ /**
+ * Execute the procedure
+ *
+ * @access public
+ * @param string $procedure Procedure name
+ * @param array $params Procedure params
+ * @return mixed
+ */
+ public function executeProcedure($procedure, array $params = array())
+ {
+ if (isset($this->callbacks[$procedure])) {
+ return $this->executeCallback($this->callbacks[$procedure], $params);
+ } elseif (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) {
+ return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params);
+ }
+
+ foreach ($this->instances as $instance) {
+ if (method_exists($instance, $procedure)) {
+ return $this->executeMethod($instance, $procedure, $params);
+ }
+ }
+
+ throw new BadFunctionCallException('Unable to find the procedure');
+ }
+
+ /**
+ * Execute a callback
+ *
+ * @access public
+ * @param Closure $callback Callback
+ * @param array $params Procedure params
+ * @return mixed
+ */
+ public function executeCallback(Closure $callback, $params)
+ {
+ $reflection = new ReflectionFunction($callback);
+
+ $arguments = $this->getArguments(
+ $params,
+ $reflection->getParameters(),
+ $reflection->getNumberOfRequiredParameters(),
+ $reflection->getNumberOfParameters()
+ );
+
+ return $reflection->invokeArgs($arguments);
+ }
+
+ /**
+ * Execute a method
+ *
+ * @access public
+ * @param mixed $class Class name or instance
+ * @param string $method Method name
+ * @param array $params Procedure params
+ * @return mixed
+ */
+ public function executeMethod($class, $method, $params)
+ {
+ $instance = is_string($class) ? new $class : $class;
+ $reflection = new ReflectionMethod($class, $method);
+
+ $this->executeBeforeMethod($instance, $method);
+
+ $arguments = $this->getArguments(
+ $params,
+ $reflection->getParameters(),
+ $reflection->getNumberOfRequiredParameters(),
+ $reflection->getNumberOfParameters()
+ );
+
+ return $reflection->invokeArgs($instance, $arguments);
+ }
+
+ /**
+ * Execute before method if defined
+ *
+ * @access public
+ * @param mixed $object
+ * @param string $method
+ */
+ public function executeBeforeMethod($object, $method)
+ {
+ if ($this->beforeMethodName !== '' && method_exists($object, $this->beforeMethodName)) {
+ call_user_func_array(array($object, $this->beforeMethodName), array($method));
+ }
+ }
+
+ /**
+ * Get procedure arguments
+ *
+ * @access public
+ * @param array $requestParams Incoming arguments
+ * @param array $methodParams Procedure arguments
+ * @param integer $nbRequiredParams Number of required parameters
+ * @param integer $nbMaxParams Maximum number of parameters
+ * @return array
+ */
+ public function getArguments(array $requestParams, array $methodParams, $nbRequiredParams, $nbMaxParams)
+ {
+ $nbParams = count($requestParams);
+
+ if ($nbParams < $nbRequiredParams) {
+ throw new InvalidArgumentException('Wrong number of arguments');
+ }
+
+ if ($nbParams > $nbMaxParams) {
+ throw new InvalidArgumentException('Too many arguments');
+ }
+
+ if ($this->isPositionalArguments($requestParams)) {
+ return $requestParams;
+ }
+
+ return $this->getNamedArguments($requestParams, $methodParams);
+ }
+
+ /**
+ * Return true if we have positional parameters
+ *
+ * @access public
+ * @param array $request_params Incoming arguments
+ * @return bool
+ */
+ public function isPositionalArguments(array $request_params)
+ {
+ return array_keys($request_params) === range(0, count($request_params) - 1);
+ }
+
+ /**
+ * Get named arguments
+ *
+ * @access public
+ * @param array $requestParams Incoming arguments
+ * @param array $methodParams Procedure arguments
+ * @return array
+ */
+ public function getNamedArguments(array $requestParams, array $methodParams)
+ {
+ $params = array();
+
+ foreach ($methodParams as $p) {
+ $name = $p->getName();
+
+ if (isset($requestParams[$name])) {
+ $params[$name] = $requestParams[$name];
+ } elseif ($p->isDefaultValueAvailable()) {
+ $params[$name] = $p->getDefaultValue();
+ } else {
+ throw new InvalidArgumentException('Missing argument: '.$name);
+ }
+ }
+
+ return $params;
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php
new file mode 100644
index 00000000..c0fc776e
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php
@@ -0,0 +1,55 @@
+payload as $payload) {
+ $responses[] = RequestParser::create()
+ ->withPayload($payload)
+ ->withProcedureHandler($this->procedureHandler)
+ ->withMiddlewareHandler($this->middlewareHandler)
+ ->withLocalException($this->localExceptions)
+ ->parse();
+ }
+
+ $responses = array_filter($responses);
+ return empty($responses) ? '' : '['.implode(',', $responses).']';
+ }
+
+ /**
+ * Return true if we have a batch request
+ *
+ * ex : [
+ * 0 => '...',
+ * 1 => '...',
+ * 2 => '...',
+ * 3 => '...',
+ * ]
+ *
+ * @static
+ * @access public
+ * @param array $payload
+ * @return bool
+ */
+ public static function isBatchRequest(array $payload)
+ {
+ return array_keys($payload) === range(0, count($payload) - 1);
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php
new file mode 100644
index 00000000..145d21c1
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php
@@ -0,0 +1,129 @@
+id = $id;
+ return $this;
+ }
+
+ /**
+ * Set method
+ *
+ * @access public
+ * @param string $procedure
+ * @return RequestBuilder
+ */
+ public function withProcedure($procedure)
+ {
+ $this->procedure = $procedure;
+ return $this;
+ }
+
+ /**
+ * Set parameters
+ *
+ * @access public
+ * @param array $params
+ * @return RequestBuilder
+ */
+ public function withParams(array $params)
+ {
+ $this->params = $params;
+ return $this;
+ }
+
+ /**
+ * Set additional request attributes
+ *
+ * @access public
+ * @param array $reqattrs
+ * @return RequestBuilder
+ */
+ public function withRequestAttributes(array $reqattrs)
+ {
+ $this->reqattrs = $reqattrs;
+ return $this;
+ }
+
+ /**
+ * Build the payload
+ *
+ * @access public
+ * @return string
+ */
+ public function build()
+ {
+ $payload = array_merge_recursive($this->reqattrs, array(
+ 'jsonrpc' => '2.0',
+ 'method' => $this->procedure,
+ 'id' => $this->id ?: mt_rand(),
+ ));
+
+ if (! empty($this->params)) {
+ $payload['params'] = $this->params;
+ }
+
+ return json_encode($payload);
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php
new file mode 100644
index 00000000..ea1b7d43
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php
@@ -0,0 +1,200 @@
+payload = $payload;
+ return $this;
+ }
+
+ /**
+ * Exception classes that should not be relayed to the client
+ *
+ * @access public
+ * @param mixed $exception
+ * @return $this
+ */
+ public function withLocalException($exception)
+ {
+ if (is_array($exception)) {
+ $this->localExceptions = array_merge($this->localExceptions, $exception);
+ } else {
+ $this->localExceptions[] = $exception;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set procedure handler
+ *
+ * @access public
+ * @param ProcedureHandler $procedureHandler
+ * @return $this
+ */
+ public function withProcedureHandler(ProcedureHandler $procedureHandler)
+ {
+ $this->procedureHandler = $procedureHandler;
+ return $this;
+ }
+
+ /**
+ * Set middleware handler
+ *
+ * @access public
+ * @param MiddlewareHandler $middlewareHandler
+ * @return $this
+ */
+ public function withMiddlewareHandler(MiddlewareHandler $middlewareHandler)
+ {
+ $this->middlewareHandler = $middlewareHandler;
+ return $this;
+ }
+
+ /**
+ * Parse incoming request
+ *
+ * @access public
+ * @return string
+ * @throws AccessDeniedException
+ * @throws AuthenticationFailureException
+ */
+ public function parse()
+ {
+ try {
+
+ JsonFormatValidator::validate($this->payload);
+ RpcFormatValidator::validate($this->payload);
+
+ $this->middlewareHandler
+ ->withProcedure($this->payload['method'])
+ ->execute();
+
+ $result = $this->procedureHandler->executeProcedure(
+ $this->payload['method'],
+ empty($this->payload['params']) ? array() : $this->payload['params']
+ );
+
+ if (! $this->isNotification()) {
+ return ResponseBuilder::create()
+ ->withId($this->payload['id'])
+ ->withResult($result)
+ ->build();
+ }
+ } catch (Exception $e) {
+ return $this->handleExceptions($e);
+ }
+
+ return '';
+ }
+
+ /**
+ * Handle exceptions
+ *
+ * @access protected
+ * @param Exception $e
+ * @return string
+ * @throws Exception
+ */
+ protected function handleExceptions(Exception $e)
+ {
+ foreach ($this->localExceptions as $exception) {
+ if ($e instanceof $exception) {
+ throw $e;
+ }
+ }
+
+ if ($e instanceof InvalidJsonRpcFormatException || ! $this->isNotification()) {
+ return ResponseBuilder::create()
+ ->withId(isset($this->payload['id']) ? $this->payload['id'] : null)
+ ->withException($e)
+ ->build();
+ }
+
+ return '';
+ }
+
+ /**
+ * Return true if the message is a notification
+ *
+ * @access protected
+ * @return bool
+ */
+ protected function isNotification()
+ {
+ return is_array($this->payload) && !isset($this->payload['id']);
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php
new file mode 100644
index 00000000..c1caff92
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php
@@ -0,0 +1,324 @@
+ 'application/json',
+ );
+
+ /**
+ * HTTP status
+ *
+ * @access private
+ * @var string
+ */
+ private $status;
+
+ /**
+ * Exception
+ *
+ * @access private
+ * @var ResponseException
+ */
+ private $exception;
+
+ /**
+ * Get new object instance
+ *
+ * @static
+ * @access public
+ * @return ResponseBuilder
+ */
+ public static function create()
+ {
+ return new static();
+ }
+
+ /**
+ * Set id
+ *
+ * @access public
+ * @param mixed $id
+ * @return $this
+ */
+ public function withId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * Set result
+ *
+ * @access public
+ * @param mixed $result
+ * @return $this
+ */
+ public function withResult($result)
+ {
+ $this->result = $result;
+ return $this;
+ }
+
+ /**
+ * Set error
+ *
+ * @access public
+ * @param integer $code
+ * @param string $message
+ * @param string $data
+ * @return $this
+ */
+ public function withError($code, $message, $data = '')
+ {
+ $this->errorCode = $code;
+ $this->errorMessage = $message;
+ $this->errorData = $data;
+ return $this;
+ }
+
+ /**
+ * Set exception
+ *
+ * @access public
+ * @param Exception $exception
+ * @return $this
+ */
+ public function withException(Exception $exception)
+ {
+ $this->exception = $exception;
+ return $this;
+ }
+
+ /**
+ * Add HTTP header
+ *
+ * @access public
+ * @param string $name
+ * @param string $value
+ * @return $this
+ */
+ public function withHeader($name, $value)
+ {
+ $this->headers[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Add HTTP Status
+ *
+ * @access public
+ * @param string $status
+ * @return $this
+ */
+ public function withStatus($status)
+ {
+ $this->status = $status;
+ return $this;
+ }
+
+ /**
+ * Get status
+ *
+ * @access public
+ * @return string
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Get headers
+ *
+ * @access public
+ * @return string[]
+ */
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ /**
+ * Build response
+ *
+ * @access public
+ * @return string
+ */
+ public function build()
+ {
+ $encodedResponse = json_encode($this->buildResponse());
+ JsonEncodingValidator::validate();
+
+ return $encodedResponse;
+ }
+
+ /**
+ * Send HTTP headers
+ *
+ * @access public
+ * @return $this
+ */
+ public function sendHeaders()
+ {
+ if (! empty($this->status)) {
+ header($this->status);
+ }
+
+ foreach ($this->headers as $name => $value) {
+ header($name.': '.$value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Build response payload
+ *
+ * @access private
+ * @return array
+ */
+ private function buildResponse()
+ {
+ $response = array('jsonrpc' => '2.0');
+ $this->handleExceptions();
+
+ if (! empty($this->errorMessage)) {
+ $response['error'] = $this->buildErrorResponse();
+ } else {
+ $response['result'] = $this->result;
+ }
+
+ $response['id'] = $this->id;
+ return $response;
+ }
+
+ /**
+ * Build response error payload
+ *
+ * @access private
+ * @return array
+ */
+ private function buildErrorResponse()
+ {
+ $response = array(
+ 'code' => $this->errorCode,
+ 'message' => $this->errorMessage,
+ );
+
+ if (! empty($this->errorData)) {
+ $response['data'] = $this->errorData;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Transform exceptions to JSON-RPC errors
+ *
+ * @access private
+ */
+ private function handleExceptions()
+ {
+ if ($this->exception instanceof InvalidJsonFormatException) {
+ $this->errorCode = -32700;
+ $this->errorMessage = 'Parse error';
+ $this->id = null;
+ } elseif ($this->exception instanceof InvalidJsonRpcFormatException) {
+ $this->errorCode = -32600;
+ $this->errorMessage = 'Invalid Request';
+ $this->id = null;
+ } elseif ($this->exception instanceof BadFunctionCallException) {
+ $this->errorCode = -32601;
+ $this->errorMessage = 'Method not found';
+ } elseif ($this->exception instanceof InvalidArgumentException) {
+ $this->errorCode = -32602;
+ $this->errorMessage = 'Invalid params';
+ } elseif ($this->exception instanceof ResponseEncodingFailureException) {
+ $this->errorCode = -32603;
+ $this->errorMessage = 'Internal error';
+ $this->errorData = $this->exception->getMessage();
+ } elseif ($this->exception instanceof AuthenticationFailureException) {
+ $this->errorCode = 401;
+ $this->errorMessage = 'Unauthorized';
+ $this->status = 'HTTP/1.0 401 Unauthorized';
+ $this->withHeader('WWW-Authenticate', 'Basic realm="JsonRPC"');
+ } elseif ($this->exception instanceof AccessDeniedException) {
+ $this->errorCode = 403;
+ $this->errorMessage = 'Forbidden';
+ $this->status = 'HTTP/1.0 403 Forbidden';
+ } elseif ($this->exception instanceof ResponseException) {
+ $this->errorCode = $this->exception->getCode();
+ $this->errorMessage = $this->exception->getMessage();
+ $this->errorData = $this->exception->getData();
+ } elseif ($this->exception instanceof Exception) {
+ $this->errorCode = $this->exception->getCode();
+ $this->errorMessage = $this->exception->getMessage();
+ }
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php
new file mode 100644
index 00000000..02d449ba
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php
@@ -0,0 +1,154 @@
+returnException = $returnException;
+ return $this;
+ }
+
+ /**
+ * Set payload
+ *
+ * @access public
+ * @param mixed $payload
+ * @return $this
+ */
+ public function withPayload($payload)
+ {
+ $this->payload = $payload;
+ return $this;
+ }
+
+ /**
+ * Parse response
+ *
+ * @return array|Exception|null
+ * @throws InvalidJsonFormatException
+ * @throws BadFunctionCallException
+ * @throws InvalidJsonRpcFormatException
+ * @throws InvalidArgumentException
+ * @throws Exception
+ * @throws ResponseException
+ */
+ public function parse()
+ {
+ JsonFormatValidator::validate($this->payload);
+
+ if ($this->isBatchResponse()) {
+ $results = array();
+
+ foreach ($this->payload as $response) {
+ $results[] = self::create()
+ ->withReturnException($this->returnException)
+ ->withPayload($response)
+ ->parse();
+ }
+
+ return $results;
+ }
+
+ if (isset($this->payload['error']['code'])) {
+ try {
+ $this->handleExceptions();
+ } catch (Exception $e) {
+ if ($this->returnException) {
+ return $e;
+ }
+ throw $e;
+ }
+ }
+
+ return isset($this->payload['result']) ? $this->payload['result'] : null;
+ }
+
+ /**
+ * Handle exceptions
+ *
+ * @access private
+ * @throws InvalidJsonFormatException
+ * @throws InvalidJsonRpcFormatException
+ * @throws ResponseException
+ */
+ private function handleExceptions()
+ {
+ switch ($this->payload['error']['code']) {
+ case -32700:
+ throw new InvalidJsonFormatException('Parse error: '.$this->payload['error']['message']);
+ case -32600:
+ throw new InvalidJsonRpcFormatException('Invalid Request: '.$this->payload['error']['message']);
+ case -32601:
+ throw new BadFunctionCallException('Procedure not found: '.$this->payload['error']['message']);
+ case -32602:
+ throw new InvalidArgumentException('Invalid arguments: '.$this->payload['error']['message']);
+ default:
+ throw new ResponseException(
+ $this->payload['error']['message'],
+ $this->payload['error']['code'],
+ null,
+ isset($this->payload['error']['data']) ? $this->payload['error']['data'] : null
+ );
+ }
+ }
+
+ /**
+ * Return true if we have a batch response
+ *
+ * @access private
+ * @return boolean
+ */
+ private function isBatchResponse()
+ {
+ return array_keys($this->payload) === range(0, count($this->payload) - 1);
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php
new file mode 100644
index 00000000..1ed075a4
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php
@@ -0,0 +1,386 @@
+payload = json_decode($request, true);
+ } else {
+ $this->payload = json_decode(file_get_contents('php://input'), true);
+ }
+
+ $this->serverVariable = $server ?: $_SERVER;
+ $this->responseBuilder = $responseBuilder ?: ResponseBuilder::create();
+ $this->requestParser = $requestParser ?: RequestParser::create();
+ $this->batchRequestParser = $batchRequestParser ?: BatchRequestParser::create();
+ $this->procedureHandler = $procedureHandler ?: new ProcedureHandler();
+ $this->middlewareHandler = $middlewareHandler ?: new MiddlewareHandler();
+ }
+
+ /**
+ * Define alternative authentication header
+ *
+ * @access public
+ * @param string $header Header name
+ * @return $this
+ */
+ public function setAuthenticationHeader($header)
+ {
+ if (! empty($header)) {
+ $header = 'HTTP_'.str_replace('-', '_', strtoupper($header));
+ $value = $this->getServerVariable($header);
+
+ if (! empty($value)) {
+ list($this->username, $this->password) = explode(':', base64_decode($value));
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get ProcedureHandler
+ *
+ * @access public
+ * @return ProcedureHandler
+ */
+ public function getProcedureHandler()
+ {
+ return $this->procedureHandler;
+ }
+
+ /**
+ * Get MiddlewareHandler
+ *
+ * @access public
+ * @return MiddlewareHandler
+ */
+ public function getMiddlewareHandler()
+ {
+ return $this->middlewareHandler;
+ }
+
+ /**
+ * Get username
+ *
+ * @access public
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->username ?: $this->getServerVariable('PHP_AUTH_USER');
+ }
+
+ /**
+ * Get password
+ *
+ * @access public
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->password ?: $this->getServerVariable('PHP_AUTH_PW');
+ }
+
+ /**
+ * IP based client restrictions
+ *
+ * @access public
+ * @param array $hosts List of hosts
+ * @return $this
+ */
+ public function allowHosts(array $hosts)
+ {
+ $this->hosts = $hosts;
+ return $this;
+ }
+
+ /**
+ * HTTP Basic authentication
+ *
+ * @access public
+ * @param array $users Dictionary of username/password
+ * @return $this
+ */
+ public function authentication(array $users)
+ {
+ $this->users = $users;
+ return $this;
+ }
+
+ /**
+ * Register a new procedure
+ *
+ * @access public
+ * @deprecated Use $server->getProcedureHandler()->withCallback($procedure, $callback)
+ * @param string $procedure Procedure name
+ * @param closure $callback Callback
+ * @return $this
+ */
+ public function register($procedure, Closure $callback)
+ {
+ $this->procedureHandler->withCallback($procedure, $callback);
+ return $this;
+ }
+
+ /**
+ * Bind a procedure to a class
+ *
+ * @access public
+ * @deprecated Use $server->getProcedureHandler()->withClassAndMethod($procedure, $class, $method);
+ * @param string $procedure Procedure name
+ * @param mixed $class Class name or instance
+ * @param string $method Procedure name
+ * @return $this
+ */
+ public function bind($procedure, $class, $method = '')
+ {
+ $this->procedureHandler->withClassAndMethod($procedure, $class, $method);
+ return $this;
+ }
+
+ /**
+ * Bind a class instance
+ *
+ * @access public
+ * @deprecated Use $server->getProcedureHandler()->withObject($instance);
+ * @param mixed $instance Instance name
+ * @return $this
+ */
+ public function attach($instance)
+ {
+ $this->procedureHandler->withObject($instance);
+ return $this;
+ }
+
+ /**
+ * Exception classes that should not be relayed to the client
+ *
+ * @access public
+ * @param Exception|string $exception
+ * @return $this
+ */
+ public function withLocalException($exception)
+ {
+ $this->localExceptions[] = $exception;
+ return $this;
+ }
+
+ /**
+ * Parse incoming requests
+ *
+ * @access public
+ * @return string
+ */
+ public function execute()
+ {
+ try {
+ JsonFormatValidator::validate($this->payload);
+ HostValidator::validate($this->hosts, $this->getServerVariable('REMOTE_ADDR'));
+ UserValidator::validate($this->users, $this->getUsername(), $this->getPassword());
+
+ $this->middlewareHandler
+ ->withUsername($this->getUsername())
+ ->withPassword($this->getPassword())
+ ;
+
+ $response = $this->parseRequest();
+
+ } catch (Exception $e) {
+ $response = $this->handleExceptions($e);
+ }
+
+ $this->responseBuilder->sendHeaders();
+ return $response;
+ }
+
+ /**
+ * Handle exceptions
+ *
+ * @access protected
+ * @param Exception $e
+ * @return string
+ * @throws Exception
+ */
+ protected function handleExceptions(Exception $e)
+ {
+ foreach ($this->localExceptions as $exception) {
+ if ($e instanceof $exception) {
+ throw $e;
+ }
+ }
+
+ return $this->responseBuilder->withException($e)->build();
+ }
+
+ /**
+ * Parse incoming request
+ *
+ * @access protected
+ * @return string
+ */
+ protected function parseRequest()
+ {
+ if (BatchRequestParser::isBatchRequest($this->payload)) {
+ return $this->batchRequestParser
+ ->withPayload($this->payload)
+ ->withProcedureHandler($this->procedureHandler)
+ ->withMiddlewareHandler($this->middlewareHandler)
+ ->withLocalException($this->localExceptions)
+ ->parse();
+ }
+
+ return $this->requestParser
+ ->withPayload($this->payload)
+ ->withProcedureHandler($this->procedureHandler)
+ ->withMiddlewareHandler($this->middlewareHandler)
+ ->withLocalException($this->localExceptions)
+ ->parse();
+ }
+
+ /**
+ * Check existence and get value of server variable
+ *
+ * @access protected
+ * @param string $variable
+ * @return string|null
+ */
+ protected function getServerVariable($variable)
+ {
+ return isset($this->serverVariable[$variable]) ? $this->serverVariable[$variable] : null;
+ }
+}
diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php b/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php
new file mode 100644
index 00000000..7f8c0a04
--- /dev/null
+++ b/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php
@@ -0,0 +1,30 @@
+db = $db;
+ $this->conditionBuilder = $condition;
+ }
+
+ /**
+ * Get object instance
+ *
+ * @static
+ * @access public
+ * @param Database $db
+ * @param ConditionBuilder $condition
+ * @return static
+ */
+ public static function getInstance(Database $db, ConditionBuilder $condition)
+ {
+ return new static($db, $condition);
+ }
+
+ /**
+ * Set table name
+ *
+ * @access public
+ * @param string $table
+ * @return $this
+ */
+ public function withTable($table)
+ {
+ $this->table = $table;
+ return $this;
+ }
+
+ /**
+ * Set columns name
+ *
+ * @access public
+ * @param string[] $columns
+ * @return $this
+ */
+ public function withColumns(array $columns)
+ {
+ $this->columns = $columns;
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php
new file mode 100644
index 00000000..b0465b6e
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php
@@ -0,0 +1,377 @@
+db = $db;
+ }
+
+ /**
+ * Build the SQL condition
+ *
+ * @access public
+ * @return string
+ */
+ public function build()
+ {
+ return empty($this->conditions) ? '' : ' WHERE '.implode(' AND ', $this->conditions);
+ }
+
+ /**
+ * Get condition values
+ *
+ * @access public
+ * @return array
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Returns true if there is some conditions
+ *
+ * @access public
+ * @return boolean
+ */
+ public function hasCondition()
+ {
+ return ! empty($this->conditions);
+ }
+
+ /**
+ * Add custom condition
+ *
+ * @access public
+ * @param string $sql
+ */
+ public function addCondition($sql)
+ {
+ if ($this->orConditionOffset > 0) {
+ $this->orConditions[$this->orConditionOffset]->withCondition($sql);
+ }
+ else {
+ $this->conditions[] = $sql;
+ }
+ }
+
+ /**
+ * Start OR condition
+ *
+ * @access public
+ */
+ public function beginOr()
+ {
+ $this->orConditionOffset++;
+ $this->orConditions[$this->orConditionOffset] = new OrConditionBuilder();
+ }
+
+ /**
+ * Close OR condition
+ *
+ * @access public
+ */
+ public function closeOr()
+ {
+ $condition = $this->orConditions[$this->orConditionOffset]->build();
+ $this->orConditionOffset--;
+
+ if ($this->orConditionOffset > 0) {
+ $this->orConditions[$this->orConditionOffset]->withCondition($condition);
+ } else {
+ $this->conditions[] = $condition;
+ }
+ }
+
+ /**
+ * Equal condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function eq($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' = ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Not equal condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function neq($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' != ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * IN condition
+ *
+ * @access public
+ * @param string $column
+ * @param array $values
+ */
+ public function in($column, array $values)
+ {
+ if (! empty($values)) {
+ $this->addCondition($this->db->escapeIdentifier($column).' IN ('.implode(', ', array_fill(0, count($values), '?')).')');
+ $this->values = array_merge($this->values, $values);
+ }
+ }
+
+ /**
+ * IN condition with a subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function inSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' IN ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * NOT IN condition
+ *
+ * @access public
+ * @param string $column
+ * @param array $values
+ */
+ public function notIn($column, array $values)
+ {
+ if (! empty($values)) {
+ $this->addCondition($this->db->escapeIdentifier($column).' NOT IN ('.implode(', ', array_fill(0, count($values), '?')).')');
+ $this->values = array_merge($this->values, $values);
+ }
+ }
+
+ /**
+ * NOT IN condition with a subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function notInSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' NOT IN ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * LIKE condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function like($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' '.$this->db->getDriver()->getOperator('LIKE').' ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * ILIKE condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function ilike($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' '.$this->db->getDriver()->getOperator('ILIKE').' ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Greater than condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function gt($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' > ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Greater than condition with subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function gtSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' > ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * Lower than condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function lt($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' < ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Lower than condition with subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function ltSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' < ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * Greater than or equals condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function gte($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' >= ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Greater than or equal condition with subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function gteSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' >= ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * Lower than or equals condition
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ */
+ public function lte($column, $value)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' <= ?');
+ $this->values[] = $value;
+ }
+
+ /**
+ * Lower than or equal condition with subquery
+ *
+ * @access public
+ * @param string $column
+ * @param Table $subquery
+ */
+ public function lteSubquery($column, Table $subquery)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' <= ('.$subquery->buildSelectQuery().')');
+ $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues());
+ }
+
+ /**
+ * IS NULL condition
+ *
+ * @access public
+ * @param string $column
+ */
+ public function isNull($column)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' IS NULL');
+ }
+
+ /**
+ * IS NOT NULL condition
+ *
+ * @access public
+ * @param string $column
+ */
+ public function notNull($column)
+ {
+ $this->addCondition($this->db->escapeIdentifier($column).' IS NOT NULL');
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php
new file mode 100644
index 00000000..9d06c405
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php
@@ -0,0 +1,36 @@
+columns as $column) {
+ $columns[] = $this->db->escapeIdentifier($column);
+ $placeholders[] = ':'.$column;
+ }
+
+ return sprintf(
+ 'INSERT INTO %s (%s) VALUES (%s)',
+ $this->db->escapeIdentifier($this->table),
+ implode(', ', $columns),
+ implode(', ', $placeholders)
+ );
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php
new file mode 100644
index 00000000..0defeaf4
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php
@@ -0,0 +1,43 @@
+conditions[] = $condition;
+ return $this;
+ }
+
+ /**
+ * Build SQL
+ *
+ * @access public
+ * @return string
+ */
+ public function build()
+ {
+ return '('.implode(' OR ', $this->conditions).')';
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php
new file mode 100644
index 00000000..300ea9b0
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php
@@ -0,0 +1,56 @@
+sumColumns = $columns;
+ return $this;
+ }
+
+ /**
+ * Build SQL
+ *
+ * @access public
+ * @return string
+ */
+ public function build()
+ {
+ $columns = array();
+
+ foreach ($this->columns as $column) {
+ $columns[] = $this->db->escapeIdentifier($column).'=?';
+ }
+
+ foreach ($this->sumColumns as $column) {
+ $columns[] = $this->db->escapeIdentifier($column).'='.$this->db->escapeIdentifier($column).' + ?';
+ }
+
+ return sprintf(
+ 'UPDATE %s SET %s %s',
+ $this->db->escapeIdentifier($this->table),
+ implode(', ', $columns),
+ $this->conditionBuilder->build()
+ );
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Database.php b/vendor/fguillot/picodb/lib/PicoDb/Database.php
new file mode 100644
index 00000000..22c9d2fb
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Database.php
@@ -0,0 +1,370 @@
+driver = DriverFactory::getDriver($settings);
+ $this->statementHandler = new StatementHandler($this);
+ }
+
+ /**
+ * Destructor
+ *
+ * @access public
+ */
+ public function __destruct()
+ {
+ $this->closeConnection();
+ }
+
+ /**
+ * Register a new database instance
+ *
+ * @static
+ * @access public
+ * @param string $name Instance name
+ * @param Closure $callback Callback
+ */
+ public static function setInstance($name, Closure $callback)
+ {
+ self::$instances[$name] = $callback;
+ }
+
+ /**
+ * Get a database instance
+ *
+ * @static
+ * @access public
+ * @param string $name Instance name
+ * @return Database
+ */
+ public static function getInstance($name)
+ {
+ if (! isset(self::$instances[$name])) {
+ throw new LogicException('No database instance created with that name');
+ }
+
+ if (is_callable(self::$instances[$name])) {
+ self::$instances[$name] = call_user_func(self::$instances[$name]);
+ }
+
+ return self::$instances[$name];
+ }
+
+ /**
+ * Add a log message
+ *
+ * @access public
+ * @param mixed $message
+ * @return Database
+ */
+ public function setLogMessage($message)
+ {
+ $this->logs[] = is_array($message) ? var_export($message, true) : $message;
+ return $this;
+ }
+
+ /**
+ * Add many log messages
+ *
+ * @access public
+ * @param array $messages
+ * @return Database
+ */
+ public function setLogMessages(array $messages)
+ {
+ foreach ($messages as $message) {
+ $this->setLogMessage($message);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get all queries logs
+ *
+ * @access public
+ * @return array
+ */
+ public function getLogMessages()
+ {
+ return $this->logs;
+ }
+
+ /**
+ * Get the PDO connection
+ *
+ * @access public
+ * @return \PDO
+ */
+ public function getConnection()
+ {
+ return $this->driver->getConnection();
+ }
+
+ /**
+ * Get the Driver instance
+ *
+ * @access public
+ * @return Mssql|Sqlite|Postgres|Mysql
+ */
+ public function getDriver()
+ {
+ return $this->driver;
+ }
+
+ /**
+ * Get the last inserted id
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLastId()
+ {
+ return (int) $this->driver->getLastId();
+ }
+
+ /**
+ * Get statement object
+ *
+ * @access public
+ * @return StatementHandler
+ */
+ public function getStatementHandler()
+ {
+ return $this->statementHandler;
+ }
+
+ /**
+ * Release the PDO connection
+ *
+ * @access public
+ */
+ public function closeConnection()
+ {
+ $this->driver->closeConnection();
+ }
+
+ /**
+ * Escape an identifier (column, table name...)
+ *
+ * @access public
+ * @param string $value Value
+ * @param string $table Table name
+ * @return string
+ */
+ public function escapeIdentifier($value, $table = '')
+ {
+ // Do not escape custom query
+ if (strpos($value, '.') !== false || strpos($value, ' ') !== false) {
+ return $value;
+ }
+
+ if (! empty($table)) {
+ return $this->driver->escape($table).'.'.$this->driver->escape($value);
+ }
+
+ return $this->driver->escape($value);
+ }
+
+ /**
+ * Escape an identifier list
+ *
+ * @access public
+ * @param array $identifiers List of identifiers
+ * @param string $table Table name
+ * @return string[]
+ */
+ public function escapeIdentifierList(array $identifiers, $table = '')
+ {
+ foreach ($identifiers as $key => $value) {
+ $identifiers[$key] = $this->escapeIdentifier($value, $table);
+ }
+
+ return $identifiers;
+ }
+
+ /**
+ * Execute a prepared statement
+ *
+ * Note: returns false on duplicate keys instead of SQLException
+ *
+ * @access public
+ * @param string $sql SQL query
+ * @param array $values Values
+ * @return \PDOStatement|false
+ */
+ public function execute($sql, array $values = array())
+ {
+ return $this->statementHandler
+ ->withSql($sql)
+ ->withPositionalParams($values)
+ ->execute();
+ }
+
+ /**
+ * Run a transaction
+ *
+ * @access public
+ * @param Closure $callback Callback
+ * @return mixed
+ */
+ public function transaction(Closure $callback)
+ {
+ try {
+
+ $this->startTransaction();
+ $result = $callback($this);
+ $this->closeTransaction();
+
+ return $result === null ? true : $result;
+ } catch (PDOException $e) {
+ return $this->statementHandler->handleSqlError($e);
+ }
+ }
+
+ /**
+ * Begin a transaction
+ *
+ * @access public
+ */
+ public function startTransaction()
+ {
+ if (! $this->getConnection()->inTransaction()) {
+ $this->getConnection()->beginTransaction();
+ }
+ }
+
+ /**
+ * Commit a transaction
+ *
+ * @access public
+ */
+ public function closeTransaction()
+ {
+ if ($this->getConnection()->inTransaction()) {
+ $this->getConnection()->commit();
+ }
+ }
+
+ /**
+ * Rollback a transaction
+ *
+ * @access public
+ */
+ public function cancelTransaction()
+ {
+ if ($this->getConnection()->inTransaction()) {
+ $this->getConnection()->rollBack();
+ }
+ }
+
+ /**
+ * Get a table object
+ *
+ * @access public
+ * @param string $table
+ * @return Table
+ */
+ public function table($table)
+ {
+ return new Table($this, $table);
+ }
+
+ /**
+ * Get a hashtable object
+ *
+ * @access public
+ * @param string $table
+ * @return Hashtable
+ */
+ public function hashtable($table)
+ {
+ return new Hashtable($this, $table);
+ }
+
+ /**
+ * Get a LOB object
+ *
+ * @access public
+ * @param string $table
+ * @return LargeObject
+ */
+ public function largeObject($table)
+ {
+ return new LargeObject($this, $table);
+ }
+
+ /**
+ * Get a schema object
+ *
+ * @access public
+ * @param string $namespace
+ * @return Schema
+ */
+ public function schema($namespace = null)
+ {
+ $schema = new Schema($this);
+
+ if ($namespace !== null) {
+ $schema->setNamespace($namespace);
+ }
+
+ return $schema;
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php
new file mode 100644
index 00000000..790cd623
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php
@@ -0,0 +1,234 @@
+requiredAttributes as $attribute) {
+ if (! isset($settings[$attribute])) {
+ throw new LogicException('This configuration parameter is missing: "'.$attribute.'"');
+ }
+ }
+
+ $this->createConnection($settings);
+ $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ }
+
+ /**
+ * Get the PDO connection
+ *
+ * @access public
+ * @return PDO
+ */
+ public function getConnection()
+ {
+ return $this->pdo;
+ }
+
+ /**
+ * Release the PDO connection
+ *
+ * @access public
+ */
+ public function closeConnection()
+ {
+ $this->pdo = null;
+ }
+
+ /**
+ * Upsert for a key/value variable
+ *
+ * @access public
+ * @param string $table
+ * @param string $keyColumn
+ * @param string $valueColumn
+ * @param array $dictionary
+ * @return bool False on failure
+ */
+ public function upsert($table, $keyColumn, $valueColumn, array $dictionary)
+ {
+ try {
+ $this->pdo->beginTransaction();
+
+ foreach ($dictionary as $key => $value) {
+
+ $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->escape($table).' WHERE '.$this->escape($keyColumn).'=?');
+ $rq->execute(array($key));
+
+ if ($rq->fetchColumn()) {
+ $rq = $this->pdo->prepare('UPDATE '.$this->escape($table).' SET '.$this->escape($valueColumn).'=? WHERE '.$this->escape($keyColumn).'=?');
+ $rq->execute(array($value, $key));
+ }
+ else {
+ $rq = $this->pdo->prepare('INSERT INTO '.$this->escape($table).' ('.$this->escape($keyColumn).', '.$this->escape($valueColumn).') VALUES (?, ?)');
+ $rq->execute(array($key, $value));
+ }
+ }
+
+ $this->pdo->commit();
+
+ return true;
+ }
+ catch (PDOException $e) {
+ $this->pdo->rollBack();
+ return false;
+ }
+ }
+
+ /**
+ * Run EXPLAIN command
+ *
+ * @access public
+ * @param string $sql
+ * @param array $values
+ * @return array
+ */
+ public function explain($sql, array $values)
+ {
+ return $this->getConnection()->query('EXPLAIN '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ /**
+ * Replace placeholder with values in prepared statement
+ *
+ * @access protected
+ * @param string $sql
+ * @param array $values
+ * @return string
+ */
+ protected function getSqlFromPreparedStatement($sql, array $values)
+ {
+ foreach ($values as $value) {
+ $sql = substr_replace($sql, "'$value'", strpos($sql, '?'), 1);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * Get database version
+ *
+ * @access public
+ * @return array
+ */
+ public function getDatabaseVersion()
+ {
+ return $this->getConnection()->query('SELECT VERSION()')->fetchColumn();
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php
new file mode 100644
index 00000000..83e75af2
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php
@@ -0,0 +1,178 @@
+
+ */
+class Mssql extends Base
+{
+ /**
+ * List of required settings options
+ *
+ * @access protected
+ * @var array
+ */
+ protected $requiredAttributes = array(
+ 'hostname',
+ 'username',
+ 'password',
+ 'database',
+ );
+
+ /**
+ * Table to store the schema version
+ *
+ * @access private
+ * @var array
+ */
+ private $schemaTable = 'schema_version';
+
+ /**
+ * Create a new PDO connection
+ *
+ * @access public
+ * @param array $settings
+ */
+ public function createConnection(array $settings)
+ {
+ $dsn = 'sqlsrv:Server=' . $settings['hostname'] . ';Database=' . $settings['database'];
+
+ if (! empty($settings['port'])) {
+ $dsn .= ';port=' . $settings['port'];
+ }
+
+ $this->pdo = new PDO($dsn, $settings['username'], $settings['password']);
+
+ if (isset($settings['schema_table'])) {
+ $this->schemaTable = $settings['schema_table'];
+ }
+ }
+
+ /**
+ * Enable foreign keys
+ *
+ * @access public
+ */
+ public function enableForeignKeys()
+ {
+ $this->pdo->exec('EXEC sp_MSforeachtable @command1="ALTER TABLE ? CHECK CONSTRAINT ALL"; GO;');
+ }
+
+ /**
+ * Disable foreign keys
+ *
+ * @access public
+ */
+ public function disableForeignKeys()
+ {
+ $this->pdo->exec('EXEC sp_MSforeachtable @command1="ALTER TABLE ? NOCHECK CONSTRAINT ALL"; GO;');
+ }
+
+ /**
+ * Return true if the error code is a duplicate key
+ *
+ * @access public
+ * @param integer $code
+ * @return boolean
+ */
+ public function isDuplicateKeyError($code)
+ {
+ return $code == 2601;
+ }
+
+ /**
+ * Escape identifier
+ *
+ * https://msdn.microsoft.com/en-us/library/ms175874.aspx
+ *
+ * @access public
+ * @param string $identifier
+ * @return string
+ */
+ public function escape($identifier)
+ {
+ return '['.$identifier.']';
+ }
+
+ /**
+ * Get non standard operator
+ *
+ * @access public
+ * @param string $operator
+ * @return string
+ */
+ public function getOperator($operator)
+ {
+ if ($operator === 'LIKE' || $operator === 'ILIKE') {
+ return 'LIKE';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get last inserted id
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLastId()
+ {
+ return $this->pdo->lastInsertId();
+ }
+
+ /**
+ * Get current schema version
+ *
+ * @access public
+ * @return integer
+ */
+ public function getSchemaVersion()
+ {
+ $this->pdo->exec("CREATE TABLE IF NOT EXISTS [".$this->schemaTable."] ([version] INT DEFAULT '0')");
+
+ $rq = $this->pdo->prepare('SELECT [version] FROM ['.$this->schemaTable.']');
+ $rq->execute();
+ $result = $rq->fetchColumn();
+
+ if ($result !== false) {
+ return (int) $result;
+ }
+ else {
+ $this->pdo->exec('INSERT INTO ['.$this->schemaTable.'] VALUES(0)');
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set current schema version
+ *
+ * @access public
+ * @param integer $version
+ */
+ public function setSchemaVersion($version)
+ {
+ $rq = $this->pdo->prepare('UPDATE ['.$this->schemaTable.'] SET [version]=?');
+ $rq->execute(array($version));
+ }
+
+ /**
+ * Run EXPLAIN command
+ *
+ * @param string $sql
+ * @param array $values
+ * @return array
+ */
+ public function explain($sql, array $values)
+ {
+ $this->getConnection()->exec('SET SHOWPLAN_ALL ON');
+ return $this->getConnection()->query($this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC);
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php
new file mode 100644
index 00000000..4f3ca64e
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php
@@ -0,0 +1,252 @@
+pdo = new PDO(
+ $this->buildDsn($settings),
+ $settings['username'],
+ $settings['password'],
+ $this->buildOptions($settings)
+ );
+
+ if (isset($settings['schema_table'])) {
+ $this->schemaTable = $settings['schema_table'];
+ }
+ }
+
+ /**
+ * Build connection DSN
+ *
+ * @access protected
+ * @param array $settings
+ * @return string
+ */
+ protected function buildDsn(array $settings)
+ {
+ $charset = empty($settings['charset']) ? 'utf8' : $settings['charset'];
+ $dsn = 'mysql:host='.$settings['hostname'].';dbname='.$settings['database'].';charset='.$charset;
+
+ if (! empty($settings['port'])) {
+ $dsn .= ';port='.$settings['port'];
+ }
+
+ return $dsn;
+ }
+
+ /**
+ * Build connection options
+ *
+ * @access protected
+ * @param array $settings
+ * @return array
+ */
+ protected function buildOptions(array $settings)
+ {
+ $options = array(
+ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode = STRICT_ALL_TABLES',
+ );
+
+ if (! empty($settings['ssl_key'])) {
+ $options[PDO::MYSQL_ATTR_SSL_KEY] = $settings['ssl_key'];
+ }
+
+ if (! empty($settings['ssl_cert'])) {
+ $options[PDO::MYSQL_ATTR_SSL_CERT] = $settings['ssl_cert'];
+ }
+
+ if (! empty($settings['ssl_ca'])) {
+ $options[PDO::MYSQL_ATTR_SSL_CA] = $settings['ssl_ca'];
+ }
+
+ return $options;
+ }
+
+ /**
+ * Enable foreign keys
+ *
+ * @access public
+ */
+ public function enableForeignKeys()
+ {
+ $this->pdo->exec('SET FOREIGN_KEY_CHECKS=1');
+ }
+
+ /**
+ * Disable foreign keys
+ *
+ * @access public
+ */
+ public function disableForeignKeys()
+ {
+ $this->pdo->exec('SET FOREIGN_KEY_CHECKS=0');
+ }
+
+ /**
+ * Return true if the error code is a duplicate key
+ *
+ * @access public
+ * @param integer $code
+ * @return boolean
+ */
+ public function isDuplicateKeyError($code)
+ {
+ return $code == 23000;
+ }
+
+ /**
+ * Escape identifier
+ *
+ * @access public
+ * @param string $identifier
+ * @return string
+ */
+ public function escape($identifier)
+ {
+ return '`'.$identifier.'`';
+ }
+
+ /**
+ * Get non standard operator
+ *
+ * @access public
+ * @param string $operator
+ * @return string
+ */
+ public function getOperator($operator)
+ {
+ if ($operator === 'LIKE') {
+ return 'LIKE BINARY';
+ }
+ else if ($operator === 'ILIKE') {
+ return 'LIKE';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get last inserted id
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLastId()
+ {
+ return $this->pdo->lastInsertId();
+ }
+
+ /**
+ * Get current schema version
+ *
+ * @access public
+ * @return integer
+ */
+ public function getSchemaVersion()
+ {
+ $this->pdo->exec("CREATE TABLE IF NOT EXISTS `".$this->schemaTable."` (`version` INT DEFAULT '0') ENGINE=InnoDB CHARSET=utf8");
+
+ $rq = $this->pdo->prepare('SELECT `version` FROM `'.$this->schemaTable.'`');
+ $rq->execute();
+ $result = $rq->fetchColumn();
+
+ if ($result !== false) {
+ return (int) $result;
+ }
+ else {
+ $this->pdo->exec('INSERT INTO `'.$this->schemaTable.'` VALUES(0)');
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set current schema version
+ *
+ * @access public
+ * @param integer $version
+ */
+ public function setSchemaVersion($version)
+ {
+ $rq = $this->pdo->prepare('UPDATE `'.$this->schemaTable.'` SET `version`=?');
+ $rq->execute(array($version));
+ }
+
+ /**
+ * Upsert for a key/value variable
+ *
+ * @access public
+ * @param string $table
+ * @param string $keyColumn
+ * @param string $valueColumn
+ * @param array $dictionary
+ * @return bool False on failure
+ */
+ public function upsert($table, $keyColumn, $valueColumn, array $dictionary)
+ {
+ try {
+
+ $sql = sprintf(
+ 'REPLACE INTO %s (%s, %s) VALUES %s',
+ $this->escape($table),
+ $this->escape($keyColumn),
+ $this->escape($valueColumn),
+ implode(', ', array_fill(0, count($dictionary), '(?, ?)'))
+ );
+
+ $values = array();
+
+ foreach ($dictionary as $key => $value) {
+ $values[] = $key;
+ $values[] = $value;
+ }
+
+ $rq = $this->pdo->prepare($sql);
+ $rq->execute($values);
+
+ return true;
+ }
+ catch (PDOException $e) {
+ return false;
+ }
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php
new file mode 100644
index 00000000..a494cdca
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php
@@ -0,0 +1,196 @@
+pdo = new PDO($dsn, $settings['username'], $settings['password']);
+
+ if (isset($settings['schema_table'])) {
+ $this->schemaTable = $settings['schema_table'];
+ }
+ }
+
+ /**
+ * Enable foreign keys
+ *
+ * @access public
+ */
+ public function enableForeignKeys()
+ {
+ }
+
+ /**
+ * Disable foreign keys
+ *
+ * @access public
+ */
+ public function disableForeignKeys()
+ {
+ }
+
+ /**
+ * Return true if the error code is a duplicate key
+ *
+ * @access public
+ * @param integer $code
+ * @return boolean
+ */
+ public function isDuplicateKeyError($code)
+ {
+ return $code == 23505 || $code == 23503;
+ }
+
+ /**
+ * Escape identifier
+ *
+ * @access public
+ * @param string $identifier
+ * @return string
+ */
+ public function escape($identifier)
+ {
+ return '"'.$identifier.'"';
+ }
+
+ /**
+ * Get non standard operator
+ *
+ * @access public
+ * @param string $operator
+ * @return string
+ */
+ public function getOperator($operator)
+ {
+ if ($operator === 'LIKE') {
+ return 'LIKE';
+ }
+ else if ($operator === 'ILIKE') {
+ return 'ILIKE';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get last inserted id
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLastId()
+ {
+ try {
+ $rq = $this->pdo->prepare('SELECT LASTVAL()');
+ $rq->execute();
+
+ return $rq->fetchColumn();
+ }
+ catch (PDOException $e) {
+ return 0;
+ }
+ }
+
+ /**
+ * Get current schema version
+ *
+ * @access public
+ * @return integer
+ */
+ public function getSchemaVersion()
+ {
+ $this->pdo->exec("CREATE TABLE IF NOT EXISTS ".$this->schemaTable." (version INTEGER DEFAULT 0)");
+
+ $rq = $this->pdo->prepare('SELECT "version" FROM "'.$this->schemaTable.'"');
+ $rq->execute();
+ $result = $rq->fetchColumn();
+
+ if ($result !== false) {
+ return (int) $result;
+ }
+ else {
+ $this->pdo->exec('INSERT INTO '.$this->schemaTable.' VALUES(0)');
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set current schema version
+ *
+ * @access public
+ * @param integer $version
+ */
+ public function setSchemaVersion($version)
+ {
+ $rq = $this->pdo->prepare('UPDATE '.$this->schemaTable.' SET version=?');
+ $rq->execute(array($version));
+ }
+
+ /**
+ * Run EXPLAIN command
+ *
+ * @param string $sql
+ * @param array $values
+ * @return array
+ */
+ public function explain($sql, array $values)
+ {
+ return $this->getConnection()->query('EXPLAIN (FORMAT YAML) '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ /**
+ * Get database version
+ *
+ * @access public
+ * @return array
+ */
+ public function getDatabaseVersion()
+ {
+ return $this->getConnection()->query('SHOW server_version')->fetchColumn();
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php
new file mode 100644
index 00000000..ea39f007
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php
@@ -0,0 +1,193 @@
+pdo = new PDO('sqlite:'.$settings['filename']);
+ $this->enableForeignKeys();
+ }
+
+ /**
+ * Enable foreign keys
+ *
+ * @access public
+ */
+ public function enableForeignKeys()
+ {
+ $this->pdo->exec('PRAGMA foreign_keys = ON');
+ }
+
+ /**
+ * Disable foreign keys
+ *
+ * @access public
+ */
+ public function disableForeignKeys()
+ {
+ $this->pdo->exec('PRAGMA foreign_keys = OFF');
+ }
+
+ /**
+ * Return true if the error code is a duplicate key
+ *
+ * @access public
+ * @param integer $code
+ * @return boolean
+ */
+ public function isDuplicateKeyError($code)
+ {
+ return $code == 23000;
+ }
+
+ /**
+ * Escape identifier
+ *
+ * @access public
+ * @param string $identifier
+ * @return string
+ */
+ public function escape($identifier)
+ {
+ return '"'.$identifier.'"';
+ }
+
+ /**
+ * Get non standard operator
+ *
+ * @access public
+ * @param string $operator
+ * @return string
+ */
+ public function getOperator($operator)
+ {
+ if ($operator === 'LIKE' || $operator === 'ILIKE') {
+ return 'LIKE';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get last inserted id
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLastId()
+ {
+ return $this->pdo->lastInsertId();
+ }
+
+ /**
+ * Get current schema version
+ *
+ * @access public
+ * @return integer
+ */
+ public function getSchemaVersion()
+ {
+ $rq = $this->pdo->prepare('PRAGMA user_version');
+ $rq->execute();
+
+ return (int) $rq->fetchColumn();
+ }
+
+ /**
+ * Set current schema version
+ *
+ * @access public
+ * @param integer $version
+ */
+ public function setSchemaVersion($version)
+ {
+ $this->pdo->exec('PRAGMA user_version='.$version);
+ }
+
+ /**
+ * Upsert for a key/value variable
+ *
+ * @access public
+ * @param string $table
+ * @param string $keyColumn
+ * @param string $valueColumn
+ * @param array $dictionary
+ * @return bool False on failure
+ */
+ public function upsert($table, $keyColumn, $valueColumn, array $dictionary)
+ {
+ try {
+ $this->pdo->beginTransaction();
+
+ foreach ($dictionary as $key => $value) {
+
+ $sql = sprintf(
+ 'INSERT OR REPLACE INTO %s (%s, %s) VALUES (?, ?)',
+ $this->escape($table),
+ $this->escape($keyColumn),
+ $this->escape($valueColumn)
+ );
+
+ $rq = $this->pdo->prepare($sql);
+ $rq->execute(array($key, $value));
+ }
+
+ $this->pdo->commit();
+
+ return true;
+ }
+ catch (PDOException $e) {
+ $this->pdo->rollBack();
+ return false;
+ }
+ }
+
+ /**
+ * Run EXPLAIN command
+ *
+ * @access public
+ * @param string $sql
+ * @param array $values
+ * @return array
+ */
+ public function explain($sql, array $values)
+ {
+ return $this->getConnection()->query('EXPLAIN QUERY PLAN '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ /**
+ * Get database version
+ *
+ * @access public
+ * @return array
+ */
+ public function getDatabaseVersion()
+ {
+ return $this->getConnection()->query('SELECT sqlite_version()')->fetchColumn();
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php b/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php
new file mode 100644
index 00000000..13151ba7
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php
@@ -0,0 +1,45 @@
+keyColumn = $column;
+ return $this;
+ }
+
+ /**
+ * Set the value column
+ *
+ * @access public
+ * @param string $column
+ * @return $this
+ */
+ public function columnValue($column)
+ {
+ $this->valueColumn = $column;
+ return $this;
+ }
+
+ /**
+ * Insert or update
+ *
+ * @access public
+ * @param array $hashmap
+ * @return boolean
+ */
+ public function put(array $hashmap)
+ {
+ return $this->db->getDriver()->upsert($this->getName(), $this->keyColumn, $this->valueColumn, $hashmap);
+ }
+
+ /**
+ * Hashmap result [ [column1 => column2], [], ...]
+ *
+ * @access public
+ * @return array
+ */
+ public function get()
+ {
+ $hashmap = array();
+
+ // setup where condition
+ if (func_num_args() > 0) {
+ $this->in($this->keyColumn, func_get_args());
+ }
+
+ // setup to select columns in case that there are more than two
+ $this->columns($this->keyColumn, $this->valueColumn);
+
+ $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues());
+ $rows = $rq->fetchAll(PDO::FETCH_NUM);
+
+ foreach ($rows as $row) {
+ $hashmap[$row[0]] = $row[1];
+ }
+
+ return $hashmap;
+ }
+
+ /**
+ * Shortcut method to get a hashmap result
+ *
+ * @access public
+ * @param string $key Key column
+ * @param string $value Value column
+ * @return array
+ */
+ public function getAll($key, $value)
+ {
+ $this->keyColumn = $key;
+ $this->valueColumn = $value;
+ return $this->get();
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php b/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php
new file mode 100644
index 00000000..ba5e3b92
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php
@@ -0,0 +1,167 @@
+limit(1);
+ $this->columns($column);
+
+ $rq = $this->db->getStatementHandler()
+ ->withSql($this->buildSelectQuery())
+ ->withPositionalParams($this->conditionBuilder->getValues())
+ ->execute();
+
+ $rq->bindColumn($column, $fd, PDO::PARAM_LOB);
+ $rq->fetch(PDO::FETCH_BOUND);
+
+ return $fd;
+ }
+
+ /**
+ * Fetch large object as string
+ *
+ * @access public
+ * @param string $column
+ * @return string
+ */
+ public function findOneColumnAsString($column)
+ {
+ $fd = $this->findOneColumnAsStream($column);
+
+ if (is_string($fd)) {
+ return $fd;
+ }
+
+ return stream_get_contents($fd);
+ }
+
+ /**
+ * Insert large object from stream
+ *
+ * @access public
+ * @param string $blobColumn
+ * @param resource|string $blobDescriptor
+ * @param array $data
+ * @return bool
+ */
+ public function insertFromStream($blobColumn, &$blobDescriptor, array $data = array())
+ {
+ $columns = array_merge(array($blobColumn), array_keys($data));
+ $this->db->startTransaction();
+
+ $result = $this->db->getStatementHandler()
+ ->withSql(InsertBuilder::getInstance($this->db, $this->conditionBuilder)
+ ->withTable($this->name)
+ ->withColumns($columns)
+ ->build()
+ )
+ ->withNamedParams($data)
+ ->withLobParam($blobColumn, $blobDescriptor)
+ ->execute();
+
+ $this->db->closeTransaction();
+
+ return $result !== false;
+ }
+
+ /**
+ * Insert large object from file
+ *
+ * @access public
+ * @param string $blobColumn
+ * @param string $filename
+ * @param array $data
+ * @return bool
+ */
+ public function insertFromFile($blobColumn, $filename, array $data = array())
+ {
+ $fp = fopen($filename, 'rb');
+ $result = $this->insertFromStream($blobColumn, $fp, $data);
+ fclose($fp);
+ return $result;
+ }
+
+ /**
+ * Insert large object from string
+ *
+ * @access public
+ * @param string $blobColumn
+ * @param string $blobData
+ * @param array $data
+ * @return bool
+ */
+ public function insertFromString($blobColumn, &$blobData, array $data = array())
+ {
+ return $this->insertFromStream($blobColumn, $blobData, $data);
+ }
+
+ /**
+ * Update large object from stream
+ *
+ * @access public
+ * @param string $blobColumn
+ * @param resource $blobDescriptor
+ * @param array $data
+ * @return bool
+ */
+ public function updateFromStream($blobColumn, &$blobDescriptor, array $data = array())
+ {
+ $values = array_merge(array_values($data), $this->conditionBuilder->getValues());
+ $columns = array_merge(array($blobColumn), array_keys($data));
+
+ $this->db->startTransaction();
+
+ $result = $this->db->getStatementHandler()
+ ->withSql(UpdateBuilder::getInstance($this->db, $this->conditionBuilder)
+ ->withTable($this->name)
+ ->withColumns($columns)
+ ->build()
+ )
+ ->withPositionalParams($values)
+ ->withLobParam($blobColumn, $blobDescriptor)
+ ->execute();
+
+ $this->db->closeTransaction();
+
+ return $result !== false;
+ }
+
+ /**
+ * Update large object from file
+ *
+ * @access public
+ * @param string $blobColumn
+ * @param string $filename
+ * @param array $data
+ * @return bool
+ */
+ public function updateFromFile($blobColumn, $filename, array $data = array())
+ {
+ $fp = fopen($filename, 'r');
+ $result = $this->updateFromStream($blobColumn, $fp, $data);
+ fclose($fp);
+ return $result;
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/SQLException.php b/vendor/fguillot/picodb/lib/PicoDb/SQLException.php
new file mode 100644
index 00000000..7e570834
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/SQLException.php
@@ -0,0 +1,15 @@
+db = $db;
+ }
+
+ /**
+ * Set another namespace
+ *
+ * @access public
+ * @param string $namespace
+ * @return Schema
+ */
+ public function setNamespace($namespace)
+ {
+ $this->namespace = $namespace;
+ return $this;
+ }
+
+ /**
+ * Get schema namespace
+ *
+ * @access public
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->namespace;
+ }
+
+ /**
+ * Check the schema version and run the migrations
+ *
+ * @access public
+ * @param integer $last_version
+ * @return boolean
+ */
+ public function check($last_version = 1)
+ {
+ $current_version = $this->db->getDriver()->getSchemaVersion();
+
+ if ($current_version < $last_version) {
+ return $this->migrateTo($current_version, $last_version);
+ }
+
+ return true;
+ }
+
+ /**
+ * Migrate the schema to one version to another
+ *
+ * @access public
+ * @param integer $current_version
+ * @param integer $next_version
+ * @return boolean
+ */
+ public function migrateTo($current_version, $next_version)
+ {
+ try {
+ for ($i = $current_version + 1; $i <= $next_version; $i++) {
+ $this->db->startTransaction();
+ $this->db->getDriver()->disableForeignKeys();
+
+ $function_name = $this->getNamespace().'\version_'.$i;
+
+ if (function_exists($function_name)) {
+ $this->db->setLogMessage('Running migration '.$function_name);
+ call_user_func($function_name, $this->db->getConnection());
+ }
+
+ $this->db->getDriver()->setSchemaVersion($i);
+ $this->db->getDriver()->enableForeignKeys();
+ $this->db->closeTransaction();
+ }
+ } catch (PDOException $e) {
+ $this->db->setLogMessage($e->getMessage());
+ $this->db->cancelTransaction();
+ $this->db->getDriver()->enableForeignKeys();
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php b/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php
new file mode 100644
index 00000000..a7021b36
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php
@@ -0,0 +1,353 @@
+db = $db;
+ }
+
+ /**
+ * Enable query logging
+ *
+ * @access public
+ * @return $this
+ */
+ public function withLogging()
+ {
+ $this->logQueries = true;
+ return $this;
+ }
+
+ /**
+ * Record query execution time
+ *
+ * @access public
+ * @return $this
+ */
+ public function withStopWatch()
+ {
+ $this->stopwatch = true;
+ return $this;
+ }
+
+ /**
+ * Execute explain command on query
+ *
+ * @access public
+ * @return $this
+ */
+ public function withExplain()
+ {
+ $this->explain = true;
+ return $this;
+ }
+
+ /**
+ * Set SQL query
+ *
+ * @access public
+ * @param string $sql
+ * @return $this
+ */
+ public function withSql($sql)
+ {
+ $this->sql = $sql;
+ return $this;
+ }
+
+ /**
+ * Set positional parameters
+ *
+ * @access public
+ * @param array $params
+ * @return $this
+ */
+ public function withPositionalParams(array $params)
+ {
+ $this->positionalParams = $params;
+ return $this;
+ }
+
+ /**
+ * Set named parameters
+ *
+ * @access public
+ * @param array $params
+ * @return $this
+ */
+ public function withNamedParams(array $params)
+ {
+ $this->namedParams = $params;
+ $this->useNamedParams = true;
+ return $this;
+ }
+
+ /**
+ * Bind large object parameter
+ *
+ * @access public
+ * @param $name
+ * @param $fp
+ * @return $this
+ */
+ public function withLobParam($name, &$fp)
+ {
+ $this->lobParams[$name] =& $fp;
+ return $this;
+ }
+
+ /**
+ * Get number of queries executed
+ *
+ * @access public
+ * @return int
+ */
+ public function getNbQueries()
+ {
+ return $this->nbQueries;
+ }
+
+ /**
+ * Execute a prepared statement
+ *
+ * Note: returns false on duplicate keys instead of SQLException
+ *
+ * @access public
+ * @return PDOStatement|false
+ */
+ public function execute()
+ {
+ try {
+ $this->beforeExecute();
+
+ $pdoStatement = $this->db->getConnection()->prepare($this->sql);
+ $this->bindParams($pdoStatement);
+ $pdoStatement->execute();
+
+ $this->afterExecute();
+ return $pdoStatement;
+ } catch (PDOException $e) {
+ return $this->handleSqlError($e);
+ }
+ }
+
+ /**
+ * Bind parameters to PDOStatement
+ *
+ * @access protected
+ * @param PDOStatement $pdoStatement
+ */
+ protected function bindParams(PDOStatement $pdoStatement)
+ {
+ $i = 1;
+
+ foreach ($this->lobParams as $name => $variable) {
+ if (! $this->useNamedParams) {
+ $parameter = $i;
+ $i++;
+ } else {
+ $parameter = $name;
+ }
+
+ $pdoStatement->bindParam($parameter, $variable, PDO::PARAM_LOB);
+ }
+
+ foreach ($this->positionalParams as $value) {
+ $pdoStatement->bindValue($i, $value, PDO::PARAM_STR);
+ $i++;
+ }
+
+ foreach ($this->namedParams as $name => $value) {
+ $pdoStatement->bindValue($name, $value, PDO::PARAM_STR);
+ }
+ }
+
+ /**
+ * Method executed before query execution
+ *
+ * @access protected
+ */
+ protected function beforeExecute()
+ {
+ if ($this->logQueries) {
+ $this->db->setLogMessage($this->sql);
+ }
+
+ if ($this->stopwatch) {
+ $this->startTime = microtime(true);
+ }
+ }
+
+ /**
+ * Method executed after query execution
+ *
+ * @access protected
+ */
+ protected function afterExecute()
+ {
+ if ($this->stopwatch) {
+ $duration = microtime(true) - $this->startTime;
+ $this->executionTime += $duration;
+ $this->db->setLogMessage('query_duration='.$duration);
+ $this->db->setLogMessage('total_execution_time='.$this->executionTime);
+ }
+
+ if ($this->explain) {
+ $this->db->setLogMessages($this->db->getDriver()->explain($this->sql, $this->positionalParams));
+ }
+
+ $this->nbQueries++;
+ $this->cleanup();
+ }
+
+ /**
+ * Reset internal properties after execution
+ * The same object instance is used
+ *
+ * @access protected
+ */
+ protected function cleanup()
+ {
+ $this->sql = '';
+ $this->useNamedParams = false;
+ $this->positionalParams = array();
+ $this->namedParams = array();
+ $this->lobParams = array();
+ }
+
+ /**
+ * Handle PDOException
+ *
+ * @access public
+ * @param PDOException $e
+ * @return bool
+ * @throws SQLException
+ */
+ public function handleSqlError(PDOException $e)
+ {
+ $this->cleanup();
+ $this->db->cancelTransaction();
+ $this->db->setLogMessage($e->getMessage());
+
+ if ($this->db->getDriver()->isDuplicateKeyError($e->getCode())) {
+ return false;
+ }
+
+ throw new SQLException('SQL error'.($this->logQueries ? ': '.$e->getMessage() : ''));
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/Table.php b/vendor/fguillot/picodb/lib/PicoDb/Table.php
new file mode 100644
index 00000000..09eb928e
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/Table.php
@@ -0,0 +1,721 @@
+db = $db;
+ $this->name = $name;
+ $this->conditionBuilder = new ConditionBuilder($db);
+ }
+
+ /**
+ * Return the table name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Return ConditionBuilder object
+ *
+ * @access public
+ * @return ConditionBuilder
+ */
+ public function getConditionBuilder()
+ {
+ return $this->conditionBuilder;
+ }
+
+ /**
+ * Insert or update
+ *
+ * @access public
+ * @param array $data
+ * @return boolean
+ */
+ public function save(array $data)
+ {
+ return $this->conditionBuilder->hasCondition() ? $this->update($data) : $this->insert($data);
+ }
+
+ /**
+ * Update
+ *
+ * @access public
+ * @param array $data
+ * @return boolean
+ */
+ public function update(array $data = array())
+ {
+ $values = array_merge(array_values($data), array_values($this->sumColumns), $this->conditionBuilder->getValues());
+ $sql = UpdateBuilder::getInstance($this->db, $this->conditionBuilder)
+ ->withTable($this->name)
+ ->withColumns(array_keys($data))
+ ->withSumColumns(array_keys($this->sumColumns))
+ ->build();
+
+ return $this->db->execute($sql, $values) !== false;
+ }
+
+ /**
+ * Insert
+ *
+ * @access public
+ * @param array $data
+ * @return boolean
+ */
+ public function insert(array $data)
+ {
+ return $this->db->getStatementHandler()
+ ->withSql(InsertBuilder::getInstance($this->db, $this->conditionBuilder)
+ ->withTable($this->name)
+ ->withColumns(array_keys($data))
+ ->build()
+ )
+ ->withNamedParams($data)
+ ->execute() !== false;
+ }
+
+ /**
+ * Insert a new row and return the ID of the primary key
+ *
+ * @access public
+ * @param array $data
+ * @return bool|int
+ */
+ public function persist(array $data)
+ {
+ if ($this->insert($data)) {
+ return $this->db->getLastId();
+ }
+
+ return false;
+ }
+
+ /**
+ * Remove
+ *
+ * @access public
+ * @return boolean
+ */
+ public function remove()
+ {
+ $sql = sprintf(
+ 'DELETE FROM %s %s',
+ $this->db->escapeIdentifier($this->name),
+ $this->conditionBuilder->build()
+ );
+
+ $result = $this->db->execute($sql, $this->conditionBuilder->getValues());
+ return $result->rowCount() > 0;
+ }
+
+ /**
+ * Fetch all rows
+ *
+ * @access public
+ * @return array
+ */
+ public function findAll()
+ {
+ $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues());
+ $results = $rq->fetchAll(PDO::FETCH_ASSOC);
+
+ if (is_callable($this->callback) && ! empty($results)) {
+ return call_user_func($this->callback, $results);
+ }
+
+ return $results;
+ }
+
+ /**
+ * Find all with a single column
+ *
+ * @access public
+ * @param string $column
+ * @return mixed
+ */
+ public function findAllByColumn($column)
+ {
+ $this->columns = array($column);
+ $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues());
+
+ return $rq->fetchAll(PDO::FETCH_COLUMN, 0);
+ }
+
+ /**
+ * Fetch one row
+ *
+ * @access public
+ * @return array|null
+ */
+ public function findOne()
+ {
+ $this->limit(1);
+ $result = $this->findAll();
+
+ return isset($result[0]) ? $result[0] : null;
+ }
+
+ /**
+ * Fetch one column, first row
+ *
+ * @access public
+ * @param string $column
+ * @return string
+ */
+ public function findOneColumn($column)
+ {
+ $this->limit(1);
+ $this->columns = array($column);
+
+ return $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues())->fetchColumn();
+ }
+
+ /**
+ * Build a subquery with an alias
+ *
+ * @access public
+ * @param string $sql
+ * @param string $alias
+ * @return $this
+ */
+ public function subquery($sql, $alias)
+ {
+ $this->columns[] = '('.$sql.') AS '.$this->db->escapeIdentifier($alias);
+ return $this;
+ }
+
+ /**
+ * Exists
+ *
+ * @access public
+ * @return integer
+ */
+ public function exists()
+ {
+ $sql = sprintf(
+ 'SELECT 1 FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build(),
+ $this->db->escapeIdentifier($this->name)
+ );
+
+ $rq = $this->db->execute($sql, $this->conditionBuilder->getValues());
+ $result = $rq->fetchColumn();
+
+ return $result ? true : false;
+ }
+
+ /**
+ * Count
+ *
+ * @access public
+ * @return integer
+ */
+ public function count()
+ {
+ $sql = sprintf(
+ 'SELECT COUNT(*) FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build().$this->sqlOrder.$this->sqlLimit.$this->sqlOffset,
+ $this->db->escapeIdentifier($this->name)
+ );
+
+ $rq = $this->db->execute($sql, $this->conditionBuilder->getValues());
+ $result = $rq->fetchColumn();
+
+ return $result ? (int) $result : 0;
+ }
+
+ /**
+ * Sum
+ *
+ * @access public
+ * @param string $column
+ * @return float
+ */
+ public function sum($column)
+ {
+ $sql = sprintf(
+ 'SELECT SUM(%s) FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build().$this->sqlOrder.$this->sqlLimit.$this->sqlOffset,
+ $this->db->escapeIdentifier($column),
+ $this->db->escapeIdentifier($this->name)
+ );
+
+ $rq = $this->db->execute($sql, $this->conditionBuilder->getValues());
+ $result = $rq->fetchColumn();
+
+ return $result ? (float) $result : 0;
+ }
+
+ /**
+ * Increment column value
+ *
+ * @access public
+ * @param string $column
+ * @param string $value
+ * @return boolean
+ */
+ public function increment($column, $value)
+ {
+ $sql = sprintf(
+ 'UPDATE %s SET %s=%s+%d '.$this->conditionBuilder->build(),
+ $this->db->escapeIdentifier($this->name),
+ $this->db->escapeIdentifier($column),
+ $this->db->escapeIdentifier($column),
+ $value
+ );
+
+ return $this->db->execute($sql, $this->conditionBuilder->getValues()) !== false;
+ }
+
+ /**
+ * Decrement column value
+ *
+ * @access public
+ * @param string $column
+ * @param string $value
+ * @return boolean
+ */
+ public function decrement($column, $value)
+ {
+ $sql = sprintf(
+ 'UPDATE %s SET %s=%s-%d '.$this->conditionBuilder->build(),
+ $this->db->escapeIdentifier($this->name),
+ $this->db->escapeIdentifier($column),
+ $this->db->escapeIdentifier($column),
+ $value
+ );
+
+ return $this->db->execute($sql, $this->conditionBuilder->getValues()) !== false;
+ }
+
+ /**
+ * Left join
+ *
+ * @access public
+ * @param string $table Join table
+ * @param string $foreign_column Foreign key on the join table
+ * @param string $local_column Local column
+ * @param string $local_table Local table
+ * @param string $alias Join table alias
+ * @return $this
+ */
+ public function join($table, $foreign_column, $local_column, $local_table = '', $alias = '')
+ {
+ $this->joins[] = sprintf(
+ 'LEFT JOIN %s ON %s=%s',
+ $this->db->escapeIdentifier($table),
+ $this->db->escapeIdentifier($alias ?: $table).'.'.$this->db->escapeIdentifier($foreign_column),
+ $this->db->escapeIdentifier($local_table ?: $this->name).'.'.$this->db->escapeIdentifier($local_column)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Left join
+ *
+ * @access public
+ * @param string $table1
+ * @param string $alias1
+ * @param string $column1
+ * @param string $table2
+ * @param string $column2
+ * @return $this
+ */
+ public function left($table1, $alias1, $column1, $table2, $column2)
+ {
+ $this->joins[] = sprintf(
+ 'LEFT JOIN %s AS %s ON %s=%s',
+ $this->db->escapeIdentifier($table1),
+ $this->db->escapeIdentifier($alias1),
+ $this->db->escapeIdentifier($alias1).'.'.$this->db->escapeIdentifier($column1),
+ $this->db->escapeIdentifier($table2).'.'.$this->db->escapeIdentifier($column2)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Inner join
+ *
+ * @access public
+ * @param string $table1
+ * @param string $alias1
+ * @param string $column1
+ * @param string $table2
+ * @param string $column2
+ * @return $this
+ */
+ public function inner($table1, $alias1, $column1, $table2, $column2)
+ {
+ $this->joins[] = sprintf(
+ 'JOIN %s AS %s ON %s=%s',
+ $this->db->escapeIdentifier($table1),
+ $this->db->escapeIdentifier($alias1),
+ $this->db->escapeIdentifier($alias1).'.'.$this->db->escapeIdentifier($column1),
+ $this->db->escapeIdentifier($table2).'.'.$this->db->escapeIdentifier($column2)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Order by
+ *
+ * @access public
+ * @param string $column Column name
+ * @param string $order Direction ASC or DESC
+ * @return $this
+ */
+ public function orderBy($column, $order = self::SORT_ASC)
+ {
+ $order = strtoupper($order);
+ $order = $order === self::SORT_ASC || $order === self::SORT_DESC ? $order : self::SORT_ASC;
+
+ if ($this->sqlOrder === '') {
+ $this->sqlOrder = ' ORDER BY '.$this->db->escapeIdentifier($column).' '.$order;
+ }
+ else {
+ $this->sqlOrder .= ', '.$this->db->escapeIdentifier($column).' '.$order;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Ascending sort
+ *
+ * @access public
+ * @param string $column
+ * @return $this
+ */
+ public function asc($column)
+ {
+ $this->orderBy($column, self::SORT_ASC);
+ return $this;
+ }
+
+ /**
+ * Descending sort
+ *
+ * @access public
+ * @param string $column
+ * @return $this
+ */
+ public function desc($column)
+ {
+ $this->orderBy($column, self::SORT_DESC);
+ return $this;
+ }
+
+ /**
+ * Limit
+ *
+ * @access public
+ * @param integer $value
+ * @return $this
+ */
+ public function limit($value)
+ {
+ if (! is_null($value)) {
+ $this->sqlLimit = ' LIMIT '.(int) $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Offset
+ *
+ * @access public
+ * @param integer $value
+ * @return $this
+ */
+ public function offset($value)
+ {
+ if (! is_null($value)) {
+ $this->sqlOffset = ' OFFSET '.(int) $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Group by
+ *
+ * @access public
+ * @return $this
+ */
+ public function groupBy()
+ {
+ $this->groupBy = func_get_args();
+ return $this;
+ }
+
+ /**
+ * Custom select
+ *
+ * @access public
+ * @param string $select
+ * @return $this
+ */
+ public function select($select)
+ {
+ $this->sqlSelect = $select;
+ return $this;
+ }
+
+ /**
+ * Define the columns for the select
+ *
+ * @access public
+ * @return $this
+ */
+ public function columns()
+ {
+ $this->columns = func_get_args();
+ return $this;
+ }
+
+ /**
+ * Sum column
+ *
+ * @access public
+ * @param string $column
+ * @param mixed $value
+ * @return $this
+ */
+ public function sumColumn($column, $value)
+ {
+ $this->sumColumns[$column] = $value;
+ return $this;
+ }
+
+ /**
+ * Distinct
+ *
+ * @access public
+ * @return $this
+ */
+ public function distinct()
+ {
+ $this->columns = func_get_args();
+ $this->distinct = true;
+ return $this;
+ }
+
+ /**
+ * Add callback to alter the resultset
+ *
+ * @access public
+ * @param Closure|array $callback
+ * @return $this
+ */
+ public function callback($callback)
+ {
+ $this->callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Build a select query
+ *
+ * @access public
+ * @return string
+ */
+ public function buildSelectQuery()
+ {
+ if (empty($this->sqlSelect)) {
+ $this->columns = $this->db->escapeIdentifierList($this->columns);
+ $this->sqlSelect = ($this->distinct ? 'DISTINCT ' : '').(empty($this->columns) ? '*' : implode(', ', $this->columns));
+ }
+
+ $this->groupBy = $this->db->escapeIdentifierList($this->groupBy);
+
+ return trim(sprintf(
+ 'SELECT %s FROM %s %s %s %s %s %s %s',
+ $this->sqlSelect,
+ $this->db->escapeIdentifier($this->name),
+ implode(' ', $this->joins),
+ $this->conditionBuilder->build(),
+ empty($this->groupBy) ? '' : 'GROUP BY '.implode(', ', $this->groupBy),
+ $this->sqlOrder,
+ $this->sqlLimit,
+ $this->sqlOffset
+ ));
+ }
+
+ /**
+ * Magic method for sql conditions
+ *
+ * @access public
+ * @param string $name
+ * @param array $arguments
+ * @return $this
+ */
+ public function __call($name, array $arguments)
+ {
+ call_user_func_array(array($this->conditionBuilder, $name), $arguments);
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php b/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php
new file mode 100644
index 00000000..d8fcaf00
--- /dev/null
+++ b/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php
@@ -0,0 +1,93 @@
+url = getenv($environmentVariable);
+ }
+
+ /**
+ * Get object instance
+ *
+ * @access public
+ * @param string $environmentVariable
+ * @return static
+ */
+ public static function getInstance($environmentVariable = 'DATABASE_URL')
+ {
+ return new static($environmentVariable);
+ }
+
+ /**
+ * Return true if the variable is defined
+ *
+ * @access public
+ * @return bool
+ */
+ public function isEnvironmentVariableDefined()
+ {
+ return ! empty($this->url);
+ }
+
+ /**
+ * Get settings from URL
+ *
+ * @access public
+ * @param string $url
+ * @return array
+ */
+ public function getSettings($url = '')
+ {
+ $url = $url ?: $this->url;
+ $components = parse_url($url);
+
+ if ($components === false) {
+ return array();
+ }
+
+ return array(
+ 'driver' => $this->getUrlComponent($components, 'scheme'),
+ 'username' => $this->getUrlComponent($components, 'user'),
+ 'password' => $this->getUrlComponent($components, 'pass'),
+ 'hostname' => $this->getUrlComponent($components, 'host'),
+ 'port' => $this->getUrlComponent($components, 'port'),
+ 'database' => ltrim($this->getUrlComponent($components, 'path'), '/'),
+ );
+ }
+
+ /**
+ * Get URL component
+ *
+ * @access private
+ * @param array $components
+ * @param string $component
+ * @return mixed|null
+ */
+ private function getUrlComponent(array $components, $component)
+ {
+ return ! empty($components[$component]) ? $components[$component] : null;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/LICENSE b/vendor/fguillot/simple-queue/LICENSE
new file mode 100644
index 00000000..a19d63a3
--- /dev/null
+++ b/vendor/fguillot/simple-queue/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Frédéric Guillot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php
new file mode 100644
index 00000000..379dd9b8
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php
@@ -0,0 +1,138 @@
+channel = $channel;
+ $this->exchange = $exchange;
+ $this->queue = $queue;
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $message = new AMQPMessage($job->serialize(), array('content_type' => 'text/plain'));
+ $this->channel->basic_publish($message, $this->exchange);
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return $this
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ $now = new DateTime();
+ $when = clone($dateTime);
+ $delay = $when->getTimestamp() - $now->getTimestamp();
+
+ $message = new AMQPMessage($job->serialize(), array('delivery_mode' => 2));
+ $message->set('application_headers', new AMQPTable(array('x-delay' => $delay)));
+
+ $this->channel->basic_publish($message, $this->exchange);
+ return $this;
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ $message = null;
+
+ $this->channel->basic_consume($this->queue, 'test', false, false, false, false, function ($msg) use (&$message) {
+ $message = $msg;
+ $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
+ });
+
+ while (count($this->channel->callbacks)) {
+ $this->channel->wait();
+ }
+
+ if ($message === null) {
+ return null;
+ }
+
+ $job = new Job();
+ $job->setId($message->get('delivery_tag'));
+ $job->unserialize($message->getBody());
+
+ return $job;
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ $this->channel->basic_ack($job->getId());
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $this->channel->basic_nack($job->getId());
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php
new file mode 100644
index 00000000..01377317
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php
@@ -0,0 +1,150 @@
+
+ */
+class AwsSqsQueueAdapter implements QueueAdapterInterface
+{
+ /**
+ * @var string
+ */
+ private $queueName;
+
+ /**
+ * @var SqsClient
+ */
+ private $sqsClient;
+
+ /**
+ * @var string
+ */
+ private $sqsUrl;
+
+ /**
+ * @var array
+ */
+ private $config;
+
+ /**
+ * AwsSqsQueueAdapter constructor.
+ *
+ * @param string $queueName The name of the SQS queue
+ * @param SqsClient $sqsClient An SQS client
+ * @param array $config Array of config values
+ */
+ public function __construct($queueName, SqsClient $sqsClient, $config = array())
+ {
+ $this->queueName = $queueName;
+ $this->sqsClient = $sqsClient;
+ $this->sqsUrl = $this->sqsClient->getQueueUrl(array('QueueName' => $this->queueName))->get('QueueUrl');
+ $this->config = $config;
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $this->sqsClient->sendMessage(array(
+ 'QueueUrl' => $this->sqsUrl,
+ 'MessageBody' => $job->serialize()
+ ));
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return $this
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ $now = new DateTime();
+ $when = clone($dateTime);
+ $delay = $when->getTimestamp() - $now->getTimestamp();
+
+ $this->sqsClient->sendMessage(array(
+ 'QueueUrl' => $this->sqsUrl,
+ 'MessageBody' => $job->serialize(),
+ 'VisibilityTimeout' => $delay
+ ));
+
+ return $this;
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ $result = $this->sqsClient->receiveMessage(array(
+ 'QueueUrl' => $this->sqsUrl,
+ 'WaitTimeSeconds' => empty($this->config['LongPollingTime']) ? 0 : (int) $this->config['LongPollingTime']
+ ));
+
+ if ($result['Messages'] == null) {
+ return null;
+ }
+
+ $resultMessage = array_pop($result['Messages']);
+
+ $job = new Job();
+ $job->setId($resultMessage['ReceiptHandle']);
+ $job->unserialize($resultMessage['Body']);
+
+ return $job;
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ $this->sqsClient->deleteMessage(array(
+ 'QueueUrl' => $this->sqsUrl,
+ 'ReceiptHandle' => $job->getId()
+ ));
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $this->sqsClient->changeMessageVisibility(array(
+ 'QueueUrl' => $this->sqsUrl,
+ 'ReceiptHandle' => $job->getId(),
+ 'VisibilityTimeout' => 0
+ ));
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php
new file mode 100644
index 00000000..407f60e2
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php
@@ -0,0 +1,120 @@
+beanstalk = $beanstalk;
+ $this->queueName = $queueName;
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $this->beanstalk->putInTube($this->queueName, $job->serialize());
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return $this
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ $now = new DateTime();
+ $when = clone($dateTime);
+ $delay = $when->getTimestamp() - $now->getTimestamp();
+
+ $this->beanstalk->putInTube($this->queueName, $job->serialize(), Pheanstalk::DEFAULT_PRIORITY, $delay);
+ return $this;
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ $beanstalkJob = $this->beanstalk->reserveFromTube($this->queueName);
+
+ if ($beanstalkJob === false) {
+ return null;
+ }
+
+ $job = new Job();
+ $job->setId($beanstalkJob->getId());
+ $job->unserialize($beanstalkJob->getData());
+
+ return $job;
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ $beanstalkJob = new BeanstalkJob($job->getId(), $job->serialize());
+ $this->beanstalk->delete($beanstalkJob);
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $beanstalkJob = new BeanstalkJob($job->getId(), $job->serialize());
+ $this->beanstalk->bury($beanstalkJob);
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php
new file mode 100644
index 00000000..047658d7
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php
@@ -0,0 +1,109 @@
+disque = $disque;
+ $this->queueName = $queueName;
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $this->disque->queue($this->queueName)->push(new DisqueJob($job->getBody()));
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return $this
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ $this->disque->queue($this->queueName)->schedule(new DisqueJob($job->serialize()), $dateTime);
+ return $this;
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ $disqueJob = $this->disque->queue($this->queueName)->pull();
+
+ if ($disqueJob === null) {
+ return null;
+ }
+
+ return new Job($disqueJob->getBody(), $disqueJob->getId());
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ $this->disque->queue($this->queueName)->processed(new DisqueJob($job->getBody(), $job->getId()));
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $this->disque->queue($this->queueName)->failed(new DisqueJob($job->getBody(), $job->getId()));
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php
new file mode 100644
index 00000000..36375d5b
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php
@@ -0,0 +1,100 @@
+queue = new SplQueue();
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $this->queue->enqueue($job->serialize());
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return bool
+ * @throws NotSupportedException
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ throw new NotSupportedException('Job delay is not supported by MemoryQueue');
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ try {
+ $job = new Job();
+ $payload = $this->queue->dequeue();
+ return $job->unserialize($payload);
+ } catch (Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $this->queue->enqueue($job->serialize());
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php b/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php
new file mode 100644
index 00000000..36106659
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php
@@ -0,0 +1,14 @@
+body = $body;
+ $this->id = $id;
+ }
+
+ /**
+ * Unserialize a payload
+ *
+ * @param string $payload
+ * @return $this
+ */
+ public function unserialize($payload)
+ {
+ $this->body = json_decode($payload, true);
+ return $this;
+ }
+
+ /**
+ * Serialize the body
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return json_encode($this->body);
+ }
+
+ /**
+ * Set body
+ *
+ * @param mixed $body
+ * @return Job
+ */
+ public function setBody($body)
+ {
+ $this->body = $body;
+ return $this;
+ }
+
+ /**
+ * Get body
+ *
+ * @return mixed
+ */
+ public function getBody()
+ {
+ return $this->body;
+ }
+
+ /**
+ * Set job ID
+ *
+ * @param mixed $jobId
+ * @return Job
+ */
+ public function setId($jobId)
+ {
+ $this->id = $jobId;
+ return $this;
+ }
+
+ /**
+ * Get job ID
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Execute job
+ */
+ public function execute()
+ {
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/Queue.php b/vendor/fguillot/simple-queue/src/Queue.php
new file mode 100644
index 00000000..a88b55cb
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/Queue.php
@@ -0,0 +1,92 @@
+queueAdapter = $queueAdapter;
+ }
+
+ /**
+ * Send a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function push(Job $job)
+ {
+ $this->queueAdapter->push($job);
+ return $this;
+ }
+
+ /**
+ * Schedule a job in the future
+ *
+ * @access public
+ * @param Job $job
+ * @param DateTime $dateTime
+ * @return $this
+ */
+ public function schedule(Job $job, DateTime $dateTime)
+ {
+ $this->queueAdapter->schedule($job, $dateTime);
+ return $this;
+ }
+
+ /**
+ * Wait and get job from a queue
+ *
+ * @access public
+ * @return Job|null
+ */
+ public function pull()
+ {
+ return $this->queueAdapter->pull();
+ }
+
+ /**
+ * Acknowledge a job
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function completed(Job $job)
+ {
+ $this->queueAdapter->completed($job);
+ return $this;
+ }
+
+ /**
+ * Mark a job as failed
+ *
+ * @access public
+ * @param Job $job
+ * @return $this
+ */
+ public function failed(Job $job)
+ {
+ $this->queueAdapter->failed($job);
+ return $this;
+ }
+}
diff --git a/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php b/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php
new file mode 100644
index 00000000..9bda3070
--- /dev/null
+++ b/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php
@@ -0,0 +1,58 @@
+data = $data;
+ $this->validators = $validators;
+ }
+
+ public function execute()
+ {
+ $result = true;
+
+ foreach ($this->validators as $validator) {
+ if (! $validator->execute($this->data)) {
+ $this->addError($validator->getField(), $validator->getErrorMessage());
+ $result = false;
+ }
+ }
+
+ return $result;
+ }
+
+ public function addError($field, $message)
+ {
+ if (! isset($this->errors[$field])) {
+ $this->errors[$field] = array();
+ }
+
+ $this->errors[$field][] = $message;
+ }
+
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php
new file mode 100644
index 00000000..c29ba481
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php
@@ -0,0 +1,15 @@
+isFieldNotEmpty($data)) {
+ return ctype_alpha($data[$this->field]);
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php
new file mode 100644
index 00000000..8d5000b4
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php
@@ -0,0 +1,15 @@
+isFieldNotEmpty($data)) {
+ return ctype_alnum($data[$this->field]);
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php
new file mode 100644
index 00000000..8157ae50
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php
@@ -0,0 +1,37 @@
+field = $field;
+ $this->error_message = $error_message;
+ }
+
+ public function getErrorMessage()
+ {
+ return $this->error_message;
+ }
+
+ public function getField()
+ {
+ if (is_array($this->field)) {
+ return $this->field[0];
+ }
+
+ return $this->field;
+ }
+
+ public function isFieldNotEmpty(array $data)
+ {
+ return isset($data[$this->field]) && $data[$this->field] !== '';
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php
new file mode 100644
index 00000000..4ec4b7fd
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php
@@ -0,0 +1,45 @@
+formats = $formats;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ foreach ($this->formats as $format) {
+ if ($this->isValidDate($data[$this->field], $format)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ public function isValidDate($value, $format)
+ {
+ $date = DateTime::createFromFormat($format, $value);
+
+ if ($date !== false) {
+ $errors = DateTime::getLastErrors();
+ if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
+ return $date->getTimestamp() > 0;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php
new file mode 100644
index 00000000..f3977042
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php
@@ -0,0 +1,67 @@
+isFieldNotEmpty($data)) {
+
+ // I use the same validation method as Firefox
+ // http://hg.mozilla.org/mozilla-central/file/cf5da681d577/content/html/content/src/nsHTMLInputElement.cpp#l3967
+
+ $value = $data[$this->field];
+ $length = strlen($value);
+
+ // If the email address begins with a '@' or ends with a '.',
+ // we know it's invalid.
+ if ($value[0] === '@' || $value[$length - 1] === '.') {
+
+ return false;
+ }
+
+ // Check the username
+ for ($i = 0; $i < $length && $value[$i] !== '@'; ++$i) {
+
+ $c = $value[$i];
+
+ if (! (ctype_alnum($c) || $c === '.' || $c === '!' || $c === '#' || $c === '$' ||
+ $c === '%' || $c === '&' || $c === '\'' || $c === '*' || $c === '+' ||
+ $c === '-' || $c === '/' || $c === '=' || $c === '?' || $c === '^' ||
+ $c === '_' || $c === '`' || $c === '{' || $c === '|' || $c === '}' ||
+ $c === '~')) {
+
+ return false;
+ }
+ }
+
+ // There is no domain name (or it's one-character long),
+ // that's not a valid email address.
+ if (++$i >= $length) return false;
+ if (($i + 1) === $length) return false;
+
+ // The domain name can't begin with a dot.
+ if ($value[$i] === '.') return false;
+
+ // Parsing the domain name.
+ for (; $i < $length; ++$i) {
+
+ $c = $value[$i];
+
+ if ($c === '.') {
+
+ // A dot can't follow a dot.
+ if ($value[$i - 1] === '.') return false;
+ }
+ elseif (! (ctype_alnum($c) || $c === '-')) {
+
+ // The domain characters have to be in this list to be valid.
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php
new file mode 100644
index 00000000..6b69dd80
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php
@@ -0,0 +1,27 @@
+field2 = $field2;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ if (! isset($data[$this->field2])) {
+ return false;
+ }
+
+ return $data[$this->field] === $data[$this->field2];
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php
new file mode 100644
index 00000000..1998e673
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php
@@ -0,0 +1,38 @@
+pdo = $pdo;
+ $this->table = $table;
+ $this->key = $key;
+ }
+
+
+ public function execute(array $data)
+ {
+ if (! $this->isFieldNotEmpty($data)) {
+ return true;
+ }
+
+ if ($this->key === '') {
+ $this->key = $this->field;
+ }
+
+ $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->table.' WHERE '.$this->key.'=?');
+ $rq->execute(array($data[$this->field]));
+
+ return $rq->fetchColumn() == 1;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php
new file mode 100644
index 00000000..6e560319
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php
@@ -0,0 +1,23 @@
+min = $min;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ return $data[$this->field] > $this->min;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php
new file mode 100644
index 00000000..f2f8c134
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php
@@ -0,0 +1,23 @@
+array = $array;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ return in_array($data[$this->field], $this->array);
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php
new file mode 100644
index 00000000..5afdc1e0
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php
@@ -0,0 +1,25 @@
+isFieldNotEmpty($data)) {
+ if (is_string($data[$this->field])) {
+
+ if ($data[$this->field][0] === '-') {
+ return ctype_digit(substr($data[$this->field], 1));
+ }
+
+ return ctype_digit($data[$this->field]);
+ }
+ else {
+ return is_int($data[$this->field]);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php
new file mode 100644
index 00000000..754f4f3e
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php
@@ -0,0 +1,15 @@
+isFieldNotEmpty($data)) {
+ return filter_var($data[$this->field], FILTER_VALIDATE_IP) !== false;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php
new file mode 100644
index 00000000..7ef241c4
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php
@@ -0,0 +1,26 @@
+min = $min;
+ $this->max = $max;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ $length = mb_strlen($data[$this->field], 'UTF-8');
+ return $length >= $this->min && $length <= $this->max;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php
new file mode 100644
index 00000000..6c4e7771
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php
@@ -0,0 +1,24 @@
+max = $max;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ $length = mb_strlen($data[$this->field], 'UTF-8');
+ return $length <= $this->max;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php
new file mode 100644
index 00000000..0ac4217a
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php
@@ -0,0 +1,24 @@
+min = $min;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ $length = mb_strlen($data[$this->field], 'UTF-8');
+ return $length >= $this->min;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php
new file mode 100644
index 00000000..bbb14b5b
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php
@@ -0,0 +1,15 @@
+field, $data)) {
+ return $data[$this->field] !== null && $data[$this->field] !== '';
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php
new file mode 100644
index 00000000..d1d949ea
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php
@@ -0,0 +1,28 @@
+field2 = $field2;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+
+ if (! isset($data[$this->field2])) {
+ return true;
+ }
+
+ return $data[$this->field] !== $data[$this->field2];
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php
new file mode 100644
index 00000000..98974c9c
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php
@@ -0,0 +1,15 @@
+isFieldNotEmpty($data)) {
+ return ! in_array($data[$this->field], $this->array);
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php
new file mode 100644
index 00000000..31226866
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php
@@ -0,0 +1,15 @@
+isFieldNotEmpty($data)) {
+ return is_numeric($data[$this->field]);
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php
new file mode 100644
index 00000000..065b2b9d
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php
@@ -0,0 +1,33 @@
+min = $min;
+ $this->max = $max;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+
+ if (! is_numeric($data[$this->field])) {
+ return false;
+ }
+
+ if ($data[$this->field] < $this->min || $data[$this->field] > $this->max) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php
new file mode 100644
index 00000000..f5e65616
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php
@@ -0,0 +1,11 @@
+isFieldNotEmpty($data);
+ }
+}
diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php
new file mode 100644
index 00000000..00caeb54
--- /dev/null
+++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php
@@ -0,0 +1,48 @@
+pdo = $pdo;
+ $this->primary_key = $primary_key;
+ $this->table = $table;
+ }
+
+ public function execute(array $data)
+ {
+ if ($this->isFieldNotEmpty($data)) {
+ if (! isset($data[$this->primary_key])) {
+ $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->table.' WHERE '.$this->field.'=?');
+ $rq->execute(array($data[$this->field]));
+ }
+ else {
+
+ $rq = $this->pdo->prepare(
+ 'SELECT 1 FROM '.$this->table.'
+ WHERE '.$this->field.'=? AND '.$this->primary_key.' != ?'
+ );
+
+ $rq->execute(array($data[$this->field], $data[$this->primary_key]));
+ }
+
+ $result = $rq->fetchColumn();
+
+ if ($result == 1) { // Postgresql returns an integer but other database returns a string '1'
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/LICENSE b/vendor/fguillot/simpleLogger/LICENSE
new file mode 100644
index 00000000..6a362bc1
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Frederic Guillot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php
new file mode 100644
index 00000000..c662a1a3
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php
@@ -0,0 +1,89 @@
+level = $level;
+ }
+
+ /**
+ * Get minimum log level
+ *
+ * @access public
+ * @return string
+ */
+ public function getLevel()
+ {
+ return $this->level;
+ }
+
+ /**
+ * Dump to log a variable (by example an array)
+ *
+ * @param mixed $variable
+ */
+ public function dump($variable)
+ {
+ $this->log(LogLevel::DEBUG, var_export($variable, true));
+ }
+
+ /**
+ * Interpolates context values into the message placeholders.
+ *
+ * @access protected
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected function interpolate($message, array $context = array())
+ {
+ // build a replacement array with braces around the context keys
+ $replace = array();
+
+ foreach ($context as $key => $val) {
+ $replace['{' . $key . '}'] = $val;
+ }
+
+ // interpolate replacement values into the message and return
+ return strtr($message, $replace);
+ }
+
+ /**
+ * Format log message
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected function formatMessage($level, $message, array $context = array())
+ {
+ return '['.date('Y-m-d H:i:s').'] ['.$level.'] '.$this->interpolate($message, $context).PHP_EOL;
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php
new file mode 100644
index 00000000..be3bfa85
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php
@@ -0,0 +1,48 @@
+filename = $filename;
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ */
+ public function log($level, $message, array $context = array())
+ {
+ $line = $this->formatMessage($level, $message, $context);
+
+ if (file_put_contents($this->filename, $line, FILE_APPEND | LOCK_EX) === false) {
+ throw new RuntimeException('Unable to write to the log file.');
+ }
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php
new file mode 100644
index 00000000..dc340cde
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php
@@ -0,0 +1,94 @@
+loggers[] = $logger;
+ }
+
+ /**
+ * Proxy method to the real loggers
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ * @return null
+ */
+ public function log($level, $message, array $context = array())
+ {
+ foreach ($this->loggers as $logger) {
+ if ($this->getLevelPriority($level) >= $this->getLevelPriority($logger->getLevel())) {
+ $logger->log($level, $message, $context);
+ }
+ }
+ }
+
+ /**
+ * Dump variables for debugging
+ *
+ * @param mixed $variable
+ */
+ public function dump($variable)
+ {
+ foreach ($this->loggers as $logger) {
+ if ($this->getLevelPriority(LogLevel::DEBUG) >= $this->getLevelPriority($logger->getLevel())) {
+ $logger->dump($variable);
+ }
+ }
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php
new file mode 100644
index 00000000..2573177e
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php
@@ -0,0 +1,25 @@
+formatMessage($level, $message, $context), FILE_APPEND);
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php
new file mode 100644
index 00000000..82d181b2
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php
@@ -0,0 +1,25 @@
+formatMessage($level, $message, $context), FILE_APPEND);
+ }
+}
diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php
new file mode 100644
index 00000000..c4e26a7a
--- /dev/null
+++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php
@@ -0,0 +1,72 @@
+getSyslogPriority($level);
+ $syslogMessage = $this->interpolate($message, $context);
+
+ syslog($syslogPriority, $syslogMessage);
+ }
+}
diff --git a/vendor/gregwar/captcha/.gitignore b/vendor/gregwar/captcha/.gitignore
new file mode 100644
index 00000000..5a275919
--- /dev/null
+++ b/vendor/gregwar/captcha/.gitignore
@@ -0,0 +1,3 @@
+demo/*.jpg
+demo/*.pgm
+demo/temp/
diff --git a/vendor/gregwar/captcha/.travis.yml b/vendor/gregwar/captcha/.travis.yml
new file mode 100644
index 00000000..9c4b7049
--- /dev/null
+++ b/vendor/gregwar/captcha/.travis.yml
@@ -0,0 +1,12 @@
+language: php
+
+php:
+ - 5.3.3
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+
+script:
+ - composer install
+ - phpunit
diff --git a/vendor/gregwar/captcha/CaptchaBuilder.php b/vendor/gregwar/captcha/CaptchaBuilder.php
new file mode 100644
index 00000000..bc6173fe
--- /dev/null
+++ b/vendor/gregwar/captcha/CaptchaBuilder.php
@@ -0,0 +1,720 @@
+
+ * @author Jeremy Livingston
+ */
+class CaptchaBuilder implements CaptchaBuilderInterface
+{
+ /**
+ * @var array
+ */
+ protected $fingerprint = array();
+
+ /**
+ * @var bool
+ */
+ protected $useFingerprint = false;
+
+ /**
+ * @var array
+ */
+ protected $textColor = null;
+
+ /**
+ * @var array
+ */
+ protected $backgroundColor = null;
+
+ /**
+ * @var array
+ */
+ protected $backgroundImages = array();
+
+ /**
+ * @var resource
+ */
+ protected $contents = null;
+
+ /**
+ * @var string
+ */
+ protected $phrase = null;
+
+ /**
+ * @var PhraseBuilderInterface
+ */
+ protected $builder;
+
+ /**
+ * @var bool
+ */
+ protected $distortion = true;
+
+ /**
+ * The maximum number of lines to draw in front of
+ * the image. null - use default algorithm
+ */
+ protected $maxFrontLines = null;
+
+ /**
+ * The maximum number of lines to draw behind
+ * the image. null - use default algorithm
+ */
+ protected $maxBehindLines = null;
+
+ /**
+ * The maximum angle of char
+ */
+ protected $maxAngle = 8;
+
+ /**
+ * The maximum offset of char
+ */
+ protected $maxOffset = 5;
+
+ /**
+ * Is the interpolation enabled ?
+ *
+ * @var bool
+ */
+ protected $interpolation = true;
+
+ /**
+ * Ignore all effects
+ *
+ * @var bool
+ */
+ protected $ignoreAllEffects = false;
+
+ /**
+ * Allowed image types for the background images
+ *
+ * @var array
+ */
+ protected $allowedBackgroundImageTypes = array('image/png', 'image/jpeg', 'image/gif');
+
+ /**
+ * The image contents
+ */
+ public function getContents()
+ {
+ return $this->contents;
+ }
+
+ /**
+ * Enable/Disables the interpolation
+ *
+ * @param $interpolate bool True to enable, false to disable
+ *
+ * @return CaptchaBuilder
+ */
+ public function setInterpolation($interpolate = true)
+ {
+ $this->interpolation = $interpolate;
+
+ return $this;
+ }
+
+ /**
+ * Temporary dir, for OCR check
+ */
+ public $tempDir = 'temp/';
+
+ public function __construct($phrase = null, PhraseBuilderInterface $builder = null)
+ {
+ if ($builder === null) {
+ $this->builder = new PhraseBuilder;
+ } else {
+ $this->builder = $builder;
+ }
+
+ if ($phrase === null) {
+ $phrase = $this->builder->build();
+ }
+
+ $this->phrase = $phrase;
+ }
+
+ /**
+ * Setting the phrase
+ */
+ public function setPhrase($phrase)
+ {
+ $this->phrase = (string) $phrase;
+ }
+
+ /**
+ * Enables/disable distortion
+ */
+ public function setDistortion($distortion)
+ {
+ $this->distortion = (bool) $distortion;
+
+ return $this;
+ }
+
+ public function setMaxBehindLines($maxBehindLines)
+ {
+ $this->maxBehindLines = $maxBehindLines;
+
+ return $this;
+ }
+
+ public function setMaxFrontLines($maxFrontLines)
+ {
+ $this->maxFrontLines = $maxFrontLines;
+
+ return $this;
+ }
+
+ public function setMaxAngle($maxAngle)
+ {
+ $this->maxAngle = $maxAngle;
+
+ return $this;
+ }
+
+ public function setMaxOffset($maxOffset)
+ {
+ $this->maxOffset = $maxOffset;
+
+ return $this;
+ }
+
+ /**
+ * Gets the captcha phrase
+ */
+ public function getPhrase()
+ {
+ return $this->phrase;
+ }
+
+ /**
+ * Returns true if the given phrase is good
+ */
+ public function testPhrase($phrase)
+ {
+ return ($this->builder->niceize($phrase) == $this->builder->niceize($this->getPhrase()));
+ }
+
+ /**
+ * Instantiation
+ */
+ public static function create($phrase = null)
+ {
+ return new self($phrase);
+ }
+
+ /**
+ * Sets the text color to use
+ */
+ public function setTextColor($r, $g, $b)
+ {
+ $this->textColor = array($r, $g, $b);
+
+ return $this;
+ }
+
+ /**
+ * Sets the background color to use
+ */
+ public function setBackgroundColor($r, $g, $b)
+ {
+ $this->backgroundColor = array($r, $g, $b);
+
+ return $this;
+ }
+
+ /**
+ * Sets the ignoreAllEffects value
+ *
+ * @param bool $ignoreAllEffects
+ * @return CaptchaBuilder
+ */
+ public function setIgnoreAllEffects($ignoreAllEffects)
+ {
+ $this->ignoreAllEffects = $ignoreAllEffects;
+
+ return $this;
+ }
+
+ /**
+ * Sets the list of background images to use (one image is randomly selected)
+ */
+ public function setBackgroundImages(array $backgroundImages)
+ {
+ $this->backgroundImages = $backgroundImages;
+
+ return $this;
+ }
+
+ /**
+ * Draw lines over the image
+ */
+ protected function drawLine($image, $width, $height, $tcol = null)
+ {
+ if ($tcol === null) {
+ $tcol = imagecolorallocate($image, $this->rand(100, 255), $this->rand(100, 255), $this->rand(100, 255));
+ }
+
+ if ($this->rand(0, 1)) { // Horizontal
+ $Xa = $this->rand(0, $width/2);
+ $Ya = $this->rand(0, $height);
+ $Xb = $this->rand($width/2, $width);
+ $Yb = $this->rand(0, $height);
+ } else { // Vertical
+ $Xa = $this->rand(0, $width);
+ $Ya = $this->rand(0, $height/2);
+ $Xb = $this->rand(0, $width);
+ $Yb = $this->rand($height/2, $height);
+ }
+ imagesetthickness($image, $this->rand(1, 3));
+ imageline($image, $Xa, $Ya, $Xb, $Yb, $tcol);
+ }
+
+ /**
+ * Apply some post effects
+ */
+ protected function postEffect($image)
+ {
+ if (!function_exists('imagefilter')) {
+ return;
+ }
+
+ if ($this->backgroundColor != null || $this->textColor != null) {
+ return;
+ }
+
+ // Negate ?
+ if ($this->rand(0, 1) == 0) {
+ imagefilter($image, IMG_FILTER_NEGATE);
+ }
+
+ // Edge ?
+ if ($this->rand(0, 10) == 0) {
+ imagefilter($image, IMG_FILTER_EDGEDETECT);
+ }
+
+ // Contrast
+ imagefilter($image, IMG_FILTER_CONTRAST, $this->rand(-50, 10));
+
+ // Colorize
+ if ($this->rand(0, 5) == 0) {
+ imagefilter($image, IMG_FILTER_COLORIZE, $this->rand(-80, 50), $this->rand(-80, 50), $this->rand(-80, 50));
+ }
+ }
+
+ /**
+ * Writes the phrase on the image
+ */
+ protected function writePhrase($image, $phrase, $font, $width, $height)
+ {
+ $length = strlen($phrase);
+ if ($length === 0) {
+ return imagecolorallocate($image, 0, 0, 0);
+ }
+
+ // Gets the text size and start position
+ $size = $width / $length - $this->rand(0, 3) - 1;
+ $box = imagettfbbox($size, 0, $font, $phrase);
+ $textWidth = $box[2] - $box[0];
+ $textHeight = $box[1] - $box[7];
+ $x = ($width - $textWidth) / 2;
+ $y = ($height - $textHeight) / 2 + $size;
+
+ if (!count($this->textColor)) {
+ $textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150));
+ } else {
+ $textColor = $this->textColor;
+ }
+ $col = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);
+
+ // Write the letters one by one, with random angle
+ for ($i=0; $i<$length; $i++) {
+ $box = imagettfbbox($size, 0, $font, $phrase[$i]);
+ $w = $box[2] - $box[0];
+ $angle = $this->rand(-$this->maxAngle, $this->maxAngle);
+ $offset = $this->rand(-$this->maxOffset, $this->maxOffset);
+ imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $phrase[$i]);
+ $x += $w;
+ }
+
+ return $col;
+ }
+
+ /**
+ * Try to read the code against an OCR
+ */
+ public function isOCRReadable()
+ {
+ if (!is_dir($this->tempDir)) {
+ @mkdir($this->tempDir, 0755, true);
+ }
+
+ $tempj = $this->tempDir . uniqid('captcha', true) . '.jpg';
+ $tempp = $this->tempDir . uniqid('captcha', true) . '.pgm';
+
+ $this->save($tempj);
+ shell_exec("convert $tempj $tempp");
+ $value = trim(strtolower(shell_exec("ocrad $tempp")));
+
+ @unlink($tempj);
+ @unlink($tempp);
+
+ return $this->testPhrase($value);
+ }
+
+ /**
+ * Builds while the code is readable against an OCR
+ */
+ public function buildAgainstOCR($width = 150, $height = 40, $font = null, $fingerprint = null)
+ {
+ do {
+ $this->build($width, $height, $font, $fingerprint);
+ } while ($this->isOCRReadable());
+ }
+
+ /**
+ * Generate the image
+ */
+ public function build($width = 150, $height = 40, $font = null, $fingerprint = null)
+ {
+ if (null !== $fingerprint) {
+ $this->fingerprint = $fingerprint;
+ $this->useFingerprint = true;
+ } else {
+ $this->fingerprint = array();
+ $this->useFingerprint = false;
+ }
+
+ if ($font === null) {
+ $font = __DIR__ . '/Font/captcha'.$this->rand(0, 5).'.ttf';
+ }
+
+ if (empty($this->backgroundImages)) {
+ // if background images list is not set, use a color fill as a background
+ $image = imagecreatetruecolor($width, $height);
+ if ($this->backgroundColor == null) {
+ $bg = imagecolorallocate($image, $this->rand(200, 255), $this->rand(200, 255), $this->rand(200, 255));
+ } else {
+ $color = $this->backgroundColor;
+ $bg = imagecolorallocate($image, $color[0], $color[1], $color[2]);
+ }
+ $this->background = $bg;
+ imagefill($image, 0, 0, $bg);
+ } else {
+ // use a random background image
+ $randomBackgroundImage = $this->backgroundImages[rand(0, count($this->backgroundImages)-1)];
+
+ $imageType = $this->validateBackgroundImage($randomBackgroundImage);
+
+ $image = $this->createBackgroundImageFromType($randomBackgroundImage, $imageType);
+ }
+
+ // Apply effects
+ if (!$this->ignoreAllEffects) {
+ $square = $width * $height;
+ $effects = $this->rand($square/3000, $square/2000);
+
+ // set the maximum number of lines to draw in front of the text
+ if ($this->maxBehindLines != null && $this->maxBehindLines > 0) {
+ $effects = min($this->maxBehindLines, $effects);
+ }
+
+ if ($this->maxBehindLines !== 0) {
+ for ($e = 0; $e < $effects; $e++) {
+ $this->drawLine($image, $width, $height);
+ }
+ }
+ }
+
+ // Write CAPTCHA text
+ $color = $this->writePhrase($image, $this->phrase, $font, $width, $height);
+
+ // Apply effects
+ if (!$this->ignoreAllEffects) {
+ $square = $width * $height;
+ $effects = $this->rand($square/3000, $square/2000);
+
+ // set the maximum number of lines to draw in front of the text
+ if ($this->maxFrontLines != null && $this->maxFrontLines > 0) {
+ $effects = min($this->maxFrontLines, $effects);
+ }
+
+ if ($this->maxFrontLines !== 0) {
+ for ($e = 0; $e < $effects; $e++) {
+ $this->drawLine($image, $width, $height, $color);
+ }
+ }
+ }
+
+ // Distort the image
+ if ($this->distortion && !$this->ignoreAllEffects) {
+ $image = $this->distort($image, $width, $height, $bg);
+ }
+
+ // Post effects
+ if (!$this->ignoreAllEffects) {
+ $this->postEffect($image);
+ }
+
+ $this->contents = $image;
+
+ return $this;
+ }
+
+ /**
+ * Distorts the image
+ */
+ public function distort($image, $width, $height, $bg)
+ {
+ $contents = imagecreatetruecolor($width, $height);
+ $X = $this->rand(0, $width);
+ $Y = $this->rand(0, $height);
+ $phase = $this->rand(0, 10);
+ $scale = 1.1 + $this->rand(0, 10000) / 30000;
+ for ($x = 0; $x < $width; $x++) {
+ for ($y = 0; $y < $height; $y++) {
+ $Vx = $x - $X;
+ $Vy = $y - $Y;
+ $Vn = sqrt($Vx * $Vx + $Vy * $Vy);
+
+ if ($Vn != 0) {
+ $Vn2 = $Vn + 4 * sin($Vn / 30);
+ $nX = $X + ($Vx * $Vn2 / $Vn);
+ $nY = $Y + ($Vy * $Vn2 / $Vn);
+ } else {
+ $nX = $X;
+ $nY = $Y;
+ }
+ $nY = $nY + $scale * sin($phase + $nX * 0.2);
+
+ if ($this->interpolation) {
+ $p = $this->interpolate(
+ $nX - floor($nX),
+ $nY - floor($nY),
+ $this->getCol($image, floor($nX), floor($nY), $bg),
+ $this->getCol($image, ceil($nX), floor($nY), $bg),
+ $this->getCol($image, floor($nX), ceil($nY), $bg),
+ $this->getCol($image, ceil($nX), ceil($nY), $bg)
+ );
+ } else {
+ $p = $this->getCol($image, round($nX), round($nY), $bg);
+ }
+
+ if ($p == 0) {
+ $p = $bg;
+ }
+
+ imagesetpixel($contents, $x, $y, $p);
+ }
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Saves the Captcha to a jpeg file
+ */
+ public function save($filename, $quality = 90)
+ {
+ imagejpeg($this->contents, $filename, $quality);
+ }
+
+ /**
+ * Gets the image GD
+ */
+ public function getGd()
+ {
+ return $this->contents;
+ }
+
+ /**
+ * Gets the image contents
+ */
+ public function get($quality = 90)
+ {
+ ob_start();
+ $this->output($quality);
+
+ return ob_get_clean();
+ }
+
+ /**
+ * Gets the HTML inline base64
+ */
+ public function inline($quality = 90)
+ {
+ return 'data:image/jpeg;base64,' . base64_encode($this->get($quality));
+ }
+
+ /**
+ * Outputs the image
+ */
+ public function output($quality = 90)
+ {
+ imagejpeg($this->contents, null, $quality);
+ }
+
+ /**
+ * @return array
+ */
+ public function getFingerprint()
+ {
+ return $this->fingerprint;
+ }
+
+ /**
+ * Returns a random number or the next number in the
+ * fingerprint
+ */
+ protected function rand($min, $max)
+ {
+ if (!is_array($this->fingerprint)) {
+ $this->fingerprint = array();
+ }
+
+ if ($this->useFingerprint) {
+ $value = current($this->fingerprint);
+ next($this->fingerprint);
+ } else {
+ $value = mt_rand($min, $max);
+ $this->fingerprint[] = $value;
+ }
+
+ return $value;
+ }
+
+ /**
+ * @param $x
+ * @param $y
+ * @param $nw
+ * @param $ne
+ * @param $sw
+ * @param $se
+ *
+ * @return int
+ */
+ protected function interpolate($x, $y, $nw, $ne, $sw, $se)
+ {
+ list($r0, $g0, $b0) = $this->getRGB($nw);
+ list($r1, $g1, $b1) = $this->getRGB($ne);
+ list($r2, $g2, $b2) = $this->getRGB($sw);
+ list($r3, $g3, $b3) = $this->getRGB($se);
+
+ $cx = 1.0 - $x;
+ $cy = 1.0 - $y;
+
+ $m0 = $cx * $r0 + $x * $r1;
+ $m1 = $cx * $r2 + $x * $r3;
+ $r = (int) ($cy * $m0 + $y * $m1);
+
+ $m0 = $cx * $g0 + $x * $g1;
+ $m1 = $cx * $g2 + $x * $g3;
+ $g = (int) ($cy * $m0 + $y * $m1);
+
+ $m0 = $cx * $b0 + $x * $b1;
+ $m1 = $cx * $b2 + $x * $b3;
+ $b = (int) ($cy * $m0 + $y * $m1);
+
+ return ($r << 16) | ($g << 8) | $b;
+ }
+
+ /**
+ * @param $image
+ * @param $x
+ * @param $y
+ *
+ * @return int
+ */
+ protected function getCol($image, $x, $y, $background)
+ {
+ $L = imagesx($image);
+ $H = imagesy($image);
+ if ($x < 0 || $x >= $L || $y < 0 || $y >= $H) {
+ return $background;
+ }
+
+ return imagecolorat($image, $x, $y);
+ }
+
+ /**
+ * @param $col
+ *
+ * @return array
+ */
+ protected function getRGB($col)
+ {
+ return array(
+ (int) ($col >> 16) & 0xff,
+ (int) ($col >> 8) & 0xff,
+ (int) ($col) & 0xff,
+ );
+ }
+
+ /**
+ * Validate the background image path. Return the image type if valid
+ *
+ * @param string $backgroundImage
+ * @return string
+ * @throws Exception
+ */
+ protected function validateBackgroundImage($backgroundImage)
+ {
+ // check if file exists
+ if (!file_exists($backgroundImage)) {
+ $backgroundImageExploded = explode('/', $backgroundImage);
+ $imageFileName = count($backgroundImageExploded) > 1? $backgroundImageExploded[count($backgroundImageExploded)-1] : $backgroundImage;
+
+ throw new Exception('Invalid background image: ' . $imageFileName);
+ }
+
+ // check image type
+ $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
+ $imageType = finfo_file($finfo, $backgroundImage);
+ finfo_close($finfo);
+
+ if (!in_array ($imageType, $this->allowedBackgroundImageTypes)) {
+ throw new Exception('Invalid background image type! Allowed types are: ' . join(', ', $this->allowedBackgroundImageTypes));
+ }
+
+ return $imageType;
+ }
+
+ /**
+ * Create background image from type
+ *
+ * @param string $backgroundImage
+ * @param string $imageType
+ * @return resource
+ * @throws Exception
+ */
+ protected function createBackgroundImageFromType($backgroundImage, $imageType)
+ {
+ switch ($imageType) {
+ case 'image/jpeg':
+ $image = imagecreatefromjpeg($backgroundImage);
+ break;
+ case 'image/png':
+ $image = imagecreatefrompng($backgroundImage);
+ break;
+ case 'image/gif':
+ $image = imagecreatefromgif($backgroundImage);
+ break;
+
+ default:
+ throw new Exception('Not supported file type for background image!');
+ break;
+ }
+
+ return $image;
+ }
+}
diff --git a/vendor/gregwar/captcha/CaptchaBuilderInterface.php b/vendor/gregwar/captcha/CaptchaBuilderInterface.php
new file mode 100644
index 00000000..bdebf38f
--- /dev/null
+++ b/vendor/gregwar/captcha/CaptchaBuilderInterface.php
@@ -0,0 +1,30 @@
+
+ * @author Jeremy Livingston
+ */
+class ImageFileHandler
+{
+ /**
+ * Name of folder for captcha images
+ * @var string
+ */
+ protected $imageFolder;
+
+ /**
+ * Absolute path to public web folder
+ * @var string
+ */
+ protected $webPath;
+
+ /**
+ * Frequency of garbage collection in fractions of 1
+ * @var int
+ */
+ protected $gcFreq;
+
+ /**
+ * Maximum age of images in minutes
+ * @var int
+ */
+ protected $expiration;
+
+ /**
+ * @param $imageFolder
+ * @param $webPath
+ * @param $gcFreq
+ * @param $expiration
+ */
+ public function __construct($imageFolder, $webPath, $gcFreq, $expiration)
+ {
+ $this->imageFolder = $imageFolder;
+ $this->webPath = $webPath;
+ $this->gcFreq = $gcFreq;
+ $this->expiration = $expiration;
+ }
+
+ /**
+ * Saves the provided image content as a file
+ *
+ * @param string $contents
+ *
+ * @return string
+ */
+ public function saveAsFile($contents)
+ {
+ $this->createFolderIfMissing();
+
+ $filename = md5(uniqid()) . '.jpg';
+ $filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename;
+ imagejpeg($contents, $filePath, 15);
+
+ return '/' . $this->imageFolder . '/' . $filename;
+ }
+
+ /**
+ * Randomly runs garbage collection on the image directory
+ *
+ * @return bool
+ */
+ public function collectGarbage()
+ {
+ if (!mt_rand(1, $this->gcFreq) == 1) {
+ return false;
+ }
+
+ $this->createFolderIfMissing();
+
+ $finder = new Finder();
+ $criteria = sprintf('<= now - %s minutes', $this->expiration);
+ $finder->in($this->webPath . '/' . $this->imageFolder)
+ ->date($criteria);
+
+ foreach($finder->files() as $file) {
+ unlink($file->getPathname());
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates the folder if it doesn't exist
+ */
+ protected function createFolderIfMissing()
+ {
+ if (!file_exists($this->webPath . '/' . $this->imageFolder)) {
+ mkdir($this->webPath . '/' . $this->imageFolder, 0755);
+ }
+ }
+}
+
diff --git a/vendor/gregwar/captcha/LICENSE b/vendor/gregwar/captcha/LICENSE
new file mode 100644
index 00000000..7db6ad8e
--- /dev/null
+++ b/vendor/gregwar/captcha/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) <2012-2015> Grégoire Passault
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/gregwar/captcha/PhraseBuilder.php b/vendor/gregwar/captcha/PhraseBuilder.php
new file mode 100644
index 00000000..b94bd61c
--- /dev/null
+++ b/vendor/gregwar/captcha/PhraseBuilder.php
@@ -0,0 +1,34 @@
+
+ */
+class PhraseBuilder implements PhraseBuilderInterface
+{
+ /**
+ * Generates random phrase of given length with given charset
+ */
+ public function build($length = 5, $charset = 'abcdefghijklmnpqrstuvwxyz123456789')
+ {
+ $phrase = '';
+ $chars = str_split($charset);
+
+ for ($i = 0; $i < $length; $i++) {
+ $phrase .= $chars[array_rand($chars)];
+ }
+
+ return $phrase;
+ }
+
+ /**
+ * "Niceize" a code
+ */
+ public function niceize($str)
+ {
+ return strtr(strtolower($str), '01', 'ol');
+ }
+}
diff --git a/vendor/gregwar/captcha/PhraseBuilderInterface.php b/vendor/gregwar/captcha/PhraseBuilderInterface.php
new file mode 100644
index 00000000..0a4f5361
--- /dev/null
+++ b/vendor/gregwar/captcha/PhraseBuilderInterface.php
@@ -0,0 +1,21 @@
+
+ */
+interface PhraseBuilderInterface
+{
+ /**
+ * Generates random phrase of given length with given charset
+ */
+ public function build($length, $charset);
+
+ /**
+ * "Niceize" a code
+ */
+ public function niceize($str);
+}
diff --git a/vendor/gregwar/captcha/README.md b/vendor/gregwar/captcha/README.md
new file mode 100644
index 00000000..9f6c17a9
--- /dev/null
+++ b/vendor/gregwar/captcha/README.md
@@ -0,0 +1,108 @@
+Captcha
+=======
+
+![Captchas examples](http://gregwar.com/captchas.png)
+
+Installation
+============
+
+With composer :
+
+``` json
+{
+ ...
+ "require": {
+ "gregwar/captcha": "1.*"
+ }
+}
+```
+
+Usage
+=====
+
+You can create a captcha with the `CaptchaBuilder` :
+
+```php
+build();
+```
+
+You can then save it to a file :
+
+```php
+save('out.jpg');
+```
+
+Or output it directly :
+
+```php
+output();
+```
+
+Or inline it directly in the HTML page:
+
+```php
+
+```
+
+You'll be able to get the code and compare it with a user input :
+
+```php
+getPhrase();
+```
+
+You can compare the phrase with user input:
+```php
+if($builder->testPhrase($userInput)) {
+ // instructions if user phrase is good
+}
+else {
+ // user phrase is wrong
+}
+```
+
+API
+===
+
+You can use theses functions :
+
+* **__construct($phrase = null)**, constructs the builder with the given phrase, if the phrase is null, a random one will be generated
+* **getPhrase()**, allow you to get the phrase contents
+* **setDistortion($distortion)**, enable or disable the distortion, call it before `build()`
+* **isOCRReadable()**, returns `true` if the OCR can be read using the `ocrad` software, you'll need to have shell_exec enabled, imagemagick and ocrad installed
+* **buildAgainstOCR($width = 150, $height = 40, $font = null)**, builds a code until it is not readable by `ocrad`
+* **build($width = 150, $height = 40, $font = null)**, builds a code with the given $width, $height and $font. By default, a random font will be used from the library
+* **save($filename, $quality = 80)**, saves the captcha into a jpeg in the $filename, with the given quality
+* **get($quality = 80)**, returns the jpeg data
+* **output($quality = 80)**, directly outputs the jpeg code to a browser
+* **setBackgroundColor($r, $g, $b)**, sets the background color to force it (this will disable many effects and is not recommended)
+* **setBackgroundImages(array($imagepath1, $imagePath2))**, Sets custom background images to be used as captcha background. It is recommended to disable image effects when passing custom images for background (ignore_all_effects). A random image is selected from the list passed, the full paths to the image files must be passed.
+* **setInterpolation($interpolate)**, enable or disable the interpolation (enabled by default), disabling it will be quicker but the images will look uglier
+* **setIgnoreAllEffects($ignoreAllEffects)**, disable all effects on the captcha image. Recommended to use when passing custom background images for the captcha.
+* **testPhrase($phrase)**, returns true if the given phrase is good
+* **setMaxBehindLines($lines)**, sets the maximum number of lines behind the code
+* **setMaxFrontLines($lines)**, sets the maximum number of lines on the front of the code
+
+Symfony 2 Bundle
+================
+
+You can have a look at the following repository to enjoy the Symfony 2 bundle packaging this captcha generator :
+https://github.com/Gregwar/CaptchaBundle
+
+License
+=======
+
+This library is under MIT license, have a look to the `LICENSE` file
diff --git a/vendor/gregwar/captcha/autoload.php b/vendor/gregwar/captcha/autoload.php
new file mode 100644
index 00000000..8b3fa392
--- /dev/null
+++ b/vendor/gregwar/captcha/autoload.php
@@ -0,0 +1,16 @@
+=5.3.0",
+ "ext-gd": "*"
+ },
+ "autoload": {
+ "psr-4": {
+ "Gregwar\\Captcha\\": "/"
+ }
+ }
+}
diff --git a/vendor/gregwar/captcha/demo/demo.php b/vendor/gregwar/captcha/demo/demo.php
new file mode 100644
index 00000000..7852745f
--- /dev/null
+++ b/vendor/gregwar/captcha/demo/demo.php
@@ -0,0 +1,14 @@
+build()
+ ->save('out.jpg')
+;
diff --git a/vendor/gregwar/captcha/demo/fingerprint.php b/vendor/gregwar/captcha/demo/fingerprint.php
new file mode 100644
index 00000000..ce30d991
--- /dev/null
+++ b/vendor/gregwar/captcha/demo/fingerprint.php
@@ -0,0 +1,15 @@
+build()
+ ->getFingerprint()
+);
+
+echo "\n";
diff --git a/vendor/gregwar/captcha/demo/index.php b/vendor/gregwar/captcha/demo/index.php
new file mode 100644
index 00000000..e543883b
--- /dev/null
+++ b/vendor/gregwar/captcha/demo/index.php
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ Captchas gallery
+
+
+
+
+
+
+
+
diff --git a/vendor/gregwar/captcha/demo/ocr.php b/vendor/gregwar/captcha/demo/ocr.php
new file mode 100644
index 00000000..3d745f65
--- /dev/null
+++ b/vendor/gregwar/captcha/demo/ocr.php
@@ -0,0 +1,42 @@
+setDistortion(false)
+ ->build()
+ ;
+
+ if ($captcha->isOCRReadable()) {
+ $passed++;
+ $captcha->save("passed$passed.jpg");
+ echo "passed at ocr... ";
+ } else {
+ echo "failed... ";
+ }
+
+ echo "pass rate: ".round(100*$passed/($i+1),2)."%\n";
+}
+
+echo "\n";
+echo "Over, $passed/$tests readed with OCR\n";
diff --git a/vendor/gregwar/captcha/demo/output.php b/vendor/gregwar/captcha/demo/output.php
new file mode 100644
index 00000000..2a4f3303
--- /dev/null
+++ b/vendor/gregwar/captcha/demo/output.php
@@ -0,0 +1,15 @@
+build()
+ ->output()
+;
diff --git a/vendor/miniflux/picofeed/LICENSE b/vendor/miniflux/picofeed/LICENSE
new file mode 100644
index 00000000..6a362bc1
--- /dev/null
+++ b/vendor/miniflux/picofeed/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Frederic Guillot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Base.php b/vendor/miniflux/picofeed/lib/PicoFeed/Base.php
new file mode 100644
index 00000000..41a6f8f0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Base.php
@@ -0,0 +1,38 @@
+config = $config ?: new Config();
+ Logger::setTimezone($this->config->getTimezone());
+ }
+
+ public function setConfig(Config $config) {
+ $this->config = $config;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/Client.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/Client.php
new file mode 100644
index 00000000..0548d5c6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Client/Client.php
@@ -0,0 +1,719 @@
+request_headers = $headers;
+ }
+
+ /**
+ * Perform the HTTP request.
+ *
+ * @param string $url URL
+ *
+ * @return Client
+ */
+ public function execute($url = '')
+ {
+ if ($url !== '') {
+ $this->url = $url;
+ }
+
+ Logger::setMessage(get_called_class().' Fetch URL: '.$this->url);
+ Logger::setMessage(get_called_class().' Etag provided: '.$this->etag);
+ Logger::setMessage(get_called_class().' Last-Modified provided: '.$this->last_modified);
+
+ $response = $this->doRequest();
+
+ $this->status_code = $response['status'];
+ $this->handleNotModifiedResponse($response);
+ $this->handleErrorResponse($response);
+ $this->handleNormalResponse($response);
+
+ $this->expiration = $this->parseExpiration($response['headers']);
+ Logger::setMessage(get_called_class().' Expiration: '.$this->expiration->format(DATE_ISO8601));
+
+ return $this;
+ }
+
+ /**
+ * Handle not modified response.
+ *
+ * @param array $response Client response
+ */
+ protected function handleNotModifiedResponse(array $response)
+ {
+ if ($response['status'] == 304) {
+ $this->is_modified = false;
+ } elseif ($response['status'] == 200) {
+ $this->is_modified = $this->hasBeenModified($response, $this->etag, $this->last_modified);
+ $this->etag = $this->getHeader($response, 'ETag');
+ $this->last_modified = $this->getHeader($response, 'Last-Modified');
+ }
+
+ if ($this->is_modified === false) {
+ Logger::setMessage(get_called_class().' Resource not modified');
+ }
+ }
+
+ /**
+ * Handle Http Error codes
+ *
+ * @param array $response Client response
+ * @throws ForbiddenException
+ * @throws InvalidUrlException
+ * @throws UnauthorizedException
+ */
+ protected function handleErrorResponse(array $response)
+ {
+ $status = $response['status'];
+ if ($status == 401) {
+ throw new UnauthorizedException('Wrong or missing credentials');
+ } else if ($status == 403) {
+ throw new ForbiddenException('Not allowed to access resource');
+ } else if ($status == 404) {
+ throw new InvalidUrlException('Resource not found');
+ }
+ }
+
+ /**
+ * Handle normal response.
+ *
+ * @param array $response Client response
+ */
+ protected function handleNormalResponse(array $response)
+ {
+ if ($response['status'] == 200) {
+ $this->content = $response['body'];
+ $this->content_type = $this->findContentType($response);
+ $this->encoding = $this->findCharset();
+ }
+ }
+
+ /**
+ * Check if a request has been modified according to the parameters.
+ *
+ * @param array $response
+ * @param string $etag
+ * @param string $lastModified
+ *
+ * @return bool
+ */
+ private function hasBeenModified($response, $etag, $lastModified)
+ {
+ $headers = array(
+ 'Etag' => $etag,
+ 'Last-Modified' => $lastModified,
+ );
+
+ // Compare the values for each header that is present
+ $presentCacheHeaderCount = 0;
+ foreach ($headers as $key => $value) {
+ if (isset($response['headers'][$key])) {
+ if ($response['headers'][$key] !== $value) {
+ return true;
+ }
+ ++$presentCacheHeaderCount;
+ }
+ }
+
+ // If at least one header is present and the values match, the response
+ // was not modified
+ if ($presentCacheHeaderCount > 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Find content type from response headers.
+ *
+ * @param array $response Client response
+ *
+ * @return string
+ */
+ public function findContentType(array $response)
+ {
+ return strtolower($this->getHeader($response, 'Content-Type'));
+ }
+
+ /**
+ * Find charset from response headers.
+ *
+ * @return string
+ */
+ public function findCharset()
+ {
+ $result = explode('charset=', $this->content_type);
+
+ return isset($result[1]) ? $result[1] : '';
+ }
+
+ /**
+ * Get header value from a client response.
+ *
+ * @param array $response Client response
+ * @param string $header Header name
+ *
+ * @return string
+ */
+ public function getHeader(array $response, $header)
+ {
+ return isset($response['headers'][$header]) ? $response['headers'][$header] : '';
+ }
+
+ /**
+ * Set the Last-Modified HTTP header.
+ *
+ * @param string $last_modified Header value
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setLastModified($last_modified)
+ {
+ $this->last_modified = $last_modified;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of the Last-Modified HTTP header.
+ *
+ * @return string
+ */
+ public function getLastModified()
+ {
+ return $this->last_modified;
+ }
+
+ /**
+ * Set the value of the Etag HTTP header.
+ *
+ * @param string $etag Etag HTTP header value
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setEtag($etag)
+ {
+ $this->etag = $etag;
+
+ return $this;
+ }
+
+ /**
+ * Get the Etag HTTP header value.
+ *
+ * @return string
+ */
+ public function getEtag()
+ {
+ return $this->etag;
+ }
+
+ /**
+ * Get the final url value.
+ *
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Set the url.
+ *
+ * @param $url
+ * @return string
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ return $this;
+ }
+
+ /**
+ * Get the HTTP response status code.
+ *
+ * @return int
+ */
+ public function getStatusCode()
+ {
+ return $this->status_code;
+ }
+
+ /**
+ * Get the body of the HTTP response.
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Get the content type value from HTTP headers.
+ *
+ * @return string
+ */
+ public function getContentType()
+ {
+ return $this->content_type;
+ }
+
+ /**
+ * Get the encoding value from HTTP headers.
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->encoding;
+ }
+
+ /**
+ * Return true if the remote resource has changed.
+ *
+ * @return bool
+ */
+ public function isModified()
+ {
+ return $this->is_modified;
+ }
+
+ /**
+ * return true if passthrough mode is enabled.
+ *
+ * @return bool
+ */
+ public function isPassthroughEnabled()
+ {
+ return $this->passthrough;
+ }
+
+ /**
+ * Set connection timeout.
+ *
+ * @param int $timeout Connection timeout
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setTimeout($timeout)
+ {
+ $this->timeout = $timeout ?: $this->timeout;
+
+ return $this;
+ }
+
+ /**
+ * Set a custom user agent.
+ *
+ * @param string $user_agent User Agent
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setUserAgent($user_agent)
+ {
+ $this->user_agent = $user_agent ?: $this->user_agent;
+
+ return $this;
+ }
+
+ /**
+ * Set the maximum number of HTTP redirections.
+ *
+ * @param int $max Maximum
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setMaxRedirections($max)
+ {
+ $this->max_redirects = $max ?: $this->max_redirects;
+
+ return $this;
+ }
+
+ /**
+ * Set the maximum size of the HTTP body.
+ *
+ * @param int $max Maximum
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setMaxBodySize($max)
+ {
+ $this->max_body_size = $max ?: $this->max_body_size;
+
+ return $this;
+ }
+
+ /**
+ * Set the proxy hostname.
+ *
+ * @param string $hostname Proxy hostname
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyHostname($hostname)
+ {
+ $this->proxy_hostname = $hostname ?: $this->proxy_hostname;
+
+ return $this;
+ }
+
+ /**
+ * Set the proxy port.
+ *
+ * @param int $port Proxy port
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyPort($port)
+ {
+ $this->proxy_port = $port ?: $this->proxy_port;
+
+ return $this;
+ }
+
+ /**
+ * Set the proxy username.
+ *
+ * @param string $username Proxy username
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyUsername($username)
+ {
+ $this->proxy_username = $username ?: $this->proxy_username;
+
+ return $this;
+ }
+
+ /**
+ * Set the proxy password.
+ *
+ * @param string $password Password
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setProxyPassword($password)
+ {
+ $this->proxy_password = $password ?: $this->proxy_password;
+
+ return $this;
+ }
+
+ /**
+ * Set the username.
+ *
+ * @param string $username Basic Auth username
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username ?: $this->username;
+
+ return $this;
+ }
+
+ /**
+ * Set the password.
+ *
+ * @param string $password Basic Auth Password
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password ?: $this->password;
+
+ return $this;
+ }
+
+ /**
+ * Enable the passthrough mode.
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function enablePassthroughMode()
+ {
+ $this->passthrough = true;
+
+ return $this;
+ }
+
+ /**
+ * Disable the passthrough mode.
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function disablePassthroughMode()
+ {
+ $this->passthrough = false;
+
+ return $this;
+ }
+
+ /**
+ * Set config object.
+ *
+ * @param \PicoFeed\Config\Config $config Config instance
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function setConfig(Config $config)
+ {
+ if ($config !== null) {
+ $this->setTimeout($config->getClientTimeout());
+ $this->setUserAgent($config->getClientUserAgent());
+ $this->setMaxRedirections($config->getMaxRedirections());
+ $this->setMaxBodySize($config->getMaxBodySize());
+ $this->setProxyHostname($config->getProxyHostname());
+ $this->setProxyPort($config->getProxyPort());
+ $this->setProxyUsername($config->getProxyUsername());
+ $this->setProxyPassword($config->getProxyPassword());
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return true if the HTTP status code is a redirection
+ *
+ * @access protected
+ * @param integer $code
+ * @return boolean
+ */
+ public function isRedirection($code)
+ {
+ return $code == 301 || $code == 302 || $code == 303 || $code == 307;
+ }
+
+ public function parseExpiration(HttpHeaders $headers)
+ {
+ try {
+
+ if (isset($headers['Cache-Control'])) {
+ if (preg_match('/s-maxage=(\d+)/', $headers['Cache-Control'], $matches)) {
+ return new DateTime('+' . $matches[1] . ' seconds');
+ } else if (preg_match('/max-age=(\d+)/', $headers['Cache-Control'], $matches)) {
+ return new DateTime('+' . $matches[1] . ' seconds');
+ }
+ }
+
+ if (! empty($headers['Expires'])) {
+ return new DateTime($headers['Expires']);
+ }
+ } catch (Exception $e) {
+ Logger::setMessage('Unable to parse expiration date: '.$e->getMessage());
+ }
+
+ return new DateTime();
+ }
+
+ /**
+ * Get expiration date time from "Expires" or "Cache-Control" headers
+ *
+ * @return DateTime
+ */
+ public function getExpiration()
+ {
+ return $this->expiration ?: new DateTime();
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php
new file mode 100644
index 00000000..b3a95c9f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Client/ClientException.php
@@ -0,0 +1,14 @@
+body_length += $length;
+
+ if ($this->body_length > $this->max_body_size) {
+ return -1;
+ }
+
+ $this->body .= $buffer;
+
+ return $length;
+ }
+
+ /**
+ * cURL callback to read HTTP headers.
+ *
+ * @param resource $ch cURL handler
+ * @param string $buffer Header line
+ *
+ * @return int Length of the buffer
+ */
+ public function readHeaders($ch, $buffer)
+ {
+ $length = strlen($buffer);
+
+ if ($buffer === "\r\n" || $buffer === "\n") {
+ ++$this->response_headers_count;
+ } else {
+ if (!isset($this->response_headers[$this->response_headers_count])) {
+ $this->response_headers[$this->response_headers_count] = '';
+ }
+
+ $this->response_headers[$this->response_headers_count] .= $buffer;
+ }
+
+ return $length;
+ }
+
+ /**
+ * cURL callback to passthrough the HTTP body to the client.
+ *
+ * If the function return -1, curl stop to read the HTTP response
+ *
+ * @param resource $ch cURL handler
+ * @param string $buffer Chunk of data
+ *
+ * @return int Length of the buffer
+ */
+ public function passthroughBody($ch, $buffer)
+ {
+ // do it only at the beginning of a transmission
+ if ($this->body_length === 0) {
+ list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1]));
+
+ if ($this->isRedirection($status)) {
+ return $this->handleRedirection($headers['Location']);
+ }
+
+ // Do not work with PHP-FPM
+ if (strpos(PHP_SAPI, 'cgi') !== false) {
+ header(':', true, $status);
+ }
+
+ if (isset($headers['Content-Type'])) {
+ header('Content-Type:' .$headers['Content-Type']);
+ }
+ }
+
+ $length = strlen($buffer);
+ $this->body_length += $length;
+
+ echo $buffer;
+
+ return $length;
+ }
+
+ /**
+ * Prepare HTTP headers.
+ *
+ * @return string[]
+ */
+ private function prepareHeaders()
+ {
+ $headers = array(
+ 'Connection: close',
+ );
+
+ if ($this->etag) {
+ $headers[] = 'If-None-Match: '.$this->etag;
+ $headers[] = 'A-IM: feed';
+ }
+
+ if ($this->last_modified) {
+ $headers[] = 'If-Modified-Since: '.$this->last_modified;
+ }
+
+ $headers = array_merge($headers, $this->request_headers);
+
+ return $headers;
+ }
+
+ /**
+ * Prepare curl proxy context.
+ *
+ * @param resource $ch
+ *
+ * @return resource $ch
+ */
+ private function prepareProxyContext($ch)
+ {
+ if ($this->proxy_hostname) {
+ Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port);
+
+ curl_setopt($ch, CURLOPT_PROXYPORT, $this->proxy_port);
+ curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP');
+ curl_setopt($ch, CURLOPT_PROXY, $this->proxy_hostname);
+
+ if ($this->proxy_username) {
+ Logger::setMessage(get_called_class().' Proxy credentials: Yes');
+ curl_setopt($ch, CURLOPT_PROXYUSERPWD, $this->proxy_username.':'.$this->proxy_password);
+ } else {
+ Logger::setMessage(get_called_class().' Proxy credentials: No');
+ }
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Prepare curl auth context.
+ *
+ * @param resource $ch
+ *
+ * @return resource $ch
+ */
+ private function prepareAuthContext($ch)
+ {
+ if ($this->username && $this->password) {
+ curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password);
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Set write/header functions.
+ *
+ * @param resource $ch
+ *
+ * @return resource $ch
+ */
+ private function prepareDownloadMode($ch)
+ {
+ $this->body = '';
+ $this->response_headers = array();
+ $this->response_headers_count = 0;
+ $write_function = 'readBody';
+ $header_function = 'readHeaders';
+
+ if ($this->isPassthroughEnabled()) {
+ $write_function = 'passthroughBody';
+ }
+
+ curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, $write_function));
+ curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, $header_function));
+
+ return $ch;
+ }
+
+ /**
+ * Prepare curl context.
+ *
+ * @return resource
+ */
+ private function prepareContext()
+ {
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $this->url);
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout);
+ curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $this->prepareHeaders());
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($ch, CURLOPT_ENCODING, '');
+ curl_setopt($ch, CURLOPT_COOKIEJAR, 'php://memory');
+ curl_setopt($ch, CURLOPT_COOKIEFILE, 'php://memory');
+
+ // Disable SSLv3 by enforcing TLSv1.x for curl >= 7.34.0 and < 7.39.0.
+ // Versions prior to 7.34 and at least when compiled against openssl
+ // interpret this parameter as "limit to TLSv1.0" which fails for sites
+ // which enforce TLS 1.1+.
+ // Starting with curl 7.39.0 SSLv3 is disabled by default.
+ $version = curl_version();
+ if ($version['version_number'] >= 467456 && $version['version_number'] < 468736) {
+ curl_setopt($ch, CURLOPT_SSLVERSION, 1);
+ }
+
+ $ch = $this->prepareDownloadMode($ch);
+ $ch = $this->prepareProxyContext($ch);
+ $ch = $this->prepareAuthContext($ch);
+
+ return $ch;
+ }
+
+ /**
+ * Execute curl context.
+ */
+ private function executeContext()
+ {
+ $ch = $this->prepareContext();
+ curl_exec($ch);
+
+ Logger::setMessage(get_called_class().' cURL total time: '.curl_getinfo($ch, CURLINFO_TOTAL_TIME));
+ Logger::setMessage(get_called_class().' cURL dns lookup time: '.curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME));
+ Logger::setMessage(get_called_class().' cURL connect time: '.curl_getinfo($ch, CURLINFO_CONNECT_TIME));
+ Logger::setMessage(get_called_class().' cURL speed download: '.curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD));
+ Logger::setMessage(get_called_class().' cURL effective url: '.curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
+
+ $curl_errno = curl_errno($ch);
+
+ if ($curl_errno) {
+ Logger::setMessage(get_called_class().' cURL error: '.curl_error($ch));
+ curl_close($ch);
+
+ $this->handleError($curl_errno);
+ }
+
+ // Update the url if there where redirects
+ $this->url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
+
+ curl_close($ch);
+ }
+
+ /**
+ * Do the HTTP request.
+ *
+ * @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
+ */
+ public function doRequest()
+ {
+ $this->executeContext();
+
+ list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1]));
+
+ if ($this->isRedirection($status)) {
+ if (empty($headers['Location'])) {
+ $status = 200;
+ } else {
+ return $this->handleRedirection($headers['Location']);
+ }
+ }
+
+ return array(
+ 'status' => $status,
+ 'body' => $this->body,
+ 'headers' => $headers,
+ );
+ }
+
+ /**
+ * Handle HTTP redirects
+ *
+ * @param string $location Redirected URL
+ * @return array
+ * @throws MaxRedirectException
+ */
+ private function handleRedirection($location)
+ {
+ $result = array();
+ $this->url = Url::resolve($location, $this->url);
+ $this->body = '';
+ $this->body_length = 0;
+ $this->response_headers = array();
+ $this->response_headers_count = 0;
+
+ while (true) {
+ $this->nbRedirects++;
+
+ if ($this->nbRedirects >= $this->max_redirects) {
+ throw new MaxRedirectException('Maximum number of redirections reached');
+ }
+
+ $result = $this->doRequest();
+
+ if ($this->isRedirection($result['status'])) {
+ $this->url = Url::resolve($result['headers']['Location'], $this->url);
+ $this->body = '';
+ $this->body_length = 0;
+ $this->response_headers = array();
+ $this->response_headers_count = 0;
+ } else {
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Handle cURL errors (throw individual exceptions).
+ *
+ * We don't use constants because they are not necessary always available
+ * (depends of the version of libcurl linked to php)
+ *
+ * @see http://curl.haxx.se/libcurl/c/libcurl-errors.html
+ *
+ * @param int $errno cURL error code
+ * @throws InvalidCertificateException
+ * @throws InvalidUrlException
+ * @throws MaxRedirectException
+ * @throws MaxSizeException
+ * @throws TimeoutException
+ */
+ private function handleError($errno)
+ {
+ switch ($errno) {
+ case 78: // CURLE_REMOTE_FILE_NOT_FOUND
+ throw new InvalidUrlException('Resource not found', $errno);
+ case 6: // CURLE_COULDNT_RESOLVE_HOST
+ throw new InvalidUrlException('Unable to resolve hostname', $errno);
+ case 7: // CURLE_COULDNT_CONNECT
+ throw new InvalidUrlException('Unable to connect to the remote host', $errno);
+ case 23: // CURLE_WRITE_ERROR
+ throw new MaxSizeException('Maximum response size exceeded', $errno);
+ case 28: // CURLE_OPERATION_TIMEDOUT
+ throw new TimeoutException('Operation timeout', $errno);
+ case 35: // CURLE_SSL_CONNECT_ERROR
+ case 51: // CURLE_PEER_FAILED_VERIFICATION
+ case 58: // CURLE_SSL_CERTPROBLEM
+ case 60: // CURLE_SSL_CACERT
+ case 59: // CURLE_SSL_CIPHER
+ case 64: // CURLE_USE_SSL_FAILED
+ case 66: // CURLE_SSL_ENGINE_INITFAILED
+ case 77: // CURLE_SSL_CACERT_BADFILE
+ case 83: // CURLE_SSL_ISSUER_ERROR
+ $msg = 'Invalid SSL certificate caused by CURL error number ' . $errno;
+ throw new InvalidCertificateException($msg, $errno);
+ case 47: // CURLE_TOO_MANY_REDIRECTS
+ throw new MaxRedirectException('Maximum number of redirections reached', $errno);
+ case 63: // CURLE_FILESIZE_EXCEEDED
+ throw new MaxSizeException('Maximum response size exceeded', $errno);
+ default:
+ throw new InvalidUrlException('Unable to fetch the URL', $errno);
+ }
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php
new file mode 100644
index 00000000..c226e95a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Client/ForbiddenException.php
@@ -0,0 +1,10 @@
+ $value) {
+ $this->headers[strtolower($key)] = $value;
+ }
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->offsetExists($offset) ? $this->headers[strtolower($offset)] : '';
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->headers[strtolower($offset)] = $value;
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->headers[strtolower($offset)]);
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->headers[strtolower($offset)]);
+ }
+
+ /**
+ * Parse HTTP headers.
+ *
+ * @static
+ *
+ * @param array $lines List of headers
+ *
+ * @return array
+ */
+ public static function parse(array $lines)
+ {
+ $status = 0;
+ $headers = array();
+
+ foreach ($lines as $line) {
+ if (strpos($line, 'HTTP/1') === 0) {
+ $headers = array();
+ $status = (int) substr($line, 9, 3);
+ } elseif (strpos($line, ': ') !== false) {
+ list($name, $value) = explode(': ', $line);
+ if ($value) {
+ $headers[trim($name)] = trim($value);
+ }
+ }
+ }
+
+ Logger::setMessage(get_called_class().' HTTP status code: '.$status);
+
+ foreach ($headers as $name => $value) {
+ Logger::setMessage(get_called_class().' HTTP header: '.$name.' => '.$value);
+ }
+
+ return array($status, new self($headers));
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php
new file mode 100644
index 00000000..8d25d7e4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php
@@ -0,0 +1,12 @@
+user_agent,
+ );
+
+ // disable compression in passthrough mode. It could result in double
+ // compressed content which isn't decodeable by browsers
+ if (function_exists('gzdecode') && !$this->isPassthroughEnabled()) {
+ $headers[] = 'Accept-Encoding: gzip';
+ }
+
+ if ($this->etag) {
+ $headers[] = 'If-None-Match: '.$this->etag;
+ $headers[] = 'A-IM: feed';
+ }
+
+ if ($this->last_modified) {
+ $headers[] = 'If-Modified-Since: '.$this->last_modified;
+ }
+
+ if ($this->proxy_username) {
+ $headers[] = 'Proxy-Authorization: Basic '.base64_encode($this->proxy_username.':'.$this->proxy_password);
+ }
+
+ if ($this->username && $this->password) {
+ $headers[] = 'Authorization: Basic '.base64_encode($this->username.':'.$this->password);
+ }
+
+ $headers = array_merge($headers, $this->request_headers);
+
+ return $headers;
+ }
+
+ /**
+ * Construct the final URL from location headers.
+ *
+ * @param array $headers List of HTTP response header
+ */
+ private function setEffectiveUrl($headers)
+ {
+ foreach ($headers as $header) {
+ if (stripos($header, 'Location') === 0) {
+ list(, $value) = explode(': ', $header);
+
+ $this->url = Url::resolve($value, $this->url);
+ }
+ }
+ }
+
+ /**
+ * Prepare stream context.
+ *
+ * @return array
+ */
+ private function prepareContext()
+ {
+ $context = array(
+ 'http' => array(
+ 'method' => 'GET',
+ 'protocol_version' => 1.1,
+ 'timeout' => $this->timeout,
+ 'max_redirects' => $this->max_redirects,
+ ),
+ );
+
+ if ($this->proxy_hostname) {
+ Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port);
+
+ $context['http']['proxy'] = 'tcp://'.$this->proxy_hostname.':'.$this->proxy_port;
+ $context['http']['request_fulluri'] = true;
+
+ if ($this->proxy_username) {
+ Logger::setMessage(get_called_class().' Proxy credentials: Yes');
+ } else {
+ Logger::setMessage(get_called_class().' Proxy credentials: No');
+ }
+ }
+
+ $context['http']['header'] = implode("\r\n", $this->prepareHeaders());
+
+ return $context;
+ }
+
+ /**
+ * Do the HTTP request.
+ *
+ * @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
+ * @throws InvalidUrlException
+ * @throws MaxSizeException
+ * @throws TimeoutException
+ */
+ public function doRequest()
+ {
+ $body = '';
+
+ // Create context
+ $context = stream_context_create($this->prepareContext());
+
+ // Make HTTP request
+ $stream = @fopen($this->url, 'r', false, $context);
+ if (!is_resource($stream)) {
+ throw new InvalidUrlException('Unable to establish a connection');
+ }
+
+ // Get HTTP headers response
+ $metadata = stream_get_meta_data($stream);
+ list($status, $headers) = HttpHeaders::parse($metadata['wrapper_data']);
+
+ if ($this->isPassthroughEnabled()) {
+ header(':', true, $status);
+
+ if (isset($headers['Content-Type'])) {
+ header('Content-Type: '.$headers['Content-Type']);
+ }
+
+ fpassthru($stream);
+ } else {
+ // Get the entire body until the max size
+ $body = stream_get_contents($stream, $this->max_body_size + 1);
+
+ // If the body size is too large abort everything
+ if (strlen($body) > $this->max_body_size) {
+ throw new MaxSizeException('Content size too large');
+ }
+
+ if ($metadata['timed_out']) {
+ throw new TimeoutException('Operation timeout');
+ }
+ }
+
+ fclose($stream);
+
+ $this->setEffectiveUrl($metadata['wrapper_data']);
+
+ return array(
+ 'status' => $status,
+ 'body' => $this->decodeBody($body, $headers),
+ 'headers' => $headers,
+ );
+ }
+
+ /**
+ * Decode body response according to the HTTP headers.
+ *
+ * @param string $body Raw body
+ * @param HttpHeaders $headers HTTP headers
+ *
+ * @return string
+ */
+ public function decodeBody($body, HttpHeaders $headers)
+ {
+ if (isset($headers['Transfer-Encoding']) && $headers['Transfer-Encoding'] === 'chunked') {
+ $body = $this->decodeChunked($body);
+ }
+
+ if (isset($headers['Content-Encoding']) && $headers['Content-Encoding'] === 'gzip') {
+ $body = gzdecode($body);
+ }
+
+ return $body;
+ }
+
+ /**
+ * Decode a chunked body.
+ *
+ * @param string $str Raw body
+ *
+ * @return string Decoded body
+ */
+ public function decodeChunked($str)
+ {
+ for ($result = ''; !empty($str); $str = trim($str)) {
+
+ // Get the chunk length
+ $pos = strpos($str, "\r\n");
+ $len = hexdec(substr($str, 0, $pos));
+
+ // Append the chunk to the result
+ $result .= substr($str, $pos + 2, $len);
+ $str = substr($str, $pos + 2 + $len);
+ }
+
+ return $result;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php
new file mode 100644
index 00000000..da98da12
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Client/TimeoutException.php
@@ -0,0 +1,12 @@
+url = $url;
+ $this->components = parse_url($url) ?: array();
+
+ // Issue with PHP < 5.4.7 and protocol relative url
+ if (version_compare(PHP_VERSION, '5.4.7', '<') && $this->isProtocolRelative()) {
+ $pos = strpos($this->components['path'], '/', 2);
+
+ if ($pos === false) {
+ $pos = strlen($this->components['path']);
+ }
+
+ $this->components['host'] = substr($this->components['path'], 2, $pos - 2);
+ $this->components['path'] = substr($this->components['path'], $pos);
+ }
+ }
+
+ /**
+ * Shortcut method to get an absolute url from relative url.
+ *
+ * @static
+ *
+ * @param mixed $item_url Unknown url (can be relative or not)
+ * @param mixed $website_url Website url
+ *
+ * @return string
+ */
+ public static function resolve($item_url, $website_url)
+ {
+ $link = is_string($item_url) ? new self($item_url) : $item_url;
+ $website = is_string($website_url) ? new self($website_url) : $website_url;
+
+ if ($link->isRelativeUrl()) {
+ if ($link->isRelativePath()) {
+ return $link->getAbsoluteUrl($website->getBaseUrl($website->getBasePath()));
+ }
+
+ return $link->getAbsoluteUrl($website->getBaseUrl());
+ } elseif ($link->isProtocolRelative()) {
+ $link->setScheme($website->getScheme());
+ }
+
+ return $link->getAbsoluteUrl();
+ }
+
+ /**
+ * Shortcut method to get a base url.
+ *
+ * @static
+ *
+ * @param string $url
+ *
+ * @return string
+ */
+ public static function base($url)
+ {
+ $link = new self($url);
+
+ return $link->getBaseUrl();
+ }
+
+ /**
+ * Get the base URL.
+ *
+ * @param string $suffix Add a suffix to the url
+ *
+ * @return string
+ */
+ public function getBaseUrl($suffix = '')
+ {
+ return $this->hasHost() ? $this->getScheme('://').$this->getHost().$this->getPort(':').$suffix : '';
+ }
+
+ /**
+ * Get the absolute URL.
+ *
+ * @param string $base_url Use this url as base url
+ *
+ * @return string
+ */
+ public function getAbsoluteUrl($base_url = '')
+ {
+ if ($base_url) {
+ $base = new self($base_url);
+ $url = $base->getAbsoluteUrl().substr($this->getFullPath(), 1);
+ } else {
+ $url = $this->hasHost() ? $this->getBaseUrl().$this->getFullPath() : '';
+ }
+
+ return $url;
+ }
+
+ /**
+ * Return true if the url is relative.
+ *
+ * @return bool
+ */
+ public function isRelativeUrl()
+ {
+ return !$this->hasScheme() && !$this->isProtocolRelative();
+ }
+
+ /**
+ * Return true if the path is relative.
+ *
+ * @return bool
+ */
+ public function isRelativePath()
+ {
+ $path = $this->getPath();
+
+ return empty($path) || $path{0}
+ !== '/';
+ }
+
+ /**
+ * Filters the path of a URI.
+ *
+ * Imported from Guzzle library: https://github.com/guzzle/psr7/blob/master/src/Uri.php#L568-L582
+ *
+ * @param $path
+ *
+ * @return string
+ */
+ public function filterPath($path, $charUnreserved = 'a-zA-Z0-9_\-\.~', $charSubDelims = '!\$&\'\(\)\*\+,;=')
+ {
+ return preg_replace_callback(
+ '/(?:[^'.$charUnreserved.$charSubDelims.':@\/%]+|%(?![A-Fa-f0-9]{2}))/',
+ function (array $matches) { return rawurlencode($matches[0]); },
+ $path
+ );
+ }
+
+ /**
+ * Get the path.
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->filterPath(empty($this->components['path']) ? '' : $this->components['path']);
+ }
+
+ /**
+ * Get the base path.
+ *
+ * @return string
+ */
+ public function getBasePath()
+ {
+ $current_path = $this->getPath();
+
+ $path = $this->isRelativePath() ? '/' : '';
+ $path .= substr($current_path, -1) === '/' ? $current_path : dirname($current_path);
+
+ return preg_replace('/\\\\\/|\/\//', '/', $path.'/');
+ }
+
+ /**
+ * Get the full path (path + querystring + fragment).
+ *
+ * @return string
+ */
+ public function getFullPath()
+ {
+ $path = $this->isRelativePath() ? '/' : '';
+ $path .= $this->getPath();
+ $path .= empty($this->components['query']) ? '' : '?'.$this->components['query'];
+ $path .= empty($this->components['fragment']) ? '' : '#'.$this->components['fragment'];
+
+ return $path;
+ }
+
+ /**
+ * Get the hostname.
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return empty($this->components['host']) ? '' : $this->components['host'];
+ }
+
+ /**
+ * Return true if the url has a hostname.
+ *
+ * @return bool
+ */
+ public function hasHost()
+ {
+ return !empty($this->components['host']);
+ }
+
+ /**
+ * Get the scheme.
+ *
+ * @param string $suffix Suffix to add when there is a scheme
+ *
+ * @return string
+ */
+ public function getScheme($suffix = '')
+ {
+ return ($this->hasScheme() ? $this->components['scheme'] : 'http').$suffix;
+ }
+
+ /**
+ * Set the scheme.
+ *
+ * @param string $scheme Set a scheme
+ *
+ * @return string
+ */
+ public function setScheme($scheme)
+ {
+ $this->components['scheme'] = $scheme;
+ }
+
+ /**
+ * Return true if the url has a scheme.
+ *
+ * @return bool
+ */
+ public function hasScheme()
+ {
+ return !empty($this->components['scheme']);
+ }
+
+ /**
+ * Get the port.
+ *
+ * @param string $prefix Prefix to add when there is a port
+ *
+ * @return string
+ */
+ public function getPort($prefix = '')
+ {
+ return $this->hasPort() ? $prefix.$this->components['port'] : '';
+ }
+
+ /**
+ * Return true if the url has a port.
+ *
+ * @return bool
+ */
+ public function hasPort()
+ {
+ return !empty($this->components['port']);
+ }
+
+ /**
+ * Return true if the url is protocol relative (start with //).
+ *
+ * @return bool
+ */
+ public function isProtocolRelative()
+ {
+ return strpos($this->url, '//') === 0;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php b/vendor/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php
new file mode 100644
index 00000000..fa0917e8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Encoding/Encoding.php
@@ -0,0 +1,33 @@
+ array('controls', 'src'),
+ 'video' => array('poster', 'controls', 'height', 'width', 'src'),
+ 'source' => array('src', 'type'),
+ 'dt' => array(),
+ 'dd' => array(),
+ 'dl' => array(),
+ 'table' => array(),
+ 'caption' => array(),
+ 'tr' => array(),
+ 'th' => array(),
+ 'td' => array(),
+ 'tbody' => array(),
+ 'thead' => array(),
+ 'h1' => array(),
+ 'h2' => array(),
+ 'h3' => array(),
+ 'h4' => array(),
+ 'h5' => array(),
+ 'h6' => array(),
+ 'strong' => array(),
+ 'em' => array(),
+ 'code' => array(),
+ 'pre' => array(),
+ 'blockquote' => array(),
+ 'p' => array(),
+ 'ul' => array(),
+ 'li' => array(),
+ 'ol' => array(),
+ 'br' => array(),
+ 'del' => array(),
+ 'a' => array('href'),
+ 'img' => array('src', 'title', 'alt'),
+ 'figure' => array(),
+ 'figcaption' => array(),
+ 'cite' => array(),
+ 'time' => array('datetime'),
+ 'abbr' => array('title'),
+ 'iframe' => array('width', 'height', 'frameborder', 'src', 'allowfullscreen'),
+ 'q' => array('cite'),
+ );
+
+ /**
+ * Scheme whitelist.
+ *
+ * For a complete list go to http://en.wikipedia.org/wiki/URI_scheme
+ *
+ * @var array
+ */
+ private $scheme_whitelist = array(
+ 'bitcoin:',
+ 'callto:',
+ 'ed2k://',
+ 'facetime://',
+ 'feed:',
+ 'ftp://',
+ 'geo:',
+ 'git://',
+ 'http://',
+ 'https://',
+ 'irc://',
+ 'irc6://',
+ 'ircs://',
+ 'jabber:',
+ 'magnet:',
+ 'mailto:',
+ 'nntp://',
+ 'rtmp://',
+ 'sftp://',
+ 'sip:',
+ 'sips:',
+ 'skype:',
+ 'smb://',
+ 'sms:',
+ 'spotify:',
+ 'ssh:',
+ 'steam:',
+ 'svn://',
+ 'tel:',
+ );
+
+ /**
+ * Iframe source whitelist, everything else is ignored.
+ *
+ * @var array
+ */
+ private $iframe_whitelist = array(
+ 'http://www.youtube.com',
+ 'https://www.youtube.com',
+ 'http://player.vimeo.com',
+ 'https://player.vimeo.com',
+ 'http://www.dailymotion.com',
+ 'https://www.dailymotion.com',
+ 'http://vk.com',
+ 'https://vk.com',
+ );
+
+ /**
+ * Blacklisted resources.
+ *
+ * @var array
+ */
+ private $media_blacklist = array(
+ 'api.flattr.com',
+ 'feeds.feedburner.com',
+ 'share.feedsportal.com',
+ 'da.feedsportal.com',
+ 'rc.feedsportal.com',
+ 'rss.feedsportal.com',
+ 'res.feedsportal.com',
+ 'res1.feedsportal.com',
+ 'res2.feedsportal.com',
+ 'res3.feedsportal.com',
+ 'pi.feedsportal.com',
+ 'rss.nytimes.com',
+ 'feeds.wordpress.com',
+ 'stats.wordpress.com',
+ 'rss.cnn.com',
+ 'twitter.com/home?status=',
+ 'twitter.com/share',
+ 'twitter_icon_large.png',
+ 'www.facebook.com/sharer.php',
+ 'facebook_icon_large.png',
+ 'plus.google.com/share',
+ 'www.gstatic.com/images/icons/gplus-16.png',
+ 'www.gstatic.com/images/icons/gplus-32.png',
+ 'www.gstatic.com/images/icons/gplus-64.png',
+ );
+
+ /**
+ * Attributes used for external resources.
+ *
+ * @var array
+ */
+ private $media_attributes = array(
+ 'src',
+ 'href',
+ 'poster',
+ );
+
+ /**
+ * Attributes that must be integer.
+ *
+ * @var array
+ */
+ private $integer_attributes = array(
+ 'width',
+ 'height',
+ 'frameborder',
+ );
+
+ /**
+ * Mandatory attributes for specified tags.
+ *
+ * @var array
+ */
+ private $required_attributes = array(
+ 'a' => array('href'),
+ 'img' => array('src'),
+ 'iframe' => array('src'),
+ 'audio' => array('src'),
+ 'source' => array('src'),
+ );
+
+ /**
+ * Add attributes to specified tags.
+ *
+ * @var array
+ */
+ private $add_attributes = array(
+ 'a' => array('rel' => 'noreferrer', 'target' => '_blank'),
+ 'video' => array('controls' => 'true'),
+ );
+
+ /**
+ * List of filters to apply.
+ *
+ * @var array
+ */
+ private $filters = array(
+ 'filterAllowedAttribute',
+ 'filterIntegerAttribute',
+ 'rewriteAbsoluteUrl',
+ 'filterIframeAttribute',
+ 'filterBlacklistResourceAttribute',
+ 'filterProtocolUrlAttribute',
+ 'rewriteImageProxyUrl',
+ 'secureIframeSrc',
+ 'removeYouTubeAutoplay',
+ );
+
+ /**
+ * Add attributes to specified tags.
+ *
+ * @var \PicoFeed\Client\Url
+ */
+ private $website;
+
+ /**
+ * Constructor.
+ *
+ * @param \PicoFeed\Client\Url $website Website url instance
+ */
+ public function __construct(Url $website)
+ {
+ $this->website = $website;
+ }
+
+ /**
+ * Apply filters to the attributes list.
+ *
+ * @param string $tag Tag name
+ * @param array $attributes Attributes dictionary
+ *
+ * @return array Filtered attributes
+ */
+ public function filter($tag, array $attributes)
+ {
+ foreach ($attributes as $attribute => &$value) {
+ foreach ($this->filters as $filter) {
+ if (!$this->$filter($tag, $attribute, $value)) {
+ unset($attributes[$attribute]);
+ break;
+ }
+ }
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Return true if the value is allowed (remove not allowed attributes).
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function filterAllowedAttribute($tag, $attribute, $value)
+ {
+ return isset($this->attribute_whitelist[$tag]) && in_array($attribute, $this->attribute_whitelist[$tag]);
+ }
+
+ /**
+ * Return true if the value is not integer (remove attributes that should have an integer value).
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function filterIntegerAttribute($tag, $attribute, $value)
+ {
+ if (in_array($attribute, $this->integer_attributes)) {
+ return ctype_digit($value);
+ }
+
+ return true;
+ }
+
+ /**
+ * Return true if the iframe source is allowed (remove not allowed iframe).
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function filterIframeAttribute($tag, $attribute, $value)
+ {
+ if ($tag === 'iframe' && $attribute === 'src') {
+ foreach ($this->iframe_whitelist as $url) {
+ if (strpos($value, $url) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return true if the resource is not blacklisted (remove blacklisted resource attributes).
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function filterBlacklistResourceAttribute($tag, $attribute, $value)
+ {
+ if ($this->isResource($attribute) && $this->isBlacklistedMedia($value)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Convert all relative links to absolute url.
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function rewriteAbsoluteUrl($tag, $attribute, &$value)
+ {
+ if ($this->isResource($attribute)) {
+ $value = Url::resolve($value, $this->website);
+ }
+
+ return true;
+ }
+
+ /**
+ * Turns iframes' src attribute from http to https to prevent
+ * mixed active content.
+ *
+ * @param string $tag Tag name
+ * @param array $attribute Atttributes name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function secureIframeSrc($tag, $attribute, &$value)
+ {
+ if ($tag === 'iframe' && $attribute === 'src' && strpos($value, 'http://') === 0) {
+ $value = substr_replace($value, 's', 4, 0);
+ }
+
+ return true;
+ }
+
+ /**
+ * Removes YouTube autoplay from iframes.
+ *
+ * @param string $tag Tag name
+ * @param array $attribute Atttributes name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function removeYouTubeAutoplay($tag, $attribute, &$value)
+ {
+ $regex = '%^(https://(?:www\.)?youtube.com/.*\?.*autoplay=)(1)(.*)%i';
+ if ($tag === 'iframe' && $attribute === 'src' && preg_match($regex, $value)) {
+ $value = preg_replace($regex, '${1}0$3', $value);
+ }
+
+ return true;
+ }
+
+ /**
+ * Rewrite image url to use with a proxy.
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function rewriteImageProxyUrl($tag, $attribute, &$value)
+ {
+ if ($tag === 'img' && $attribute === 'src'
+ && !($this->image_proxy_limit_protocol !== '' && stripos($value, $this->image_proxy_limit_protocol.':') !== 0)) {
+ if ($this->image_proxy_url) {
+ $value = sprintf($this->image_proxy_url, rawurlencode($value));
+ } elseif (is_callable($this->image_proxy_callback)) {
+ $value = call_user_func($this->image_proxy_callback, $value);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Return true if the scheme is authorized.
+ *
+ * @param string $tag Tag name
+ * @param string $attribute Attribute name
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function filterProtocolUrlAttribute($tag, $attribute, $value)
+ {
+ if ($this->isResource($attribute) && !$this->isAllowedProtocol($value)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Automatically add/override some attributes for specific tags.
+ *
+ * @param string $tag Tag name
+ * @param array $attributes Attributes list
+ *
+ * @return array
+ */
+ public function addAttributes($tag, array $attributes)
+ {
+ if (isset($this->add_attributes[$tag])) {
+ $attributes += $this->add_attributes[$tag];
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Return true if all required attributes are present.
+ *
+ * @param string $tag Tag name
+ * @param array $attributes Attributes list
+ *
+ * @return bool
+ */
+ public function hasRequiredAttributes($tag, array $attributes)
+ {
+ if (isset($this->required_attributes[$tag])) {
+ foreach ($this->required_attributes[$tag] as $attribute) {
+ if (!isset($attributes[$attribute])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if an attribute name is an external resource.
+ *
+ * @param string $attribute Attribute name
+ *
+ * @return bool
+ */
+ public function isResource($attribute)
+ {
+ return in_array($attribute, $this->media_attributes);
+ }
+
+ /**
+ * Detect if the protocol is allowed or not.
+ *
+ * @param string $value Attribute value
+ *
+ * @return bool
+ */
+ public function isAllowedProtocol($value)
+ {
+ foreach ($this->scheme_whitelist as $protocol) {
+ if (strpos($value, $protocol) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Detect if an url is blacklisted.
+ *
+ * @param string $resource Attribute value (URL)
+ *
+ * @return bool
+ */
+ public function isBlacklistedMedia($resource)
+ {
+ foreach ($this->media_blacklist as $name) {
+ if (strpos($resource, $name) !== false) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Convert the attribute list to html.
+ *
+ * @param array $attributes Attributes
+ *
+ * @return string
+ */
+ public function toHtml(array $attributes)
+ {
+ $html = array();
+
+ foreach ($attributes as $attribute => $value) {
+ $html[] = sprintf('%s="%s"', $attribute, Filter::escape($value));
+ }
+
+ return implode(' ', $html);
+ }
+
+ /**
+ * Set whitelisted tags and attributes for each tag.
+ *
+ * @param array $values List of tags: ['video' => ['src', 'cover'], 'img' => ['src']]
+ *
+ * @return Attribute
+ */
+ public function setWhitelistedAttributes(array $values)
+ {
+ $this->attribute_whitelist = $values ?: $this->attribute_whitelist;
+
+ return $this;
+ }
+
+ /**
+ * Set scheme whitelist.
+ *
+ * @param array $values List of scheme: ['http://', 'ftp://']
+ *
+ * @return Attribute
+ */
+ public function setSchemeWhitelist(array $values)
+ {
+ $this->scheme_whitelist = $values ?: $this->scheme_whitelist;
+
+ return $this;
+ }
+
+ /**
+ * Set media attributes (used to load external resources).
+ *
+ * @param array $values List of values: ['src', 'href']
+ *
+ * @return Attribute
+ */
+ public function setMediaAttributes(array $values)
+ {
+ $this->media_attributes = $values ?: $this->media_attributes;
+
+ return $this;
+ }
+
+ /**
+ * Set blacklisted external resources.
+ *
+ * @param array $values List of tags: ['http://google.com/', '...']
+ *
+ * @return Attribute
+ */
+ public function setMediaBlacklist(array $values)
+ {
+ $this->media_blacklist = $values ?: $this->media_blacklist;
+
+ return $this;
+ }
+
+ /**
+ * Set mandatory attributes for whitelisted tags.
+ *
+ * @param array $values List of tags: ['img' => 'src']
+ *
+ * @return Attribute
+ */
+ public function setRequiredAttributes(array $values)
+ {
+ $this->required_attributes = $values ?: $this->required_attributes;
+
+ return $this;
+ }
+
+ /**
+ * Set attributes to automatically to specific tags.
+ *
+ * @param array $values List of tags: ['a' => 'target="_blank"']
+ *
+ * @return Attribute
+ */
+ public function setAttributeOverrides(array $values)
+ {
+ $this->add_attributes = $values ?: $this->add_attributes;
+
+ return $this;
+ }
+
+ /**
+ * Set attributes that must be an integer.
+ *
+ * @param array $values List of tags: ['width', 'height']
+ *
+ * @return Attribute
+ */
+ public function setIntegerAttributes(array $values)
+ {
+ $this->integer_attributes = $values ?: $this->integer_attributes;
+
+ return $this;
+ }
+
+ /**
+ * Set allowed iframe resources.
+ *
+ * @param array $values List of tags: ['http://www.youtube.com']
+ *
+ * @return Attribute
+ */
+ public function setIframeWhitelist(array $values)
+ {
+ $this->iframe_whitelist = $values ?: $this->iframe_whitelist;
+
+ return $this;
+ }
+
+ /**
+ * Set image proxy URL.
+ *
+ * The original image url will be urlencoded
+ *
+ * @param string $url Proxy URL
+ *
+ * @return Attribute
+ */
+ public function setImageProxyUrl($url)
+ {
+ $this->image_proxy_url = $url ?: $this->image_proxy_url;
+
+ return $this;
+ }
+
+ /**
+ * Set image proxy callback.
+ *
+ * @param \Closure $callback
+ *
+ * @return Attribute
+ */
+ public function setImageProxyCallback($callback)
+ {
+ $this->image_proxy_callback = $callback ?: $this->image_proxy_callback;
+
+ return $this;
+ }
+
+ /**
+ * Set image proxy protocol restriction.
+ *
+ * @param string $value
+ *
+ * @return Attribute
+ */
+ public function setImageProxyProtocol($value)
+ {
+ $this->image_proxy_limit_protocol = $value ?: $this->image_proxy_limit_protocol;
+
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php
new file mode 100644
index 00000000..bae2aff0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Filter.php
@@ -0,0 +1,155 @@
+]*>\s*~i', '', $data);
+ }
+
+ /**
+ * Remove the XML tag from a document.
+ *
+ * @static
+ *
+ * @param string $data Input data
+ *
+ * @return string
+ */
+ public static function stripXmlTag($data)
+ {
+ if (strpos($data, '') + 2));
+ }
+
+ do {
+ $pos = strpos($data, '') + 2));
+ }
+ } while ($pos !== false && $pos < 200);
+
+ return $data;
+ }
+
+ /**
+ * Strip head tag from the HTML content.
+ *
+ * @static
+ *
+ * @param string $data Input data
+ *
+ * @return string
+ */
+ public static function stripHeadTags($data)
+ {
+ return preg_replace('@]*?>.*?@siu', '', $data);
+ }
+
+ /**
+ * Trim whitespace from the begining, the end and inside a string and don't break utf-8 string.
+ *
+ * @static
+ *
+ * @param string $value Raw data
+ *
+ * @return string Normalized data
+ */
+ public static function stripWhiteSpace($value)
+ {
+ $value = str_replace("\r", ' ', $value);
+ $value = str_replace("\t", ' ', $value);
+ $value = str_replace("\n", ' ', $value);
+ // $value = preg_replace('/\s+/', ' ', $value); <= break utf-8
+ return trim($value);
+ }
+
+ /**
+ * Fixes before XML parsing.
+ *
+ * @static
+ *
+ * @param string $data Raw data
+ *
+ * @return string Normalized data
+ */
+ public static function normalizeData($data)
+ {
+ $entities = array(
+ '/()(\d+);/m', // decimal encoded
+ '/()([a-f0-9]+);/mi', // hex encoded
+ );
+
+ // strip invalid XML 1.0 characters which are encoded as entities
+ $data = preg_replace_callback($entities, function ($matches) {
+ $code_point = $matches[2];
+
+ // convert hex entity to decimal
+ if (strtolower($matches[1]) === '') {
+ $code_point = hexdec($code_point);
+ }
+
+ $code_point = (int) $code_point;
+
+ // replace invalid characters
+ if ($code_point < 9
+ || ($code_point > 10 && $code_point < 13)
+ || ($code_point > 13 && $code_point < 32)
+ || ($code_point > 55295 && $code_point < 57344)
+ || ($code_point > 65533 && $code_point < 65536)
+ || $code_point > 1114111
+ ) {
+ return '';
+ };
+
+ return $matches[0];
+ }, $data);
+
+ // strip every utf-8 character than isn't in the range of valid XML 1.0 characters
+ return (string) preg_replace('/[^\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', '', $data);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Html.php b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Html.php
new file mode 100644
index 00000000..0ccc192f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Html.php
@@ -0,0 +1,243 @@
+config = new Config();
+ $this->input = XmlParser::htmlToXml($html);
+ $this->output = '';
+ $this->tag = new Tag($this->config);
+ $this->website = $website;
+ $this->attribute = new Attribute(new Url($website));
+ }
+
+ /**
+ * Set config object.
+ *
+ * @param \PicoFeed\Config\Config $config Config instance
+ *
+ * @return \PicoFeed\Filter\Html
+ */
+ public function setConfig($config)
+ {
+ $this->config = $config;
+
+ if ($this->config !== null) {
+ $this->attribute->setImageProxyCallback($this->config->getFilterImageProxyCallback());
+ $this->attribute->setImageProxyUrl($this->config->getFilterImageProxyUrl());
+ $this->attribute->setImageProxyProtocol($this->config->getFilterImageProxyProtocol());
+ $this->attribute->setIframeWhitelist($this->config->getFilterIframeWhitelist(array()));
+ $this->attribute->setIntegerAttributes($this->config->getFilterIntegerAttributes(array()));
+ $this->attribute->setAttributeOverrides($this->config->getFilterAttributeOverrides(array()));
+ $this->attribute->setRequiredAttributes($this->config->getFilterRequiredAttributes(array()));
+ $this->attribute->setMediaBlacklist($this->config->getFilterMediaBlacklist(array()));
+ $this->attribute->setMediaAttributes($this->config->getFilterMediaAttributes(array()));
+ $this->attribute->setSchemeWhitelist($this->config->getFilterSchemeWhitelist(array()));
+ $this->attribute->setWhitelistedAttributes($this->config->getFilterWhitelistedTags(array()));
+ $this->tag->setWhitelistedTags(array_keys($this->config->getFilterWhitelistedTags(array())));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Run tags/attributes filtering.
+ *
+ * @return string
+ */
+ public function execute()
+ {
+ $this->preFilter();
+
+ $parser = xml_parser_create();
+
+ xml_set_object($parser, $this);
+ xml_set_element_handler($parser, 'startTag', 'endTag');
+ xml_set_character_data_handler($parser, 'dataTag');
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
+ xml_parse($parser, $this->input, true);
+ xml_parser_free($parser);
+
+ $this->postFilter();
+
+ return $this->output;
+ }
+
+ /**
+ * Called before XML parsing.
+ */
+ public function preFilter()
+ {
+ $this->input = $this->tag->removeBlacklistedTags($this->input);
+ }
+
+ /**
+ * Called after XML parsing.
+ */
+ public function postFilter()
+ {
+ $this->output = $this->tag->removeEmptyTags($this->output);
+ $this->output = $this->filterRules($this->output);
+ $this->output = $this->tag->removeMultipleBreakTags($this->output);
+ $this->output = trim($this->output);
+ }
+
+ /**
+ * Called after XML parsing.
+ *
+ * @param string $content the content that should be filtered
+ */
+ public function filterRules($content)
+ {
+ // the constructor should require a config, then this if can be removed
+ if ($this->config === null) {
+ $config = new Config();
+ } else {
+ $config = $this->config;
+ }
+
+ $loader = new RuleLoader($config);
+ $rules = $loader->getRules($this->website);
+
+ $url = new Url($this->website);
+ $sub_url = $url->getFullPath();
+
+ if (isset($rules['filter'])) {
+ foreach ($rules['filter'] as $pattern => $rule) {
+ if (preg_match($pattern, $sub_url)) {
+ foreach ($rule as $search => $replace) {
+ $content = preg_replace($search, $replace, $content);
+ }
+ }
+ }
+ }
+
+ return $content;
+ }
+
+ /**
+ * Parse opening tag.
+ *
+ * @param resource $parser XML parser
+ * @param string $tag Tag name
+ * @param array $attributes Tag attributes
+ */
+ public function startTag($parser, $tag, array $attributes)
+ {
+ $this->empty = true;
+
+ if ($this->tag->isAllowed($tag, $attributes)) {
+ $attributes = $this->attribute->filter($tag, $attributes);
+
+ if ($this->attribute->hasRequiredAttributes($tag, $attributes)) {
+ $attributes = $this->attribute->addAttributes($tag, $attributes);
+
+ $this->output .= $this->tag->openHtmlTag($tag, $this->attribute->toHtml($attributes));
+ $this->empty = false;
+ }
+ }
+
+ $this->empty_tags[] = $this->empty;
+ }
+
+ /**
+ * Parse closing tag.
+ *
+ * @param resource $parser XML parser
+ * @param string $tag Tag name
+ */
+ public function endTag($parser, $tag)
+ {
+ if (!array_pop($this->empty_tags) && $this->tag->isAllowedTag($tag)) {
+ $this->output .= $this->tag->closeHtmlTag($tag);
+ }
+ }
+
+ /**
+ * Parse tag content.
+ *
+ * @param resource $parser XML parser
+ * @param string $content Tag content
+ */
+ public function dataTag($parser, $content)
+ {
+ // Replace with normal space
+ $content = str_replace("\xc2\xa0", ' ', $content);
+ $this->output .= Filter::escape($content);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php
new file mode 100644
index 00000000..84a298a7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Filter/Tag.php
@@ -0,0 +1,218 @@
+isAllowedTag($tag) && !$this->isPixelTracker($tag, $attributes);
+ }
+
+ /**
+ * Return the HTML opening tag.
+ *
+ * @param string $tag Tag name
+ * @param string $attributes Attributes converted in html
+ *
+ * @return string
+ */
+ public function openHtmlTag($tag, $attributes = '')
+ {
+ return '<'.$tag.(empty($attributes) ? '' : ' '.$attributes).($this->isSelfClosingTag($tag) ? '/>' : '>');
+ }
+
+ /**
+ * Return the HTML closing tag.
+ *
+ * @param string $tag Tag name
+ *
+ * @return string
+ */
+ public function closeHtmlTag($tag)
+ {
+ return $this->isSelfClosingTag($tag) ? '' : ''.$tag.'>';
+ }
+
+ /**
+ * Return true is the tag is self-closing.
+ *
+ * @param string $tag Tag name
+ *
+ * @return bool
+ */
+ public function isSelfClosingTag($tag)
+ {
+ return $tag === 'br' || $tag === 'img';
+ }
+
+ /**
+ * Check if a tag is on the whitelist.
+ *
+ * @param string $tag Tag name
+ *
+ * @return bool
+ */
+ public function isAllowedTag($tag)
+ {
+ return in_array($tag, array_merge(
+ $this->tag_whitelist,
+ array_keys($this->config->getFilterWhitelistedTags(array()))
+ ));
+ }
+
+ /**
+ * Detect if an image tag is a pixel tracker.
+ *
+ * @param string $tag Tag name
+ * @param array $attributes Tag attributes
+ *
+ * @return bool
+ */
+ public function isPixelTracker($tag, array $attributes)
+ {
+ return $tag === 'img' &&
+ isset($attributes['height']) && isset($attributes['width']) &&
+ $attributes['height'] == 1 && $attributes['width'] == 1;
+ }
+
+ /**
+ * Remove script tags.
+ *
+ * @param string $data Input data
+ *
+ * @return string
+ */
+ public function removeBlacklistedTags($data)
+ {
+ $dom = XmlParser::getDomDocument($data);
+
+ if ($dom === false) {
+ return '';
+ }
+
+ $xpath = new DOMXpath($dom);
+
+ $nodes = $xpath->query(implode(' | ', $this->tag_blacklist));
+
+ foreach ($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * Remove empty tags.
+ *
+ * @param string $data Input data
+ *
+ * @return string
+ */
+ public function removeEmptyTags($data)
+ {
+ return preg_replace('/<([^<\/>]*)>([\s]*?|(?R))<\/\1>/imsU', '', $data);
+ }
+
+ /**
+ * Replace
by only one.
+ *
+ * @param string $data Input data
+ *
+ * @return string
+ */
+ public function removeMultipleBreakTags($data)
+ {
+ return preg_replace("/(
\s*)+/", '
', $data);
+ }
+
+ /**
+ * Set whitelisted tags adn attributes for each tag.
+ *
+ * @param array $values List of tags: ['video' => ['src', 'cover'], 'img' => ['src']]
+ *
+ * @return Tag
+ */
+ public function setWhitelistedTags(array $values)
+ {
+ $this->tag_whitelist = $values ?: $this->tag_whitelist;
+
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php b/vendor/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php
new file mode 100644
index 00000000..5c2f205c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php
@@ -0,0 +1,23 @@
+extensions as $extension) {
+ if (substr($item->getUrl(), - strlen($extension)) === $extension) {
+ $item->setContent(''.$item->getUrl().'');
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php b/vendor/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php
new file mode 100644
index 00000000..198090d4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php
@@ -0,0 +1,67 @@
+hasNamespace('yt')) {
+ return $this->generateHtmlFromXml($item);
+ }
+
+ return $this->generateHtmlFromUrl($item);
+ }
+
+ /**
+ * Generate HTML
+ *
+ * @access public
+ * @param Item $item
+ * @return boolean
+ */
+ private function generateHtmlFromXml(Item $item)
+ {
+ $videoId = $item->getTag('yt:videoId');
+
+ if (! empty($videoId)) {
+ $item->setContent('');
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Generate HTML from item URL
+ *
+ * @access public
+ * @param Item $item
+ * @return bool
+ */
+ public function generateHtmlFromUrl(Item $item)
+ {
+ if (preg_match('/youtube\.com\/watch\?v=(.*)/', $item->getUrl(), $matches)) {
+ $item->setContent('');
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php b/vendor/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php
new file mode 100644
index 00000000..caec463f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Logging/Logger.php
@@ -0,0 +1,114 @@
+format('Y-m-d H:i:s').'] '.$message;
+ }
+ }
+
+ /**
+ * Get all logged messages.
+ *
+ * @static
+ *
+ * @return array
+ */
+ public static function getMessages()
+ {
+ return self::$messages;
+ }
+
+ /**
+ * Remove all logged messages.
+ *
+ * @static
+ */
+ public static function deleteMessages()
+ {
+ self::$messages = array();
+ }
+
+ /**
+ * Set a different timezone.
+ *
+ * @static
+ *
+ * @see http://php.net/manual/en/timezones.php
+ *
+ * @param string $timezone Timezone
+ */
+ public static function setTimeZone($timezone)
+ {
+ self::$timezone = $timezone ?: self::$timezone;
+ }
+
+ /**
+ * Get all messages serialized into a string.
+ *
+ * @static
+ *
+ * @return string
+ */
+ public static function toString()
+ {
+ return implode(PHP_EOL, self::$messages).PHP_EOL;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php
new file mode 100644
index 00000000..1c570a08
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Atom.php
@@ -0,0 +1,382 @@
+ 'http://www.w3.org/2005/Atom',
+ );
+
+ /**
+ * Get the path to the items XML tree.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ *
+ * @return SimpleXMLElement
+ */
+ public function getItemsTree(SimpleXMLElement $xml)
+ {
+ return XmlParser::getXPathResult($xml, 'atom:entry', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'entry');
+ }
+
+ /**
+ * Find the feed url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setFeedUrl($this->getUrl($xml, 'self'));
+ }
+
+ /**
+ * Find the site url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setSiteUrl($this->getUrl($xml, 'alternate', true));
+ }
+
+ /**
+ * Find the feed description.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
+ {
+ $description = XmlParser::getXPathResult($xml, 'atom:subtitle', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'subtitle');
+
+ $feed->setDescription(XmlParser::getValue($description));
+ }
+
+ /**
+ * Find the feed logo url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
+ {
+ $logo = XmlParser::getXPathResult($xml, 'atom:logo', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'logo');
+
+ $feed->setLogo(XmlParser::getValue($logo));
+ }
+
+ /**
+ * Find the feed icon.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
+ {
+ $icon = XmlParser::getXPathResult($xml, 'atom:icon', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'icon');
+
+ $feed->setIcon(XmlParser::getValue($icon));
+ }
+
+ /**
+ * Find the feed title.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
+ {
+ $title = XmlParser::getXPathResult($xml, 'atom:title', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'title');
+
+ $feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the feed language.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
+ {
+ $language = XmlParser::getXPathResult($xml, '*[not(self::atom:entry)]/@xml:lang', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, '@xml:lang');
+
+ $feed->setLanguage(XmlParser::getValue($language));
+ }
+
+ /**
+ * Find the feed id.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedId(SimpleXMLElement $xml, Feed $feed)
+ {
+ $id = XmlParser::getXPathResult($xml, 'atom:id', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'id');
+
+ $feed->setId(XmlParser::getValue($id));
+ }
+
+ /**
+ * Find the feed date.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
+ {
+ $updated = XmlParser::getXPathResult($xml, 'atom:updated', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'updated');
+
+ $feed->setDate($this->getDateParser()->getDateTime(XmlParser::getValue($updated)));
+ }
+
+ /**
+ * Find the item published date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $date = XmlParser::getXPathResult($entry, 'atom:published', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'published');
+
+ $item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime((string) current($date)) : null);
+ }
+
+ /**
+ * Find the item updated date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $date = XmlParser::getXPathResult($entry, 'atom:updated', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'updated');
+
+ $item->setUpdatedDate(!empty($date) ? $this->getDateParser()->getDateTime((string) current($date)) : null);
+ }
+
+ /**
+ * Find the item title.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ */
+ public function findItemTitle(SimpleXMLElement $entry, Item $item)
+ {
+ $title = XmlParser::getXPathResult($entry, 'atom:title', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'title');
+
+ $item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $item->getUrl());
+ }
+
+ /**
+ * Find the item author.
+ *
+ * @param SimpleXMLElement $xml Feed
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
+ {
+ $author = XmlParser::getXPathResult($entry, 'atom:author/atom:name', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'author/name')
+ ?: XmlParser::getXPathResult($xml, 'atom:author/atom:name', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'author/name');
+
+ $item->setAuthor(XmlParser::getValue($author));
+ }
+
+ /**
+ * Find the item content.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemContent(SimpleXMLElement $entry, Item $item)
+ {
+ $item->setContent($this->getContent($entry));
+ }
+
+ /**
+ * Find the item URL.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemUrl(SimpleXMLElement $entry, Item $item)
+ {
+ $item->setUrl($this->getUrl($entry, 'alternate', true));
+ }
+
+ /**
+ * Genereate the item id.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $id = XmlParser::getXPathResult($entry, 'atom:id', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'id');
+
+ if (!empty($id)) {
+ $item->setId($this->generateId(XmlParser::getValue($id)));
+ } else {
+ $item->setId($this->generateId(
+ $item->getTitle(), $item->getUrl(), $item->getContent()
+ ));
+ }
+ }
+
+ /**
+ * Find the item enclosure.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $enclosure = $this->findLink($entry, 'enclosure');
+
+ if ($enclosure) {
+ $item->setEnclosureUrl(Url::resolve((string) $enclosure['href'], $feed->getSiteUrl()));
+ $item->setEnclosureType((string) $enclosure['type']);
+ }
+ }
+
+ /**
+ * Find the item language.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $language = XmlParser::getXPathResult($entry, './/@xml:lang');
+ $item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
+ }
+
+ /**
+ * Find the item categories.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param Feed $feed Feed object
+ */
+ public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $categories = XmlParser::getXPathResult($entry, 'atom:category/@term', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'category/@term');
+ $item->setCategoriesFromXml($categories);
+ }
+
+ /**
+ * Get the URL from a link tag.
+ *
+ * @param SimpleXMLElement $xml XML tag
+ * @param string $rel Link relationship: alternate, enclosure, related, self, via
+ *
+ * @return string
+ */
+ private function getUrl(SimpleXMLElement $xml, $rel, $fallback = false)
+ {
+ $link = $this->findLink($xml, $rel);
+
+ if ($link) {
+ return (string) $link['href'];
+ }
+
+ if ($fallback) {
+ $link = $this->findLink($xml, '');
+ return $link ? (string) $link['href'] : '';
+ }
+
+ return '';
+ }
+
+ /**
+ * Get a link tag that match a relationship.
+ *
+ * @param SimpleXMLElement $xml XML tag
+ * @param string $rel Link relationship: alternate, enclosure, related, self, via
+ *
+ * @return SimpleXMLElement|null
+ */
+ private function findLink(SimpleXMLElement $xml, $rel)
+ {
+ $links = XmlParser::getXPathResult($xml, 'atom:link', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'link');
+
+ foreach ($links as $link) {
+ if ($rel === (string) $link['rel']) {
+ return $link;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the entry content.
+ *
+ * @param SimpleXMLElement $entry XML Entry
+ *
+ * @return string
+ */
+ private function getContent(SimpleXMLElement $entry)
+ {
+ $content = current(
+ XmlParser::getXPathResult($entry, 'atom:content', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'content')
+ );
+
+ if (!empty($content) && count($content->children())) {
+ $xml_string = '';
+
+ foreach ($content->children() as $child) {
+ $xml_string .= $child->asXML();
+ }
+
+ return $xml_string;
+ } elseif (trim((string) $content) !== '') {
+ return (string) $content;
+ }
+
+ $summary = XmlParser::getXPathResult($entry, 'atom:summary', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'summary');
+
+ return (string) current($summary);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php
new file mode 100644
index 00000000..0e5b80e3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/DateParser.php
@@ -0,0 +1,128 @@
+ length ].
+ *
+ * @var array
+ */
+ public $formats = array(
+ DATE_ATOM => null,
+ DATE_RSS => null,
+ DATE_COOKIE => null,
+ DATE_ISO8601 => null,
+ DATE_RFC822 => null,
+ DATE_RFC850 => null,
+ DATE_RFC1036 => null,
+ DATE_RFC1123 => null,
+ DATE_RFC2822 => null,
+ DATE_RFC3339 => null,
+ 'l, d M Y H:i:s' => null,
+ 'D, d M Y H:i:s' => 25,
+ 'D, d M Y h:i:s' => 25,
+ 'D M d Y H:i:s' => 24,
+ 'j M Y H:i:s' => 20,
+ 'Y-m-d H:i:s' => 19,
+ 'Y-m-d\TH:i:s' => 19,
+ 'd/m/Y H:i:s' => 19,
+ 'D, d M Y' => 16,
+ 'Y-m-d' => 10,
+ 'd-m-Y' => 10,
+ 'm-d-Y' => 10,
+ 'd.m.Y' => 10,
+ 'm.d.Y' => 10,
+ 'd/m/Y' => 10,
+ 'm/d/Y' => 10,
+ );
+
+ /**
+ * Try to parse all date format for broken feeds.
+ *
+ * @param string $value Original date format
+ *
+ * @return DateTime
+ */
+ public function getDateTime($value)
+ {
+ $value = trim($value);
+
+ foreach ($this->formats as $format => $length) {
+ $truncated_value = $value;
+ if ($length !== null) {
+ $truncated_value = substr($truncated_value, 0, $length);
+ }
+
+ $date = $this->getValidDate($format, $truncated_value);
+ if ($date !== false) {
+ return $date;
+ }
+ }
+
+ return $this->getCurrentDateTime();
+ }
+
+ /**
+ * Get a valid date from a given format.
+ *
+ * @param string $format Date format
+ * @param string $value Original date value
+ *
+ * @return DateTime|bool
+ */
+ public function getValidDate($format, $value)
+ {
+ $date = DateTime::createFromFormat($format, $value, $this->getTimeZone());
+
+ if ($date !== false) {
+ $errors = DateTime::getLastErrors();
+
+ if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
+ return $date;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the current datetime.
+ *
+ * @return DateTime
+ */
+ public function getCurrentDateTime()
+ {
+ return new DateTime('now', $this->getTimeZone());
+ }
+
+ /**
+ * Get DateTimeZone instance
+ *
+ * @access public
+ * @return DateTimeZone
+ */
+ public function getTimeZone()
+ {
+ return new DateTimeZone($this->config->getTimezone() ?: $this->timezone);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php
new file mode 100644
index 00000000..a56e71c3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Feed.php
@@ -0,0 +1,315 @@
+$property.PHP_EOL;
+ }
+
+ $output .= 'Feed::date = '.$this->date->format(DATE_RFC822).PHP_EOL;
+ $output .= 'Feed::isRTL() = '.($this->isRTL() ? 'true' : 'false').PHP_EOL;
+ $output .= 'Feed::items = '.count($this->items).' items'.PHP_EOL;
+
+ foreach ($this->items as $item) {
+ $output .= '----'.PHP_EOL;
+ $output .= $item;
+ }
+
+ return $output;
+ }
+
+ /**
+ * Get title.
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Get description.
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Get the logo url.
+ */
+ public function getLogo()
+ {
+ return $this->logo;
+ }
+
+ /**
+ * Get the icon url.
+ */
+ public function getIcon()
+ {
+ return $this->icon;
+ }
+
+ /**
+ * Get feed url.
+ */
+ public function getFeedUrl()
+ {
+ return $this->feedUrl;
+ }
+
+ /**
+ * Get site url.
+ */
+ public function getSiteUrl()
+ {
+ return $this->siteUrl;
+ }
+
+ /**
+ * Get date.
+ */
+ public function getDate()
+ {
+ return $this->date;
+ }
+
+ /**
+ * Get language.
+ */
+ public function getLanguage()
+ {
+ return $this->language;
+ }
+
+ /**
+ * Get id.
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Get feed items.
+ */
+ public function getItems()
+ {
+ return $this->items;
+ }
+
+ /**
+ * Return true if the feed is "Right to Left".
+ *
+ * @return bool
+ */
+ public function isRTL()
+ {
+ return Parser::isLanguageRTL($this->language);
+ }
+
+ /**
+ * Set feed items.
+ *
+ * @param Item[] $items
+ * @return Feed
+ */
+ public function setItems(array $items)
+ {
+ $this->items = $items;
+ return $this;
+ }
+
+ /**
+ * Set feed id.
+ *
+ * @param string $id
+ * @return Feed
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * Set feed title.
+ *
+ * @param string $title
+ * @return Feed
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * Set feed description.
+ *
+ * @param string $description
+ * @return Feed
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ return $this;
+ }
+
+ /**
+ * Set feed url.
+ *
+ * @param string $feedUrl
+ * @return Feed
+ */
+ public function setFeedUrl($feedUrl)
+ {
+ $this->feedUrl = $feedUrl;
+ return $this;
+ }
+
+ /**
+ * Set feed website url.
+ *
+ * @param string $siteUrl
+ * @return Feed
+ */
+ public function setSiteUrl($siteUrl)
+ {
+ $this->siteUrl = $siteUrl;
+ return $this;
+ }
+
+ /**
+ * Set feed date.
+ *
+ * @param \DateTime $date
+ * @return Feed
+ */
+ public function setDate($date)
+ {
+ $this->date = $date;
+ return $this;
+ }
+
+ /**
+ * Set feed language.
+ *
+ * @param string $language
+ * @return Feed
+ */
+ public function setLanguage($language)
+ {
+ $this->language = $language;
+ return $this;
+ }
+
+ /**
+ * Set feed logo.
+ *
+ * @param string $logo
+ * @return Feed
+ */
+ public function setLogo($logo)
+ {
+ $this->logo = $logo;
+ return $this;
+ }
+
+ /**
+ * Set feed icon.
+ *
+ * @param string $icon
+ * @return Feed
+ */
+ public function setIcon($icon)
+ {
+ $this->icon = $icon;
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Item.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Item.php
new file mode 100644
index 00000000..f9581941
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Item.php
@@ -0,0 +1,534 @@
+namespaces);
+ }
+
+ /**
+ * Get specific XML tag or attribute value.
+ *
+ * @param string $tag Tag name (examples: guid, media:content)
+ * @param string $attribute Tag attribute
+ *
+ * @return array|false Tag values or error
+ */
+ public function getTag($tag, $attribute = '')
+ {
+ if ($attribute !== '') {
+ $attribute = '/@'.$attribute;
+ }
+
+ $query = './/'.$tag.$attribute;
+ $elements = XmlParser::getXPathResult($this->xml, $query, $this->namespaces);
+
+ if ($elements === false) { // xPath error
+ return false;
+ }
+
+ return array_map(function ($element) { return (string) $element;}, $elements);
+ }
+
+ /**
+ * Return item information.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $output = '';
+
+ foreach (array('id', 'title', 'url', 'language', 'author', 'enclosureUrl', 'enclosureType') as $property) {
+ $output .= 'Item::'.$property.' = '.$this->$property.PHP_EOL;
+ }
+
+ $publishedDate = $this->publishedDate != null ? $this->publishedDate->format(DATE_RFC822) : null;
+ $updatedDate = $this->updatedDate != null ? $this->updatedDate->format(DATE_RFC822) : null;
+
+ $categoryString = $this->categories != null ? implode(',', $this->categories) : null;
+
+ $output .= 'Item::date = '.$this->date->format(DATE_RFC822).PHP_EOL;
+ $output .= 'Item::publishedDate = '.$publishedDate.PHP_EOL;
+ $output .= 'Item::updatedDate = '.$updatedDate.PHP_EOL;
+ $output .= 'Item::isRTL() = '.($this->isRTL() ? 'true' : 'false').PHP_EOL;
+ $output .= 'Item::categories = ['.$categoryString.']'.PHP_EOL;
+ $output .= 'Item::content = '.strlen($this->content).' bytes'.PHP_EOL;
+
+ return $output;
+ }
+
+ /**
+ * Get title.
+ *
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Get URL
+ *
+ * @access public
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Set URL
+ *
+ * @access public
+ * @param string $url
+ * @return Item
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ return $this;
+ }
+
+ /**
+ * Get id.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Get date.
+ *
+ * @return \DateTime
+ */
+ public function getDate()
+ {
+ return $this->date;
+ }
+
+ /**
+ * Get published date.
+ *
+ * @return \DateTime
+ */
+ public function getPublishedDate()
+ {
+ return $this->publishedDate;
+ }
+
+ /**
+ * Get updated date.
+ *
+ * @return \DateTime
+ */
+ public function getUpdatedDate()
+ {
+ return $this->updatedDate;
+ }
+
+ /**
+ * Get content.
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Set content
+ *
+ * @access public
+ * @param string $value
+ * @return Item
+ */
+ public function setContent($value)
+ {
+ $this->content = $value;
+ return $this;
+ }
+
+ /**
+ * Get enclosure url.
+ *
+ * @return string
+ */
+ public function getEnclosureUrl()
+ {
+ return $this->enclosureUrl;
+ }
+
+ /**
+ * Get enclosure type.
+ *
+ * @return string
+ */
+ public function getEnclosureType()
+ {
+ return $this->enclosureType;
+ }
+
+ /**
+ * Get language.
+ *
+ * @return string
+ */
+ public function getLanguage()
+ {
+ return $this->language;
+ }
+
+ /**
+ * Get categories.
+ *
+ * @return string
+ */
+ public function getCategories()
+ {
+ return $this->categories;
+ }
+
+ /**
+ * Get author.
+ *
+ * @return string
+ */
+ public function getAuthor()
+ {
+ return $this->author;
+ }
+
+ /**
+ * Return true if the item is "Right to Left".
+ *
+ * @return bool
+ */
+ public function isRTL()
+ {
+ return Parser::isLanguageRTL($this->language);
+ }
+
+ /**
+ * Set item id.
+ *
+ * @param string $id
+ * @return Item
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * Set item title.
+ *
+ * @param string $title
+ * @return Item
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * Set author.
+ *
+ * @param string $author
+ * @return Item
+ */
+ public function setAuthor($author)
+ {
+ $this->author = $author;
+ return $this;
+ }
+
+ /**
+ * Set item date.
+ *
+ * @param \DateTime $date
+ * @return Item
+ */
+ public function setDate($date)
+ {
+ $this->date = $date;
+ return $this;
+ }
+
+ /**
+ * Set item published date.
+ *
+ * @param \DateTime $publishedDate
+ * @return Item
+ */
+ public function setPublishedDate($publishedDate)
+ {
+ $this->publishedDate = $publishedDate;
+ return $this;
+ }
+
+ /**
+ * Set item updated date.
+ *
+ * @param \DateTime $updatedDate
+ * @return Item
+ */
+ public function setUpdatedDate($updatedDate)
+ {
+ $this->updatedDate = $updatedDate;
+ return $this;
+ }
+
+ /**
+ * Set enclosure url.
+ *
+ * @param string $enclosureUrl
+ * @return Item
+ */
+ public function setEnclosureUrl($enclosureUrl)
+ {
+ $this->enclosureUrl = $enclosureUrl;
+ return $this;
+ }
+
+ /**
+ * Set enclosure type.
+ *
+ * @param string $enclosureType
+ * @return Item
+ */
+ public function setEnclosureType($enclosureType)
+ {
+ $this->enclosureType = $enclosureType;
+ return $this;
+ }
+
+ /**
+ * Set item language.
+ *
+ * @param string $language
+ * @return Item
+ */
+ public function setLanguage($language)
+ {
+ $this->language = $language;
+ return $this;
+ }
+
+ /**
+ * Set item categories.
+ *
+ * @param array $categories
+ * @return Item
+ */
+ public function setCategories($categories)
+ {
+ $this->categories = $categories;
+ return $this;
+ }
+
+ /**
+ * Set item categories from xml.
+ *
+ * @param SimpleXMLElement[] $categories
+ * @return Item
+ */
+ public function setCategoriesFromXml($categories)
+ {
+ if ($categories !== false) {
+ $this->setCategories(
+ array_map(
+ function ($element) {
+ return trim((string) $element);
+ },
+ $categories
+ )
+ );
+ } else {
+ $categories = array();
+ }
+ return $this;
+ }
+
+ /**
+ * Set raw XML.
+ *
+ * @param \SimpleXMLElement $xml
+ * @return Item
+ */
+ public function setXml($xml)
+ {
+ $this->xml = $xml;
+ return $this;
+ }
+
+ /**
+ * Get raw XML.
+ *
+ * @return \SimpleXMLElement
+ */
+ public function getXml()
+ {
+ return $this->xml;
+ }
+
+ /**
+ * Set XML namespaces.
+ *
+ * @param array $namespaces
+ * @return Item
+ */
+ public function setNamespaces($namespaces)
+ {
+ $this->namespaces = $namespaces;
+ return $this;
+ }
+
+ /**
+ * Get XML namespaces.
+ *
+ * @return array
+ */
+ public function getNamespaces()
+ {
+ return $this->namespaces;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php
new file mode 100644
index 00000000..efaf0ff1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php
@@ -0,0 +1,13 @@
+fallback_url = $fallback_url;
+ $xml_encoding = XmlParser::getEncodingFromXmlTag($content);
+
+ // Strip XML tag to avoid multiple encoding/decoding in the next XML processing
+ $this->content = Filter::stripXmlTag($content);
+
+ // Encode everything in UTF-8
+ Logger::setMessage(get_called_class().': HTTP Encoding "'.$http_encoding.'" ; XML Encoding "'.$xml_encoding.'"');
+ $this->content = Encoding::convert($this->content, $xml_encoding ?: $http_encoding);
+
+ $this->itemPostProcessor = new ItemPostProcessor($this->config);
+ $this->itemPostProcessor->register(new ContentGeneratorProcessor($this->config));
+ $this->itemPostProcessor->register(new ContentFilterProcessor($this->config));
+ }
+
+ /**
+ * Parse the document.
+ *
+ * @return \PicoFeed\Parser\Feed
+ */
+ public function execute()
+ {
+ Logger::setMessage(get_called_class().': begin parsing');
+
+ $xml = XmlParser::getSimpleXml($this->content);
+
+ if ($xml === false) {
+ Logger::setMessage(get_called_class().': Applying XML workarounds');
+ $this->content = Filter::normalizeData($this->content);
+ $xml = XmlParser::getSimpleXml($this->content);
+
+ if ($xml === false) {
+ Logger::setMessage(get_called_class().': XML parsing error');
+ Logger::setMessage(XmlParser::getErrors());
+ throw new MalformedXmlException('XML parsing error');
+ }
+ }
+
+ $this->used_namespaces = $xml->getNamespaces(true);
+ $xml = $this->registerSupportedNamespaces($xml);
+
+ $feed = new Feed();
+
+ $this->findFeedUrl($xml, $feed);
+ $this->checkFeedUrl($feed);
+
+ $this->findSiteUrl($xml, $feed);
+ $this->checkSiteUrl($feed);
+
+ $this->findFeedTitle($xml, $feed);
+ $this->findFeedDescription($xml, $feed);
+ $this->findFeedLanguage($xml, $feed);
+ $this->findFeedId($xml, $feed);
+ $this->findFeedDate($xml, $feed);
+ $this->findFeedLogo($xml, $feed);
+ $this->findFeedIcon($xml, $feed);
+
+ foreach ($this->getItemsTree($xml) as $entry) {
+ $entry = $this->registerSupportedNamespaces($entry);
+
+ $item = new Item();
+ $item->xml = $entry;
+ $item->namespaces = $this->used_namespaces;
+
+ $this->findItemAuthor($xml, $entry, $item);
+
+ $this->findItemUrl($entry, $item);
+ $this->checkItemUrl($feed, $item);
+
+ $this->findItemTitle($entry, $item);
+ $this->findItemContent($entry, $item);
+
+ // Id generation can use the item url/title/content (order is important)
+ $this->findItemId($entry, $item, $feed);
+ $this->findItemDate($entry, $item, $feed);
+ $this->findItemEnclosure($entry, $item, $feed);
+ $this->findItemLanguage($entry, $item, $feed);
+ $this->findItemCategories($entry, $item, $feed);
+
+ $this->itemPostProcessor->execute($feed, $item);
+ $feed->items[] = $item;
+ }
+
+ Logger::setMessage(get_called_class().PHP_EOL.$feed);
+
+ return $feed;
+ }
+
+ /**
+ * Check if the feed url is correct.
+ *
+ * @param Feed $feed Feed object
+ */
+ public function checkFeedUrl(Feed $feed)
+ {
+ if ($feed->getFeedUrl() === '') {
+ $feed->feedUrl = $this->fallback_url;
+ } else {
+ $feed->feedUrl = Url::resolve($feed->getFeedUrl(), $this->fallback_url);
+ }
+ }
+
+ /**
+ * Check if the site url is correct.
+ *
+ * @param Feed $feed Feed object
+ */
+ public function checkSiteUrl(Feed $feed)
+ {
+ if ($feed->getSiteUrl() === '') {
+ $feed->siteUrl = Url::base($feed->getFeedUrl());
+ } else {
+ $feed->siteUrl = Url::resolve($feed->getSiteUrl(), $this->fallback_url);
+ }
+ }
+
+ /**
+ * Check if the item url is correct.
+ *
+ * @param Feed $feed Feed object
+ * @param Item $item Item object
+ */
+ public function checkItemUrl(Feed $feed, Item $item)
+ {
+ $item->url = Url::resolve($item->getUrl(), $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the item date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $this->findItemPublishedDate($entry, $item, $feed);
+ $this->findItemUpdatedDate($entry, $item, $feed);
+
+ if ($item->getPublishedDate() === null) {
+ // Use the updated date if available, otherwise use the feed date
+ $item->setPublishedDate($item->getUpdatedDate() ?: $feed->getDate());
+ }
+
+ if ($item->getUpdatedDate() === null) {
+ // Use the published date as fallback
+ $item->setUpdatedDate($item->getPublishedDate());
+ }
+
+ // Use the most recent of published and updated dates
+ $item->setDate(max($item->getPublishedDate(), $item->getUpdatedDate()));
+ }
+
+ /**
+ * Get Item Post Processor instance
+ *
+ * @access public
+ * @return ItemPostProcessor
+ */
+ public function getItemPostProcessor()
+ {
+ return $this->itemPostProcessor;
+ }
+
+ /**
+ * Get DateParser instance
+ *
+ * @access public
+ * @return DateParser
+ */
+ public function getDateParser()
+ {
+ if ($this->dateParser === null) {
+ $this->dateParser = new DateParser($this->config);
+ }
+
+ return $this->dateParser;
+ }
+
+ /**
+ * Generate a unique id for an entry (hash all arguments).
+ *
+ * @return string
+ */
+ public function generateId()
+ {
+ return hash($this->hash_algo, implode(func_get_args()));
+ }
+
+ /**
+ * Return true if the given language is "Right to Left".
+ *
+ * @static
+ *
+ * @param string $language Language: fr-FR, en-US
+ *
+ * @return bool
+ */
+ public static function isLanguageRTL($language)
+ {
+ $language = strtolower($language);
+
+ $rtl_languages = array(
+ 'ar', // Arabic (ar-**)
+ 'fa', // Farsi (fa-**)
+ 'ur', // Urdu (ur-**)
+ 'ps', // Pashtu (ps-**)
+ 'syr', // Syriac (syr-**)
+ 'dv', // Divehi (dv-**)
+ 'he', // Hebrew (he-**)
+ 'yi', // Yiddish (yi-**)
+ );
+
+ foreach ($rtl_languages as $prefix) {
+ if (strpos($language, $prefix) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set Hash algorithm used for id generation.
+ *
+ * @param string $algo Algorithm name
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function setHashAlgo($algo)
+ {
+ $this->hash_algo = $algo ?: $this->hash_algo;
+ return $this;
+ }
+
+ /**
+ * Set config object.
+ *
+ * @param \PicoFeed\Config\Config $config Config instance
+ *
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function setConfig($config)
+ {
+ $this->config = $config;
+ $this->itemPostProcessor->setConfig($config);
+ return $this;
+ }
+
+ /**
+ * Enable the content grabber.
+ *
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function disableContentFiltering()
+ {
+ $this->itemPostProcessor->unregister('PicoFeed\Processor\ContentFilterProcessor');
+ return $this;
+ }
+
+ /**
+ * Enable the content grabber.
+ *
+ * @param bool $needsRuleFile true if only pages with rule files should be
+ * scraped
+ * @param null|\Closure $scraperCallback Callback function that gets called for each
+ * scraper execution
+ *
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function enableContentGrabber($needsRuleFile = false, $scraperCallback = null)
+ {
+ $processor = new ScraperProcessor($this->config);
+
+ if ($needsRuleFile) {
+ $processor->getScraper()->disableCandidateParser();
+ }
+
+ if ($scraperCallback !== null) {
+ $processor->setExecutionCallback($scraperCallback);
+ }
+
+ $this->itemPostProcessor->register($processor);
+ return $this;
+ }
+
+ /**
+ * Set ignored URLs for the content grabber.
+ *
+ * @param array $urls URLs
+ *
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function setGrabberIgnoreUrls(array $urls)
+ {
+ $this->itemPostProcessor->getProcessor('PicoFeed\Processor\ScraperProcessor')->ignoreUrls($urls);
+ return $this;
+ }
+
+ /**
+ * Register all supported namespaces to be used within an xpath query.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ *
+ * @return SimpleXMLElement
+ */
+ public function registerSupportedNamespaces(SimpleXMLElement $xml)
+ {
+ foreach ($this->namespaces as $prefix => $ns) {
+ $xml->registerXPathNamespace($prefix, $ns);
+ }
+
+ return $xml;
+ }
+
+
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php
new file mode 100644
index 00000000..b5fbb699
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/ParserException.php
@@ -0,0 +1,15 @@
+ 'http://purl.org/rss/1.0/',
+ 'dc' => 'http://purl.org/dc/elements/1.1/',
+ 'content' => 'http://purl.org/rss/1.0/modules/content/',
+ 'feedburner' => 'http://rssnamespace.org/feedburner/ext/1.0',
+ );
+
+ /**
+ * Get the path to the items XML tree.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ *
+ * @return SimpleXMLElement
+ */
+ public function getItemsTree(SimpleXMLElement $xml)
+ {
+ return XmlParser::getXPathResult($xml, 'rss:item', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'item')
+ ?: $xml->item;
+ }
+
+ /**
+ * Find the feed url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setFeedUrl('');
+ }
+
+ /**
+ * Find the site url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $value = XmlParser::getXPathResult($xml, 'rss:channel/rss:link', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/link')
+ ?: $xml->channel->link;
+
+ $feed->setSiteUrl(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the feed description.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
+ {
+ $description = XmlParser::getXPathResult($xml, 'rss:channel/rss:description', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/description')
+ ?: $xml->channel->description;
+
+ $feed->setDescription(XmlParser::getValue($description));
+ }
+
+ /**
+ * Find the feed logo url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
+ {
+ $logo = XmlParser::getXPathResult($xml, 'rss:image/rss:url', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'image/url');
+
+ $feed->setLogo(XmlParser::getValue($logo));
+ }
+
+ /**
+ * Find the feed icon.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setIcon('');
+ }
+
+ /**
+ * Find the feed title.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
+ {
+ $title = XmlParser::getXPathResult($xml, 'rss:channel/rss:title', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/title')
+ ?: $xml->channel->title;
+
+ $feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the feed language.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
+ {
+ $language = XmlParser::getXPathResult($xml, 'rss:channel/dc:language', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/dc:language', $this->namespaces);
+
+ $feed->setLanguage(XmlParser::getValue($language));
+ }
+
+ /**
+ * Find the feed id.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedId(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setId($feed->getFeedUrl() ?: $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the feed date.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
+ {
+ $date = XmlParser::getXPathResult($xml, 'rss:channel/dc:date', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/dc:date', $this->namespaces);
+
+ $feed->setDate($this->getDateParser()->getDateTime(XmlParser::getValue($date)));
+ }
+
+ /**
+ * Find the item published date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $date = XmlParser::getXPathResult($entry, 'dc:date', $this->namespaces);
+
+ $item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($date)) : null);
+ }
+
+ /**
+ * Find the item updated date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ if ($item->publishedDate === null) {
+ $this->findItemPublishedDate($entry, $item, $feed);
+ }
+ $item->setUpdatedDate($item->getPublishedDate()); // No updated date in RSS 1.0 specifications
+ }
+
+ /**
+ * Find the item title.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemTitle(SimpleXMLElement $entry, Item $item)
+ {
+ $title = XmlParser::getXPathResult($entry, 'rss:title', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'title')
+ ?: $entry->title;
+
+ $item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $item->getUrl());
+ }
+
+ /**
+ * Find the item author.
+ *
+ * @param SimpleXMLElement $xml Feed
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
+ {
+ $author = XmlParser::getXPathResult($entry, 'dc:creator', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'rss:channel/dc:creator', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/dc:creator', $this->namespaces);
+
+ $item->setAuthor(XmlParser::getValue($author));
+ }
+
+ /**
+ * Find the item content.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemContent(SimpleXMLElement $entry, Item $item)
+ {
+ $content = XmlParser::getXPathResult($entry, 'content:encoded', $this->namespaces);
+
+ if (XmlParser::getValue($content) === '') {
+ $content = XmlParser::getXPathResult($entry, 'rss:description', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'description')
+ ?: $entry->description;
+ }
+
+ $item->setContent(XmlParser::getValue($content));
+ }
+
+ /**
+ * Find the item URL.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemUrl(SimpleXMLElement $entry, Item $item)
+ {
+ $link = XmlParser::getXPathResult($entry, 'feedburner:origLink', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'rss:link', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'link')
+ ?: $entry->link;
+
+ $item->setUrl(XmlParser::getValue($link));
+ }
+
+ /**
+ * Genereate the item id.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $item->setId($this->generateId(
+ $item->getTitle(), $item->getUrl(), $item->getContent()
+ ));
+ }
+
+ /**
+ * Find the item enclosure.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ }
+
+ /**
+ * Find the item language.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $language = XmlParser::getXPathResult($entry, 'dc:language', $this->namespaces);
+
+ $item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
+ }
+
+ /**
+ * Find the item categories.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param Feed $feed Feed object
+ */
+ public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $categories = XmlParser::getXPathResult($entry, 'dc:subject', $this->namespaces);
+ $item->setCategoriesFromXml($categories);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php
new file mode 100644
index 00000000..1dd3bf8c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss20.php
@@ -0,0 +1,319 @@
+ 'http://purl.org/dc/elements/1.1/',
+ 'content' => 'http://purl.org/rss/1.0/modules/content/',
+ 'feedburner' => 'http://rssnamespace.org/feedburner/ext/1.0',
+ 'atom' => 'http://www.w3.org/2005/Atom',
+ );
+
+ /**
+ * Get the path to the items XML tree.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ *
+ * @return SimpleXMLElement
+ */
+ public function getItemsTree(SimpleXMLElement $xml)
+ {
+ return XmlParser::getXPathResult($xml, 'channel/item');
+ }
+
+ /**
+ * Find the feed url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setFeedUrl('');
+ }
+
+ /**
+ * Find the site url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
+ {
+ $value = XmlParser::getXPathResult($xml, 'channel/link');
+ $feed->setSiteUrl(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the feed description.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
+ {
+ $value = XmlParser::getXPathResult($xml, 'channel/description');
+ $feed->setDescription(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the feed logo url.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
+ {
+ $value = XmlParser::getXPathResult($xml, 'channel/image/url');
+ $feed->setLogo(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the feed icon.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setIcon('');
+ }
+
+ /**
+ * Find the feed title.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
+ {
+ $title = XmlParser::getXPathResult($xml, 'channel/title');
+ $feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the feed language.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
+ {
+ $value = XmlParser::getXPathResult($xml, 'channel/language');
+ $feed->setLanguage(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the feed id.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedId(SimpleXMLElement $xml, Feed $feed)
+ {
+ $feed->setId($feed->getFeedUrl() ?: $feed->getSiteUrl());
+ }
+
+ /**
+ * Find the feed date.
+ *
+ * @param SimpleXMLElement $xml Feed xml
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
+ {
+ $publish_date = XmlParser::getXPathResult($xml, 'channel/pubDate');
+ $update_date = XmlParser::getXPathResult($xml, 'channel/lastBuildDate');
+
+ $published = !empty($publish_date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($publish_date)) : null;
+ $updated = !empty($update_date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($update_date)) : null;
+
+ if ($published === null && $updated === null) {
+ $feed->setDate($this->getDateParser()->getCurrentDateTime()); // We use the current date if there is no date for the feed
+ } elseif ($published !== null && $updated !== null) {
+ $feed->setDate(max($published, $updated)); // We use the most recent date between published and updated
+ } else {
+ $feed->setDate($updated ?: $published);
+ }
+ }
+
+ /**
+ * Find the item published date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $date = XmlParser::getXPathResult($entry, 'pubDate');
+
+ $item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($date)) : null);
+ }
+
+ /**
+ * Find the item updated date.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ if ($item->publishedDate === null) {
+ $this->findItemPublishedDate($entry, $item, $feed);
+ }
+ $item->setUpdatedDate($item->getPublishedDate()); // No updated date in RSS 2.0 specifications
+ }
+
+ /**
+ * Find the item title.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemTitle(SimpleXMLElement $entry, Item $item)
+ {
+ $value = XmlParser::getXPathResult($entry, 'title');
+ $item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($value)) ?: $item->getUrl());
+ }
+
+ /**
+ * Find the item author.
+ *
+ * @param SimpleXMLElement $xml Feed
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
+ {
+ $value = XmlParser::getXPathResult($entry, 'dc:creator', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'author')
+ ?: XmlParser::getXPathResult($xml, 'channel/dc:creator', $this->namespaces)
+ ?: XmlParser::getXPathResult($xml, 'channel/managingEditor');
+
+ $item->setAuthor(XmlParser::getValue($value));
+ }
+
+ /**
+ * Find the item content.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemContent(SimpleXMLElement $entry, Item $item)
+ {
+ $content = XmlParser::getXPathResult($entry, 'content:encoded', $this->namespaces);
+
+ if (XmlParser::getValue($content) === '') {
+ $content = XmlParser::getXPathResult($entry, 'description');
+ }
+
+ $item->setContent(XmlParser::getValue($content));
+ }
+
+ /**
+ * Find the item URL.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ */
+ public function findItemUrl(SimpleXMLElement $entry, Item $item)
+ {
+ $link = XmlParser::getXPathResult($entry, 'feedburner:origLink', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'link')
+ ?: XmlParser::getXPathResult($entry, 'atom:link/@href', $this->namespaces);
+
+ if (!empty($link)) {
+ $item->setUrl(XmlParser::getValue($link));
+ } else {
+ $link = XmlParser::getXPathResult($entry, 'guid');
+ $link = XmlParser::getValue($link);
+
+ if (filter_var($link, FILTER_VALIDATE_URL) !== false) {
+ $item->setUrl($link);
+ }
+ }
+ }
+
+ /**
+ * Genereate the item id.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $id = XmlParser::getValue(XmlParser::getXPathResult($entry, 'guid'));
+
+ if ($id) {
+ $item->setId($this->generateId($id));
+ } else {
+ $item->setId($this->generateId(
+ $item->getTitle(), $item->getUrl(), $item->getContent()
+ ));
+ }
+ }
+
+ /**
+ * Find the item enclosure.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ if (isset($entry->enclosure)) {
+ $type = XmlParser::getXPathResult($entry, 'enclosure/@type');
+ $url = XmlParser::getXPathResult($entry, 'feedburner:origEnclosureLink', $this->namespaces)
+ ?: XmlParser::getXPathResult($entry, 'enclosure/@url');
+
+ $item->setEnclosureUrl(Url::resolve(XmlParser::getValue($url), $feed->getSiteUrl()));
+ $item->setEnclosureType(XmlParser::getValue($type));
+ }
+ }
+
+ /**
+ * Find the item language.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param \PicoFeed\Parser\Item $item Item object
+ * @param \PicoFeed\Parser\Feed $feed Feed object
+ */
+ public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $language = XmlParser::getXPathResult($entry, 'dc:language', $this->namespaces);
+ $item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
+ }
+
+ /**
+ * Find the item categories.
+ *
+ * @param SimpleXMLElement $entry Feed item
+ * @param Item $item Item object
+ * @param Feed $feed Feed object
+ */
+ public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
+ {
+ $categories = XmlParser::getXPathResult($entry, 'category');
+ $item->setCategoriesFromXml($categories);
+ }
+
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php
new file mode 100644
index 00000000..058fca1b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Parser/Rss91.php
@@ -0,0 +1,13 @@
+childNodes->length === 0) {
+ return false;
+ }
+
+ return $dom;
+ }
+
+ /**
+ * Small wrapper around ZendXml to turn their exceptions into PicoFeed exceptions
+ *
+ * @static
+ * @access private
+ * @param string $input
+ * @param DOMDocument $dom
+ * @throws XmlEntityException
+ * @return SimpleXMLElement|DomDocument|boolean
+ */
+ private static function scan($input, $dom = null)
+ {
+ try {
+ return Security::scan($input, $dom);
+ } catch(RuntimeException $e) {
+ throw new XmlEntityException($e->getMessage());
+ }
+ }
+
+ /**
+ * Load HTML document by using a DomDocument instance or return false on failure.
+ *
+ * @static
+ * @access public
+ * @param string $input XML content
+ * @return DOMDocument
+ */
+ public static function getHtmlDocument($input)
+ {
+ $dom = new DomDocument();
+
+ if (empty($input)) {
+ return $dom;
+ }
+
+ libxml_use_internal_errors(true);
+
+ if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
+ $dom->loadHTML($input, LIBXML_NONET);
+ } else {
+ $dom->loadHTML($input);
+ }
+
+ return $dom;
+ }
+
+ /**
+ * Convert a HTML document to XML.
+ *
+ * @static
+ * @access public
+ * @param string $html HTML document
+ * @return string
+ */
+ public static function htmlToXml($html)
+ {
+ $dom = self::getHtmlDocument(''.$html);
+ return $dom->saveXML($dom->getElementsByTagName('body')->item(0));
+ }
+
+ /**
+ * Get XML parser errors.
+ *
+ * @static
+ * @access public
+ * @return string
+ */
+ public static function getErrors()
+ {
+ $errors = array();
+
+ foreach (libxml_get_errors() as $error) {
+ $errors[] = sprintf('XML error: %s (Line: %d - Column: %d - Code: %d)',
+ $error->message,
+ $error->line,
+ $error->column,
+ $error->code
+ );
+ }
+
+ return implode(', ', $errors);
+ }
+
+ /**
+ * Get the encoding from a xml tag.
+ *
+ * @static
+ * @access public
+ * @param string $data Input data
+ * @return string
+ */
+ public static function getEncodingFromXmlTag($data)
+ {
+ $encoding = '';
+
+ if (strpos($data, ''));
+ $data = str_replace("'", '"', $data);
+
+ $p1 = strpos($data, 'encoding=');
+ $p2 = strpos($data, '"', $p1 + 10);
+
+ if ($p1 !== false && $p2 !== false) {
+ $encoding = substr($data, $p1 + 10, $p2 - $p1 - 10);
+ $encoding = strtolower($encoding);
+ }
+ }
+
+ return $encoding;
+ }
+
+ /**
+ * Get the charset from a meta tag.
+ *
+ * @static
+ * @access public
+ * @param string $data Input data
+ * @return string
+ */
+ public static function getEncodingFromMetaTag($data)
+ {
+ $encoding = '';
+
+ if (preg_match('/;]+)/i', $data, $match) === 1) {
+ $encoding = strtolower($match[1]);
+ }
+
+ return $encoding;
+ }
+
+ /**
+ * Rewrite XPath query to use namespace-uri and local-name derived from prefix.
+ *
+ * @static
+ * @access public
+ * @param string $query XPath query
+ * @param array $ns Prefix to namespace URI mapping
+ * @return string
+ */
+ public static function replaceXPathPrefixWithNamespaceURI($query, array $ns)
+ {
+ return preg_replace_callback('/([A-Z0-9]+):([A-Z0-9]+)/iu', function ($matches) use ($ns) {
+ // don't try to map the special prefix XML
+ if (strtolower($matches[1]) === 'xml') {
+ return $matches[0];
+ }
+
+ return '*[namespace-uri()="'.$ns[$matches[1]].'" and local-name()="'.$matches[2].'"]';
+ },
+ $query);
+ }
+
+ /**
+ * Get the result elements of a XPath query.
+ *
+ * @static
+ * @access public
+ * @param SimpleXMLElement $xml XML element
+ * @param string $query XPath query
+ * @param array $ns Prefix to namespace URI mapping
+ * @return SimpleXMLElement[]
+ */
+ public static function getXPathResult(SimpleXMLElement $xml, $query, array $ns = array())
+ {
+ if (!empty($ns)) {
+ $query = static::replaceXPathPrefixWithNamespaceURI($query, $ns);
+ }
+
+ return $xml->xpath($query);
+ }
+
+ /**
+ * Get the first Xpath result or SimpleXMLElement value
+ *
+ * @static
+ * @access public
+ * @param mixed $value
+ * @return string
+ */
+ public static function getValue($value)
+ {
+ $result = '';
+
+ if (is_array($value) && count($value) > 0) {
+ $result = (string) $value[0];
+ } elseif (is_a($value, 'SimpleXMLElement')) {
+ return $result = (string) $value;
+ }
+
+ return trim($result);
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php b/vendor/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php
new file mode 100644
index 00000000..2de9e4b7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/PicoFeedException.php
@@ -0,0 +1,14 @@
+config->getContentFiltering(true)) {
+ $filter = Filter::html($item->getContent(), $feed->getSiteUrl());
+ $filter->setConfig($this->config);
+ $item->setContent($filter->execute());
+ } else {
+ Logger::setMessage(get_called_class().': Content filtering disabled');
+ }
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php
new file mode 100644
index 00000000..49adf9cc
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php
@@ -0,0 +1,49 @@
+generators as $generator) {
+ $className = '\PicoFeed\Generator\\'.ucfirst($generator).'ContentGenerator';
+ $object = new $className($this->config);
+
+ if ($object->execute($item)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php
new file mode 100644
index 00000000..d2787677
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php
@@ -0,0 +1,106 @@
+processors as $processor) {
+ if ($processor->execute($feed, $item)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Register a new Item post-processor
+ *
+ * @access public
+ * @param ItemProcessorInterface $processor
+ * @return ItemPostProcessor
+ */
+ public function register(ItemProcessorInterface $processor)
+ {
+ $this->processors[get_class($processor)] = $processor;
+ return $this;
+ }
+
+ /**
+ * Remove Processor instance
+ *
+ * @access public
+ * @param string $class
+ * @return ItemPostProcessor
+ */
+ public function unregister($class)
+ {
+ if (isset($this->processors[$class])) {
+ unset($this->processors[$class]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Checks wheather a specific processor is registered or not
+ *
+ * @access public
+ * @param string $class
+ * @return bool
+ */
+ public function hasProcessor($class)
+ {
+ return isset($this->processors[$class]);
+ }
+
+ /**
+ * Get Processor instance
+ *
+ * @access public
+ * @param string $class
+ * @return ItemProcessorInterface|null
+ */
+ public function getProcessor($class)
+ {
+ return isset($this->processors[$class]) ? $this->processors[$class] : null;
+ }
+
+ public function setConfig(Config $config)
+ {
+ foreach ($this->processors as $processor) {
+ $processor->setConfig($config);
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php
new file mode 100644
index 00000000..5d532262
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php
@@ -0,0 +1,25 @@
+executionCallback = $executionCallback;
+ return $this;
+ }
+
+ /**
+ * Execute Item Processor
+ *
+ * @access public
+ * @param Feed $feed
+ * @param Item $item
+ * @return bool
+ */
+ public function execute(Feed $feed, Item $item)
+ {
+ if (!in_array($item->getUrl(), $this->ignoredUrls)) {
+ $scraper = $this->getScraper();
+ $scraper->setUrl($item->getUrl());
+ $scraper->execute();
+
+ if ($this->executionCallback && is_callable($this->executionCallback)) {
+ call_user_func($this->executionCallback, $feed, $item, $scraper);
+ }
+
+ if ($scraper->hasRelevantContent()) {
+ $item->setContent($scraper->getFilteredContent());
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Ignore list of URLs
+ *
+ * @access public
+ * @param array $urls
+ * @return $this
+ */
+ public function ignoreUrls(array $urls)
+ {
+ $this->ignoredUrls = $urls;
+ return $this;
+ }
+
+ /**
+ * Returns Scraper instance
+ *
+ * @access public
+ * @return Scraper
+ */
+ public function getScraper()
+ {
+ if ($this->scraper === null) {
+ $this->scraper = new Scraper($this->config);
+ }
+
+ return $this->scraper;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php
new file mode 100644
index 00000000..d4ca07db
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Favicon.php
@@ -0,0 +1,186 @@
+content;
+ }
+
+ /**
+ * Get the icon file type (available only after the download).
+ *
+ * @return string
+ */
+ public function getType()
+ {
+ foreach ($this->types as $type) {
+ if (strpos($this->content_type, $type) === 0) {
+ return $type;
+ }
+ }
+
+ return 'image/x-icon';
+ }
+
+ /**
+ * Get data URI (http://en.wikipedia.org/wiki/Data_URI_scheme).
+ *
+ * @return string
+ */
+ public function getDataUri()
+ {
+ if (empty($this->content)) {
+ return '';
+ }
+
+ return sprintf(
+ 'data:%s;base64,%s',
+ $this->getType(),
+ base64_encode($this->content)
+ );
+ }
+
+ /**
+ * Download and check if a resource exists.
+ *
+ * @param string $url URL
+ * @return \PicoFeed\Client\Client Client instance
+ */
+ public function download($url)
+ {
+ $client = Client::getInstance();
+ $client->setConfig($this->config);
+
+ Logger::setMessage(get_called_class().' Download => '.$url);
+
+ try {
+ $client->execute($url);
+ } catch (ClientException $e) {
+ Logger::setMessage(get_called_class().' Download Failed => '.$e->getMessage());
+ }
+
+ return $client;
+ }
+
+ /**
+ * Check if a remote file exists.
+ *
+ * @param string $url URL
+ * @return bool
+ */
+ public function exists($url)
+ {
+ return $this->download($url)->getContent() !== '';
+ }
+
+ /**
+ * Get the icon link for a website.
+ *
+ * @param string $website_link URL
+ * @param string $favicon_link optional URL
+ * @return string
+ */
+ public function find($website_link, $favicon_link = '')
+ {
+ $website = new Url($website_link);
+
+ if ($favicon_link !== '') {
+ $icons = array($favicon_link);
+ } else {
+ $icons = $this->extract($this->download($website->getBaseUrl('/'))->getContent());
+ $icons[] = $website->getBaseUrl('/favicon.ico');
+ }
+
+ foreach ($icons as $icon_link) {
+ $icon_link = Url::resolve($icon_link, $website);
+ $resource = $this->download($icon_link);
+ $this->content = $resource->getContent();
+ $this->content_type = $resource->getContentType();
+
+ if ($this->content !== '') {
+ return $icon_link;
+ } elseif ($favicon_link !== '') {
+ return $this->find($website_link);
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Extract the icon links from the HTML.
+ *
+ * @param string $html HTML
+ * @return array
+ */
+ public function extract($html)
+ {
+ $icons = array();
+
+ if (empty($html)) {
+ return $icons;
+ }
+
+ $dom = XmlParser::getHtmlDocument($html);
+
+ $xpath = new DOMXpath($dom);
+ $elements = $xpath->query('//link[@rel="icon" or @rel="shortcut icon" or @rel="Shortcut Icon" or @rel="icon shortcut"]');
+
+ for ($i = 0; $i < $elements->length; ++$i) {
+ $icons[] = $elements->item($i)->getAttribute('href');
+ }
+
+ return $icons;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php
new file mode 100644
index 00000000..769ffe93
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/Reader.php
@@ -0,0 +1,190 @@
+ '//feed',
+ 'Rss20' => '//rss[@version="2.0"]',
+ 'Rss92' => '//rss[@version="0.92"]',
+ 'Rss91' => '//rss[@version="0.91"]',
+ 'Rss10' => '//rdf',
+ );
+
+ /**
+ * Download a feed (no discovery).
+ *
+ * @param string $url Feed url
+ * @param string $last_modified Last modified HTTP header
+ * @param string $etag Etag HTTP header
+ * @param string $username HTTP basic auth username
+ * @param string $password HTTP basic auth password
+ *
+ * @return \PicoFeed\Client\Client
+ */
+ public function download($url, $last_modified = '', $etag = '', $username = '', $password = '')
+ {
+ $url = $this->prependScheme($url);
+
+ return Client::getInstance()
+ ->setConfig($this->config)
+ ->setLastModified($last_modified)
+ ->setEtag($etag)
+ ->setUsername($username)
+ ->setPassword($password)
+ ->execute($url);
+ }
+
+ /**
+ * Discover and download a feed.
+ *
+ * @param string $url Feed or website url
+ * @param string $last_modified Last modified HTTP header
+ * @param string $etag Etag HTTP header
+ * @param string $username HTTP basic auth username
+ * @param string $password HTTP basic auth password
+ * @return Client
+ * @throws SubscriptionNotFoundException
+ */
+ public function discover($url, $last_modified = '', $etag = '', $username = '', $password = '')
+ {
+ $client = $this->download($url, $last_modified, $etag, $username, $password);
+
+ // It's already a feed or the feed was not modified
+ if (!$client->isModified() || $this->detectFormat($client->getContent())) {
+ return $client;
+ }
+
+ // Try to find a subscription
+ $links = $this->find($client->getUrl(), $client->getContent());
+
+ if (empty($links)) {
+ throw new SubscriptionNotFoundException('Unable to find a subscription');
+ }
+
+ return $this->download($links[0], $last_modified, $etag, $username, $password);
+ }
+
+ /**
+ * Find feed urls inside a HTML document.
+ *
+ * @param string $url Website url
+ * @param string $html HTML content
+ *
+ * @return array List of feed links
+ */
+ public function find($url, $html)
+ {
+ Logger::setMessage(get_called_class().': Try to discover subscriptions');
+
+ $dom = XmlParser::getHtmlDocument($html);
+ $xpath = new DOMXPath($dom);
+ $links = array();
+
+ $queries = array(
+ '//link[@type="application/rss+xml"]',
+ '//link[@type="application/atom+xml"]',
+ );
+
+ foreach ($queries as $query) {
+ $nodes = $xpath->query($query);
+
+ foreach ($nodes as $node) {
+ $link = $node->getAttribute('href');
+
+ if (!empty($link)) {
+ $feedUrl = new Url($link);
+ $siteUrl = new Url($url);
+
+ $links[] = $feedUrl->getAbsoluteUrl($feedUrl->isRelativeUrl() ? $siteUrl->getBaseUrl() : '');
+ }
+ }
+ }
+
+ Logger::setMessage(get_called_class().': '.implode(', ', $links));
+
+ return $links;
+ }
+
+ /**
+ * Get a parser instance.
+ *
+ * @param string $url Site url
+ * @param string $content Feed content
+ * @param string $encoding HTTP encoding
+ *
+ * @return \PicoFeed\Parser\Parser
+ */
+ public function getParser($url, $content, $encoding)
+ {
+ $format = $this->detectFormat($content);
+
+ if (empty($format)) {
+ throw new UnsupportedFeedFormatException('Unable to detect feed format');
+ }
+
+ $className = '\PicoFeed\Parser\\'.$format;
+
+ $parser = new $className($content, $encoding, $url);
+ $parser->setHashAlgo($this->config->getParserHashAlgo());
+ $parser->setConfig($this->config);
+
+ return $parser;
+ }
+
+ /**
+ * Detect the feed format.
+ *
+ * @param string $content Feed content
+ *
+ * @return string
+ */
+ public function detectFormat($content)
+ {
+ $dom = XmlParser::getHtmlDocument($content);
+ $xpath = new DOMXPath($dom);
+
+ foreach ($this->formats as $parser_name => $query) {
+ $nodes = $xpath->query($query);
+
+ if ($nodes->length === 1) {
+ return $parser_name;
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Add the prefix "http://" if the end-user just enter a domain name.
+ *
+ * @param string $url Url
+ * @retunr string
+ */
+ public function prependScheme($url)
+ {
+ if (!preg_match('%^https?://%', $url)) {
+ $url = 'http://'.$url;
+ }
+
+ return $url;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php
new file mode 100644
index 00000000..4f03dbe0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Reader/ReaderException.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://combat.blog.lemonde.fr/2013/08/31/teddy-riner-le-rookie-devenu-rambo/#xtor=RSS-3208',
+ 'body' => array(
+ '//div[@class="entry-content"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "fb-like") or contains(@class, "social")]'
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php
new file mode 100644
index 00000000..ee641b09
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'title' => '//header/h1',
+ 'test_url' => 'http://bits.blogs.nytimes.com/2012/01/16/wikipedia-plans-to-go-dark-on-wednesday-to-protest-sopa/',
+ 'body' => array(
+ '//div[@class="postContent"]',
+ ),
+ 'strip' => array(
+ '//*[@class="shareToolsBox"]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.igen.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.igen.fr.php
new file mode 100644
index 00000000..f2028f4e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.igen.fr.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.igen.fr/ailleurs/2014/05/nvidia-va-delaisser-les-smartphones-grand-public-86031',
+ 'body' => array(
+ '//div[contains(@class, "field-name-body")]'
+ ),
+ 'strip' => array(
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.nytimes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.nytimes.com.php
new file mode 100644
index 00000000..ed27bb5c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.nytimes.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nytimes.com/2011/05/15/world/middleeast/15prince.html',
+ 'body' => array(
+ '//div[@class="articleBody"]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.over-blog.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.over-blog.com.php
new file mode 100644
index 00000000..cc5d83c7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.over-blog.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://eliascarpe.over-blog.com/2015/12/re-upload-projets-d-avenir.html',
+ 'body' => array(
+ '//div[contains(concat(" ", normalize-space(@class), " "), " ob-section ")]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.phoronix.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.phoronix.com.php
new file mode 100644
index 00000000..66713f71
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.phoronix.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.phoronix.com/scan.php?page=article&item=amazon_ec2_bare&num=1',
+ 'body' => array(
+ '//div[@class="content"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.slate.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.slate.com.php
new file mode 100644
index 00000000..a795bca3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.slate.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.slate.com/articles/business/moneybox/2013/08/microsoft_ceo_steve_ballmer_retires_a_firsthand_account_of_the_company_s.html',
+ 'body' => array(
+ '//div[@class="sl-art-body"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "social") or contains(@class, "comments") or contains(@class, "sl-article-floatin-tools") or contains(@class, "sl-art-pag")]',
+ '//*[@id="mys_slate_logged_in"]',
+ '//*[@id="sl_article_tools_myslate_bottom"]',
+ '//*[@id="mys_myslate"]',
+ '//*[@class="sl-viral-container"]',
+ '//*[@class="sl-art-creds-cntr"]',
+ '//*[@class="sl-art-ad-midflex"]',
+ )
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.theguardian.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.theguardian.com.php
new file mode 100644
index 00000000..e0d6f3fd
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.theguardian.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.theguardian.com/sustainable-business/2015/feb/02/2015-hyper-transparency-global-business',
+ 'body' => array(
+ '//div[contains(@class, "content__main-column--article")]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class, "meta-container")]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wikipedia.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wikipedia.org.php
new file mode 100644
index 00000000..7b8f76e5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wikipedia.org.php
@@ -0,0 +1,29 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://en.wikipedia.org/wiki/Grace_Hopper',
+ 'body' => array(
+ '//div[@id="bodyContent"]',
+ ),
+ 'strip' => array(
+ "//div[@id='toc']",
+ "//div[@id='catlinks']",
+ "//div[@id='jump-to-nav']",
+ "//div[@class='thumbcaption']//div[@class='magnify']",
+ "//table[@class='navbox']",
+ "//table[contains(@class, 'infobox')]",
+ "//div[@class='dablink']",
+ "//div[@id='contentSub']",
+ "//div[@id='siteSub']",
+ "//table[@id='persondata']",
+ "//table[contains(@class, 'metadata')]",
+ "//*[contains(@class, 'noprint')]",
+ "//*[contains(@class, 'printfooter')]",
+ "//*[contains(@class, 'editsection')]",
+ "//*[contains(@class, 'error')]",
+ "//span[@title='pronunciation:']",
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wired.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wired.com.php
new file mode 100644
index 00000000..952b09ac
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wired.com.php
@@ -0,0 +1,44 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.wired.com/gamelife/2013/09/ouya-free-the-games/',
+ 'body' => array(
+ '//div[@data-js="gallerySlides"]',
+ '//div[starts-with(@class,"post")]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//nav',
+ '//button',
+ '//figure[starts-with(@class,"rad-slide")]',
+ '//figure[starts-with(@class,"end-slate")]',
+ '//div[contains(@class,"mobile-")]',
+ '//div[starts-with(@class,"mob-gallery-launcher")]',
+ '//div[contains(@id,"mobile-")]',
+ '//span[contains(@class,"slide-count")]',
+ '//div[contains(@class,"show-ipad")]',
+ '//img[contains(@id,"-hero-bg")]',
+ '//div[@data-js="overlayWrap"]',
+ '//ul[contains(@class,"metadata")]',
+ '//div[@class="opening center"]',
+ '//p[contains(@class="byline-mob"]',
+ '//div[@id="o-gallery"]',
+ '//div[starts-with(@class,"sm-col")]',
+ '//div[contains(@class,"pad-b-huge")]',
+ '//a[contains(@class,"visually-hidden")]',
+ '//*[@class="social"]',
+ '//i',
+ '//div[@data-js="mobGalleryAd"]',
+ '//div[contains(@class,"footer")]',
+ '//div[contains(@data-js,"fader")]',
+ '//div[@id="sharing"]',
+ '//div[contains(@id,"related")]',
+ '//div[@id="most-pop"]',
+ '//ul[@id="article-tags"]',
+ '//style',
+ '//section[contains(@class,"footer")]'
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wsj.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wsj.com.php
new file mode 100644
index 00000000..f6e6cc12
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/.wsj.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://online.wsj.com/article/SB10001424127887324108204579023143974408428.html',
+ 'body' => array(
+ '//div[@class="articlePage"]',
+ ),
+ 'strip' => array(
+ '//*[@id="articleThumbnail_2"]',
+ '//*[@class="socialByline"]',
+ )
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/01net.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/01net.com.php
new file mode 100644
index 00000000..6d144f05
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/01net.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.01net.com/editorial/624550/twitter-rachete-madbits-un-specialiste-francais-de-lanalyse-dimages/',
+ 'body' => array(
+ '//div[@class="article_ventre_box"]',
+ ),
+ 'strip' => array(
+ '//link',
+ '//*[contains(@class, "article_navigation")]',
+ '//h1',
+ '//*[contains(@class, "article_toolbarMain")]',
+ '//*[contains(@class, "article_imagehaute_box")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php
new file mode 100644
index 00000000..752d0413
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%alt="(.+)" title="(.+)" */>%' => '/>
$1
$2',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/adventuregamers.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/adventuregamers.com.php
new file mode 100644
index 00000000..98d384e6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/adventuregamers.com.php
@@ -0,0 +1,23 @@
+ array(
+ '%^/news.*%' => array(
+ 'test_url' => 'http://www.adventuregamers.com/news/view/31079',
+ 'body' => array(
+ '//div[@class="bodytext"]',
+ )
+ ),
+ '%^/videos.*%' => array(
+ 'test_url' => 'http://www.adventuregamers.com/videos/view/31056',
+ 'body' => array(
+ '//iframe',
+ )
+ ),
+ '%^/articles.*%' => array(
+ 'test_url' => 'http://www.adventuregamers.com/articles/view/31049',
+ 'body' => array(
+ '//div[@class="cleft"]',
+ )
+ )
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/alainonline.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/alainonline.net.php
new file mode 100644
index 00000000..f440b234
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/alainonline.net.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.alainonline.net/news_details.php?lang=arabic&sid=18907',
+ 'body' => array(
+ '//div[@class="news_details"]',
+ ),
+ 'strip' => array(
+ '//div[@class="news_details"]/div/div[last()]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/aljazeera.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/aljazeera.com.php
new file mode 100644
index 00000000..c02eb219
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/aljazeera.com.php
@@ -0,0 +1,25 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.aljazeera.com/news/2015/09/xi-jinping-seattle-china-150922230118373.html',
+ 'body' => array(
+ '//article[@id="main-story"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//header',
+ '//ul',
+ '//section[contains(@class,"profile")]',
+ '//a[@target="_self"]',
+ '//div[contains(@id,"_2")]',
+ '//div[contains(@id,"_3")]',
+ '//img[@class="viewMode"]',
+ '//table[contains(@class,"in-article-item")]',
+ '//div[@data-embed-type="Brightcove"]',
+ '//div[@class="QuoteContainer"]',
+ '//div[@class="BottomByLine"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allafrica.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allafrica.com.php
new file mode 100644
index 00000000..e8a506d4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allafrica.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.aljazeera.com/news/2015/09/xi-jinping-seattle-china-150922230118373.html',
+ 'body' => array(
+ '//div[@class="story-body"]',
+ ),
+ 'strip' => array(
+ '//p[@class="kindofstory"]',
+ '//cite[@class="byline"]',
+ '//div[@class="useful-top"]',
+ '//div[contains(@class,"related-topics")]',
+ '//links',
+ '//sharebar',
+ '//related-topics',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allgemeine-zeitung.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allgemeine-zeitung.de.php
new file mode 100644
index 00000000..8ede99b1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/allgemeine-zeitung.de.php
@@ -0,0 +1,23 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.allgemeine-zeitung.de/lokales/polizei/mainz-gonsenheim-unbekannte-rauben-esso-tankstelle-in-kurt-schumacher-strasse-aus_14913147.htm',
+ 'body' => array(
+ '//div[contains(@class, "article")][1]',
+ ),
+ 'strip' => array(
+ '//read/h1',
+ '//*[@id="t-map"]',
+ '//*[contains(@class, "modules")]',
+ '//*[contains(@class, "adsense")]',
+ '//*[contains(@class, "linkbox")]',
+ '//*[contains(@class, "info")]',
+ '//*[@class="skip"]',
+ '//*[@class="funcs"]',
+ '//span[@class="nd address"]',
+ '//a[contains(@href, "abo-und-services")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php
new file mode 100644
index 00000000..51247f76
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//img[@id="comic_image"]',
+ '//div[@class="comment-wrapper"][position()=1]',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://www.anythingcomic.com/comics/2108929/stress-free/',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ap.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ap.org.php
new file mode 100644
index 00000000..5bb2bb6c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ap.org.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://hosted.ap.org/dynamic/stories/A/AS_CHINA_GAO_ZHISHENG?SITE=AP&SECTION=HOME&TEMPLATE=DEFAULT',
+ 'body' => array(
+ '//img[@class="ap-smallphoto-img"]',
+ '//span[@class="entry-content"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/areadvd.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/areadvd.de.php
new file mode 100644
index 00000000..fc569220
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/areadvd.de.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.areadvd.de/news/daily-deals-angebote-bei-lautsprecher-teufel-3/',
+ 'body' => array('//div[contains(@class,"entry")]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/arstechnica.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/arstechnica.com.php
new file mode 100644
index 00000000..55e01ce3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/arstechnica.com.php
@@ -0,0 +1,25 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://arstechnica.com/tech-policy/2015/09/judge-warners-2m-happy-birthday-copyright-is-bogus/',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//h4[@class="post-upperdek"]',
+ '//h1',
+ '//ul[@class="lSPager lSGallery"]',
+ '//div[@class="lSAction"]',
+ '//section[@class="post-meta"]',
+ '//figcaption',
+ '//aside',
+ '//div[@class="gallery-image-credit"]',
+ '//section[@class="article-author"]',
+ '//*[contains(@id,"social-")]',
+ '//div[contains(@id,"footer")]',
+ ),
+ ),
+ ),
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/awkwardzombie.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/awkwardzombie.com.php
new file mode 100644
index 00000000..5ab70514
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/awkwardzombie.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%/index.php.*comic=.*%' => array(
+ 'test_url' => 'http://www.awkwardzombie.com/index.php?comic=041315',
+ 'body' => array('//*[@id="comic"]/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/backchannel.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/backchannel.com.php
new file mode 100644
index 00000000..bc5932a2
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/backchannel.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://medium.com/lessons-learned/917b8b63ae3e',
+ 'body' => array(
+ '//div[contains(@class,"section-inner")]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"metabar")]',
+ '//img[contains(@class,"thumbnail")]',
+ '//h1',
+ '//blockquote',
+ '//p[contains(@class,"graf-after--h4")]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bangkokpost.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bangkokpost.com.php
new file mode 100644
index 00000000..165515bb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bangkokpost.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bangkokpost.com/news/politics/704204/new-us-ambassador-arrives-in-bangkok',
+ 'body' => array(
+ '//article/div[@class="articleContents"]',
+ ),
+ 'strip' => array(
+ '//h2',
+ '//h4',
+ '//div[@class="text-size"]',
+ '//div[@class="relate-story"]',
+ '//div[@class="text-ads"]',
+ '//ul',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bgr.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bgr.com.php
new file mode 100644
index 00000000..7507a2f1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bgr.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://bgr.com/2015/09/27/iphone-6s-waterproof-testing/',
+ 'body' => array(
+ '//img[contains(@class,"img")]',
+ '//div[@class="text-column"]',
+ ),
+ 'strip' => array(
+ '//strong',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigfootjustice.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigfootjustice.com.php
new file mode 100644
index 00000000..d06ed124
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigfootjustice.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigpicture.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigpicture.ru.php
new file mode 100644
index 00000000..55c40894
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bigpicture.ru.php
@@ -0,0 +1,31 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://bigpicture.ru/?p=556658',
+ 'body' => array(
+ '//div[@class="article container"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//h1',
+ '//*[@class="wp-smiley"]',
+ '//div[@class="ipmd"]',
+ '//div[@class="tags"]',
+ '//div[@class="social-button"]',
+ '//div[@class="bottom-share"]',
+ '//div[@class="raccoonbox"]',
+ '//div[@class="yndadvert"]',
+ '//div[@class="we-recommend"]',
+ '//div[@class="relap-bigpicture_ru-wrapper"]',
+ '//div[@id="mmail"]',
+ '//div[@id="mobile-ads-cut"]',
+ '//div[@id="liquidstorm-alt-html"]',
+ '//div[contains(@class, "post-tags")]',
+ '//*[contains(text(),"Смотрите также")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bizjournals.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bizjournals.com.php
new file mode 100644
index 00000000..d1cc3da9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bizjournals.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bizjournals.com/milwaukee/news/2015/09/30/bucks-will-hike-prices-on-best-seats-at-new-arena.html',
+ 'body' => array(
+ '//figure/div/a/img',
+ '//p[@class="content__segment"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/biztimes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/biztimes.com.php
new file mode 100644
index 00000000..d21aa98c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/biztimes.com.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.biztimes.com/2017/02/10/settlement-would-revive-fowler-lake-condo-project-in-oconomowoc/',
+ 'body' => array(
+ '//h2/span[@class="subhead"]',
+ '//div[contains(@class,"article-content")]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//div[contains(@class,"mobile-article-content")]',
+ '//div[contains(@class,"sharedaddy")]',
+ '//div[contains(@class,"author-details")]',
+ '//div[@class="row ad"]',
+ '//div[contains(@class,"relatedposts")]',
+ '//div[@class="col-lg-12"]',
+ '//div[contains(@class,"widget")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bleepingcomputer.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bleepingcomputer.com.php
new file mode 100644
index 00000000..7b740600
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bleepingcomputer.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.bleepingcomputer.com/news/google/chromes-sandbox-feature-infringes-on-three-patents-so-google-must-now-pay-20m/',
+ 'body' => array(
+ '//div[@class="article_section"]',
+ ),
+ 'strip' => array(
+ '//*[@itemprop="headline"]',
+ '//div[@class="cz-news-story-title-section"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.fefe.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.fefe.de.php
new file mode 100644
index 00000000..39c88ae4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.fefe.de.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://blog.fefe.de/?ts=ad706a73',
+ 'body' => array(
+ '/html/body/ul',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.mapillary.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.mapillary.com.php
new file mode 100644
index 00000000..ce016510
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/blog.mapillary.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://blog.mapillary.com/update/2015/08/26/traffic-sign-updates.html',
+ 'body' => array(
+ '//div[contains(@class, "blog-post__content")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/brewers.mlb.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/brewers.mlb.com.php
new file mode 100644
index 00000000..be406faf
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/brewers.mlb.com.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://m.brewers.mlb.com/news/article/161364798',
+ 'body' => array(
+ '//article[contains(@class,"article")]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"ad-slot")]',
+ '//h1',
+ '//span[@class="timestamp"]',
+ '//div[contains(@class,"contributor-bottom")]',
+ '//div[contains(@class,"video")]',
+ '//ul[contains(@class,"social")]',
+ '//p[@class="tagline"]',
+ '//div[contains(@class,"social")]',
+ '//div[@class="button-wrap"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buenosairesherald.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buenosairesherald.com.php
new file mode 100644
index 00000000..4e73e79f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buenosairesherald.com.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.buenosairesherald.com/article/199344/manzur-named-next-governor-of-tucum%C3%A1n',
+ 'body' => array(
+ '//div[@style="float:none"]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class, "bz_alias_short_desc_container"]',
+ '//td[@id="bz_show_bug_column_1"]',
+ '//table[@id="attachment_table"]',
+ '//table[@class="bz_comment_table"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bunicomic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bunicomic.com.php
new file mode 100644
index 00000000..ad83e436
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/bunicomic.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bunicomic.com/comic/buni-623/',
+ 'body' => array(
+ '//div[@class="comic-table"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buttersafe.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buttersafe.com.php
new file mode 100644
index 00000000..1f313cd0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/buttersafe.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://buttersafe.com/2015/04/21/the-incredible-flexible-man/',
+ 'body' => array(
+ '//div[@id="comic"]',
+ '//div[@class="post-comic"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cad-comic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cad-comic.com.php
new file mode 100644
index 00000000..a631c97f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cad-comic.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%/cad/.+%' => array(
+ 'test_url' => 'http://www.cad-comic.com/cad/20150417',
+ 'body' => array(
+ '//*[@id="content"]/img',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chaoslife.findchaos.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chaoslife.findchaos.com.php
new file mode 100644
index 00000000..ea6191e8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chaoslife.findchaos.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://chaoslife.findchaos.com/pets-in-the-wild',
+ 'body' => array('//div[@id="comic"]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chinafile.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chinafile.com.php
new file mode 100644
index 00000000..450117b3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/chinafile.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.chinafile.com/books/shanghai-faithful?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+chinafile%2FAll+%28ChinaFile%29',
+ 'body' => array(
+ '//div[contains(@class,"pane-featured-photo-panel-pane-1")]',
+ '//div[contains(@class,"video-above-fold")]',
+ '//div[@class="sc-media"]',
+ '//div[contains(@class,"field-name-body")]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"cboxes")]',
+ '//div[contains(@class,"l-middle")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cliquerefresh.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cliquerefresh.com.php
new file mode 100644
index 00000000..9dcc7e54
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cliquerefresh.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%/comic.*%' => array(
+ 'test_url' => 'http://cliquerefresh.com/comic/078-stating-the-obvious/',
+ 'body' => array('//div[@class="comicImg"]/img | //div[@class="comicImg"]/a/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cnet.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cnet.com.php
new file mode 100644
index 00000000..60767a53
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cnet.com.php
@@ -0,0 +1,37 @@
+ array(
+ '%^/products.*%' => array(
+ 'test_url' => 'http://www.cnet.com/products/fibaro-flood-sensor/#ftag=CADf328eec',
+ 'body' => array(
+ '//li[contains(@class,"slide first"] || //figure[contains(@class,(promoFigure))]',
+ '//div[@class="quickInfo"]',
+ '//div[@class="col-6 ratings"]',
+ '//div[@id="editorReview"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//a[@class="clickToEnlarge"]',
+ '//div[@section="topSharebar"]',
+ '//div[contains(@class,"related")]',
+ '//div[contains(@class,"ad-")]',
+ '//div[@section="shortcodeGallery"]',
+ ),
+ ),
+ '%.*%' => array(
+ 'test_url' => 'http://cnet.com.feedsportal.com/c/34938/f/645093/s/4a340866/sc/28/l/0L0Scnet0N0Cnews0Cman0Eclaims0Eonline0Epsychic0Emade0Ehim0Ebuy0E10Emillion0Epowerball0Ewinning0Eticket0C0Tftag0FCAD590Aa51e/story01.htm',
+ 'body' => array(
+ '//p[@itemprop="description"]',
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//a[@class="clickToEnlarge"]',
+ '//div[@section="topSharebar"]',
+ '//div[contains(@class,"related")]',
+ '//div[contains(@class,"ad-")]',
+ '//div[@section="shortcodeGallery"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/consomac.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/consomac.fr.php
new file mode 100644
index 00000000..9209f9cb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/consomac.fr.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://consomac.fr/news-2430-l-iphone-6-toujours-un-secret-bien-garde.html',
+ 'body' => array(
+ '//div[contains(@id, "newscontent")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/crash.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/crash.net.php
new file mode 100644
index 00000000..9d9b35a6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/crash.net.php
@@ -0,0 +1,28 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.crash.net/motogp/interview/247550/1/exclusive-andrea-dovizioso-interview.html',
+ 'body' => array(
+ '//div[@id="content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//style',
+ '//*[@title="Social Networking"]',
+ '//*[@class="crash-ad2"]',
+ '//*[@class="clearfix"]',
+ '//*[@class="crash-ad2"]',
+ '//*[contains(@id, "divCB"]',
+ '//*[@class="pnlComment"]',
+ '//*[@class="comments-tabs"]',
+ '//*[contains(@class, "ad-twocol"]',
+ '//*[@class="stories-list"]',
+ '//*[contains(@class, "btn")]',
+ '//*[@class="content"]',
+ '//h3',
+ ),
+ ),
+ ),
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/csmonitor.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/csmonitor.com.php
new file mode 100644
index 00000000..481e4b09
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/csmonitor.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.csmonitor.com/USA/Politics/2015/0925/John-Boehner-steps-down-Self-sacrificing-but-will-it-lead-to-better-government',
+ 'body' => array(
+ '//h2[@id="summary"]',
+ '//div[@class="flex-video youtube"]',
+ '//div[contains(@class,"eza-body")]',
+ ),
+ 'strip' => array(
+ '//span[@id="breadcrumb"]',
+ '//div[@id="byline-wrapper"]',
+ '//div[@class="injection"]',
+ '//*[contains(@class,"promo_link")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyjs.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyjs.com.php
new file mode 100644
index 00000000..20eb1d75
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyjs.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://dailyjs.com/2014/08/07/p5js/',
+ 'body' => array(
+ '//div[@id="post"]',
+ ),
+ 'strip' => array(
+ '//h2[@class="post"]',
+ '//div[@class="meta"]',
+ '//*[contains(@class, "addthis_toolbox")]',
+ '//*[contains(@class, "addthis_default_style")]',
+ '//*[@class="navigation small"]',
+ '//*[@id="related"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyreporter.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyreporter.com.php
new file mode 100644
index 00000000..db3fc0e1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailyreporter.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://dailyreporter.com/2016/01/09/us-supreme-court-case-could-weaken-government-workers-unions/',
+ 'body' => array(
+ '//div[contains(@class, "entry-content")]',
+ ),
+ 'strip' => array(
+ '//div[@class="dmcss_login_form"]',
+ '//*[contains(@class, "sharedaddy")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailytech.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailytech.com.php
new file mode 100644
index 00000000..5d1df4a9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dailytech.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.dailytech.com/Apples+First+Fixes+to+iOS+9+Land+w+iOS++901+Release/article37495.htm',
+ 'body' => array(
+ '//div[@class="NewsBodyImage"]',
+ '//span[@id="lblSummary"]',
+ '//span[@id="lblBody"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/degroupnews.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/degroupnews.com.php
new file mode 100644
index 00000000..91f5c56e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/degroupnews.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.degroupnews.com/medias/vodsvod/amazon-concurrence-la-chromecast-de-google-avec-fire-tv-stick',
+ 'body' => array(
+ '//div[@class="contenu"]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class, "a2a")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/derstandard.at.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/derstandard.at.php
new file mode 100644
index 00000000..7e95a51f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/derstandard.at.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://derstandard.at/2000010267354/The-Witcher-3-Hohe-Hardware-Anforderungen-fuer-PC-Spieler?ref=rss',
+ 'body' => array(
+ '//div[@class="copytext"]',
+ '//ul[@id="media-list"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dilbert.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dilbert.com.php
new file mode 100644
index 00000000..b8e9b3d6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dilbert.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//img[@class="img-responsive img-comic"]',
+ ),
+ 'test_url' => 'http://dilbert.com/strip/2016-01-28',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/discovermagazine.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/discovermagazine.com.php
new file mode 100644
index 00000000..ae0dfe71
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/discovermagazine.com.php
@@ -0,0 +1,26 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://blogs.discovermagazine.com/neuroskeptic/2017/01/25/publishers-jeffrey-beall/',
+ 'body' => array(
+ '//div[@class="contentWell"]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//div[@class="breadcrumbs"]',
+ '//div[@class="mobile"]',
+ '//div[@class="fromIssue"]',
+ '//div[contains(@class,"belowDeck")]',
+ '//div[@class="meta"]',
+ '//div[@class="shareIcons"]',
+ '//div[@class="categories"]',
+ '//div[@class="navigation"]',
+ '//div[@class="heading"]',
+ '//div[contains(@id,"-ad")]',
+ '//div[@class="relatedArticles"]',
+ '//div[@id="disqus_thread"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/distrowatch.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/distrowatch.com.php
new file mode 100644
index 00000000..aefc8f81
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/distrowatch.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://distrowatch.com/?newsid=08355',
+ 'body' => array(
+ '//td[@class="NewsText"][1]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dozodomo.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dozodomo.com.php
new file mode 100644
index 00000000..e1166957
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/dozodomo.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://dozodomo.com/bento/2014/03/04/lart-des-maki-de-takayo-kiyota/',
+ 'body' => array(
+ '//div[@class="joke"]',
+ '//div[@class="story-cover"]',
+ '//div[@class="story-content"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php
new file mode 100644
index 00000000..cd30f2e0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//img[@id="comicimage"]'),
+ 'strip' => array(),
+ 'test_url' => 'http://drawingboardcomic.com/index.php?comic=208',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/e-w-e.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/e-w-e.ru.php
new file mode 100644
index 00000000..8139cc9a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/e-w-e.ru.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://e-w-e.ru/16-prekrasnyx-izobretenij-zhenshhin/',
+ 'body' => array(
+ '//div[contains(@class, "post_text")]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[@class="views_post"]',
+ '//*[@class="adman_mobile"]',
+ '//*[@class="adman_desctop"]',
+ '//*[contains(@rel, "nofollow")]',
+ '//*[contains(@class, "wp-smiley")]',
+ '//*[contains(text(),"Источник:")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/economist.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/economist.com.php
new file mode 100644
index 00000000..522032fd
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/economist.com.php
@@ -0,0 +1,25 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.economist.com/blogs/buttonwood/2017/02/mixed-signals?fsrc=rss',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//span[@class="blog-post__siblings-list-header "]',
+ '//h1',
+ '//aside',
+ '//div[@class="blog-post__asideable-wrapper"]',
+ '//div[@class="share_inline_header"]',
+ '//div[@id="column-right"]',
+ '//div[contains(@class,"blog-post__siblings-list-aside")]',
+ '//div[@class="video-player__wrapper"]',
+ '//div[@class="blog-post__bottom-panel"]',
+ '//div[contains(@class,"latest-updates-panel__container")]',
+ '//div[contains(@class,"blog-post__asideable-content")]',
+ '//div[@aria-label="Advertisement"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/encyclopedie.naheulbeuk.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/encyclopedie.naheulbeuk.com.php
new file mode 100644
index 00000000..19bcbdef
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/encyclopedie.naheulbeuk.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://encyclopedie.naheulbeuk.com/article.php3?id_article=352',
+ 'body' => array(
+ '//td//h1[@class="titre-texte"]',
+ '//td//div[@class="surtitre"]',
+ '//td//div[@class="texte"]',
+ ),
+ )
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php
new file mode 100644
index 00000000..d06ed124
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/engadget.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/engadget.com.php
new file mode 100644
index 00000000..cf9e4485
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/engadget.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.engadget.com/2015/04/20/dark-matter-discovery/?ncid=rss_truncated',
+ 'body' => array('//div[@id="page_body"]/div[@class="container@m-"]'),
+ 'strip' => array('//aside[@role="banner"]'),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php
new file mode 100644
index 00000000..e86b59cb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php
@@ -0,0 +1,45 @@
+ array(
+ '%/articles/view/comicsandcosplay/comics/critical-miss.*%' => array(
+ 'body' => array('//*[@class="body"]/span/img | //div[@class="folder_nav_links"]/following::p'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/critical-miss/13776-Critical-Miss-on-Framerates?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay/comics/namegame.*%' => array(
+ 'body' => array('//*[@class="body"]/span/p/img[@height != "120"]'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/namegame/9759-Leaving-the-Nest?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay/comics/stolen-pixels.*%' => array(
+ 'body' => array('//*[@class="body"]/span/p[2]/img'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/stolen-pixels/8866-Stolen-Pixels-258-Where-the-Boys-Are?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay/comics/bumhugparade.*%' => array(
+ 'body' => array('//*[@class="body"]/span/p[2]/img'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/bumhugparade/8262-Bumhug-Parade-13?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay.*/comics/escapistradiotheater%' => array(
+ 'body' => array('//*[@class="body"]/span/p[2]/img'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/escapistradiotheater/8265-The-Escapist-Radio-Theater-13?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay/comics/paused.*%' => array(
+ 'body' => array('//*[@class="body"]/span/p[2]/img | //*[@class="body"]/span/div/img'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/paused/8263-Paused-16?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/comicsandcosplay/comics/fraughtwithperil.*%' => array(
+ 'body' => array('//*[@class="body"]'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/comicsandcosplay/comics/fraughtwithperil/12166-The-Escapist-Presents-Escapist-Comics-Critical-Miss-B-lyeh-Fhlop?utm_source=rss&utm_medium=rss&utm_campaign=articles',
+ 'strip' => array(),
+ ),
+ '%/articles/view/video-games/columns/.*%' => array(
+ 'body' => array('//*[@id="article_content"]'),
+ 'test_url' => 'http://www.escapistmagazine.com/articles/view/video-games/columns/experienced-points/13971-What-50-Shades-and-Batman-Have-in-Common.2',
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/espn.go.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/espn.go.com.php
new file mode 100644
index 00000000..76a20f74
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/espn.go.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://espn.go.com/nfl/story/_/id/13388208/jason-whitlock-chip-kelly-controversy',
+ 'body' => array(
+ '//p',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/exocomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/exocomics.com.php
new file mode 100644
index 00000000..5adc59f8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/exocomics.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//a[@class="comic"]/img'),
+ 'strip' => array(),
+ 'test_url' => 'http://www.exocomics.com/379',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/explosm.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/explosm.net.php
new file mode 100644
index 00000000..3fdf02c0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/explosm.net.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://explosm.net/comics/3803/',
+ 'body' => array(
+ '//div[@id="comic-container"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php
new file mode 100644
index 00000000..12697ccb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/factroom.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/factroom.ru.php
new file mode 100644
index 00000000..a572061d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/factroom.ru.php
@@ -0,0 +1,27 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.factroom.ru/life/20-facts-about-oil',
+ 'body' => array(
+ '//div[@class="post"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//h1',
+ '//div[@id="yandex_ad2"]',
+ '//*[@class="jp-relatedposts"]',
+ '//div[contains(@class, "likely-desktop")]',
+ '//div[contains(@class, "likely-mobile")]',
+ '//p[last()]',
+ '//div[contains(@class, "facebook")]',
+ '//div[contains(@class, "desktop-underpost-direct")]',
+ '//div[contains(@class, "source-box")]',
+ '//div[contains(@class, "under-likely-desktop")]',
+ '//div[contains(@class, "mobile-down-post")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcodesign.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcodesign.com.php
new file mode 100644
index 00000000..74e70a86
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcodesign.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.fastcodesign.com/3026548/exposure/peek-inside-the-worlds-forbidden-subway-tunnels',
+ 'body' => array(
+ '//article[contains(@class, "body prose")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcoexist.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcoexist.com.php
new file mode 100644
index 00000000..6916f280
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcoexist.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.fastcoexist.com/3026114/take-a-seat-on-this-gates-funded-future-toilet-that-will-change-how-we-think-about-poop',
+ 'body' => array(
+ '//article[contains(@class, "body prose")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcompany.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcompany.com.php
new file mode 100644
index 00000000..e0869a29
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fastcompany.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.fastcompany.com/3026712/fast-feed/elon-musk-an-apple-tesla-merger-is-very-unlikely',
+ 'body' => array(
+ '//article[contains(@class, "body prose")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ffworld.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ffworld.com.php
new file mode 100644
index 00000000..20a47b2d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ffworld.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.ffworld.com/?rub=news&page=voir&id=2709',
+ 'body' => array(
+ '//div[@class="news_body"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/foreignpolicy.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/foreignpolicy.com.php
new file mode 100644
index 00000000..3cbcddc4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/foreignpolicy.com.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://foreignpolicy.com/2016/01/09/networking-giant-pulls-nsa-linked-code-exploited-by-hackers/',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//div[@id="post-category"]',
+ '//div[@id="desktop-right"]',
+ '//h1',
+ '//section[@class="article-meta"]',
+ '//div[@class="side-panel-wrapper"]',
+ '//*[contains(@class, "share-")]',
+ '//*[contains(@id, "taboola-")]',
+ '//div[@class="comments"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fossbytes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fossbytes.com.php
new file mode 100644
index 00000000..6ce47256
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fossbytes.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://fossbytes.com/fbi-hacked-1000-computers-to-shut-down-largest-child-pornography-site-on-the-dark-web/',
+ 'body' => array(
+ '//div[@class="entry-inner"]',
+ ),
+ 'strip' => array(
+ '//*[@class="at-above-post addthis_default_style addthis_toolbox at-wordpress-hide"]',
+ '//*[@class="at-below-post addthis_default_style addthis_toolbox at-wordpress-hide"]',
+ '//*[@class="at-below-post-recommended addthis_default_style addthis_toolbox at-wordpress-hide"]',
+ '//*[@class="code-block code-block-12 ai-desktop"]',
+ '//*[@class="code-block code-block-13 ai-tablet-phone"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fototelegraf.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fototelegraf.ru.php
new file mode 100644
index 00000000..ca2f85aa
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fototelegraf.ru.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://fototelegraf.ru/?p=348232',
+ 'body' => array(
+ '//div[@class="post-content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//div[@class="imageButtonsBlock"]',
+ '//div[@class="adOnPostBtwImg"]',
+ '//div[contains(@class, "post-tags")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fowllanguagecomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fowllanguagecomics.com.php
new file mode 100644
index 00000000..3f62f071
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/fowllanguagecomics.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//*[@id="comic"] | //*[@class="post-image"]'),
+ 'strip' => array(),
+ 'test_url' => 'http://www.fowllanguagecomics.com/comic/working-out/',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geek.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geek.com.php
new file mode 100644
index 00000000..d9ccecc2
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geek.com.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.geek.com/news/the-11-best-ways-to-eat-eggs-1634076/',
+ 'body' => array(
+ '//div[@class="articleinfo"]/figure',
+ '//div[@class="articleinfo"]/article',
+ '//span[@class="by"]',
+ ),
+ 'strip' => array(
+ '//span[@class="red"]',
+ '//div[@class="on-target"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geektimes.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geektimes.ru.php
new file mode 100644
index 00000000..19541386
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/geektimes.ru.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://geektimes.ru/post/289151/',
+ 'body' => array(
+ "//div[contains(concat(' ',normalize-space(@class),' '),' content ')]"
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gerbilwithajetpack.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gerbilwithajetpack.com.php
new file mode 100644
index 00000000..44013b3b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gerbilwithajetpack.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//div[@id="comic-1"]',
+ '//div[@class="entry"]',
+ ),
+ 'test_url' => 'http://gerbilwithajetpack.com/passing-the-digital-buck/',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/giantitp.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/giantitp.com.php
new file mode 100644
index 00000000..d9c3ae5d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/giantitp.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%/comics/oots.*%' => array(
+ 'test_url' => 'http://www.giantitp.com/comics/oots0989.html',
+ 'body' => array(
+ '//td[@align="center"]/img',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/github.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/github.com.php
new file mode 100644
index 00000000..726634f9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/github.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://github.com/audreyr/favicon-cheat-sheet',
+ 'body' => array(
+ '//article[contains(@class, "entry-content")]',
+ ),
+ 'strip' => array(
+ '//h1',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gocomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gocomics.com.php
new file mode 100644
index 00000000..32960f0e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gocomics.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.gocomics.com/pearlsbeforeswine/2015/05/30',
+ 'body' => array(
+ '//div[1]/p[1]/a[1]/img',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/golem.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/golem.de.php
new file mode 100644
index 00000000..84224830
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/golem.de.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.golem.de/news/breko-telekom-verzoegert-gezielt-den-vectoring-ausbau-1311-102974.html',
+ 'body' => array(
+ '//header[@class="cluster-header"]',
+ '//header[@class="paged-cluster-header"]',
+ '//div[@class="formatted"]',
+ ),
+ 'next_page' => array(
+ '//a[@id="atoc_next"]'
+ ),
+ 'strip' => array(
+ '//header[@class="cluster-header"]/a',
+ '//div[@id="iqadtile4"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gorabbit.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gorabbit.ru.php
new file mode 100644
index 00000000..4e432481
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/gorabbit.ru.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://gorabbit.ru/article/10-oshchushcheniy-za-rulem-kogda-tolko-poluchil-voditelskie-prava',
+ 'body' => array(
+ '//div[@class="detail_text"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//div[@class="socials"]',
+ '//div[@id="cr_1"]',
+ '//div[@class="related_items"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/habrahabr.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/habrahabr.ru.php
new file mode 100644
index 00000000..3f1ec165
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/habrahabr.ru.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://habrahabr.ru/company/pentestit/blog/328606/',
+ 'body' => array(
+ "//div[contains(concat(' ',normalize-space(@class),' '),' content ')]"
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/happletea.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/happletea.com.php
new file mode 100644
index 00000000..75b0b83d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/happletea.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//div[@id="comic"]',
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array('//div[@class="ssba"]'),
+ 'test_url' => 'http://www.happletea.com/comic/mans-best-friend/',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hardware.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hardware.fr.php
new file mode 100644
index 00000000..56aec4f4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hardware.fr.php
@@ -0,0 +1,11 @@
+ array(
+ '%^/news.*%' => array(
+ 'test_url' => 'http://www.hardware.fr/news/14760/intel-lance-nouveaux-ssd-nand-3d.html',
+ 'body' => array(
+ '//div[@class="content_actualite"]/div[@class="md"]',
+ )
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/heise.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/heise.de.php
new file mode 100644
index 00000000..2055b3bc
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/heise.de.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.heise.de/security/meldung/BND-300-Millionen-Euro-fuer-Fruehwarnsystem-gegen-Cyber-Attacken-2192237.html',
+ 'body' => array(
+ '//div[@class="meldung_wrapper"]',
+ '//div[@class="artikel_content"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hotshowlife.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hotshowlife.com.php
new file mode 100644
index 00000000..faf01f3d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/hotshowlife.com.php
@@ -0,0 +1,23 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://hotshowlife.com/top-10-chempionov-produktov-po-szhiganiyu-kalorij/',
+ 'body' => array(
+ '//div[@class="entry-content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//div[@class="ads2"]',
+ '//div[@class="mistape_caption"]',
+ '//div[contains(@class, "et_social_media_hidden")]',
+ '//div[contains(@class, "et_social_inline_bottom")]',
+ '//div[contains(@class, "avatar")]',
+ '//ul[contains(@class, "entry-tags")]',
+ '//div[contains(@class, "entry-meta")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/huffingtonpost.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/huffingtonpost.com.php
new file mode 100644
index 00000000..b52b07b5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/huffingtonpost.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.huffingtonpost.com/2014/02/20/centscere-social-media-syracuse_n_4823848.html',
+ 'body' => array(
+ '//article[@class="content")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/imogenquest.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/imogenquest.net.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/imogenquest.net.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/indiehaven.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/indiehaven.com.php
new file mode 100644
index 00000000..a40ce694
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/indiehaven.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://indiehaven.com/no-mans-sky-is-a-solo-space-adventure-and-im-ok-with-that/',
+ 'body' => array(
+ '//section[contains(@class, "entry-content")]',
+ )
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ing.dk.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ing.dk.php
new file mode 100644
index 00000000..5a021a08
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ing.dk.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://ing.dk/artikel/smart-husisolering-og-styring-skal-mindske-japans-energikrise-164517',
+ 'body' => array(
+ '//section[contains(@class, "teaser")]',
+ '//section[contains(@class, "body")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php
new file mode 100644
index 00000000..90f87597
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%()%' => '$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ir.amd.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ir.amd.com.php
new file mode 100644
index 00000000..af99fe99
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ir.amd.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//span[@class="ccbnTxt"]'),
+ 'strip' => array(),
+ 'test_url' => 'http://ir.amd.com/phoenix.zhtml?c=74093&p=RssLanding&cat=news&id=2055819',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantimes.co.jp.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantimes.co.jp.php
new file mode 100644
index 00000000..9959441d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantimes.co.jp.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.japantimes.co.jp/news/2015/09/27/world/social-issues-world/pope-meets-sex-abuse-victims-philadelphia-promises-accountability/',
+ 'body' => array(
+ '//article[@role="main"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//header',
+ '//div[contains(@class, "meta")]',
+ '//div[@class="clearfix"]',
+ '//div[@class="OUTBRAIN"]',
+ '//ul[@id="content_footer_menu"]',
+ '//div[@class="article_footer_ad"]',
+ '//div[@id="disqus_thread"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantoday.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantoday.com.php
new file mode 100644
index 00000000..22485d69
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/japantoday.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.japantoday.com/category/politics/view/japan-u-s-to-sign-new-base-environment-pact',
+ 'body' => array(
+ '//div[@id="article_container"]',
+ ),
+ 'strip' => array(
+ '//h2',
+ '//div[@id="article_info"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/journaldugeek.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/journaldugeek.com.php
new file mode 100644
index 00000000..876b2698
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/journaldugeek.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www./2014/05/20/le-playstation-now-arrive-en-beta-fermee-aux-etats-unis/',
+ 'body' => array(
+ '//div[@class="post-content"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/jsonline.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/jsonline.com.php
new file mode 100644
index 00000000..5895256e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/jsonline.com.php
@@ -0,0 +1,37 @@
+ array(
+ '%.%/picture-gallery/%' => array(
+ 'test_url' => 'http://www.jsonline.com/picture-gallery/news/local/milwaukee/2017/02/22/photos-aclu-sues-milwaukee-police-over-profiling-stop-and-frisk/98250836/',
+ 'body' => array(
+ '//div[@class="priority-asset-gallery galleries standalone hasendslate"]',
+ ),
+ 'strip' => array(
+ '//div[@class="buy-photo-btn"]',
+ '//div[@class="gallery-thumbs thumbs pag-thumbs")]',
+ ),
+ ),
+ '%.*%' => array(
+ 'test_url' => 'http://www.jsonline.com/news/usandworld/as-many-as-a-million-expected-for-popes-last-mass-in-us-b99585180z1-329688131.html',
+ 'body' => array(
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//iframe',
+ '//span[@class="mycapture-small-btn mycapture-btn-with-text mycapture-expandable-photo-btn-small js-mycapture-btn-small"]',
+ '//div[@class="close-wrap"]',
+ '//div[contains(@class,"ui-video-wrapper")]',
+ '//div[contains(@class,"media-mob")]',
+ '//div[contains(@class,"left-mob")]',
+ '//div[contains(@class,"nerdbox")]',
+ '//p/span',
+ '//div[contains(@class,"oembed-asset")]',
+ '//*[contains(@class,"share")]',
+ '//div[contains(@class,"gallery-asset")]',
+ '//div[contains(@class,"oembed-asset")]',
+ '//div[@class="article-print-url"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/justcoolidea.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/justcoolidea.ru.php
new file mode 100644
index 00000000..089ff29c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/justcoolidea.ru.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://justcoolidea.ru/idealnyj-sad-samodelnye-proekty-dlya-berezhlivogo-domovladeltsa/',
+ 'body' => array(
+ '//section[@class="entry-content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[contains(@class, "essb_links")]',
+ '//*[contains(@rel, "nofollow")]',
+ '//*[contains(@class, "ads")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kanpai.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kanpai.fr.php
new file mode 100644
index 00000000..c3a1abc4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kanpai.fr.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.kanpai.fr/japon/comment-donner-lheure-en-japonais.html',
+ 'body' => array(
+ '//div[@class="single-left"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/karriere.jobfinder.dk.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/karriere.jobfinder.dk.php
new file mode 100644
index 00000000..25d6dfa3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/karriere.jobfinder.dk.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://karriere.jobfinder.dk/artikel/dansk-professor-skal-lede-smart-grid-forskning-20-millioner-dollars-763',
+ 'body' => array(
+ '//section[contains(@class, "teaser")]',
+ '//section[contains(@class, "body")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kodi.tv.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kodi.tv.php
new file mode 100644
index 00000000..439fc907
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/kodi.tv.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://kodi.tv/article/andwere-baaaaack',
+ 'body' => array(
+ '//div[@class="l-region--content"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreaherald.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreaherald.com.php
new file mode 100644
index 00000000..96510560
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreaherald.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.koreaherald.com/view.php?ud=20150926000018',
+ 'body' => array(
+ '//div[@id="articleText"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreatimes.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreatimes.php
new file mode 100644
index 00000000..f274b4a9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/koreatimes.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.koreatimes.co.kr/www/news/nation/2015/12/116_192409.html',
+ 'body' => array(
+ '//div[@id="p"]',
+ ),
+ 'strip' => array(
+ '//div[@id="webtalks_btn_listenDiv"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php
new file mode 100644
index 00000000..12697ccb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/legorafi.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/legorafi.fr.php
new file mode 100644
index 00000000..e6aae46b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/legorafi.fr.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => array(
+ 'http://www.legorafi.fr/2016/12/16/gorafi-magazine-bravo-vous-avez-bientot-presque-survecu-a-2016/',
+ 'http://www.legorafi.fr/2016/12/15/manuel-valls-promet-quune-fois-elu-il-debarrassera-la-france-de-manuel-valls/',
+ ),
+ 'body' => array(
+ '//section[@id="banner_magazine"]',
+ '//figure[@class="main_picture"]',
+ '//div[@class="content"]',
+ ),
+ 'strip' => array(
+ '//figcaption',
+ '//div[@class="sharebox"]',
+ '//div[@class="tags"]',
+ '//section[@class="taboola_article"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lejapon.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lejapon.fr.php
new file mode 100644
index 00000000..8f2b2932
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lejapon.fr.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://lejapon.fr/guide-voyage-japon/5223/tokyo-sous-la-neige.htm',
+ 'body' => array(
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "addthis_toolbox")]',
+ '//*[contains(@class, "addthis_default_style")]',
+ '//*[@class="navigation small"]',
+ '//*[@id="related"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lesjoiesducode.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lesjoiesducode.fr.php
new file mode 100644
index 00000000..369206ab
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lesjoiesducode.fr.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://lesjoiesducode.fr/post/75576211207/quand-lappli-ne-fonctionne-plus-sans-aucune-raison',
+ 'body' => array(
+ '//div[@class="blog-post-content"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lfg.co.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lfg.co.php
new file mode 100644
index 00000000..d978a5fc
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lfg.co.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.lfg.co/page/871/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+LookingForGroup+%28Looking+For+Group%29&utm_content=FeedBurner',
+ 'body' => array(
+ '//*[@id="comic"]/img | //*[@class="content"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.com.php
new file mode 100644
index 00000000..b9a69338
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://lifehacker.com/bring-water-bottle-caps-into-concerts-to-protect-your-d-1269334973',
+ 'body' => array(
+ '//div[contains(@class, "row")/img',
+ '//div[contains(@class, "content-column")]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "meta")]',
+ '//span[contains(@class, "icon")]',
+ '//h1',
+ '//aside',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.ru.php
new file mode 100644
index 00000000..bc140f67
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lifehacker.ru.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://lifehacker.ru/2016/03/03/polymail/',
+ 'body' => array(
+ '//div[@class="post-content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[@class="wp-thumbnail-caption"]',
+ '//*[contains(@class, "social-likes")]',
+ '//*[@class="jp-relatedposts"]',
+ '//*[contains(@class, "wpappbox")]',
+ '//*[contains(@class, "icon__image")]',
+ '//div[@id="hypercomments_widget"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.php
new file mode 100644
index 00000000..2520d0d0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.linux.org/threads/lua-the-scripting-interpreter.8352/',
+ 'body' => array(
+ '//div[@class="messageContent"]',
+ ),
+ 'strip' => array(
+ '//aside',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.ru.php
new file mode 100644
index 00000000..7fa02497
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linux.org.ru.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.linux.org/threads/lua-the-scripting-interpreter.8352/',
+ 'body' => array(
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linuxinsider.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linuxinsider.com.php
new file mode 100644
index 00000000..4e0a4cc1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/linuxinsider.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.linuxinsider.com/story/82526.html?rss=1',
+ 'body' => array(
+ '//div[@id="story"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//h1',
+ '//div[@id="story-toolbox1"]',
+ '//div[@id="story-byline"]',
+ '//div[@id="story"]/p',
+ '//div[@class="story-advertisement"]',
+ '//iframe',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lists.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lists.php
new file mode 100644
index 00000000..c7051a20
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lists.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://lists.freebsd.org/pipermail/freebsd-announce/2013-September/001504.html',
+ 'body' => array(
+ '//pre',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loadingartist.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loadingartist.com.php
new file mode 100644
index 00000000..d06ed124
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loadingartist.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loldwell.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loldwell.com.php
new file mode 100644
index 00000000..d358e156
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/loldwell.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://loldwell.com/?comic=food-math-101',
+ 'body' => array('//*[@id="comic"]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lukesurl.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lukesurl.com.php
new file mode 100644
index 00000000..816233dd
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/lukesurl.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//div[@id="comic"]//img'),
+ 'strip' => array(),
+ 'test_url' => 'http://www.lukesurl.com/archives/comic/665-3-of-clubs',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/macg.co.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/macg.co.php
new file mode 100644
index 00000000..bbe6dbcd
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/macg.co.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.macg.co//logiciels/2014/05/feedly-sameliore-un-petit-peu-sur-mac-82205',
+ 'body' => array(
+ '//div[contains(@class, "field-name-body")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marc.info.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marc.info.php
new file mode 100644
index 00000000..5f582a6d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marc.info.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://marc.info/?l=openbsd-misc&m=141987113202061&w=2',
+ 'body' => array(
+ '//pre',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php
new file mode 100644
index 00000000..469640df
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.marriedtothesea.com/index.php?date=052915',
+ 'body' => array(
+ '//div[@align]/a/img',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marycagle.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marycagle.com.php
new file mode 100644
index 00000000..b8665e35
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/marycagle.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//img[@id="cc-comic"]',
+ '//div[@class="cc-newsbody"]',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://www.marycagle.com/letsspeakenglish/74-grim-reality/',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/maximumble.thebookofbiff.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/maximumble.thebookofbiff.com.php
new file mode 100644
index 00000000..88800546
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/maximumble.thebookofbiff.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://maximumble.thebookofbiff.com/2015/04/20/1084-change/',
+ 'body' => array('//div[@id="comic"]/div/a/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/medium.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/medium.com.php
new file mode 100644
index 00000000..e20860e0
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/medium.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://medium.com/lessons-learned/917b8b63ae3e',
+ 'body' => array(
+ '//div[@class="section-content"]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"metabar")]',
+ '//img[contains(@class,"thumbnail")]',
+ '//h1',
+ '//blockquote',
+ '//div[@class="aspectRatioPlaceholder-fill"]',
+ '//footer'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mercworks.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mercworks.net.php
new file mode 100644
index 00000000..c7a27dea
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mercworks.net.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'body' => array('//div[@id="comic"]',
+ '//div[contains(@class,"entry-content")]',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://mercworks.net/comicland/healthy-choice/',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/metronieuws.nl.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/metronieuws.nl.php
new file mode 100644
index 00000000..5011169f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/metronieuws.nl.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.metronieuws.nl/sport/2015/04/broer-fellaini-zorgde-bijna-voor-paniek-bij-mourinho',
+ 'body' => array('//div[contains(@class,"article-top")]/div[contains(@class,"image-component")] | //div[@class="article-full-width"]/div[1]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/milwaukeenns.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/milwaukeenns.php
new file mode 100644
index 00000000..ddb29a56
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/milwaukeenns.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://milwaukeenns.org/2016/01/08/united-way-grant-enables-sdc-to-restore-free-tax-assistance-program/',
+ 'body' => array(
+ '//div[@class="pf-content"]',
+ ),
+ 'strip' => array(
+ '//div[@class="printfriendly"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mokepon.smackjeeves.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mokepon.smackjeeves.com.php
new file mode 100644
index 00000000..1ddcd407
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mokepon.smackjeeves.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://mokepon.smackjeeves.com/comics/2120096/chapter-9-page-68/',
+ 'body' => array('//*[@id="comic_area_inner"]/img | //*[@id="comic_area_inner"]/a/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monandroid.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monandroid.com.php
new file mode 100644
index 00000000..f87560e2
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monandroid.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.monandroid.com/blog/tutoriel-avance-activer-le-stockage-fusionne-sur-android-6-marshamallow-t12.html',
+ 'body' => array(
+ '//div[@class="blog-post-body"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monwindows.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monwindows.com.php
new file mode 100644
index 00000000..b2b24d74
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/monwindows.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.monwindows.com/tout-savoir-sur-le-centre-d-action-de-windows-phone-8-1-t40574.html',
+ 'body' => array(
+ '//div[@class="blog-post-body"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/moya-planeta.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/moya-planeta.ru.php
new file mode 100644
index 00000000..dd842844
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/moya-planeta.ru.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.moya-planeta.ru/travel/view/chto_yaponcu_horosho_russkomu_ne_ponyat_20432/',
+ 'body' => array(
+ '//div[@class="full_object"]',
+ ),
+ 'strip' => array(
+ '//div[@class="full_object_panel object_panel"]',
+ '//div[@class="full_object_panel_geo object_panel"]',
+ '//div[@class="full_object_title"]',
+ '//div[@class="full_object_social_likes"]',
+ '//div[@class="full_object_planeta_likes"]',
+ '//div[@class="full_object_go2comments"]',
+ '//div[@id="yandex_ad_R-163191-3"]',
+ '//div[@class="full_object_shop_article_recommend"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php
new file mode 100644
index 00000000..b971091f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php
@@ -0,0 +1,9 @@
+ array(
+ '%.*%' => array(
+ '%alt="(.+)" */>%' => '/>
$1',
+ '%\.png%' => '_rollover.png',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/muckrock.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/muckrock.com.php
new file mode 100644
index 00000000..9e354a36
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/muckrock.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.muckrock.com/news/archives/2016/jan/13/5-concerns-private-prisons/',
+ 'body' => array(
+ '//div[@class="content"]',
+ ),
+ 'strip' => array(
+ '//div[@class="newsletter-widget"]',
+ '//div[@class="contributors"]',
+ '//time',
+ '//h1',
+ '//div[@class="secondary"]',
+ '//aside',
+ '//div[@class="articles__related"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mynorthshorenow.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mynorthshorenow.com.php
new file mode 100644
index 00000000..b6309157
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/mynorthshorenow.com.php
@@ -0,0 +1,27 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.mynorthshorenow.com/story/news/local/fox-point/2017/04/04/fox-point-building-board-approves-dunwood-commons-project/99875570/',
+ 'body' => array(
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//iframe',
+ '//span[@class="mycapture-small-btn mycapture-btn-with-text mycapture-expandable-photo-btn-small js-mycapture-btn-small"]',
+ '//div[@class="close-wrap"]',
+ '//div[contains(@class,"ui-video-wrapper")]',
+ '//div[contains(@class,"media-mob")]',
+ '//div[contains(@class,"left-mob")]',
+ '//div[contains(@class,"nerdbox")]',
+ '//p/span',
+ '//div[contains(@class,"oembed-asset")]',
+ '//*[contains(@class,"share")]',
+ '//div[contains(@class,"gallery-asset")]',
+ '//div[contains(@class,"oembed-asset")]',
+ '//div[@class="article-print-url"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nakedCapitalism.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nakedCapitalism.php
new file mode 100644
index 00000000..ec2d5fd5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nakedCapitalism.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://feedproxy.google.com/~r/NakedCapitalism/~3/JOBxEHxN8ZI/mark-blyth-liberalism-undermined-democracy-failure-democratic-party.html',
+ 'body' => array(
+ '//div[@class="pf-content"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nasa.gov.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nasa.gov.php
new file mode 100644
index 00000000..c6692d07
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nasa.gov.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.nasa.gov/image-feature/jpl/pia20514/coy-dione',
+ 'body' => array(
+ '//div[@class="article-body"]',
+ ),
+ 'strip' => array(
+ '//div[@class="title-bar"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nat-geo.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nat-geo.ru.php
new file mode 100644
index 00000000..1a42d997
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nat-geo.ru.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nat-geo.ru/fact/868093-knidos-antichnyy-naukograd/',
+ 'body' => array(
+ '//div[@class="article-inner-text"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nationaljournal.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nationaljournal.com.php
new file mode 100644
index 00000000..5e612bef
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nationaljournal.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nationaljournal.com/s/354962/south-carolina-evangelicals-outstrip-establishment?mref=home_top_main',
+ 'body' => array(
+ '//div[@class="section-body"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "-related")]',
+ '//*[contains(@class, "social")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nature.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nature.com.php
new file mode 100644
index 00000000..6b9e87f4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nature.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nature.com/doifinder/10.1038/nature.2015.18340',
+ 'body' => array(
+ '//div[contains(@class,"main-content")]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nba.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nba.com.php
new file mode 100644
index 00000000..c8ea926f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nba.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nba.com/2015/news/09/25/knicks-jackson-to-spend-more-time-around-coaching-staff.ap/index.html?rss=true',
+ 'body' => array(
+ '//div[@class="paragraphs"]',
+ ),
+ 'strip' => array(
+ '//div[@id="nbaArticleSocialWrapper_bot"]',
+ '//h5',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nedroid.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nedroid.com.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nedroid.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/networkworld.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/networkworld.com.php
new file mode 100644
index 00000000..18524354
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/networkworld.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.networkworld.com/article/3020585/security/the-incident-response-fab-five.html',
+ 'body' => array(
+ '//figure/img[@class="hero-img"]',
+ '//section[@class="deck"]',
+ '//div[@itemprop="articleBody"] | //div[@itemprop="reviewBody"]',
+ '//div[@class="carousel-inside-crop"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//aside',
+ '//div[@class="credit"]',
+ '//div[@class="view-large"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/neustadt-ticker.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/neustadt-ticker.de.php
new file mode 100644
index 00000000..e0c0d19d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/neustadt-ticker.de.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.neustadt-ticker.de/41302/alltag/kultur/demo-auf-der-boehmischen',
+ 'body' => array(
+ '//div[@class="entry-content"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "sharedaddy")]',
+ '//*[contains(@class, "yarpp-related")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nextinpact.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nextinpact.com.php
new file mode 100644
index 00000000..29dd9d6b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nextinpact.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.nextinpact.com/news/101122-3d-nand-intel-lance-six-nouvelles-gammes-ssd-pour-tous-usages.htm',
+ 'body' => array(
+ '//div[@class="container_article"]',
+ ),
+ 'strip' => array(
+ '//div[@class="infos_article"]',
+ '//div[@id="actu_auteur"]',
+ '//div[@id="soutenir_journaliste"]',
+ '//section[@id="bandeau_abonnez_vous"]',
+ '//br'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/niceteethcomic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/niceteethcomic.com.php
new file mode 100644
index 00000000..f41e4438
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/niceteethcomic.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%/archives.*%' => array(
+ 'test_url' => 'http://niceteethcomic.com/archives/page119/',
+ 'body' => array('//*[@class="comicpane"]/a/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nichtlustig.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nichtlustig.de.php
new file mode 100644
index 00000000..4d083f98
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/nichtlustig.de.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%.*static.nichtlustig.de/comics/full/(\\d+).*%s' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/oglaf.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/oglaf.com.php
new file mode 100644
index 00000000..8b2b5b65
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/oglaf.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//img[@id="strip"]',
+ '//a/div[@id="nx"]/..',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://oglaf.com/slodging/',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%alt="(.+)" title="(.+)" */>%' => '/>
$1
$2
',
+ '%%' => 'Next page',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onhax.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onhax.net.php
new file mode 100644
index 00000000..213849d8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onhax.net.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://onhax.net/process-lasso-8-9-1-4-pro-key-portable-is-here-latest',
+ 'body' => array(
+ '//div[@class="postcontent"]',
+ ),
+ 'strip' => array(
+ '//*[@class="sharedaddy sd-sharing-enabled"]',
+ '//*[@class="yarpp-related"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onmilwaukee.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onmilwaukee.php
new file mode 100644
index 00000000..f66ac4b8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/onmilwaukee.php
@@ -0,0 +1,24 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://onmilwaukee.com/movies/articles/downerspelunking.html',
+ 'body' => array(
+ '//article[contains(@class, "show")]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//div[contains(@class,"-ad")]',
+ '//div[contains(@class,"_ad")]',
+ '//div[@id="pub_wrapper"]',
+ '//div[contains(@class,"share_tools")]',
+ '//div[@class="clearfix"]',
+ '//div[contains(@class,"image_control")]',
+ '//section[@class="ribboned"]',
+ '//div[contains(@class,"sidebar")]',
+ '//aside[@class="article_tag_list"]',
+ '//section[contains(@id,"more_posts")]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openculture.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openculture.com.php
new file mode 100644
index 00000000..84f2beed
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openculture.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.openculture.com/2017/03/are-we-living-inside-a-computer-simulation-watch-the-simulation-argument.html',
+ 'body' => array(
+ '//div[@class="entry"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opennet.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opennet.ru.php
new file mode 100644
index 00000000..1fb7722b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opennet.ru.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.opennet.ru/opennews/art.shtml?num=46549',
+ 'body' => array(
+ '//*[@id="r_memo"]',
+ ),
+ 'strip' => array(
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openrightsgroup.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openrightsgroup.org.php
new file mode 100644
index 00000000..94139a72
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/openrightsgroup.org.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.openrightsgroup.org/blog/2014/3-days-to-go-till-orgcon2014',
+ 'body' => array(
+ '//div[contains(@class, "content")]/div',
+ ),
+ 'strip' => array(
+ '//h2[1]',
+ '//div[@class="info"]',
+ '//div[@class="tags"]',
+ '//div[@class="comments"]',
+ '//div[@class="breadcrumbs"]',
+ '//h1[@class="pageTitle"]',
+ '//p[@class="bookmarkThis"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opensource.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opensource.com.php
new file mode 100644
index 00000000..60f3577b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/opensource.com.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://opensource.com/life/15/10/how-internet-things-will-change-way-we-think',
+ 'body' => array(
+ '//div[@id="article-template"]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"os-article__sidebar")]',
+ '//div[@class="panel-pane pane-node-title"]',
+ '//div[@class="panel-pane pane-os-article-byline"]',
+ '//ul',
+ '//div[contains(@class,"-license")]',
+ '//div[contains(@class,"-tags")]',
+ '//div[@class="panel-pane pane-os-article-byline"]',
+ '//div[@class="os-article__content-below"]',
+ '//div[@id="comments"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/optipess.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/optipess.com.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/optipess.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/osnews.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/osnews.com.php
new file mode 100644
index 00000000..1d1396c8
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/osnews.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://osnews.com/story/28863/Google_said_to_be_under_US_antitrust_scrutiny_over_Android',
+ 'body' => array(
+ '//div[@class="newscontent1"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pastebin.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pastebin.com.php
new file mode 100644
index 00000000..b20bf41c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pastebin.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://pastebin.com/ed1pP9Ak',
+ 'body' => array(
+ '//div[@class="text"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/peebleslab.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/peebleslab.com.php
new file mode 100644
index 00000000..ce4891d1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/peebleslab.com.php
@@ -0,0 +1,9 @@
+ array(
+ '%.*%' => array(
+ // the extra space is required to strip the title cleanly
+ '%title="(.+) " */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/penny-arcade.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/penny-arcade.com.php
new file mode 100644
index 00000000..dd39983b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/penny-arcade.com.php
@@ -0,0 +1,21 @@
+ array(
+ '%/news/.*%' => array(
+ 'test_url' => 'http://penny-arcade.com/news/post/2015/04/15/101-part-two',
+ 'body' => array(
+ '//*[@class="postBody"]/*',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ '%/comic/.*%' => array(
+ 'test_url' => 'http://penny-arcade.com/comic/2015/04/15',
+ 'body' => array(
+ '//*[@id="comicFrame"]/a/img',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php
new file mode 100644
index 00000000..fa9052ea
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.pixelbeat.org/programming/sigpipe_handling.html#1425573246',
+ 'body' => array(
+ '//div[@class="contentText"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/plus.google.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/plus.google.com.php
new file mode 100644
index 00000000..5e48a6cf
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/plus.google.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://plus.google.com/+LarryPage/posts/Lh8SKC6sED1',
+ 'body' => array(
+ '//div[@role="article"]/div[contains(@class, "eE")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/popstrip.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/popstrip.com.php
new file mode 100644
index 00000000..801a2814
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/popstrip.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%( '$1$2$1bonus.png"/>',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publicpolicyforum.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publicpolicyforum.org.php
new file mode 100644
index 00000000..5dc8be88
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publicpolicyforum.org.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://publicpolicyforum.org/blog/going-extra-mile',
+ 'body' => array(
+ '//div[contains(@class,"field-name-post-date")]',
+ '//div[contains(@class,"field-name-body")]',
+ ),
+ 'strip' => array(
+ '//img[@src="http://publicpolicyforum.org/sites/default/files/logo3.jpg"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publy.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publy.ru.php
new file mode 100644
index 00000000..bcfeeb99
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/publy.ru.php
@@ -0,0 +1,24 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.publy.ru/post/19988',
+ 'body' => array(
+ '//div[@class="singlepost"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[@class="featured"]',
+ '//*[@class="toc_white no_bullets"]',
+ '//*[@class="toc_title"]',
+ '//*[@class="pba"]',
+ '//*[@class="comments"]',
+ '//*[contains(@class, "g-single")]',
+ '//*[@class="ts-fab-wrapper"]',
+ '//*[contains(@class, "wp_rp_wrap")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/putaindecode.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/putaindecode.fr.php
new file mode 100644
index 00000000..9fa5568c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/putaindecode.fr.php
@@ -0,0 +1,16 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://putaindecode.fr/posts/js/etat-lieux-js-modulaire-front/',
+ 'body' => array(
+ '//*[@class="putainde-Post-md"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "inlineimg")]',
+ '//*[contains(@class, "comment-respond")]',
+ '//header',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/recode.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/recode.net.php
new file mode 100644
index 00000000..343cd12f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/recode.net.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://recode.net/2015/09/26/big-tech-rolls-out-red-carpet-for-indian-prime-minister-lobbies-behind-closed-doors/',
+ 'body' => array(
+ '//img[contains(@class,"attachment-large")]',
+ '//div[contains(@class,"postarea")]',
+ '//li[@class,"author"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//div[contains(@class,"sharedaddy")]',
+ '//div[@class="post-send-off"]',
+ '//div[@class="large-12 columns"]',
+ '//div[contains(@class,"inner-related-article")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/retractionwatch.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/retractionwatch.com.php
new file mode 100644
index 00000000..b97c73ed
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/retractionwatch.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://retractionwatch.com/2015/11/12/psychologist-jens-forster-settles-case-by-agreeing-to-2-retractions/',
+ 'body' => array(
+ '//*[@class="main"]',
+ '//*[@class="entry-content"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "sharedaddy")]',
+ '//*[contains(@class, "jp-relatedposts")]',
+ '//p[@class="p1"]',
+ )
+ )
+ )
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rockpapershotgun.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rockpapershotgun.com.php
new file mode 100644
index 00000000..71110786
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rockpapershotgun.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.rockpapershotgun.com/2016/08/26/the-divisions-expansions-delayed-to-improve-the-game/',
+ 'body' => array(
+ '//div[@class="entry"]',
+ )
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rue89.nouvelobs.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rue89.nouvelobs.com.php
new file mode 100644
index 00000000..cb9116a3
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rue89.nouvelobs.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://rue89.feedsportal.com/c/33822/f/608948/s/30999fa0/sc/24/l/0L0Srue890N0C20A130C0A80C30A0Cfaisait0Eboris0Eboillon0Eex0Esarko0Eboy0E350A0E0A0A0A0Eeuros0Egare0Enord0E245315/story01.htm',
+ 'body' => array(
+ '//*[@id="article"]/div[contains(@class, "content")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php
new file mode 100644
index 00000000..9915c234
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.rugbyrama.fr/rugby/top-14/2015-2016/top-14-hayman-coupe-du-monde-finale-2012-lutte.-voici-levan-chilachava-toulon_sto5283863/story.shtml',
+ 'body' => array(
+ '//div[@class="storyfull__content"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[@class="share-buttons"]',
+ '//*[@class="ad"]',
+ '//*[@class="hide-desktop"]',
+ '//*[@id="tracking_img"]',
+ )
+ )
+ )
+);
\ No newline at end of file
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/satwcomic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/satwcomic.com.php
new file mode 100644
index 00000000..d63fc11c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/satwcomic.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://satwcomic.com/day-at-the-beach',
+ 'body' => array(
+ '//div[@class="container"]/center/a/img',
+ '//span[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/scrumalliance.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/scrumalliance.org.php
new file mode 100644
index 00000000..7835fd9e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/scrumalliance.org.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://www.scrumalliance.org/community/articles/2015/march/an-introduction-to-agile-project-intake?feed=articles',
+ 'body' => array(
+ '//div[@class="article_content"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/securityfocus.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/securityfocus.com.php
new file mode 100644
index 00000000..01045148
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/securityfocus.com.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.securityfocus.com/archive/1/540139',
+ 'body' => array(
+ '//div[@id="vulnerability"]',
+ '//div[@class="comments_reply"]',
+ ),
+ 'strip' => array(
+ '//span[@class="title"]',
+ '//div[@id="logo_new"]',
+ '//div[@id="bannerAd"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php
new file mode 100644
index 00000000..f4354179
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//div[@class="comicpane"]/a/img',
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://sentfromthemoon.com/archives/1417',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sitepoint.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sitepoint.com.php
new file mode 100644
index 00000000..ab0eb7d4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sitepoint.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.sitepoint.com/creating-hello-world-app-swift/',
+ 'body' => array(
+ '//section[@class="article_body"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/slashdot.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/slashdot.org.php
new file mode 100644
index 00000000..89ced8b6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/slashdot.org.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://science.slashdot.org/story/15/04/20/0528253/pull-top-can-tabs-at-50-reach-historic-archaeological-status',
+ 'body' => array(
+ '//article/div[@class="body"] | //article[@class="layout-article"]/div[@class="elips"]', ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smallhousebliss.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smallhousebliss.com.php
new file mode 100644
index 00000000..8c13c44c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smallhousebliss.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://smallhousebliss.com/2013/08/29/house-g-by-lode-architecture/',
+ 'body' => array(
+ '//div[@class="post-content"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "gallery")]',
+ '//*[contains(@class, "share")]',
+ '//*[contains(@class, "wpcnt")]',
+ '//*[contains(@class, "meta")]',
+ '//*[contains(@class, "postitle")]',
+ '//*[@id="nav-below"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smarthomewelt.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smarthomewelt.de.php
new file mode 100644
index 00000000..7463abc7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smarthomewelt.de.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://smarthomewelt.de/apple-tv-amazon-echo-smart-home/',
+ 'body' => array('//div[@class="entry-inner"]/p | //div[@class="entry-inner"]/div[contains(@class,"wp-caption")]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smashingmagazine.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smashingmagazine.com.php
new file mode 100644
index 00000000..cbe10726
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smashingmagazine.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.smashingmagazine.com/2015/04/17/using-sketch-for-responsive-web-design-case-study/',
+ 'body' => array('//article[contains(@class,"post")]/p'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php
new file mode 100644
index 00000000..42262dc9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.smbc-comics.com/comic/the-troll-toll',
+ 'body' => array(
+ '//div[@id="cc-comicbody"]',
+ '//div[@id="aftercomic"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/snopes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/snopes.com.php
new file mode 100644
index 00000000..b0fe6557
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/snopes.com.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.snopes.com/bacca-brides-on-tour/',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//span[@itemprop="author"]',
+ '//div[contains(@class,"author-")]',
+ '//h1',
+ '//style',
+ '//div[contains(@class,"socialShares")]',
+ '//div[contains(@class,"ad-unit")]',
+ '//aside',
+ '//div[contains(@class,"boomtrain")]',
+ '//footer'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/soundandvision.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/soundandvision.com.php
new file mode 100644
index 00000000..6448bb05
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/soundandvision.com.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.soundandvision.com/content/james-guthrie-mixing-roger-waters-and-pink-floyd-51',
+ 'body' => array(
+ '//div[@id="left"]',
+ ),
+ 'strip' => array(
+ '//div[@class="meta"]',
+ '//div[@class="ratingsbox"]',
+ '//h1',
+ '//h2',
+ '//addthis',
+ '//comment-links',
+ '//div[@class="book-navigation"]',
+ '//div[@class="comment-links"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/spiegel.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/spiegel.de.php
new file mode 100644
index 00000000..e2e3db00
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/spiegel.de.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.spiegel.de/politik/ausland/afrika-angola-geht-gegen-islam-vor-und-schliesst-moscheen-a-935788.html',
+ 'body' => array(
+ '//div[contains(@class, "article-section")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stereophile.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stereophile.com.php
new file mode 100644
index 00000000..8e410be4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stereophile.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.stereophile.com/content/2015-rocky-mountain-audio-fest-starts-friday',
+ 'body' => array(
+ '//div[@class="content clear-block"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stupidfox.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stupidfox.net.php
new file mode 100644
index 00000000..61182d72
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/stupidfox.net.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://stupidfox.net/134-sleepy-time',
+ 'body' => array(
+ '//div[@class="comicmid"]/center/a/img',
+ '//div[@class="stand_high"]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/subtraction.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/subtraction.com.php
new file mode 100644
index 00000000..6d744277
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/subtraction.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.subtraction.com/2015/06/06/time-lapse-video-of-one-world-trade-center/',
+ 'body' => array('//article/div[@class="entry-content"]'),
+ 'strip' => array(),
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%\+%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sz.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sz.de.php
new file mode 100644
index 00000000..90bde5a9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/sz.de.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://sz.de/1.2443161',
+ 'body' => array('//article[@id="sitecontent"]/section[@class="topenrichment"]//img | //article[@id="sitecontent"]/section[@class="body"]/section[@class="authors"]/preceding-sibling::*[not(contains(@class, "ad"))]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/takprosto.cc.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/takprosto.cc.php
new file mode 100644
index 00000000..624ef907
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/takprosto.cc.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://takprosto.cc/kokteyl-dlya-pohudeniya-v-domashnih-usloviyah/',
+ 'body' => array(
+ '//div[contains(@class, "entry-contentt")]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//form',
+ '//style',
+ '//*[@class="views_post"]',
+ '//*[contains(@class, "mailchimp-box")]',
+ '//*[contains(@class, "essb_links")]',
+ '//*[contains(@rel, "nofollow")]',
+ '//*[contains(@class, "ads")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/techcrunch.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/techcrunch.com.php
new file mode 100644
index 00000000..d6e620f6
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/techcrunch.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://techcrunch.com/2013/08/31/indias-visa-maze/',
+ 'body' => array(
+ '//div[contains(@class, "media-container")]',
+ '//div[@class="body-copy"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "module-crunchbase")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/the-ebook-reader.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/the-ebook-reader.com.php
new file mode 100644
index 00000000..3b01eb96
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/the-ebook-reader.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://blog.the-ebook-reader.com/2015/09/25/kobo-glo-hd-and-kobo-touch-2-0-covers-and-cases-roundup/',
+ 'body' => array(
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(
+ '//div[@id="share"]',
+ '//div[contains(@class,"ItemCenter")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theatlantic.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theatlantic.com.php
new file mode 100644
index 00000000..bfad4ab2
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theatlantic.com.php
@@ -0,0 +1,23 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.theatlantic.com/politics/archive/2015/09/what-does-it-mean-to-lament-the-poor-inside-panem/407317/',
+ 'body' => array(
+ '//picture[@class="img"]',
+ '//figure/figcaption/span',
+ '//div/p[@itemprop="description"]',
+ '//div[@class="article-body"]',
+ '//ul[@class="photos"]',
+ ),
+ 'strip' => array(
+ '//aside[@class="callout"]',
+ '//span[@class="credit"]',
+ '//figcaption[@class="credit"]',
+ '//aside[contains(@class,"partner-box")]',
+ '//div[contains(@class,"ad")]',
+ '//a[contains(@class,"social-icon")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php
new file mode 100644
index 00000000..fd4f3d50
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%/comic/.*%' => array(
+ 'test_url' => 'http://theawkwardyeti.com/comic/things-to-do/',
+ 'body' => array(
+ '//div[@id="comic"]'
+ ),
+ 'strip' => array()
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thecodinglove.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thecodinglove.com.php
new file mode 100644
index 00000000..c6ec5bf5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thecodinglove.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://thecodinglove.com/post/116897934767',
+ 'body' => array('//div[@class="bodytype"]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php
new file mode 100644
index 00000000..d2f840d7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//div[@class="comicpane"]/a/img',
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(),
+ 'test_url' => 'http://thedoghousediaries.com/6023',
+ ),
+ ),
+ 'filter' => array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thegamercat.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thegamercat.com.php
new file mode 100644
index 00000000..f9b4637b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thegamercat.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.thegamercat.com/comic/just-no/',
+ 'body' => array('//div[@id="comic"] | //div[@class="post-content"]/div[@class="entry"]/p'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thehindu.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thehindu.com.php
new file mode 100644
index 00000000..1e6735ba
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thehindu.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.thehindu.com/sci-tech/science/why-is-the-shape-of-cells-in-a-honeycomb-always-hexagonal/article7692306.ece?utm_source=RSS_Feed&utm_medium=RSS&utm_campaign=RSS_Syndication',
+ 'body' => array(
+ '//div/img[@class="main-image"]',
+ '//div[@class="photo-caption"]',
+ '//div[@class="articleLead"]',
+ '//p',
+ '//span[@class="upper"]',
+ ),
+ 'strip' => array(
+ '//div[@id="articleKeywords"]',
+ '//div[@class="photo-source"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thelocal.se.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thelocal.se.php
new file mode 100644
index 00000000..c3ec250c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thelocal.se.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'www.thelocal.se/20161219/this-swede-can-memorize-hundreds-of-numbers-in-only-five-minutes',
+ 'body' => array(
+ '//div[@id="article-photo"]',
+ '//div[@id="article-description"]',
+ '//div[@id="article-body"]',
+ ),
+ 'strip' => array(
+ '//div[@id="article-info-middle"]',
+ )
+ )
+ )
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themerepublic.net.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themerepublic.net.php
new file mode 100644
index 00000000..bc47b278
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themerepublic.net.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.themerepublic.net/2015/04/david-lopez-pitoko.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+blogspot%2FDngUJ+%28Theme+Republic%29&utm_content=FeedBurner',
+ 'body' => array('//*[@class="post-body"]'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themoscowtimes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themoscowtimes.com.php
new file mode 100644
index 00000000..0f5bf75e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/themoscowtimes.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.themoscowtimes.com/business/article/535500.html',
+ 'body' => array(
+ '//div[@class="article_main_img"]',
+ '//div[@class="article_text"]',
+ ),
+ 'strip' => array(
+ '//div[@class="articlebottom"]',
+ '//p/b',
+ '//p/a[contains(@href, "/article.php?id=")]',
+ '//div[@class="disqus_wrap"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thenewslens.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thenewslens.com.php
new file mode 100644
index 00000000..75381707
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thenewslens.com.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://international.thenewslens.com/post/255032/',
+ 'body' => array(
+ '//div[@class="article-section"]',
+ ),
+ 'strip' => array(
+ '//div[contains(@class,"ad-")]',
+ '//div[@class="article-title-box"]',
+ '//div[@class="function-box"]',
+ '//p/span',
+ '//aside',
+ '//footer',
+ '//div[@class="article-infoBot-box"]',
+ '//div[contains(@class,"standard-container")]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theodd1sout.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theodd1sout.com.php
new file mode 100644
index 00000000..d06ed124
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theodd1sout.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%-150x150%' => '',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theonion.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theonion.com.php
new file mode 100644
index 00000000..acbfd36b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/theonion.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.theonion.com/article/wild-eyed-jim-harbaugh-informs-players-they-must-k-51397?utm_medium=RSS&utm_campaign=feeds',
+ 'body' => array(
+ '//div[@class="content-masthead"]/figure/div/noscript/img',
+ '//div[@class="content-text"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thestandard.com.hk.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thestandard.com.hk.php
new file mode 100644
index 00000000..1163b345
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/thestandard.com.hk.php
@@ -0,0 +1,22 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.thestandard.com.hk/breaking_news_detail.asp?id=67156',
+ 'body' => array(
+ '//table/tr/td/span[@class="bodyCopy"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//br',
+ '//map[@name="gif_bar"]',
+ '//img[contains(@usemap,"gif_bar")]',
+ '//a',
+ '//span[@class="bodyHeadline"]',
+ '//i',
+ '//b',
+ '//table',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/threepanelsoul.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/threepanelsoul.com.php
new file mode 100644
index 00000000..4af6196e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/threepanelsoul.com.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'body' => array(
+ '//img[@id="cc-comic"]',
+ ),
+ 'test_url' => 'http://www.threepanelsoul.com/comic/uncloaking',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/timesofindia.indiatimes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/timesofindia.indiatimes.com.php
new file mode 100644
index 00000000..19246806
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/timesofindia.indiatimes.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://timesofindia.indiatimes.com/city/mangaluru/Adani-UPCL-to-release-CSR-grant-of-Rs-3-74-crore-to-YellurGram-Panchayat/articleshow/50512116.cms',
+ 'body' => array(
+ '//div[@class="article_content clearfix"]',
+ '//section[@class="highlight clearfix"]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/travel-dealz.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/travel-dealz.de.php
new file mode 100644
index 00000000..4ee4fcdc
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/travel-dealz.de.php
@@ -0,0 +1,15 @@
+ array(
+ '%^/blog.*%' => array(
+ 'test_url' => 'http://travel-dealz.de/blog/venere-gutschein/',
+ 'body' => array('//div[@class="post-entry"]'),
+ 'strip' => array(
+ '//*[@id="jp-relatedposts"]',
+ '//*[@class="post-meta"]',
+ '//*[@class="post-data"]',
+ '//*[@id="author-meta"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treehugger.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treehugger.com.php
new file mode 100644
index 00000000..55eb7e01
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treehugger.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.treehugger.com/uncategorized/top-ten-posts-week-bunnies-2.html',
+ 'body' => array(
+ '//div[contains(@class, "promo-image")]',
+ '//div[contains(@id, "entry-body")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treelobsters.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treelobsters.com.php
new file mode 100644
index 00000000..3214c62a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/treelobsters.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%title="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twogag.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twogag.com.php
new file mode 100644
index 00000000..79f4f62e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twogag.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%http://www.twogag.com/comics-rss/([^.]+)\\.jpg%' => 'http://www.twogag.com/comics/$1.jpg',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twokinds.keenspot.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twokinds.keenspot.com.php
new file mode 100644
index 00000000..3428fcb4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/twokinds.keenspot.com.php
@@ -0,0 +1,10 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://twokinds.keenspot.com/archive.php?p=0',
+ 'body' => array('//*[@class="comic"]/div/a/img | //*[@class="comic"]/div/img | //*[@id="cg_img"]/img | //*[@id="cg_img"]/a/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/undeadly.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/undeadly.org.php
new file mode 100644
index 00000000..8b15900a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/undeadly.org.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://undeadly.org/cgi?action=article&sid=20141101181155',
+ 'body' => array(
+ '/html/body/table[3]/tbody/tr/td[1]/table[2]/tr/td[1]',
+ ),
+ 'strip' => array(
+ '//font',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/upi.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/upi.com.php
new file mode 100644
index 00000000..ec8d1a1a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/upi.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.upi.com/Top_News/US/2015/09/26/Tech-giants-Hollywood-stars-among-guests-at-state-dinner-for-Chinas-Xi-Jinping/4541443281006/',
+ 'body' => array(
+ '//div[@class="img"]',
+ '//div/article[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//div[@align="center"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/usatoday.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/usatoday.com.php
new file mode 100644
index 00000000..edd6aa44
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/usatoday.com.php
@@ -0,0 +1,27 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.usatoday.com/story/life/music/2017/02/13/things-you-should-know-happened-grammy-awards-2017/97833734/',
+ 'body' => array(
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//script',
+ '//h1',
+ '//iframe',
+ '//span[@class="mycapture-small-btn mycapture-btn-with-text mycapture-expandable-photo-btn-small js-mycapture-btn-small"]',
+ '//div[@class="close-wrap"]',
+ '//div[contains(@class,"ui-video-wrapper")]',
+ '//div[contains(@class,"media-mob")]',
+ '//div[contains(@class,"left-mob")]',
+ '//div[contains(@class,"nerdbox")]',
+ '//div[contains(@class,"oembed-asset")]',
+ '//*[contains(@class,"share")]',
+ '//div[contains(@class,"gallery-asset")]',
+ '//div[contains(@class,"oembed-asset")]',
+ '//div[@class="article-print-url"]'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/version2.dk.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/version2.dk.php
new file mode 100644
index 00000000..a6d49f2e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/version2.dk.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.version2.dk/artikel/surface-pro-2-fungerer-bedre-til-arbejde-end-fornoejelse-55195',
+ 'body' => array(
+ '//section[contains(@class, "teaser")]',
+ '//section[contains(@class, "body")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vgcats.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vgcats.com.php
new file mode 100644
index 00000000..b2830a37
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vgcats.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%/comics.*%' => array(
+ 'test_url' => 'http://www.vgcats.com/comics/?strip_id=358',
+ 'body' => array('//*[@align="center"]/img'),
+ 'strip' => array(),
+ ),
+ '%/super.*%' => array(
+ 'test_url' => 'http://www.vgcats.com/super/?strip_id=84',
+ 'body' => array('//*[@align="center"]/p/img'),
+ 'strip' => array(),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vuxml.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vuxml.org.php
new file mode 100644
index 00000000..b9bef7a4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/vuxml.org.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.vuxml.org/freebsd/a5f160fa-deee-11e4-99f8-080027ef73ec.html',
+ 'body' => array(
+ '//body',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//div[@class="blurb"]',
+ '//hr',
+ '//p[@class="copyright"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/wausaudailyherald.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/wausaudailyherald.com.php
new file mode 100644
index 00000000..58aceeaf
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/wausaudailyherald.com.php
@@ -0,0 +1,27 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.wausaudailyherald.com/story/news/2017/04/01/hundreds-gather-remember-attorney-killed-shooting-spree/99826062/?from=global&sessionKey=&autologin=',
+ 'body' => array(
+ '//div[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//iframe',
+ '//span[@class="mycapture-small-btn mycapture-btn-with-text mycapture-expandable-photo-btn-small js-mycapture-btn-small"]',
+ '//div[@class="close-wrap"]',
+ '//div[contains(@class,"ui-video-wrapper")]',
+ '//div[contains(@class,"media-mob")]',
+ '//div[contains(@class,"left-mob")]',
+ '//div[contains(@class,"nerdbox")]',
+ '//p/span',
+ '//div[contains(@class,"oembed-asset")]',
+ '//*[contains(@class,"share")]',
+ '//div[contains(@class,"gallery-asset")]',
+ '//div[contains(@class,"oembed-asset")]',
+ '//div[@class="article-print-url"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php
new file mode 100644
index 00000000..98fc368a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php
@@ -0,0 +1,33 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bbc.co.uk/news/world-middle-east-23911833',
+ 'body' => array(
+ '//div[@class="story-body__inner"] | //div[@class="article"]',
+ '//div[@class="indPost"]',
+ ),
+ 'strip' => array(
+ '//form',
+ '//div[@id="headline"]',
+ '//*[@class="warning"]',
+ '//span[@class="off-screen"]',
+ '//span[@class="story-image-copyright"]',
+ '//ul[@class="story-body__unordered-list"]',
+ '//div[@class="ad_wrapper"]',
+ '//div[@id="article-sidebar"]',
+ '//div[@class="data-table-outer"]',
+ '//*[@class="story-date"]',
+ '//*[@class="story-header"]',
+ '//figure[contains(@class,"has-caption")]',
+ '//*[@class="story-related"]',
+ '//*[contains(@class, "byline")]',
+ '//p[contains(@class, "media-message")]',
+ '//*[contains(@class, "story-feature")]',
+ '//*[@id="video-carousel-container"]',
+ '//*[@id="also-related-links"]',
+ '//*[contains(@class, "share") or contains(@class, "hidden") or contains(@class, "hyper")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bdgest.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bdgest.com.php
new file mode 100644
index 00000000..41ef68d4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bdgest.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bdgest.com/chronique-6027-BD-Adrastee-Tome-2.html',
+ 'body' => array(
+ '//*[contains(@class, "chronique")]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "post-review")]',
+ '//*[contains(@class, "footer-review")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bgr.in.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bgr.in.php
new file mode 100644
index 00000000..63ca069e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.bgr.in.php
@@ -0,0 +1,23 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.bgr.in/news/xiaomi-redmi-3-with-13-megapixel-camera-snapdragon-616-launched-price-specifications-and-features/',
+ 'body' => array(
+ '//div[@class="article-content"]',
+ ),
+ 'strip' => array(
+ '//*[@class="article-meta"]',
+ '//*[@class="contentAdsense300"]',
+ '//*[@class="iwpl-social-hide"]',
+ '//iframe[@class="iframeads"]',
+ '//*[@class="disqus_thread"]',
+ '//*[@class="outb-mobile OUTBRAIN"]',
+ '//*[@class="wdt_smart_alerts"]',
+ '//*[@class="footnote"]',
+ '//*[@id="gadget-widget"]',
+ '//header[@class="article-title entry-header"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.businessweek.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.businessweek.com.php
new file mode 100644
index 00000000..0acc44ec
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.businessweek.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.businessweek.com/articles/2013-09-18/elon-musks-hyperloop-will-work-says-some-very-smart-software',
+ 'body' => array(
+ '//div[@id="lead_graphic"]',
+ '//div[@id="article_body"]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "related_item")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.cnn.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.cnn.com.php
new file mode 100644
index 00000000..31d03ed9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.cnn.com.php
@@ -0,0 +1,24 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.cnn.com/2013/08/31/world/meast/syria-civil-war/index.html?hpt=hp_t1',
+ 'body' => array(
+ '//div[@class="cnn_strycntntlft"]',
+ ),
+ 'strip' => array(
+ '//div[@class="cnn_stryshrwdgtbtm"]',
+ '//div[@class="cnn_strybtmcntnt"]',
+ '//div[@class="cnn_strylftcntnt"]',
+ '//div[contains(@class, "cnnGalleryContainer")]',
+ '//div[contains(@class, "cnn_strylftcexpbx")]',
+ '//div[contains(@class, "articleGalleryNavContainer")]',
+ '//div[contains(@class, "cnnArticleGalleryCaptionControl")]',
+ '//div[contains(@class, "cnnArticleGalleryNavPrevNextDisabled")]',
+ '//div[contains(@class, "cnnArticleGalleryNavPrevNext")]',
+ '//div[contains(@class, "cnn_html_media_title_new")]',
+ '//div[contains(@id, "disqus")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.developpez.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.developpez.com.php
new file mode 100644
index 00000000..1535e437
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.developpez.com.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.developpez.com/actu/81757/Mozilla-annonce-la-disponibilite-de-Firefox-36-qui-passe-au-HTTP-2-et-permet-la-synchronisation-de-son-ecran-d-accueil/',
+ 'body' => array(
+ '//*[@itemprop="articleBody"]',
+ ),
+ 'strip' => array(
+ '//form',
+ '//div[@class="content"]/img',
+ '//a[last()]/following-sibling::*',
+ '//*[contains(@class,"actuTitle")]',
+ '//*[contains(@class,"date")]',
+ '//*[contains(@class,"inlineimg")]',
+ '//*[@id="signaler"]',
+ '//*[@id="signalerFrame"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.egscomics.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.egscomics.com.php
new file mode 100644
index 00000000..263f0755
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.egscomics.com.php
@@ -0,0 +1,12 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.egscomics.com/index.php?id=1690',
+ 'title' => '/html/head/title',
+ 'body' => array(
+ '//img[@id="comic"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.fakingnews.firstpost.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.fakingnews.firstpost.com.php
new file mode 100644
index 00000000..c948c77b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.fakingnews.firstpost.com.php
@@ -0,0 +1,17 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.fakingnews.firstpost.com/2016/01/engineering-student-creates-record-in-a-decade-becomes-the-first-to-completely-exhaust-ball-pen-refill/',
+ 'body' => array(
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(
+ '//*[@class="socialshare_bar"]',
+ '//*[@class="authorbox"]',
+ '//*[@class="cf5_rps"]',
+ '//*[@class="60563 fb-comments fb-social-plugin"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.forbes.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.forbes.com.php
new file mode 100644
index 00000000..fd16ed57
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.forbes.com.php
@@ -0,0 +1,20 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.forbes.com/sites/andygreenberg/2013/09/05/follow-the-bitcoins-how-we-got-busted-buying-drugs-on-silk-roads-black-market/',
+ 'body' => array(
+ '//div[@id="leftRail"]/div[contains(@class, body)]',
+ ),
+ 'strip' => array(
+ '//aside',
+ '//div[contains(@class, "entity_block")]',
+ '//div[contains(@class, "vestpocket") and not contains(@class, "body")]',
+ '//div[contains(@style, "display")]',
+ '//div[contains(@id, "comment")]',
+ '//div[contains(@class, "widget")]',
+ '//div[contains(@class, "pagination")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.franceculture.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.franceculture.fr.php
new file mode 100644
index 00000000..f7ec0d8d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.franceculture.fr.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.franceculture.fr/emission-culture-eco-la-finance-aime-toujours-la-france-2016-01-08',
+ 'body' => array(
+ '//div[@class="text-zone"]',
+ ),
+ 'strip' => array(
+ '//ul[@class="tags"]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.futura-sciences.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.futura-sciences.com.php
new file mode 100644
index 00000000..ea94a0fb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.futura-sciences.com.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.futura-sciences.com/magazines/espace/infos/actu/d/astronautique-curiosity-franchi-succes-dune-dingo-gap-52289/#xtor=RSS-8',
+ 'body' => array(
+ '//div[contains(@class, "content fiche-")]',
+ ),
+ 'strip' => array(
+ '//h1',
+ '//*[contains(@class, "content-date")]',
+ '//*[contains(@class, "diaporama")]',
+ '//*[contains(@class, "slider")]',
+ '//*[contains(@class, "cartouche")]',
+ '//*[contains(@class, "noprint")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.geekculture.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.geekculture.com.php
new file mode 100644
index 00000000..3d0b6c75
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.geekculture.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.geekculture.com/joyoftech/joyarchives/2180.html',
+ 'body' => array(
+ '//p[contains(@class,"Maintext")][2]/a/img[contains(@src,"joyimages")]',
+ ),
+ 'strip' => array(),
+ ),
+ ),
+);
+
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.howtogeek.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.howtogeek.com.php
new file mode 100644
index 00000000..6879e767
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.howtogeek.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.howtogeek.com/235283/what-is-a-wireless-hard-drive-and-should-i-get-one/',
+ 'body' => array(
+ '//div[@class="thecontent"]',
+ ),
+ 'strip' => array(
+ '//*[@class="relatedside"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php
new file mode 100644
index 00000000..dcb7e484
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.lepoint.fr/c-est-arrive-aujourd-hui/19-septembre-1783-pour-la-premiere-fois-un-mouton-un-canard-et-un-coq-s-envoient-en-l-air-devant-louis-xvi-18-09-2012-1507704_494.php',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//*[contains(@class, "info_article")]',
+ '//*[contains(@class, "fildariane_titre")]',
+ '//*[contains(@class, "entete2_article")]',
+ '//*[contains(@class, "signature_article")]',
+ '//*[contains(@id, "share")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lesnumeriques.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lesnumeriques.com.php
new file mode 100644
index 00000000..0137e209
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.lesnumeriques.com.php
@@ -0,0 +1,25 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.lesnumeriques.com/blender/kitchenaid-diamond-5ksb1585-p27473/test.html',
+ 'body' => array(
+ '//*[@id="product-content"]',
+ '//*[@id="news-content"]',
+ '//*[@id="article-content"]',
+ ),
+ 'strip' => array(
+ '//form',
+ '//div[contains(@class, "price-v4"])',
+ '//div[contains(@class, "authors-and-date")]',
+ '//div[contains(@class, "mini-product")]',
+ '//div[@id="articles-related-authors"]',
+ '//div[@id="tags-socials"]',
+ '//div[@id="user-reviews"]',
+ '//div[@id="product-reviews"]',
+ '//div[@id="publication-breadcrumbs-and-date"]',
+ '//div[@id="publication-breadcrumbs-and-date"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.mac4ever.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.mac4ever.com.php
new file mode 100644
index 00000000..60bc1bd4
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.mac4ever.com.php
@@ -0,0 +1,13 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.mac4ever.com/actu/87392_video-quand-steve-jobs-et-bill-gates-jouaient-au-bachelor-avec-le-mac',
+ 'body' => array(
+ '//div[contains(@class, "news-news-content")]',
+ ),
+ 'strip' => array(
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.makeuseof.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.makeuseof.com.php
new file mode 100644
index 00000000..a274564a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.makeuseof.com.php
@@ -0,0 +1,18 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.makeuseof.com/tag/having-problems-with-audio-in-windows-10-heres-a-likely-fix/',
+ 'body' => array(
+ '//div[@class="entry"]',
+ ),
+ 'strip' => array(
+ '//*[@class="new_sharebar"]',
+ '//*[@class="author"]',
+ '//*[@class="wdt_grouvi"]',
+ '//*[@class="wdt_smart_alerts"]',
+ '//*[@class="modal fade grouvi"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.monsieur-le-chien.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.monsieur-le-chien.fr.php
new file mode 100644
index 00000000..5f5e987b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.monsieur-le-chien.fr.php
@@ -0,0 +1,11 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.monsieur-le-chien.fr/index.php?planche=672',
+ 'body' => array(
+ '//img[starts-with(@src, "i/planches/")]',
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.npr.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.npr.org.php
new file mode 100644
index 00000000..ecc0213a
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.npr.org.php
@@ -0,0 +1,28 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.npr.org/blogs/thesalt/2013/09/17/223345977/auto-brewery-syndrome-apparently-you-can-make-beer-in-your-gut',
+ 'body' => array(
+ '//article[contains(@class,"story")]',
+ ),
+ 'strip' => array(
+ '//div[@class="story-tools"]',
+ '//h3[@class="slug"]',
+ '//div[@class="storytitle"]',
+ '//div[@id="story-meta"]',
+ '//a[@id="mainContent"]',
+ '//div[@class="credit-caption"]',
+ '//div[@class="enlarge_html"]',
+ '//button',
+ '//div[contains(@id,"pullquote")]',
+ '//div[contains(@class,"internallink")]',
+ '//div[contains(@class,"video")]',
+ '//div[@class="simplenodate"]',
+ '//div[contains(@class,"share-")]',
+ '//div[@class="tags"]',
+ '//aside'
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.numerama.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.numerama.com.php
new file mode 100644
index 00000000..fe4971c5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.numerama.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.numerama.com/sciences/125959-recherches-ladn-recompensees-nobel-de-chimie.html',
+ 'body' => array(
+ '//article',
+ ),
+ 'strip' => array(
+ '//footer',
+ '//section[@class="related-article"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.oneindia.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.oneindia.com.php
new file mode 100644
index 00000000..320c2147
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.oneindia.com.php
@@ -0,0 +1,14 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.oneindia.com/india/b-luru-govt-likely-remove-word-eunuch-from-sec-36-a-karnataka-police-act-1981173.html',
+ 'body' => array(
+ '//div[@class="ecom-ad-content"]',
+ ),
+ 'strip' => array(
+ '//*[@id="view_cmtns"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.pseudo-sciences.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.pseudo-sciences.org.php
new file mode 100644
index 00000000..9e467edf
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.pseudo-sciences.org.php
@@ -0,0 +1,16 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.pseudo-sciences.org/spip.php?article2275',
+ 'body' => array(
+ '//div[@id="art_main"]',
+ ),
+ 'strip' => array(
+ '//div[@id="art_print"]',
+ '//div[@id="art_chapo"]',
+ '//img[@class="puce"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.sciencemag.org.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.sciencemag.org.php
new file mode 100644
index 00000000..ae7a93ac
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.sciencemag.org.php
@@ -0,0 +1,16 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.sciencemag.org/news/2016/01/could-bright-foamy-wak$',
+ 'body' => array(
+ '//div[@class="row--hero"]',
+ '//article[contains(@class,"primary")]',
+ ),
+ 'strip' => array(
+ '//header[@class="article__header"]',
+ '//footer[@class="article__foot"]',
+ ),
+ ),
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.slate.fr.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.slate.fr.php
new file mode 100644
index 00000000..8c8dc893
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.slate.fr.php
@@ -0,0 +1,19 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.slate.fr/monde/77034/allemagne-2013-couacs-campagne',
+ 'body' => array(
+ '//div[@class="article_content"]',
+ ),
+ 'strip' => array(
+ '//*[@id="slate_associated_bn"]',
+ '//*[@id="ligatus-article"]',
+ '//*[@id="article_sidebar"]',
+ '//div[contains(@id, "reseaux")]',
+ '//*[contains(@class, "smart") or contains(@class, "article_tags") or contains(@class, "article_reactions")]',
+ '//*[contains(@class, "OUTBRAIN") or contains(@class, "related_item") or contains(@class, "share")]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.universfreebox.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.universfreebox.com.php
new file mode 100644
index 00000000..0747d0fb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.universfreebox.com.php
@@ -0,0 +1,15 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://www.universfreebox.com/article/24305/4G-Bouygues-Telecom-lance-une-vente-flash-sur-son-forfait-Sensation-3Go',
+ 'body' => array(
+ '//div[@id="corps_corps"]',
+ ),
+ 'strip' => array(
+ '//*[@id="formulaire"]',
+ '//*[@id="commentaire"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.zeit.de.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.zeit.de.php
new file mode 100644
index 00000000..316c2656
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/www.zeit.de.php
@@ -0,0 +1,41 @@
+ array(
+ '%^/zeit-magazin.*%' => array(
+ 'test_url' => 'http://www.zeit.de/zeit-magazin/2015/15/pegida-kathrin-oertel-lutz-bachmann',
+ 'body' => array(
+ '//article[@class="article"]',
+ ),
+ 'strip' => array(
+ '//header/div/h1',
+ '//header/div/div[@class="article__head__subtitle"]',
+ '//header/div/div[@class="article__column__author"]',
+ '//header/div/div[@class="article__column__author"]',
+ '//header/div/span[@class="article__head__meta-wrap"]',
+ '//form',
+ '//style',
+ '//div[contains(@class, "ad-tile")]',
+ '//div[@class="iqd-mobile-adplace"]',
+ '//div[@id="iq-artikelanker"]',
+ '//div[@id="js-social-services"]',
+ '//section[@id="js-comments"]',
+ '//aside',
+ ),
+ ),
+ '%.*%' => array(
+ 'test_url' => 'http://www.zeit.de/politik/ausland/2015-04/thessaloniki-krise-griechenland-yannis-boutaris/',
+ 'body' => array(
+ '//div[@class="article-body"]',
+ ),
+ 'strip' => array(
+ '//*[@class="articleheader"]',
+ '//*[@class="excerpt"]',
+ '//div[contains(@class, "ad")]',
+ '//div[@itemprop="video"]',
+ '//*[@class="articlemeta"]',
+ '//*[@class="articlemeta-clear"]',
+ '//*[@class="zol_inarticletools"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/xkcd.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/xkcd.com.php
new file mode 100644
index 00000000..84957268
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/xkcd.com.php
@@ -0,0 +1,8 @@
+ array(
+ '%.*%' => array(
+ '%alt="(.+)" */>%' => '/>
$1',
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php
new file mode 100644
index 00000000..9fd83f18
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php
@@ -0,0 +1,21 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'https://ymatuhin.ru/tools/git-default-editor/',
+ 'body' => array(
+ '//section',
+ ),
+ 'strip' => array(
+ "//script",
+ "//style",
+ "//h1",
+ "//time",
+ "//aside",
+ "/html/body/section/ul",
+ "//amp-iframe",
+ "/html/body/section/h4"
+ ),
+ )
+ )
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Rules/zdnet.com.php b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/zdnet.com.php
new file mode 100644
index 00000000..79b35ddb
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Rules/zdnet.com.php
@@ -0,0 +1,23 @@
+ array(
+ '%.*%' => array(
+ 'test_url' => 'http://zdnet.com.feedsportal.com/c/35462/f/675637/s/4a33c93e/sc/11/l/0L0Szdnet0N0Carticle0Cchina0Eus0Eagree0Eon0Ecybercrime0Ecooperation0Eamid0Econtinued0Etension0C0Tftag0FRSSbaffb68/story01.htm',
+ 'body' => array(
+ '//p[@class="summary"]',
+ '//div[contains(@class,"storyBody")]',
+ ),
+ 'strip' => array(
+ '//*[contains(@class,"ad-")]',
+ '//p/span',
+ '//script',
+ '//p[@class="summary"]',
+ '//div[contains(@class,"relatedContent")]',
+ '//div[contains(@class,"loader")]',
+ '//p[@class="photoDetails"]',
+ '//div[@class="thumbnailSlider"]',
+ '//div[@class="shortcodeGalleryWrapper"]',
+ ),
+ ),
+ ),
+);
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php
new file mode 100644
index 00000000..6c53a289
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/CandidateParser.php
@@ -0,0 +1,283 @@
+dom = XmlParser::getHtmlDocument(''.$html);
+ $this->xpath = new DOMXPath($this->dom);
+ }
+
+ /**
+ * Get the relevant content with the list of potential attributes.
+ *
+ * @return string
+ */
+ public function execute()
+ {
+ $content = $this->findContentWithCandidates();
+
+ if (strlen($content) < 200) {
+ $content = $this->findContentWithArticle();
+ }
+
+ if (strlen($content) < 50) {
+ $content = $this->findContentWithBody();
+ }
+
+ return $this->stripGarbage($content);
+ }
+
+ /**
+ * Find content based on the list of tag candidates.
+ *
+ * @return string
+ */
+ public function findContentWithCandidates()
+ {
+ foreach ($this->candidatesAttributes as $candidate) {
+ Logger::setMessage(get_called_class().': Try this candidate: "'.$candidate.'"');
+
+ $nodes = $this->xpath->query('//*[(contains(@class, "'.$candidate.'") or @id="'.$candidate.'") and not (contains(@class, "nav") or contains(@class, "page"))]');
+
+ if ($nodes !== false && $nodes->length > 0) {
+ Logger::setMessage(get_called_class().': Find candidate "'.$candidate.'"');
+
+ return $this->dom->saveXML($nodes->item(0));
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Find tag.
+ *
+ * @return string
+ */
+ public function findContentWithArticle()
+ {
+ $nodes = $this->xpath->query('//article');
+
+ if ($nodes !== false && $nodes->length > 0) {
+ Logger::setMessage(get_called_class().': Find tag');
+
+ return $this->dom->saveXML($nodes->item(0));
+ }
+
+ return '';
+ }
+
+ /**
+ * Find tag.
+ *
+ * @return string
+ */
+ public function findContentWithBody()
+ {
+ $nodes = $this->xpath->query('//body');
+
+ if ($nodes !== false && $nodes->length > 0) {
+ Logger::setMessage(get_called_class().' Find ');
+
+ return $this->dom->saveXML($nodes->item(0));
+ }
+
+ return '';
+ }
+
+ /**
+ * Strip useless tags.
+ *
+ * @param string $content
+ *
+ * @return string
+ */
+ public function stripGarbage($content)
+ {
+ $dom = XmlParser::getDomDocument($content);
+
+ if ($dom !== false) {
+ $xpath = new DOMXPath($dom);
+
+ $this->stripTags($xpath);
+ $this->stripAttributes($dom, $xpath);
+
+ $content = $dom->saveXML($dom->documentElement);
+ }
+
+ return $content;
+ }
+
+ /**
+ * Remove blacklisted tags.
+ *
+ * @param DOMXPath $xpath
+ */
+ public function stripTags(DOMXPath $xpath)
+ {
+ foreach ($this->stripTags as $tag) {
+ $nodes = $xpath->query('//'.$tag);
+
+ if ($nodes !== false && $nodes->length > 0) {
+ Logger::setMessage(get_called_class().': Strip tag: "'.$tag.'"');
+
+ foreach ($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove blacklisted attributes.
+ *
+ * @param DomDocument $dom
+ * @param DOMXPath $xpath
+ */
+ public function stripAttributes(DomDocument $dom, DOMXPath $xpath)
+ {
+ foreach ($this->stripAttributes as $attribute) {
+ $nodes = $xpath->query('//*[contains(@class, "'.$attribute.'") or contains(@id, "'.$attribute.'")]');
+
+ if ($nodes !== false && $nodes->length > 0) {
+ Logger::setMessage(get_called_class().': Strip attribute: "'.$attribute.'"');
+
+ foreach ($nodes as $node) {
+ if ($this->shouldRemove($dom, $node)) {
+ $node->parentNode->removeChild($node);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Find link for next page of the article.
+ *
+ * @return string
+ */
+ public function findNextLink()
+ {
+ return null;
+ }
+
+ /**
+ * Return false if the node should not be removed.
+ *
+ * @param DomDocument $dom
+ * @param DomNode $node
+ *
+ * @return bool
+ */
+ public function shouldRemove(DomDocument $dom, $node)
+ {
+ $document_length = strlen($dom->textContent);
+ $node_length = strlen($node->textContent);
+
+ if ($document_length === 0) {
+ return true;
+ }
+
+ $ratio = $node_length * 100 / $document_length;
+
+ if ($ratio >= 90) {
+ Logger::setMessage(get_called_class().': Should not remove this node ('.$node->nodeName.') ratio: '.$ratio.'%');
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php
new file mode 100644
index 00000000..3ded4b1c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/ParserInterface.php
@@ -0,0 +1,20 @@
+getRulesFileList($hostname);
+
+ foreach ($this->getRulesFolders() as $folder) {
+ $rule = $this->loadRuleFile($folder, $files);
+
+ if (!empty($rule)) {
+ return $rule;
+ }
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * Get the list of possible rules file names for a given hostname.
+ *
+ * @param string $hostname Hostname
+ *
+ * @return array
+ */
+ public function getRulesFileList($hostname)
+ {
+ $files = array($hostname); // subdomain.domain.tld
+ $parts = explode('.', $hostname);
+ $len = count($parts);
+
+ if ($len > 2) {
+ $subdomain = array_shift($parts);
+ $files[] = implode('.', $parts); // domain.tld
+ $files[] = '.'.implode('.', $parts); // .domain.tld
+ $files[] = $subdomain; // subdomain
+ } elseif ($len === 2) {
+ $files[] = '.'.implode('.', $parts); // .domain.tld
+ $files[] = $parts[0]; // domain
+ }
+
+ return $files;
+ }
+
+ /**
+ * Load a rule file from the defined folder.
+ *
+ * @param string $folder Rule directory
+ * @param array $files List of possible file names
+ *
+ * @return array
+ */
+ public function loadRuleFile($folder, array $files)
+ {
+ foreach ($files as $file) {
+ $filename = $folder.'/'.$file.'.php';
+ if (file_exists($filename)) {
+ Logger::setMessage(get_called_class().' Load rule: '.$file);
+
+ return include $filename;
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * Get the list of folders that contains rules.
+ *
+ * @return array
+ */
+ public function getRulesFolders()
+ {
+ $folders = array();
+
+ if ($this->config !== null && $this->config->getGrabberRulesFolder() !== null) {
+ $folders[] = $this->config->getGrabberRulesFolder();
+ }
+
+ $folders[] = __DIR__ . '/../Rules';
+
+ return $folders;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php
new file mode 100644
index 00000000..9beb59c1
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/RuleParser.php
@@ -0,0 +1,102 @@
+rules = $rules;
+ $this->dom = XmlParser::getHtmlDocument(''.$html);
+ $this->xpath = new DOMXPath($this->dom);
+ }
+
+ /**
+ * Get the relevant content with predefined rules.
+ *
+ * @return string
+ */
+ public function execute()
+ {
+ $this->stripTags();
+
+ return $this->findContent();
+ }
+
+ /**
+ * Remove HTML tags.
+ */
+ public function stripTags()
+ {
+ if (isset($this->rules['strip']) && is_array($this->rules['strip'])) {
+ foreach ($this->rules['strip'] as $pattern) {
+ $nodes = $this->xpath->query($pattern);
+
+ if ($nodes !== false && $nodes->length > 0) {
+ foreach ($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Fetch content based on Xpath rules.
+ */
+ public function findContent()
+ {
+ $content = '';
+ if (isset($this->rules['body']) && is_array($this->rules['body'])) {
+ foreach ($this->rules['body'] as $pattern) {
+ $nodes = $this->xpath->query($pattern);
+
+ if ($nodes !== false && $nodes->length > 0) {
+ foreach ($nodes as $node) {
+ $content .= $this->dom->saveXML($node);
+ }
+ }
+ }
+ }
+
+ return $content;
+ }
+
+ /**
+ * Fetch next link based on Xpath rules.
+ *
+ * @return string
+ */
+ public function findNextLink()
+ {
+ if (isset($this->rules['next_page']) && is_array($this->rules['next_page'])) {
+ foreach ($this->rules['next_page'] as $pattern) {
+ $nodes = $this->xpath->query($pattern);
+ if ($nodes !== false && $nodes->length > 0) {
+ foreach ($nodes as $node) {
+ return $node->getAttribute('href');
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php
new file mode 100644
index 00000000..e5b9817f
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Scraper/Scraper.php
@@ -0,0 +1,279 @@
+enableCandidateParser = false;
+ return $this;
+ }
+
+ /**
+ * Get encoding.
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->encoding;
+ }
+
+ /**
+ * Set encoding.
+ *
+ * @param string $encoding
+ *
+ * @return Scraper
+ */
+ public function setEncoding($encoding)
+ {
+ $this->encoding = $encoding;
+
+ return $this;
+ }
+
+ /**
+ * Get URL to download.
+ *
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Set URL to download.
+ *
+ * @param string $url URL
+ *
+ * @return Scraper
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+
+ return $this;
+ }
+
+ /**
+ * Return true if the scraper found relevant content.
+ *
+ * @return bool
+ */
+ public function hasRelevantContent()
+ {
+ return !empty($this->content);
+ }
+
+ /**
+ * Get relevant content.
+ *
+ * @return string
+ */
+ public function getRelevantContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Get raw content (unfiltered).
+ *
+ * @return string
+ */
+ public function getRawContent()
+ {
+ return $this->html;
+ }
+
+ /**
+ * Set raw content (unfiltered).
+ *
+ * @param string $html
+ *
+ * @return Scraper
+ */
+ public function setRawContent($html)
+ {
+ $this->html = $html;
+
+ return $this;
+ }
+
+ /**
+ * Get filtered relevant content.
+ *
+ * @return string
+ */
+ public function getFilteredContent()
+ {
+ $filter = Filter::html($this->content, $this->url);
+ $filter->setConfig($this->config);
+
+ return $filter->execute();
+ }
+
+ /**
+ * Download the HTML content.
+ *
+ * @return bool
+ */
+ public function download()
+ {
+ if (!empty($this->url)) {
+
+ // Clear everything
+ $this->html = '';
+ $this->content = '';
+ $this->encoding = '';
+
+ try {
+ $client = Client::getInstance();
+ $client->setConfig($this->config);
+ $client->setTimeout($this->config->getGrabberTimeout());
+ $client->setUserAgent($this->config->getGrabberUserAgent());
+ $client->execute($this->url);
+
+ $this->url = $client->getUrl();
+ $this->html = $client->getContent();
+ $this->encoding = $client->getEncoding();
+
+ return true;
+ } catch (ClientException $e) {
+ Logger::setMessage(get_called_class().': '.$e->getMessage());
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Execute the scraper.
+ */
+ public function execute($pageContent = '', $recursionDepth = 0)
+ {
+ $this->html = '';
+ $this->encoding = '';
+ $this->content = '';
+ $this->download();
+ $this->prepareHtml();
+
+ $parser = $this->getParser();
+
+ if ($parser !== null) {
+ $maxRecursions = $this->config->getMaxRecursions();
+ if(!isset($maxRecursions)){
+ $maxRecursions = 25;
+ }
+ $pageContent .= $parser->execute();
+ // check if there is a link to next page and recursively get content (max 25 pages)
+ if((($nextLink = $parser->findNextLink()) !== null) && $recursionDepth < $maxRecursions){
+ $nextLink = Url::resolve($nextLink,$this->url);
+ $this->setUrl($nextLink);
+ $this->execute($pageContent,$recursionDepth+1);
+ }
+ else{
+ $this->content = $pageContent;
+ }
+ Logger::setMessage(get_called_class().': Content length: '.strlen($this->content).' bytes');
+ }
+ }
+
+ /**
+ * Get the parser.
+ *
+ * @return ParserInterface
+ */
+ public function getParser()
+ {
+ $ruleLoader = new RuleLoader($this->config);
+ $rules = $ruleLoader->getRules($this->url);
+
+ if (!empty($rules['grabber'])) {
+ Logger::setMessage(get_called_class().': Parse content with rules');
+
+ foreach ($rules['grabber'] as $pattern => $rule) {
+ $url = new Url($this->url);
+ $sub_url = $url->getFullPath();
+
+ if (preg_match($pattern, $sub_url)) {
+ Logger::setMessage(get_called_class().': Matched url '.$sub_url);
+ return new RuleParser($this->html, $rule);
+ }
+ }
+ } elseif ($this->enableCandidateParser) {
+ Logger::setMessage(get_called_class().': Parse content with candidates');
+ }
+
+ return new CandidateParser($this->html);
+ }
+
+ /**
+ * Normalize encoding and strip head tag.
+ */
+ public function prepareHtml()
+ {
+ $html_encoding = XmlParser::getEncodingFromMetaTag($this->html);
+
+ $this->html = Encoding::convert($this->html, $html_encoding ?: $this->encoding);
+ $this->html = Filter::stripHeadTags($this->html);
+
+ Logger::setMessage(get_called_class().': HTTP Encoding "'.$this->encoding.'" ; HTML Encoding "'.$html_encoding.'"');
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php
new file mode 100644
index 00000000..12eccfd5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/Subscription.php
@@ -0,0 +1,175 @@
+title = $title;
+ return $this;
+ }
+
+ /**
+ * Get title
+ *
+ * @access public
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Set feed URL
+ *
+ * @access public
+ * @param string $feedUrl
+ * @return Subscription
+ */
+ public function setFeedUrl($feedUrl)
+ {
+ $this->feedUrl = $feedUrl;
+ return $this;
+ }
+
+ /**
+ * Get feed URL
+ *
+ * @access public
+ * @return string
+ */
+ public function getFeedUrl()
+ {
+ return $this->feedUrl;
+ }
+
+ /**
+ * Set site URL
+ *
+ * @access public
+ * @param string $siteUrl
+ * @return Subscription
+ */
+ public function setSiteUrl($siteUrl)
+ {
+ $this->siteUrl = $siteUrl;
+ return $this;
+ }
+
+ /**
+ * Get site URL
+ *
+ * @access public
+ * @return string
+ */
+ public function getSiteUrl()
+ {
+ return $this->siteUrl;
+ }
+
+ /**
+ * Set category
+ *
+ * @access public
+ * @param string $category
+ * @return Subscription
+ */
+ public function setCategory($category)
+ {
+ $this->category = $category;
+ return $this;
+ }
+
+ /**
+ * Get category
+ *
+ * @access public
+ * @return string
+ */
+ public function getCategory()
+ {
+ return $this->category;
+ }
+
+ /**
+ * Set description
+ *
+ * @access public
+ * @param string $description
+ * @return Subscription
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ return $this;
+ }
+
+ /**
+ * Get description
+ *
+ * @access public
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Set type
+ *
+ * @access public
+ * @param string $type
+ * @return Subscription
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * Get type
+ *
+ * @access public
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php
new file mode 100644
index 00000000..b173f89b
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php
@@ -0,0 +1,75 @@
+title = $title;
+ return $this;
+ }
+
+ /**
+ * Get title
+ *
+ * @access public
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Add subscription
+ *
+ * @access public
+ * @param Subscription $subscription
+ * @return SubscriptionList
+ */
+ public function addSubscription(Subscription $subscription)
+ {
+ $this->subscriptions[] = $subscription;
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php
new file mode 100644
index 00000000..838e4cb5
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php
@@ -0,0 +1,204 @@
+subscriptionList = $subscriptionList;
+ }
+
+ /**
+ * Get object instance
+ *
+ * @static
+ * @access public
+ * @param SubscriptionList $subscriptionList
+ * @return SubscriptionListBuilder
+ */
+ public static function create(SubscriptionList $subscriptionList)
+ {
+ return new static($subscriptionList);
+ }
+
+ /**
+ * Build OPML feed
+ *
+ * @access public
+ * @param string $filename
+ * @return string
+ */
+ public function build($filename = '')
+ {
+ $this->document = new DomDocument('1.0', 'UTF-8');
+ $this->document->formatOutput = true;
+
+ $opmlElement = $this->document->createElement('opml');
+ $opmlElement->setAttribute('version', '1.0');
+
+ $headElement = $this->document->createElement('head');
+
+ if ($this->subscriptionList->getTitle() !== '') {
+ $titleElement = $this->document->createElement('title');
+ $titleElement->appendChild($this->document->createTextNode($this->subscriptionList->getTitle()));
+ $headElement->appendChild($titleElement);
+ }
+
+ $opmlElement->appendChild($headElement);
+ $opmlElement->appendChild($this->buildBody());
+ $this->document->appendChild($opmlElement);
+
+ if ($filename !== '') {
+ $this->document->save($filename);
+ return '';
+ }
+
+ return $this->document->saveXML();
+ }
+
+ /**
+ * Return true if the list has categories
+ *
+ * @access public
+ * @return bool
+ */
+ public function hasCategories()
+ {
+ foreach ($this->subscriptionList->subscriptions as $subscription) {
+ if ($subscription->getCategory() !== '') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Build OPML body
+ *
+ * @access protected
+ * @return DOMElement
+ */
+ protected function buildBody()
+ {
+ $bodyElement = $this->document->createElement('body');
+
+ if ($this->hasCategories()) {
+ $this->buildCategories($bodyElement);
+ return $bodyElement;
+ }
+
+ foreach ($this->subscriptionList->subscriptions as $subscription) {
+ $bodyElement->appendChild($this->buildSubscription($subscription));
+ }
+
+ return $bodyElement;
+ }
+
+ /**
+ * Build categories section
+ *
+ * @access protected
+ * @param DOMElement $bodyElement
+ */
+ protected function buildCategories(DOMElement $bodyElement)
+ {
+ $categories = $this->groupByCategories();
+
+ foreach ($categories as $category => $subscriptions) {
+ $bodyElement->appendChild($this->buildCategory($category, $subscriptions));
+ }
+ }
+
+ /**
+ * Build category tag
+ *
+ * @access protected
+ * @param string $category
+ * @param array $subscriptions
+ * @return DOMElement
+ */
+ protected function buildCategory($category, array $subscriptions)
+ {
+ $outlineElement = $this->document->createElement('outline');
+ $outlineElement->setAttribute('text', $category);
+
+ foreach ($subscriptions as $subscription) {
+ $outlineElement->appendChild($this->buildSubscription($subscription));
+ }
+
+ return $outlineElement;
+ }
+
+ /**
+ * Build subscription entry
+ *
+ * @access public
+ * @param Subscription $subscription
+ * @return DOMElement
+ */
+ protected function buildSubscription(Subscription $subscription)
+ {
+ $outlineElement = $this->document->createElement('outline');
+ $outlineElement->setAttribute('type', $subscription->getType() ?: 'rss');
+ $outlineElement->setAttribute('text', $subscription->getTitle() ?: $subscription->getFeedUrl());
+ $outlineElement->setAttribute('xmlUrl', $subscription->getFeedUrl());
+
+ if ($subscription->getTitle() !== '') {
+ $outlineElement->setAttribute('title', $subscription->getTitle());
+ }
+
+ if ($subscription->getDescription() !== '') {
+ $outlineElement->setAttribute('description', $subscription->getDescription());
+ }
+
+ if ($subscription->getSiteUrl() !== '') {
+ $outlineElement->setAttribute('htmlUrl', $subscription->getSiteUrl());
+ }
+
+ return $outlineElement;
+ }
+
+ /**
+ * Group subscriptions by category
+ *
+ * @access private
+ * @return array
+ */
+ private function groupByCategories()
+ {
+ $categories = array();
+
+ foreach ($this->subscriptionList->subscriptions as $subscription) {
+ $categories[$subscription->getCategory()][] = $subscription;
+ }
+
+ return $categories;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php
new file mode 100644
index 00000000..9085588c
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php
@@ -0,0 +1,100 @@
+subscriptionList = new SubscriptionList();
+ $this->data = trim($data);
+ }
+
+ /**
+ * Get object instance
+ *
+ * @static
+ * @access public
+ * @param string $data
+ * @return SubscriptionListParser
+ */
+ public static function create($data)
+ {
+ return new static($data);
+ }
+
+ /**
+ * Parse a subscription list entry
+ *
+ * @access public
+ * @throws MalformedXmlException
+ * @return SubscriptionList
+ */
+ public function parse()
+ {
+ $xml = XmlParser::getSimpleXml($this->data);
+
+ if (! $xml || !isset($xml->head) || !isset($xml->body)) {
+ throw new MalformedXmlException('Unable to parse OPML file: invalid XML');
+ }
+
+ $this->parseTitle($xml->head);
+ $this->parseEntries($xml->body);
+
+ return $this->subscriptionList;
+ }
+
+ /**
+ * Parse title
+ *
+ * @access protected
+ * @param SimpleXMLElement $xml
+ */
+ protected function parseTitle(SimpleXMLElement $xml)
+ {
+ $this->subscriptionList->setTitle((string) $xml->title);
+ }
+
+ /**
+ * Parse entries
+ *
+ * @access protected
+ * @param SimpleXMLElement $body
+ */
+ private function parseEntries(SimpleXMLElement $body)
+ {
+ foreach ($body->outline as $outlineElement) {
+ if (isset($outlineElement->outline)) {
+ $this->parseEntries($outlineElement);
+ } else {
+ $this->subscriptionList->subscriptions[] = SubscriptionParser::create($body, $outlineElement)->parse();
+ }
+ }
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php
new file mode 100644
index 00000000..caff07c2
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php
@@ -0,0 +1,142 @@
+parentElement = $parentElement;
+ $this->outlineElement = $outlineElement;
+ $this->subscription = new Subscription();
+ }
+
+ /**
+ * Get object instance
+ *
+ * @static
+ * @access public
+ * @param SimpleXMLElement $parentElement
+ * @param SimpleXMLElement $outlineElement
+ * @return SubscriptionParser
+ */
+ public static function create(SimpleXMLElement $parentElement, SimpleXMLElement $outlineElement)
+ {
+ return new static($parentElement, $outlineElement);
+ }
+
+ /**
+ * Parse subscription entry
+ *
+ * @access public
+ * @return Subscription
+ */
+ public function parse()
+ {
+ $this->subscription->setCategory($this->findCategory());
+ $this->subscription->setTitle($this->findTitle());
+ $this->subscription->setFeedUrl($this->findFeedUrl());
+ $this->subscription->setSiteUrl($this->findSiteUrl());
+ $this->subscription->setType($this->findType());
+ $this->subscription->setDescription($this->findDescription());
+
+ return $this->subscription;
+ }
+
+ /**
+ * Find category.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findCategory()
+ {
+ return isset($this->parentElement['text']) ? (string) $this->parentElement['text'] : '';
+ }
+
+ /**
+ * Find title.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findTitle()
+ {
+ return isset($this->outlineElement['title']) ? (string) $this->outlineElement['title'] : (string) $this->outlineElement['text'];
+ }
+
+ /**
+ * Find feed url.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findFeedUrl()
+ {
+ return (string) $this->outlineElement['xmlUrl'];
+ }
+
+ /**
+ * Find site url.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findSiteUrl()
+ {
+ return isset($this->outlineElement['htmlUrl']) ? (string) $this->outlineElement['htmlUrl'] : $this->findFeedUrl();
+ }
+
+ /**
+ * Find type.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findType()
+ {
+ return isset($this->outlineElement['version']) ? (string) $this->outlineElement['version'] :
+ isset($this->outlineElement['type']) ? (string) $this->outlineElement['type'] : 'rss';
+ }
+
+ /**
+ * Find description.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function findDescription()
+ {
+ return isset($this->outlineElement['description']) ? (string) $this->outlineElement['description'] : $this->findTitle();
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php
new file mode 100644
index 00000000..34f37800
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php
@@ -0,0 +1,65 @@
+helper = new AtomHelper($this->getDocument());
+
+ $this->feedElement = $this->getDocument()->createElement('feed');
+ $this->feedElement->setAttributeNodeNS(new DomAttr('xmlns', 'http://www.w3.org/2005/Atom'));
+
+ $generator = $this->getDocument()->createElement('generator', 'PicoFeed');
+ $generator->setAttribute('uri', 'https://github.com/miniflux/picoFeed');
+ $this->feedElement->appendChild($generator);
+
+ $this->helper
+ ->buildTitle($this->feedElement, $this->feedTitle)
+ ->buildId($this->feedElement, $this->feedUrl)
+ ->buildDate($this->feedElement, $this->feedDate)
+ ->buildLink($this->feedElement, $this->siteUrl)
+ ->buildLink($this->feedElement, $this->feedUrl, 'self', 'application/atom+xml')
+ ->buildAuthor($this->feedElement, $this->authorName, $this->authorEmail, $this->authorUrl)
+ ;
+
+ foreach ($this->items as $item) {
+ $this->feedElement->appendChild($item->build());
+ }
+
+ $this->getDocument()->appendChild($this->feedElement);
+
+ if ($filename !== '') {
+ $this->getDocument()->save($filename);
+ }
+
+ return $this->getDocument()->saveXML();
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php
new file mode 100644
index 00000000..def6b0b9
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomHelper.php
@@ -0,0 +1,139 @@
+document = $document;
+ }
+
+ /**
+ * Build node
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $tag
+ * @param string $value
+ * @return AtomHelper
+ */
+ public function buildNode(DOMElement $element, $tag, $value)
+ {
+ $node = $this->document->createElement($tag);
+ $node->appendChild($this->document->createTextNode($value));
+ $element->appendChild($node);
+ return $this;
+ }
+
+ /**
+ * Build title
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $title
+ * @return AtomHelper
+ */
+ public function buildTitle(DOMElement $element, $title)
+ {
+ return $this->buildNode($element, 'title', $title);
+ }
+
+ /**
+ * Build id
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $id
+ * @return AtomHelper
+ */
+ public function buildId(DOMElement $element, $id)
+ {
+ return $this->buildNode($element, 'id', $id);
+ }
+
+ /**
+ * Build date element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param DateTime $date
+ * @param string $type
+ * @return AtomHelper
+ */
+ public function buildDate(DOMElement $element, DateTime $date, $type = 'updated')
+ {
+ return $this->buildNode($element, $type, $date->format(DateTime::ATOM));
+ }
+
+ /**
+ * Build link element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $url
+ * @param string $rel
+ * @param string $type
+ * @return AtomHelper
+ */
+ public function buildLink(DOMElement $element, $url, $rel = 'alternate', $type = 'text/html')
+ {
+ $node = $this->document->createElement('link');
+ $node->setAttribute('rel', $rel);
+ $node->setAttribute('type', $type);
+ $node->setAttribute('href', $url);
+ $element->appendChild($node);
+
+ return $this;
+ }
+
+ /**
+ * Build author element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $authorName
+ * @param string $authorEmail
+ * @param string $authorUrl
+ * @return AtomHelper
+ */
+ public function buildAuthor(DOMElement $element, $authorName, $authorEmail, $authorUrl)
+ {
+ if (!empty($authorName)) {
+ $author = $this->document->createElement('author');
+ $this->buildNode($author, 'name', $authorName);
+
+ if (!empty($authorEmail)) {
+ $this->buildNode($author, 'email', $authorEmail);
+ }
+
+ if (!empty($authorUrl)) {
+ $this->buildNode($author, 'uri', $authorUrl);
+ }
+
+ $element->appendChild($author);
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php
new file mode 100644
index 00000000..dfdfe68d
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php
@@ -0,0 +1,63 @@
+itemElement = $this->feedBuilder->getDocument()->createElement('entry');
+ $this->helper = new AtomHelper($this->feedBuilder->getDocument());
+
+ if (!empty($this->itemId)) {
+ $this->helper->buildId($this->itemElement, $this->itemId);
+ } else {
+ $this->helper->buildId($this->itemElement, $this->itemUrl);
+ }
+
+ $this->helper
+ ->buildTitle($this->itemElement, $this->itemTitle)
+ ->buildLink($this->itemElement, $this->itemUrl)
+ ->buildDate($this->itemElement, $this->itemUpdatedDate, 'updated')
+ ->buildDate($this->itemElement, $this->itemPublishedDate, 'published')
+ ->buildAuthor($this->itemElement, $this->authorName, $this->authorEmail, $this->authorUrl)
+ ;
+
+ if (!empty($this->itemSummary)) {
+ $this->helper->buildNode($this->itemElement, 'summary', $this->itemSummary);
+ }
+
+ if (!empty($this->itemContent)) {
+ $node = $this->feedBuilder->getDocument()->createElement('content');
+ $node->setAttribute('type', 'html');
+ $node->appendChild($this->feedBuilder->getDocument()->createCDATASection($this->itemContent));
+ $this->itemElement->appendChild($node);
+ }
+
+ return $this->itemElement;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php
new file mode 100644
index 00000000..cf9d024e
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php
@@ -0,0 +1,185 @@
+document = new DomDocument('1.0', 'UTF-8');
+ $this->document->formatOutput = true;
+ }
+
+ /**
+ * Get new object instance
+ *
+ * @access public
+ * @return static
+ */
+ public static function create()
+ {
+ return new static();
+ }
+
+ /**
+ * Add feed title
+ *
+ * @access public
+ * @param string $title
+ * @return $this
+ */
+ public function withTitle($title)
+ {
+ $this->feedTitle = $title;
+ return $this;
+ }
+
+ /**
+ * Add feed url
+ *
+ * @access public
+ * @param string $url
+ * @return $this
+ */
+ public function withFeedUrl($url)
+ {
+ $this->feedUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Add website url
+ *
+ * @access public
+ * @param string $url
+ * @return $this
+ */
+ public function withSiteUrl($url)
+ {
+ $this->siteUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Add feed date
+ *
+ * @access public
+ * @param DateTime $date
+ * @return $this
+ */
+ public function withDate(DateTime $date)
+ {
+ $this->feedDate = $date;
+ return $this;
+ }
+
+ /**
+ * Add feed author
+ *
+ * @access public
+ * @param string $name
+ * @param string $email
+ * @param string $url
+ * @return $this
+ */
+ public function withAuthor($name, $email = '', $url ='')
+ {
+ $this->authorName = $name;
+ $this->authorEmail = $email;
+ $this->authorUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Add feed item
+ *
+ * @access public
+ * @param ItemBuilder $item
+ * @return $this
+ */
+ public function withItem(ItemBuilder $item)
+ {
+ $this->items[] = $item;
+ return $this;
+ }
+
+ /**
+ * Get DOM document
+ *
+ * @access public
+ * @return DOMDocument
+ */
+ public function getDocument()
+ {
+ return $this->document;
+ }
+
+ /**
+ * Build feed
+ *
+ * @abstract
+ * @access public
+ * @param string $filename
+ * @return string
+ */
+ abstract public function build($filename = '');
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php
new file mode 100644
index 00000000..86985bc7
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php
@@ -0,0 +1,209 @@
+feedBuilder = $feedBuilder;
+ }
+
+ /**
+ * Get new object instance
+ *
+ * @access public
+ * @param FeedBuilder $feedBuilder
+ * @return static
+ */
+ public static function create(FeedBuilder $feedBuilder)
+ {
+ return new static($feedBuilder);
+ }
+
+ /**
+ * Add item title
+ *
+ * @access public
+ * @param string $title
+ * @return $this
+ */
+ public function withTitle($title)
+ {
+ $this->itemTitle = $title;
+ return $this;
+ }
+
+ /**
+ * Add item id
+ *
+ * @access public
+ * @param string $id
+ * @return $this
+ */
+ public function withId($id)
+ {
+ $this->itemId = $id;
+ return $this;
+ }
+
+ /**
+ * Add item url
+ *
+ * @access public
+ * @param string $url
+ * @return $this
+ */
+ public function withUrl($url)
+ {
+ $this->itemUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Add item summary
+ *
+ * @access public
+ * @param string $summary
+ * @return $this
+ */
+ public function withSummary($summary)
+ {
+ $this->itemSummary = $summary;
+ return $this;
+ }
+
+ /**
+ * Add item content
+ *
+ * @access public
+ * @param string $content
+ * @return $this
+ */
+ public function withContent($content)
+ {
+ $this->itemContent = $content;
+ return $this;
+ }
+
+ /**
+ * Add item updated date
+ *
+ * @access public
+ * @param DateTime $date
+ * @return $this
+ */
+ public function withUpdatedDate(DateTime $date)
+ {
+ $this->itemUpdatedDate = $date;
+ return $this;
+ }
+
+ /**
+ * Add item published date
+ *
+ * @access public
+ * @param DateTime $date
+ * @return $this
+ */
+ public function withPublishedDate(DateTime $date)
+ {
+ $this->itemPublishedDate = $date;
+ return $this;
+ }
+
+ /**
+ * Add item author
+ *
+ * @access public
+ * @param string $name
+ * @param string $email
+ * @param string $url
+ * @return $this
+ */
+ public function withAuthor($name, $email = '', $url ='')
+ {
+ $this->authorName = $name;
+ $this->authorEmail = $email;
+ $this->authorUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Build item
+ *
+ * @abstract
+ * @access public
+ * @return DOMElement
+ */
+ abstract public function build();
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php
new file mode 100644
index 00000000..bc3f5135
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php
@@ -0,0 +1,76 @@
+helper = new Rss20Helper($this->getDocument());
+
+ $this->rssElement = $this->getDocument()->createElement('rss');
+ $this->rssElement->setAttribute('version', '2.0');
+ $this->rssElement->setAttributeNodeNS(new DomAttr('xmlns:content', 'http://purl.org/rss/1.0/modules/content/'));
+ $this->rssElement->setAttributeNodeNS(new DomAttr('xmlns:atom', 'http://www.w3.org/2005/Atom'));
+
+ $this->channelElement = $this->getDocument()->createElement('channel');
+ $this->helper
+ ->buildNode($this->channelElement, 'generator', 'PicoFeed (https://github.com/miniflux/picoFeed)')
+ ->buildTitle($this->channelElement, $this->feedTitle)
+ ->buildNode($this->channelElement, 'description', $this->feedTitle)
+ ->buildDate($this->channelElement, $this->feedDate)
+ ->buildAuthor($this->channelElement, 'webMaster', $this->authorName, $this->authorEmail)
+ ->buildLink($this->channelElement, $this->siteUrl)
+ ;
+
+ $link = $this->getDocument()->createElement('atom:link');
+ $link->setAttribute('href', $this->feedUrl);
+ $link->setAttribute('rel', 'self');
+ $link->setAttribute('type', 'application/rss+xml');
+ $this->channelElement->appendChild($link);
+
+ foreach ($this->items as $item) {
+ $this->channelElement->appendChild($item->build());
+ }
+
+ $this->rssElement->appendChild($this->channelElement);
+ $this->getDocument()->appendChild($this->rssElement);
+
+ if ($filename !== '') {
+ $this->getDocument()->save($filename);
+ }
+
+ return $this->getDocument()->saveXML();
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php
new file mode 100644
index 00000000..72a19e56
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php
@@ -0,0 +1,115 @@
+document = $document;
+ }
+
+ /**
+ * Build node
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $tag
+ * @param string $value
+ * @return $this
+ */
+ public function buildNode(DOMElement $element, $tag, $value)
+ {
+ $node = $this->document->createElement($tag);
+ $node->appendChild($this->document->createTextNode($value));
+ $element->appendChild($node);
+ return $this;
+ }
+
+ /**
+ * Build title
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $title
+ * @return $this
+ */
+ public function buildTitle(DOMElement $element, $title)
+ {
+ return $this->buildNode($element, 'title', $title);
+ }
+
+ /**
+ * Build date element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param DateTime $date
+ * @param string $type
+ * @return $this
+ */
+ public function buildDate(DOMElement $element, DateTime $date, $type = 'pubDate')
+ {
+ return $this->buildNode($element, $type, $date->format(DateTime::RSS));
+ }
+
+ /**
+ * Build link element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $url
+ * @return $this
+ */
+ public function buildLink(DOMElement $element, $url)
+ {
+ return $this->buildNode($element, 'link', $url);
+ }
+
+ /**
+ * Build author element
+ *
+ * @access public
+ * @param DOMElement $element
+ * @param string $tag
+ * @param string $authorName
+ * @param string $authorEmail
+ * @return $this
+ */
+ public function buildAuthor(DOMElement $element, $tag, $authorName, $authorEmail)
+ {
+ if (!empty($authorName)) {
+ $value = '';
+
+ if (!empty($authorEmail)) {
+ $value .= $authorEmail.' ('.$authorName.')';
+ } else {
+ $value = $authorName;
+ }
+
+ $this->buildNode($element, $tag, $value);
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php
new file mode 100644
index 00000000..125dc6ac
--- /dev/null
+++ b/vendor/miniflux/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php
@@ -0,0 +1,67 @@
+itemElement = $this->feedBuilder->getDocument()->createElement('item');
+ $this->helper = new Rss20Helper($this->feedBuilder->getDocument());
+
+ if (!empty($this->itemId)) {
+ $guid = $this->feedBuilder->getDocument()->createElement('guid');
+ $guid->setAttribute('isPermaLink', 'false');
+ $guid->appendChild($this->feedBuilder->getDocument()->createTextNode($this->itemId));
+ $this->itemElement->appendChild($guid);
+ } else {
+ $guid = $this->feedBuilder->getDocument()->createElement('guid');
+ $guid->setAttribute('isPermaLink', 'true');
+ $guid->appendChild($this->feedBuilder->getDocument()->createTextNode($this->itemUrl));
+ $this->itemElement->appendChild($guid);
+ }
+
+ $this->helper
+ ->buildTitle($this->itemElement, $this->itemTitle)
+ ->buildLink($this->itemElement, $this->itemUrl)
+ ->buildDate($this->itemElement, $this->itemPublishedDate)
+ ->buildAuthor($this->itemElement, 'author', $this->authorName, $this->authorEmail)
+ ;
+
+ if (!empty($this->itemSummary)) {
+ $this->helper->buildNode($this->itemElement, 'description', $this->itemSummary);
+ }
+
+ if (!empty($this->itemContent)) {
+ $node = $this->feedBuilder->getDocument()->createElement('content:encoded');
+ $node->appendChild($this->feedBuilder->getDocument()->createCDATASection($this->itemContent));
+ $this->itemElement->appendChild($node);
+ }
+
+ return $this->itemElement;
+ }
+}
diff --git a/vendor/miniflux/picofeed/picofeed b/vendor/miniflux/picofeed/picofeed
new file mode 100755
index 00000000..8f35737a
--- /dev/null
+++ b/vendor/miniflux/picofeed/picofeed
@@ -0,0 +1,135 @@
+#!/usr/bin/env php
+discover($url);
+
+ $parser = $reader->getParser(
+ $resource->getUrl(),
+ $resource->getContent(),
+ $resource->getEncoding()
+ );
+
+ if ($disable_filtering) {
+ $parser->disableContentFiltering();
+ }
+
+ return $parser->execute();
+ }
+ catch (PicoFeedException $e) {
+ echo 'Exception thrown ===> "'.$e->getMessage().'"'.PHP_EOL;
+ return false;
+ }
+}
+
+function get_item($feed, $item_id)
+{
+ foreach ($feed->items as $item) {
+ if ($item->getId() === $item_id) {
+ echo $item;
+ echo "============= CONTENT ================\n";
+ echo $item->getContent();
+ echo "\n============= CONTENT ================\n";
+ break;
+ }
+ }
+}
+
+function dump_feed($url)
+{
+ $feed = get_feed($url);
+ echo $feed;
+}
+
+function debug_feed($url)
+{
+ get_feed($url);
+ print_r(Logger::getMessages());
+}
+
+function dump_item($url, $item_id)
+{
+ $feed = get_feed($url);
+
+ if ($feed !== false) {
+ get_item($feed, $item_id);
+ }
+}
+
+function nofilter_item($url, $item_id)
+{
+ $feed = get_feed($url, true);
+
+ if ($feed !== false) {
+ get_item($feed, $item_id);
+ }
+}
+
+function grabber($url)
+{
+ $grabber = new Scraper(new Config);
+ $grabber->setUrl($url);
+ $grabber->execute();
+
+ print_r(Logger::getMessages());
+ echo "============= CONTENT ================\n";
+ echo $grabber->getRelevantContent().PHP_EOL;
+ echo "============= FILTERED ================\n";
+ echo $grabber->getFilteredContent().PHP_EOL;
+}
+
+function fetch_favicon($url)
+{
+ $favicon = new Favicon();
+ echo $favicon->find($url) . PHP_EOL;
+}
+
+// Parse command line arguments
+if ($argc === 4) {
+ switch ($argv[1]) {
+ case 'item':
+ dump_item($argv[2], $argv[3]);
+ die;
+ case 'nofilter':
+ nofilter_item($argv[2], $argv[3]);
+ die;
+ }
+} else if ($argc === 3) {
+ switch ($argv[1]) {
+ case 'feed':
+ dump_feed($argv[2]);
+ die;
+ case 'debug':
+ debug_feed($argv[2]);
+ die;
+ case 'grabber':
+ grabber($argv[2]);
+ die;
+ case 'favicon':
+ fetch_favicon($argv[2]);
+ die;
+ }
+}
+
+printf("Usage:\n");
+printf("%s feed \n", $argv[0]);
+printf("%s debug \n", $argv[0]);
+printf("%s item \n", $argv[0]);
+printf("%s nofilter \n", $argv[0]);
+printf("%s grabber \n", $argv[0]);
+printf("%s favicon \n", $argv[0]);
diff --git a/vendor/paragonie/random_compat/CHANGELOG.md b/vendor/paragonie/random_compat/CHANGELOG.md
new file mode 100644
index 00000000..247deace
--- /dev/null
+++ b/vendor/paragonie/random_compat/CHANGELOG.md
@@ -0,0 +1,260 @@
+### Version 2.0.2 - 2016-04-03
+
+Added a consistency check (discovered by Taylor Hornby in his
+[PHP encryption library](https://github.com/defuse/php-encryption)). It
+wasn't likely causing any trouble for us.
+
+### Version 2.0.1 - 2016-03-18
+
+Update comment in random.php
+
+### Version 2.0.0 - 2016-03-18
+
+Due to downstream errors, the OpenSSL removal now belongs in version
+2.0.0.
+
+### Version 1.3.1 - 2016-03-18
+
+* Add more possible values to `open_baseir` check.
+
+### Version 1.3.0 - 2016-03-17
+
+* Removed `openssl_random_pseudo_bytes()` entirely. If you are using
+ random_compat in PHP on a Unix-like OS but cannot access
+ `/dev/urandom`, version 1.3+ will throw an `Exception`. If you want to
+ trust OpenSSL, feel free to write your own fallback code. e.g.
+
+ ```php
+ try {
+ $bytes = random_bytes(32);
+ } catch (Exception $ex) {
+ $strong = false;
+ $bytes = openssl_random_pseudo_bytes(32, $strong);
+ if (!$strong) {
+ throw $ex;
+ }
+ }
+ ```
+
+### Version 1.2.2 - 2016-03-11
+
+* To prevent applications from hanging, if `/dev/urandom` is not
+ accessible to PHP, skip mcrypt (which just fails before giving OpenSSL
+ a chance and was morally equivalent to not offering OpenSSL at all).
+
+### Version 1.2.1 - 2016-02-29
+
+* PHP 5.6.10 - 5.6.12 will hang when mcrypt is used on Unix-based operating
+ systems ([PHP bug 69833](https://bugs.php.net/bug.php?id=69833)). If you are
+ running one of these versions, please upgrade (or make sure `/dev/urandom` is
+ readable) otherwise you're relying on OpenSSL.
+
+### Version 1.2.0 - 2016-02-05
+
+* Whitespace and other cosmetic changes
+* Added a changelog.
+* We now ship with a command line utility to build a PHP Archive from the
+ command line.
+
+ Every time we publish a new release, we will also upload a .phar
+ to Github. Our public key is signed by our GPG key.
+
+### Version 1.1.6 - 2016-01-29
+
+* Eliminate `open_basedir` warnings by detecting this configuration setting.
+ (Thanks [@oucil](https://github.com/oucil) for reporting this.)
+* Added install instructions to the README.
+* Documentation cleanup (there is, in fact, no `MCRYPT_CREATE_IV` constant, I
+ meant to write `MCRYPT_DEV_URANDOM`)
+
+### Version 1.1.5 - 2016-01-06
+
+Prevent fatal errors on platforms with older versions of libsodium.
+
+### Version 1.1.4 - 2015-12-10
+
+Thanks [@narfbg](https://github.com/narfbg) for [critiquing the previous patch](https://github.com/paragonie/random_compat/issues/79#issuecomment-163590589)
+and suggesting a fix.
+
+### Version 1.1.3 - 2015-12-09
+
+The test for COM in disabled_classes is now case-insensitive.
+
+### Version 1.1.2 - 2015-12-09
+
+Don't instantiate COM if it's a disabled class. Removes the E_WARNING on Windows.
+
+### Version 1.1.1 - 2015-11-30
+
+Fix a performance issue with `/dev/urandom` buffering.
+
+### Version 1.1.0 - 2015-11-09
+
+Fix performance issues with ancient versions of PHP on Windows, but dropped
+support for PHP < 5.4.1 without mcrypt on Windows 7+ in the process. Since this
+ is a BC break, semver dictates a minor version bump.
+
+### Version 1.0.10 - 2015-10-23
+
+* Avoid a performance killer with OpenSSL on Windows PHP 5.3.0 - 5.3.3 that was
+ affecting [WordPress users](https://core.trac.wordpress.org/ticket/34409).
+* Use `$var = null` instead of `unset($var)` to avoid triggering the garbage
+ collector and slowing things down.
+
+### Version 1.0.9 - 2015-10-20
+
+There is an outstanding issue `mcrypt_create_iv()` and PHP 7's `random_bytes()`
+on Windows reported by [@nicolas-grekas](https://github.com/nicolas-grekas) caused by `proc_open()` and environment
+variable handling (discovered by Appveyor when developing Symfony).
+
+Since the break is consistent, it's not our responsibility to fix it, but we
+should fail the same way PHP 7 will (i.e. throw an `Exception` rather than raise
+an error and then throw an `Exception`).
+
+### Version 1.0.8 - 2015-10-18
+
+* Fix usability issues with Windows (`new COM('CAPICOM.Utilities.1')` is not
+ always available).
+* You can now test all the possible drivers by running `phpunit.sh each` in the
+ `tests` directory.
+
+### Version 1.0.7 - 2015-10-16
+
+Several large integer handling bugfixes were contributed by [@oittaa](https://github.com/oittaa).
+
+### Version 1.0.6 - 2015-10-15
+
+Don't let the version number fool you, this was a pretty significant change.
+
+1. Added support for ext-libsodium, if it exists on the system. This is morally
+ equivalent to adding `getrandom(2)` support without having to expose the
+ syscall interface in PHP-land.
+2. Relaxed open_basedir restrictions. In previous versions, if open_basedir was
+ set, PHP wouldn't even try to read from `/dev/urandom`. Now it will still do
+ so if you can.
+3. Fixed integer casting inconsistencies between random_compat and PHP 7.
+4. Handle edge cases where an integer overflow turns one of the parameters into
+ a float.
+
+One change that we discussed was making `random_bytes()` and `random_int()`
+strict typed; meaning you could *only* pass integers to either function. While
+most veteran programmers are probably only doing this already (we strongly
+encourage it), it wouldn't be consistent with how these functions behave in PHP
+7. Please use these functions responsibly.
+
+We've had even more of the PHP community involved in this release; the
+contributors list has been updated. If I forgot anybody, I promise you it's not
+because your contributions (either code or ideas) aren't valued, it's because
+I'm a bit overloaded with information at the moment. Please let me know
+immediately and I will correct my oversight.
+
+Thanks everyone for helping make random_compat better.
+
+### Version 1.0.5 - 2015-10-08
+
+Got rid of the methods in the `Throwable` interface, which was causing problems
+on PHP 5.2. While we would normally not care about 5.2 (since [5.4 and earlier are EOL'd](https://secure.php.net/supported-versions.php)),
+we do want to encourage widespread adoption (e.g. [Wordpress](https://core.trac.wordpress.org/ticket/28633)).
+
+### Version 1.0.4 - 2015-10-02
+
+Removed redundant `if()` checks, since `lib/random.php` is the entrypoint people
+should use.
+
+### Version 1.0.3 - 2015-10-02
+
+This release contains bug fixes contributed by the community.
+
+* Avoid a PHP Notice when PHP is running without the mbstring extension
+* Use a compatible version of PHPUnit for testing on older versions of PHP
+
+Although none of these bugs were outright security-affecting, updating ASAP is
+still strongly encouraged.
+
+### Version 1.0.2 - 2015-09-23
+
+Less strict input validation on `random_int()` parameters. PHP 7's `random_int()`
+accepts strings and floats that look like numbers, so we should too.
+
+Thanks [@dd32](https://github.com/@dd32) for correcting this oversight.
+
+### Version 1.0.1 - 2015-09-10
+
+Instead of throwing an Exception immediately on insecure platforms, only do so
+when `random_bytes()` is invoked.
+
+### Version 1.0.0 - 2015-09-07
+
+Our API is now stable and forward-compatible with the CSPRNG features in PHP 7
+(as of 7.0.0 RC3).
+
+A lot of great people have contributed their time and expertise to make this
+compatibility library possible. That this library has reached a stable release
+is more a reflection on the community than it is on PIE.
+
+We are confident that random_compat will serve as the simplest and most secure
+CSPRNG interface available for PHP5 projects.
+
+### Version 0.9.7 (pre-release) - 2015-09-01
+
+An attempt to achieve compatibility with Error/TypeError in the RFC.
+
+This should be identical to 1.0.0 sans any last-minute changes or performance enhancements.
+
+### Version 0.9.6 (pre-release) - 2015-08-06
+
+* Split the implementations into their own file (for ease of auditing)
+* Corrected the file type check after `/dev/urandom` has been opened (thanks
+ [@narfbg](https://github.com/narfbg) and [@jedisct1](https://github.com/jedisct1))
+
+### Version 0.9.5 (pre-release) - 2015-07-31
+
+* Validate that `/dev/urandom` is a character device
+ * Reported by [@lokdnet](https://twitter.com/lokdnet)
+ * Investigated by [@narfbg](https://github.com/narfbg) and [frymaster](http://stackoverflow.com/users/1226810/frymaster) on [StackOverflow](http://stackoverflow.com/q/31631066/2224584)
+* Remove support for `/dev/arandom` which is an old OpenBSD feature, thanks [@jedisct1](https://github.com/jedisct1)
+* Prevent race conditions on the `filetype()` check, thanks [@jedisct1](https://github.com/jedisct1)
+* Buffer file reads to 8 bytes (performance optimization; PHP defaults to 8192 bytes)
+
+### Version 0.9.4 (pre-release) - 2015-07-27
+
+* Add logic to verify that `/dev/arandom` and `/dev/urandom` are actually devices.
+* Some clean-up in the comments
+
+### Version 0.9.3 (pre-release) - 2015-07-22
+
+Unless the Exceptions change to PHP 7 fails, this should be the last pre-release
+version. If need be, we'll make one more pre-release version with compatible
+behavior.
+
+Changes since 0.9.2:
+
+* Prioritize `/dev/arandom` and `/dev/urandom` over mcrypt.
+[@oittaa](https://github.com/oittaa) removed the -1 and +1 juggling on `$range` calculations for `random_int()`
+* Whitespace and comment clean-up, plus better variable names
+* Actually put a description in the composer.json file...
+
+### Version 0.9.2 (pre-release) - 2015-07-16
+
+* Consolidated `$range > PHP_INT_MAX` logic with `$range <= PHP_INT_MAX` (thanks
+ [@oittaa](https://github.com/oittaa) and [@CodesInChaos](https://github.com/CodesInChaos))
+* `tests/phpunit.sh` now also runs the tests with `mbstring.func_overload` and
+ `open_basedir`
+* Style consistency, whitespace cleanup, more meaningful variable names
+
+### Version 0.9.1 (pre-release) - 2015-07-09
+
+* Return random values on integer ranges > `PHP_INT_MAX` (thanks [@CodesInChaos](https://github.com/CodesInChaos))
+* Determined CSPRNG preference:
+ 1. `mcrypt_create_iv()` with `MCRYPT_DEV_URANDOM`
+ 2. `/dev/arandom`
+ 3. `/dev/urandom`
+ 4. `openssl_random_pseudo_bytes()`
+* Optimized backend selection (thanks [@lt](https://github.com/lt))
+* Fix #3 (thanks [@scottchiefbaker](https://github.com/scottchiefbaker))
+
+### Version 0.9.0 (pre-release) - 2015-07-07
+
+This should be a sane polyfill for PHP 7's `random_bytes()` and `random_int()`.
+We hesitate to call it production ready until it has received sufficient third
+party review.
\ No newline at end of file
diff --git a/vendor/paragonie/random_compat/ERRATA.md b/vendor/paragonie/random_compat/ERRATA.md
new file mode 100644
index 00000000..0561630d
--- /dev/null
+++ b/vendor/paragonie/random_compat/ERRATA.md
@@ -0,0 +1,34 @@
+## Errata (Design Decisions)
+
+### Reasoning Behind the Order of Preferred Random Data Sources
+
+The order is:
+
+ 1. `libsodium if available`
+ 2. `fread() /dev/urandom if available`
+ 3. `mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)`
+ 4. `COM('CAPICOM.Utilities.1')->GetRandom()`
+
+If libsodium is available, we get random data from it. This is the preferred
+method on all OSes, but libsodium is not very widely installed, so other
+fallbacks are available.
+
+Next, we read `/dev/urandom` (if it exists). This is the preferred file to read
+for random data for cryptographic purposes for BSD and Linux.
+
+Despite [strongly urging people not to use mcrypt in their projects](https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-re-doing-it-wrong),
+because libmcrypt is abandonware and the API puts too much responsibility on the
+implementor, we prioritize `mcrypt_create_iv()` with `MCRYPT_DEV_URANDOM` above
+the remaining implementations.
+
+The reason is simple: `mcrypt_create_iv()` is part of PHP's `ext/mcrypt` code,
+and is not part `libmcrypt`. It actually does the right thing:
+
+ * On Unix-based operating systems, it reads from `/dev/urandom`, which unlike `/dev/random`
+ is the sane and correct thing to do.
+ * On Windows, it reads from `CryptGenRandom`, which is an exclusively Windows
+ way to get random bytes.
+
+If we're on Windows and don't have access to `mcrypt`, we use `CAPICOM.Utilities.1`.
+
+As of random_compat 1.3, we no longer fall through to OpenSSL.
diff --git a/vendor/paragonie/random_compat/LICENSE b/vendor/paragonie/random_compat/LICENSE
new file mode 100644
index 00000000..45c7017d
--- /dev/null
+++ b/vendor/paragonie/random_compat/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Paragon Initiative Enterprises
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/paragonie/random_compat/README.md b/vendor/paragonie/random_compat/README.md
new file mode 100644
index 00000000..80560862
--- /dev/null
+++ b/vendor/paragonie/random_compat/README.md
@@ -0,0 +1,176 @@
+# random_compat
+
+[![Build Status](https://travis-ci.org/paragonie/random_compat.svg?branch=master)](https://travis-ci.org/paragonie/random_compat)
+[![Scrutinizer](https://scrutinizer-ci.com/g/paragonie/random_compat/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/paragonie/random_compat)
+
+PHP 5.x polyfill for `random_bytes()` and `random_int()` created and maintained
+by [Paragon Initiative Enterprises](https://paragonie.com).
+
+Although this library *should* function in earlier versions of PHP, we will only
+consider issues relevant to [supported PHP versions](https://secure.php.net/supported-versions.php).
+**If you are using an unsupported version of PHP, please upgrade as soon as possible.**
+
+## Important
+
+Although this library has been examined by some security experts in the PHP
+community, there will always be a chance that we overlooked something. Please
+ask your favorite trusted hackers to hammer it for implementation errors and
+bugs before even thinking about deploying it in production.
+
+**Do not use the master branch, use a [stable release](https://github.com/paragonie/random_compat/releases/latest).**
+
+For the background of this library, please refer to our blog post on
+[Generating Random Integers and Strings in PHP](https://paragonie.com/blog/2015/07/how-safely-generate-random-strings-and-integers-in-php).
+
+### Usability Notice
+
+If PHP cannot safely generate random data, this library will throw an `Exception`.
+It will never fall back to insecure random data. If this keeps happening, upgrade
+to a newer version of PHP immediately.
+
+## Installing
+
+**With [Composer](https://getcomposer.org):**
+
+ composer require paragonie/random_compat
+
+**Signed PHP Archive:**
+
+As of version 1.2.0, we also ship an ECDSA-signed PHP Archive with each stable
+release on Github.
+
+1. Download [the `.phar`, `.phar.pubkey`, and `.phar.pubkey.asc`](https://github.com/paragonie/random_compat/releases/latest) files.
+2. (**Recommended** but not required) Verify the PGP signature of `.phar.pubkey`
+ (contained within the `.asc` file) using the [PGP public key for Paragon Initiative Enterprises](https://paragonie.com/static/gpg-public-key.txt).
+3. Extract both `.phar` and `.phar.pubkey` files to the same directory.
+4. `require_once "/path/to/random_compat.phar";`
+5. When a new version is released, you only need to replace the `.phar` file;
+ the `.pubkey` will not change (unless our signing key is ever compromised).
+
+**Manual Installation:**
+
+1. Download [a stable release](https://github.com/paragonie/random_compat/releases/latest).
+2. Extract the files into your project.
+3. `require_once "/path/to/random_compat/lib/random.php";`
+
+## Usage
+
+This library exposes the [CSPRNG functions added in PHP 7](https://secure.php.net/manual/en/ref.csprng.php)
+for use in PHP 5 projects. Their behavior should be identical.
+
+### Generate a string of random bytes
+
+```php
+try {
+ $string = random_bytes(32);
+} catch (TypeError $e) {
+ // Well, it's an integer, so this IS unexpected.
+ die("An unexpected error has occurred");
+} catch (Error $e) {
+ // This is also unexpected because 32 is a reasonable integer.
+ die("An unexpected error has occurred");
+} catch (Exception $e) {
+ // If you get this message, the CSPRNG failed hard.
+ die("Could not generate a random string. Is our OS secure?");
+}
+
+var_dump(bin2hex($string));
+// string(64) "5787c41ae124b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2eeac6f"
+```
+
+### Generate a random integer between two given integers (inclusive)
+
+```php
+try {
+ $int = random_int(0,255);
+
+} catch (TypeError $e) {
+ // Well, it's an integer, so this IS unexpected.
+ die("An unexpected error has occurred");
+} catch (Error $e) {
+ // This is also unexpected because 0 and 255 are both reasonable integers.
+ die("An unexpected error has occurred");
+} catch (Exception $e) {
+ // If you get this message, the CSPRNG failed hard.
+ die("Could not generate a random string. Is our OS secure?");
+}
+
+var_dump($int);
+// int(47)
+```
+
+### Exception handling
+
+When handling exceptions and errors you must account for differences between
+PHP 5 and PHP7.
+
+The differences:
+
+* Catching `Error` works, so long as it is caught before `Exception`.
+* Catching `Exception` has different behavior, without previously catching `Error`.
+* There is *no* portable way to catch all errors/exceptions.
+
+#### Our recommendation
+
+**Always** catch `Error` before `Exception`.
+
+#### Example
+
+```php
+try {
+ return random_int(1, $userInput);
+} catch (TypeError $e) {
+ // This is okay, so long as `Error` is caught before `Exception`.
+ throw new Exception('Please enter a number!');
+} catch (Error $e) {
+ // This is required, if you do not need to do anything just rethrow.
+ throw $e;
+} catch (Exception $e) {
+ // This is optional and maybe omitted if you do not want to handle errors
+ // during generation.
+ throw new InternalServerErrorException(
+ 'Oops, our server is bust and cannot generate any random data.',
+ 500,
+ $e
+ );
+}
+```
+
+## Contributors
+
+This project would not be anywhere near as excellent as it is today if it
+weren't for the contributions of the following individuals:
+
+* [@AndrewCarterUK (Andrew Carter)](https://github.com/AndrewCarterUK)
+* [@asgrim (James Titcumb)](https://github.com/asgrim)
+* [@bcremer (Benjamin Cremer)](https://github.com/bcremer)
+* [@CodesInChaos (Christian Winnerlein)](https://github.com/CodesInChaos)
+* [@chriscct7 (Chris Christoff)](https://github.com/chriscct7)
+* [@cs278 (Chris Smith)](https://github.com/cs278)
+* [@cweagans (Cameron Eagans)](https://github.com/cweagans)
+* [@dd32 (Dion Hulse)](https://github.com/dd32)
+* [@geggleto (Glenn Eggleton)](https://github.com/geggleto)
+* [@ircmaxell (Anthony Ferrara)](https://github.com/ircmaxell)
+* [@jedisct1 (Frank Denis)](https://github.com/jedisct1)
+* [@juliangut (Julián Gutiérrez)](https://github.com/juliangut)
+* [@kelunik (Niklas Keller)](https://github.com/kelunik)
+* [@lt (Leigh)](https://github.com/lt)
+* [@MasonM (Mason Malone)](https://github.com/MasonM)
+* [@mmeyer2k (Michael M)](https://github.com/mmeyer2k)
+* [@narfbg (Andrey Andreev)](https://github.com/narfbg)
+* [@nicolas-grekas (Nicolas Grekas)](https://github.com/nicolas-grekas)
+* [@oittaa](https://github.com/oittaa)
+* [@oucil (Kevin Farley)](https://github.com/oucil)
+* [@redragonx (Stephen Chavez)](https://github.com/redragonx)
+* [@rchouinard (Ryan Chouinard)](https://github.com/rchouinard)
+* [@SammyK (Sammy Kaye Powers)](https://github.com/SammyK)
+* [@scottchiefbaker (Scott Baker)](https://github.com/scottchiefbaker)
+* [@skyosev (Stoyan Kyosev)](https://github.com/skyosev)
+* [@stof (Christophe Coevoet)](https://github.com/stof)
+* [@teohhanhui (Teoh Han Hui)](https://github.com/teohhanhui)
+* [@tom-- (Tom Worster)](https://github.com/tom--)
+* [@tsyr2ko](https://github.com/tsyr2ko)
+* [@trowski (Aaron Piotrowski)](https://github.com/trowski)
+* [@twistor (Chris Lepannen)](https://github.com/twistor)
+* [@voku (Lars Moelleken)](https://github.com/voku)
+* [@xabbuh (Christian Flothmann)](https://github.com/xabbuh)
diff --git a/vendor/paragonie/random_compat/SECURITY.md b/vendor/paragonie/random_compat/SECURITY.md
new file mode 100644
index 00000000..8f731b38
--- /dev/null
+++ b/vendor/paragonie/random_compat/SECURITY.md
@@ -0,0 +1,108 @@
+# An Invitation to Security Researchers
+
+Every company says they take security "very seriously." Rather than bore anyone
+with banal boilerplate, here are some quick answers followed by detailed
+elaboration. If you have any questions about our policies, please email them to
+`scott@paragonie.com`.
+
+## Quick Answers
+
+* There is no compulsion to disclose vulnerabilities privately, but we
+ appreciate a head's up.
+* `security@paragonie.com` will get your reports to the right person. Our GPG
+ fingerprint, should you decide to encrypt your report, is
+ `7F52 D5C6 1D12 55C7 3136 2E82 6B97 A1C2 8264 04DA`.
+
+* **YES**, we will reward security researchers who disclose vulnerabilities in
+ our software.
+* In most cases, **No Proof-of-Concept Required.**
+
+## How to Report a Security Bug to Paragon Initiative Enterprises
+
+### There is no compulsion to disclose privately.
+
+We believe vulnerability disclosure style is a personal choice and enjoy working
+with a diverse community. We understand and appreciate the importance of Full
+Disclosure in the history and practice of security research.
+
+We would *like* to know about high-severity bugs before they become public
+knowledge, so we can fix them in a timely manner, but **we do not believe in
+threatening researchers or trying to enforce vulnerability embargoes**.
+
+Ultimately, if you discover a security-affecting vulnerability, what you do with
+it is your choice. We would like to work with people, and to celebrate and
+reward their skill, experience, and dedication. We appreciate being informed of
+our mistakes so we can learn from them and build a better product. Our goal is
+to empower the community.
+
+### Where to Send Security Vulnerabilities
+
+Our security email address is `security@paragonie.com`. Also feel free to open a
+new issue on Github if you want to disclose publicly.
+
+```
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG
+
+mQENBFUgwRUBCADcIpqNwyYc5UmY/tpx1sF/rQ3knR1YNXYZThzFV+Gmqhp1fDH5
+qBs9foh1xwI6O7knWmQngnf/nBumI3x6xj7PuOdEZUh2FwCG/VWnglW8rKmoHzHA
+ivjiu9SLnPIPAgHSHeh2XD7q3Ndm3nenbjAiRFNl2iXcwA2cTQp9Mmfw9vVcw0G0
+z1o0G3s8cC8ZS6flFySIervvfSRWj7A1acI5eE3+AH/qXJRdEJ+9J8OB65p1JMfk
+6+fWgOB1XZxMpz70S0rW6IX38WDSRhEK2fXyZJAJjyt+YGuzjZySNSoQR/V6vNYn
+syrNPCJ2i5CgZQxAkyBBcr7koV9RIhPRzct/ABEBAAG0IVNlY3VyaXR5IDxzZWN1
+cml0eUBwYXJhZ29uaWUuY29tPokBOQQTAQIAIwUCVSDBFQIbAwcLCQgHAwIBBhUI
+AgkKCwQWAgMBAh4BAheAAAoJEGuXocKCZATat2YIAIoejNFEQ2c1iaOEtSuB7Pn/
+WLbsDsHNLDKOV+UnfaCjv/vL7D+5NMChFCi2frde/NQb2TsjqmIH+V+XbnJtlrXD
+Vj7yvMVal+Jqjwj7v4eOEWcKVcFZk+9cfUgh7t92T2BMX58RpgZF0IQZ6Z1R3FfC
+9Ub4X6ykW+te1q0/4CoRycniwmlQi6iGSr99LQ5pfJq2Qlmz/luTZ0UX0h575T7d
+cp2T1sX/zFRk/fHeANWSksipdDBjAXR7NMnYZgw2HghEdFk/xRDY7K1NRWNZBf05
+WrMHmh6AIVJiWZvI175URxEe268hh+wThBhXQHMhFNJM1qPIuzb4WogxM3UUD7m5
+AQ0EVSDBFQEIALNkpzSuJsHAHh79sc0AYWztdUe2MzyofQbbOnOCpWZebYsC3EXU
+335fIg59k0m6f+O7GmEZzzIv5v0i99GS1R8CJm6FvhGqtH8ZqmOGbc71WdJSiNVE
+0kpQoJlVzRbig6ZyyjzrggbM1eh5OXOk5pw4+23FFEdw7JWU0HJS2o71r1hwp05Z
+vy21kcUEobz/WWQQyGS0Neo7PJn+9KS6wOxXul/UE0jct/5f7KLMdWMJ1VgniQmm
+hjvkHLPSICteqCI04RfcmMseW9gueHQXeUu1SNIvsWa2MhxjeBej3pDnrZWszKwy
+gF45GO9/v4tkIXNMy5J1AtOyRgQ3IUMqp8EAEQEAAYkBHwQYAQIACQUCVSDBFQIb
+DAAKCRBrl6HCgmQE2jnIB/4/xFz8InpM7eybnBOAir3uGcYfs3DOmaKn7qWVtGzv
+rKpQPYnVtlU2i6Z5UO4c4jDLT/8Xm1UDz3Lxvqt4xCaDwJvBZexU5BMK8l5DvOzH
+6o6P2L1UDu6BvmPXpVZz7/qUhOnyf8VQg/dAtYF4/ax19giNUpI5j5o5mX5w80Rx
+qSXV9NdSL4fdjeG1g/xXv2luhoV53T1bsycI3wjk/x5tV+M2KVhZBvvuOm/zhJje
+oLWp0saaESkGXIXqurj6gZoujJvSvzl0n9F9VwqMEizDUfrXgtD1siQGhP0sVC6q
+ha+F/SAEJ0jEquM4TfKWWU2S5V5vgPPpIQSYRnhQW4b1
+=xJPW
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
+### We Will Reward Security Researchers
+
+**This process has not been formalized; nor have dollar amounts been
+discussed.**
+
+However, if you report a valid security-affecting bug, we will compensate you
+for the time spent finding the vulnerability and reward you for being a good
+neighbor.
+
+#### What does a "valid" bug mean?
+
+There are two sides to this:
+
+1. Some have spammed projects with invalid bug reports hoping to collect
+ bounties for pressing a button and running an automated analysis tool. This
+ is not cool.
+2. There is a potential for the developers of a project to declare all security
+ bug reports as invalid to save money.
+
+Our team members have an established history of reporting vulnerabilities to
+large open source projects. **We aren't in the business of ripping people off.**
+When in doubt, our policy is to err on the side of generosity.
+
+### No Proof-of-Concept Required
+
+We might ask for one if we feel we do not understand some of the details
+pertaining to a specific vulnerability. We certainly appreciate them if you
+include them in your report, but we believe **the burden lies with the developer
+to prove their software *is* secure** rather than with the researcher to prove
+that it isn't.
+
+In our experience, most bugs are simpler to fix than they are to exploit.
+
diff --git a/vendor/paragonie/random_compat/build-phar.sh b/vendor/paragonie/random_compat/build-phar.sh
new file mode 100755
index 00000000..b4a5ba31
--- /dev/null
+++ b/vendor/paragonie/random_compat/build-phar.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )
+
+php -dphar.readonly=0 "$basedir/other/build_phar.php" $*
\ No newline at end of file
diff --git a/vendor/paragonie/random_compat/composer.json b/vendor/paragonie/random_compat/composer.json
new file mode 100644
index 00000000..d363f4c8
--- /dev/null
+++ b/vendor/paragonie/random_compat/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "paragonie/random_compat",
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "random",
+ "pseudorandom"
+ ],
+ "license": "MIT",
+ "type": "library",
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/paragonie/random_compat/issues",
+ "email": "info@paragonie.com",
+ "source": "https://github.com/paragonie/random_compat"
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "autoload": {
+ "files": ["lib/random.php"]
+ }
+}
diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey
new file mode 100644
index 00000000..eb50ebfc
--- /dev/null
+++ b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey
@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
+pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
++h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
+-----END PUBLIC KEY-----
diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc
new file mode 100644
index 00000000..6a1d7f30
--- /dev/null
+++ b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2.0.22 (MingW32)
+
+iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
+QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
+1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
+NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
+NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
+JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
+=B6+8
+-----END PGP SIGNATURE-----
diff --git a/vendor/paragonie/random_compat/lib/byte_safe_strings.php b/vendor/paragonie/random_compat/lib/byte_safe_strings.php
new file mode 100644
index 00000000..dec5d306
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/byte_safe_strings.php
@@ -0,0 +1,181 @@
+ RandomCompat_strlen($binary_string)) {
+ return false;
+ }
+
+ return mb_substr($binary_string, $start, $length, '8bit');
+ }
+
+ } else {
+
+ /**
+ * substr() implementation that isn't brittle to mbstring.func_overload
+ *
+ * This version just uses the default substr()
+ *
+ * @param string $binary_string
+ * @param int $start
+ * @param int $length (optional)
+ *
+ * @throws TypeError
+ *
+ * @return string
+ */
+ function RandomCompat_substr($binary_string, $start, $length = null)
+ {
+ if (!is_string($binary_string)) {
+ throw new TypeError(
+ 'RandomCompat_substr(): First argument should be a string'
+ );
+ }
+
+ if (!is_int($start)) {
+ throw new TypeError(
+ 'RandomCompat_substr(): Second argument should be an integer'
+ );
+ }
+
+ if ($length !== null) {
+ if (!is_int($length)) {
+ throw new TypeError(
+ 'RandomCompat_substr(): Third argument should be an integer, or omitted'
+ );
+ }
+
+ return substr($binary_string, $start, $length);
+ }
+
+ return substr($binary_string, $start);
+ }
+ }
+}
diff --git a/vendor/paragonie/random_compat/lib/cast_to_int.php b/vendor/paragonie/random_compat/lib/cast_to_int.php
new file mode 100644
index 00000000..f441c5d9
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/cast_to_int.php
@@ -0,0 +1,71 @@
+ operators might accidentally let a float
+ * through.
+ *
+ * @param int|float $number The number we want to convert to an int
+ * @param boolean $fail_open Set to true to not throw an exception
+ *
+ * @return int (or float if $fail_open)
+ *
+ * @throws TypeError
+ */
+ function RandomCompat_intval($number, $fail_open = false)
+ {
+ if (is_numeric($number)) {
+ $number += 0;
+ }
+
+ if (
+ is_float($number)
+ &&
+ $number > ~PHP_INT_MAX
+ &&
+ $number < PHP_INT_MAX
+ ) {
+ $number = (int) $number;
+ }
+
+ if (is_int($number) || $fail_open) {
+ return $number;
+ }
+
+ throw new TypeError(
+ 'Expected an integer.'
+ );
+ }
+}
diff --git a/vendor/paragonie/random_compat/lib/error_polyfill.php b/vendor/paragonie/random_compat/lib/error_polyfill.php
new file mode 100644
index 00000000..57cfefdc
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/error_polyfill.php
@@ -0,0 +1,42 @@
+GetRandom()
+ * 5. openssl_random_pseudo_bytes() (absolute last resort)
+ *
+ * See ERRATA.md for our reasoning behind this particular order
+ */
+ if (extension_loaded('libsodium')) {
+ // See random_bytes_libsodium.php
+ if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) {
+ require_once $RandomCompatDIR.'/random_bytes_libsodium.php';
+ } elseif (method_exists('Sodium', 'randombytes_buf')) {
+ require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php';
+ }
+ }
+
+ /**
+ * Reading directly from /dev/urandom:
+ */
+ if (DIRECTORY_SEPARATOR === '/') {
+ // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
+ // way to exclude Windows.
+ $RandomCompatUrandom = true;
+ $RandomCompat_basedir = ini_get('open_basedir');
+
+ if (!empty($RandomCompat_basedir)) {
+ $RandomCompat_open_basedir = explode(
+ PATH_SEPARATOR,
+ strtolower($RandomCompat_basedir)
+ );
+ $RandomCompatUrandom = (array() !== array_intersect(
+ array('/dev', '/dev/', '/dev/urandom'),
+ $RandomCompat_open_basedir
+ ));
+ $RandomCompat_open_basedir = null;
+ }
+
+ if (
+ !function_exists('random_bytes')
+ &&
+ $RandomCompatUrandom
+ &&
+ @is_readable('/dev/urandom')
+ ) {
+ // Error suppression on is_readable() in case of an open_basedir
+ // or safe_mode failure. All we care about is whether or not we
+ // can read it at this point. If the PHP environment is going to
+ // panic over trying to see if the file can be read in the first
+ // place, that is not helpful to us here.
+
+ // See random_bytes_dev_urandom.php
+ require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php';
+ }
+ // Unset variables after use
+ $RandomCompat_basedir = null;
+ } else {
+ $RandomCompatUrandom = false;
+ }
+
+ /**
+ * mcrypt_create_iv()
+ */
+ if (
+ !function_exists('random_bytes')
+ &&
+ PHP_VERSION_ID >= 50307
+ &&
+ extension_loaded('mcrypt')
+ &&
+ (DIRECTORY_SEPARATOR !== '/' || $RandomCompatUrandom)
+ ) {
+ // Prevent this code from hanging indefinitely on non-Windows;
+ // see https://bugs.php.net/bug.php?id=69833
+ if (
+ DIRECTORY_SEPARATOR !== '/' ||
+ (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
+ ) {
+ // See random_bytes_mcrypt.php
+ require_once $RandomCompatDIR.'/random_bytes_mcrypt.php';
+ }
+ }
+ $RandomCompatUrandom = null;
+
+ if (
+ !function_exists('random_bytes')
+ &&
+ extension_loaded('com_dotnet')
+ &&
+ class_exists('COM')
+ ) {
+ $RandomCompat_disabled_classes = preg_split(
+ '#\s*,\s*#',
+ strtolower(ini_get('disable_classes'))
+ );
+
+ if (!in_array('com', $RandomCompat_disabled_classes)) {
+ try {
+ $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
+ if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
+ // See random_bytes_com_dotnet.php
+ require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php';
+ }
+ } catch (com_exception $e) {
+ // Don't try to use it.
+ }
+ }
+ $RandomCompat_disabled_classes = null;
+ $RandomCompatCOMtest = null;
+ }
+
+ /**
+ * throw new Exception
+ */
+ if (!function_exists('random_bytes')) {
+ /**
+ * We don't have any more options, so let's throw an exception right now
+ * and hope the developer won't let it fail silently.
+ */
+ function random_bytes($length)
+ {
+ throw new Exception(
+ 'There is no suitable CSPRNG installed on your system'
+ );
+ }
+ }
+ }
+
+ if (!function_exists('random_int')) {
+ require_once $RandomCompatDIR.'/random_int.php';
+ }
+
+ $RandomCompatDIR = null;
+}
diff --git a/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php
new file mode 100644
index 00000000..34228254
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php
@@ -0,0 +1,81 @@
+GetRandom($bytes, 0));
+ if (RandomCompat_strlen($buf) >= $bytes) {
+ /**
+ * Return our random entropy buffer here:
+ */
+ return RandomCompat_substr($buf, 0, $bytes);
+ }
+ ++$execCount;
+ } while ($execCount < $bytes);
+
+ /**
+ * If we reach here, PHP has failed us.
+ */
+ throw new Exception(
+ 'Could not gather sufficient random data'
+ );
+}
diff --git a/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php
new file mode 100644
index 00000000..db93b075
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php
@@ -0,0 +1,148 @@
+ 0);
+
+ /**
+ * Is our result valid?
+ */
+ if ($buf !== false) {
+ if (RandomCompat_strlen($buf) === $bytes) {
+ /**
+ * Return our random entropy buffer here:
+ */
+ return $buf;
+ }
+ }
+ }
+
+ /**
+ * If we reach here, PHP has failed us.
+ */
+ throw new Exception(
+ 'Error reading from source device'
+ );
+}
diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php
new file mode 100644
index 00000000..f802d4e1
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php
@@ -0,0 +1,86 @@
+ 2147483647) {
+ $buf = '';
+ for ($i = 0; $i < $bytes; $i += 1073741824) {
+ $n = ($bytes - $i) > 1073741824
+ ? 1073741824
+ : $bytes - $i;
+ $buf .= \Sodium\randombytes_buf($n);
+ }
+ } else {
+ $buf = \Sodium\randombytes_buf($bytes);
+ }
+
+ if ($buf !== false) {
+ if (RandomCompat_strlen($buf) === $bytes) {
+ return $buf;
+ }
+ }
+
+ /**
+ * If we reach here, PHP has failed us.
+ */
+ throw new Exception(
+ 'Could not gather sufficient random data'
+ );
+}
diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php
new file mode 100644
index 00000000..44fddbf6
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php
@@ -0,0 +1,86 @@
+ 2147483647) {
+ $buf = '';
+ for ($i = 0; $i < $bytes; $i += 1073741824) {
+ $n = ($bytes - $i) > 1073741824
+ ? 1073741824
+ : $bytes - $i;
+ $buf .= Sodium::randombytes_buf($n);
+ }
+ } else {
+ $buf = Sodium::randombytes_buf($bytes);
+ }
+
+ if ($buf !== false) {
+ if (RandomCompat_strlen($buf) === $bytes) {
+ return $buf;
+ }
+ }
+
+ /**
+ * If we reach here, PHP has failed us.
+ */
+ throw new Exception(
+ 'Could not gather sufficient random data'
+ );
+}
diff --git a/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php
new file mode 100644
index 00000000..7ac9d910
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php
@@ -0,0 +1,76 @@
+ operators might accidentally let a float
+ * through.
+ */
+
+ try {
+ $min = RandomCompat_intval($min);
+ } catch (TypeError $ex) {
+ throw new TypeError(
+ 'random_int(): $min must be an integer'
+ );
+ }
+
+ try {
+ $max = RandomCompat_intval($max);
+ } catch (TypeError $ex) {
+ throw new TypeError(
+ 'random_int(): $max must be an integer'
+ );
+ }
+
+ /**
+ * Now that we've verified our weak typing system has given us an integer,
+ * let's validate the logic then we can move forward with generating random
+ * integers along a given range.
+ */
+ if ($min > $max) {
+ throw new Error(
+ 'Minimum value must be less than or equal to the maximum value'
+ );
+ }
+
+ if ($max === $min) {
+ return $min;
+ }
+
+ /**
+ * Initialize variables to 0
+ *
+ * We want to store:
+ * $bytes => the number of random bytes we need
+ * $mask => an integer bitmask (for use with the &) operator
+ * so we can minimize the number of discards
+ */
+ $attempts = $bits = $bytes = $mask = $valueShift = 0;
+
+ /**
+ * At this point, $range is a positive number greater than 0. It might
+ * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
+ * a float and we will lose some precision.
+ */
+ $range = $max - $min;
+
+ /**
+ * Test for integer overflow:
+ */
+ if (!is_int($range)) {
+
+ /**
+ * Still safely calculate wider ranges.
+ * Provided by @CodesInChaos, @oittaa
+ *
+ * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
+ *
+ * We use ~0 as a mask in this case because it generates all 1s
+ *
+ * @ref https://eval.in/400356 (32-bit)
+ * @ref http://3v4l.org/XX9r5 (64-bit)
+ */
+ $bytes = PHP_INT_SIZE;
+ $mask = ~0;
+
+ } else {
+
+ /**
+ * $bits is effectively ceil(log($range, 2)) without dealing with
+ * type juggling
+ */
+ while ($range > 0) {
+ if ($bits % 8 === 0) {
+ ++$bytes;
+ }
+ ++$bits;
+ $range >>= 1;
+ $mask = $mask << 1 | 1;
+ }
+ $valueShift = $min;
+ }
+
+ /**
+ * Now that we have our parameters set up, let's begin generating
+ * random integers until one falls between $min and $max
+ */
+ do {
+ /**
+ * The rejection probability is at most 0.5, so this corresponds
+ * to a failure probability of 2^-128 for a working RNG
+ */
+ if ($attempts > 128) {
+ throw new Exception(
+ 'random_int: RNG is broken - too many rejections'
+ );
+ }
+
+ /**
+ * Let's grab the necessary number of random bytes
+ */
+ $randomByteString = random_bytes($bytes);
+ if ($randomByteString === false) {
+ throw new Exception(
+ 'Random number generator failure'
+ );
+ }
+
+ /**
+ * Let's turn $randomByteString into an integer
+ *
+ * This uses bitwise operators (<< and |) to build an integer
+ * out of the values extracted from ord()
+ *
+ * Example: [9F] | [6D] | [32] | [0C] =>
+ * 159 + 27904 + 3276800 + 201326592 =>
+ * 204631455
+ */
+ $val = 0;
+ for ($i = 0; $i < $bytes; ++$i) {
+ $val |= ord($randomByteString[$i]) << ($i * 8);
+ }
+
+ /**
+ * Apply mask
+ */
+ $val &= $mask;
+ $val += $valueShift;
+
+ ++$attempts;
+ /**
+ * If $val overflows to a floating point number,
+ * ... or is larger than $max,
+ * ... or smaller than $min,
+ * then try again.
+ */
+ } while (!is_int($val) || $val > $max || $val < $min);
+
+ return (int) $val;
+}
diff --git a/vendor/paragonie/random_compat/other/build_phar.php b/vendor/paragonie/random_compat/other/build_phar.php
new file mode 100644
index 00000000..70ef4b2e
--- /dev/null
+++ b/vendor/paragonie/random_compat/other/build_phar.php
@@ -0,0 +1,57 @@
+buildFromDirectory(dirname(__DIR__).'/lib');
+rename(
+ dirname(__DIR__).'/lib/index.php',
+ dirname(__DIR__).'/lib/random.php'
+);
+
+/**
+ * If we pass an (optional) path to a private key as a second argument, we will
+ * sign the Phar with OpenSSL.
+ *
+ * If you leave this out, it will produce an unsigned .phar!
+ */
+if ($argc > 1) {
+ if (!@is_readable($argv[1])) {
+ echo 'Could not read the private key file:', $argv[1], "\n";
+ exit(255);
+ }
+ $pkeyFile = file_get_contents($argv[1]);
+
+ $private = openssl_get_privatekey($pkeyFile);
+ if ($private !== false) {
+ $pkey = '';
+ openssl_pkey_export($private, $pkey);
+ $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
+
+ /**
+ * Save the corresponding public key to the file
+ */
+ if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
+ $details = openssl_pkey_get_details($private);
+ file_put_contents(
+ $dist.'/random_compat.phar.pubkey',
+ $details['key']
+ );
+ }
+ } else {
+ echo 'An error occurred reading the private key from OpenSSL.', "\n";
+ exit(255);
+ }
+}
diff --git a/vendor/pimple/pimple/.gitignore b/vendor/pimple/pimple/.gitignore
new file mode 100644
index 00000000..c089b095
--- /dev/null
+++ b/vendor/pimple/pimple/.gitignore
@@ -0,0 +1,3 @@
+phpunit.xml
+composer.lock
+/vendor/
diff --git a/vendor/pimple/pimple/.travis.yml b/vendor/pimple/pimple/.travis.yml
new file mode 100644
index 00000000..5f8bb7c9
--- /dev/null
+++ b/vendor/pimple/pimple/.travis.yml
@@ -0,0 +1,32 @@
+language: php
+
+env:
+ matrix:
+ - PIMPLE_EXT=no
+ - PIMPLE_EXT=yes
+ global:
+ - REPORT_EXIT_STATUS=1
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - composer self-update
+ - COMPOSER_ROOT_VERSION=dev-master composer dump-autoload
+ - if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi
+ - if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
+
+script:
+ - cd ext/pimple
+ - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi
+ - cd ../..
+ - phpunit
+
+matrix:
+ exclude:
+ - php: hhvm
+ env: PIMPLE_EXT=yes
diff --git a/vendor/pimple/pimple/CHANGELOG b/vendor/pimple/pimple/CHANGELOG
new file mode 100644
index 00000000..cc679972
--- /dev/null
+++ b/vendor/pimple/pimple/CHANGELOG
@@ -0,0 +1,35 @@
+* 3.0.2 (2015-09-11)
+
+ * refactored the C extension
+ * minor non-significant changes
+
+* 3.0.1 (2015-07-30)
+
+ * simplified some code
+ * fixed a segfault in the C extension
+
+* 3.0.0 (2014-07-24)
+
+ * removed the Pimple class alias (use Pimple\Container instead)
+
+* 2.1.1 (2014-07-24)
+
+ * fixed compiler warnings for the C extension
+ * fixed code when dealing with circular references
+
+* 2.1.0 (2014-06-24)
+
+ * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
+ deprecated alias which will be removed in Pimple 3.0)
+ * added Pimple\ServiceProviderInterface (and Pimple::register())
+
+* 2.0.0 (2014-02-10)
+
+ * changed extend to automatically re-assign the extended service and keep it as shared or factory
+ (to keep BC, extend still returns the extended service)
+ * changed services to be shared by default (use factory() for factory
+ services)
+
+* 1.0.0
+
+ * initial version
diff --git a/vendor/pimple/pimple/LICENSE b/vendor/pimple/pimple/LICENSE
new file mode 100644
index 00000000..d7949e2f
--- /dev/null
+++ b/vendor/pimple/pimple/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2009-2015 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/pimple/pimple/README.rst b/vendor/pimple/pimple/README.rst
new file mode 100644
index 00000000..93fb35a8
--- /dev/null
+++ b/vendor/pimple/pimple/README.rst
@@ -0,0 +1,201 @@
+Pimple
+======
+
+.. caution::
+
+ This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
+ the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
+ way to learn more about how to create a simple Dependency Injection
+ Container (recent versions of Pimple are more focused on performance).
+
+Pimple is a small Dependency Injection Container for PHP.
+
+Installation
+------------
+
+Before using Pimple in your project, add it to your ``composer.json`` file:
+
+.. code-block:: bash
+
+ $ ./composer.phar require pimple/pimple ~3.0
+
+Alternatively, Pimple is also available as a PHP C extension:
+
+.. code-block:: bash
+
+ $ git clone https://github.com/silexphp/Pimple
+ $ cd Pimple/ext/pimple
+ $ phpize
+ $ ./configure
+ $ make
+ $ make install
+
+Usage
+-----
+
+Creating a container is a matter of creating a ``Container`` instance:
+
+.. code-block:: php
+
+ use Pimple\Container;
+
+ $container = new Container();
+
+As many other dependency injection containers, Pimple manages two different
+kind of data: **services** and **parameters**.
+
+Defining Services
+~~~~~~~~~~~~~~~~~
+
+A service is an object that does something as part of a larger system. Examples
+of services: a database connection, a templating engine, or a mailer. Almost
+any **global** object can be a service.
+
+Services are defined by **anonymous functions** that return an instance of an
+object:
+
+.. code-block:: php
+
+ // define some services
+ $container['session_storage'] = function ($c) {
+ return new SessionStorage('SESSION_ID');
+ };
+
+ $container['session'] = function ($c) {
+ return new Session($c['session_storage']);
+ };
+
+Notice that the anonymous function has access to the current container
+instance, allowing references to other services or parameters.
+
+As objects are only created when you get them, the order of the definitions
+does not matter.
+
+Using the defined services is also very easy:
+
+.. code-block:: php
+
+ // get the session object
+ $session = $container['session'];
+
+ // the above call is roughly equivalent to the following code:
+ // $storage = new SessionStorage('SESSION_ID');
+ // $session = new Session($storage);
+
+Defining Factory Services
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, each time you get a service, Pimple returns the **same instance**
+of it. If you want a different instance to be returned for all calls, wrap your
+anonymous function with the ``factory()`` method
+
+.. code-block:: php
+
+ $container['session'] = $container->factory(function ($c) {
+ return new Session($c['session_storage']);
+ });
+
+Now, each call to ``$container['session']`` returns a new instance of the
+session.
+
+Defining Parameters
+~~~~~~~~~~~~~~~~~~~
+
+Defining a parameter allows to ease the configuration of your container from
+the outside and to store global values:
+
+.. code-block:: php
+
+ // define some parameters
+ $container['cookie_name'] = 'SESSION_ID';
+ $container['session_storage_class'] = 'SessionStorage';
+
+If you change the ``session_storage`` service definition like below:
+
+.. code-block:: php
+
+ $container['session_storage'] = function ($c) {
+ return new $c['session_storage_class']($c['cookie_name']);
+ };
+
+You can now easily change the cookie name by overriding the
+``session_storage_class`` parameter instead of redefining the service
+definition.
+
+Protecting Parameters
+~~~~~~~~~~~~~~~~~~~~~
+
+Because Pimple sees anonymous functions as service definitions, you need to
+wrap anonymous functions with the ``protect()`` method to store them as
+parameters:
+
+.. code-block:: php
+
+ $container['random_func'] = $container->protect(function () {
+ return rand();
+ });
+
+Modifying Services after Definition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In some cases you may want to modify a service definition after it has been
+defined. You can use the ``extend()`` method to define additional code to be
+run on your service just after it is created:
+
+.. code-block:: php
+
+ $container['session_storage'] = function ($c) {
+ return new $c['session_storage_class']($c['cookie_name']);
+ };
+
+ $container->extend('session_storage', function ($storage, $c) {
+ $storage->...();
+
+ return $storage;
+ });
+
+The first argument is the name of the service to extend, the second a function
+that gets access to the object instance and the container.
+
+Extending a Container
+~~~~~~~~~~~~~~~~~~~~~
+
+If you use the same libraries over and over, you might want to reuse some
+services from one project to the next one; package your services into a
+**provider** by implementing ``Pimple\ServiceProviderInterface``:
+
+.. code-block:: php
+
+ use Pimple\Container;
+
+ class FooProvider implements Pimple\ServiceProviderInterface
+ {
+ public function register(Container $pimple)
+ {
+ // register some services and parameters
+ // on $pimple
+ }
+ }
+
+Then, register the provider on a Container:
+
+.. code-block:: php
+
+ $pimple->register(new FooProvider());
+
+Fetching the Service Creation Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you access an object, Pimple automatically calls the anonymous function
+that you defined, which creates the service object for you. If you want to get
+raw access to this function, you can use the ``raw()`` method:
+
+.. code-block:: php
+
+ $container['session'] = function ($c) {
+ return new Session($c['session_storage']);
+ };
+
+ $sessionFunction = $container->raw('session');
+
+.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1
diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json
new file mode 100644
index 00000000..a5268f16
--- /dev/null
+++ b/vendor/pimple/pimple/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "pimple/pimple",
+ "type": "library",
+ "description": "Pimple, a simple Dependency Injection Container",
+ "keywords": ["dependency injection", "container"],
+ "homepage": "http://pimple.sensiolabs.org",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-0": { "Pimple": "src/" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ }
+}
diff --git a/vendor/pimple/pimple/ext/pimple/.gitignore b/vendor/pimple/pimple/ext/pimple/.gitignore
new file mode 100644
index 00000000..1861088a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/.gitignore
@@ -0,0 +1,30 @@
+*.sw*
+.deps
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+acinclude.m4
+aclocal.m4
+build/
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+install-sh
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+run-tests.php
+*.loT
+.libs/
+modules/
+*.la
+*.lo
diff --git a/vendor/pimple/pimple/ext/pimple/README.md b/vendor/pimple/pimple/ext/pimple/README.md
new file mode 100644
index 00000000..7b39eb29
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/README.md
@@ -0,0 +1,12 @@
+This is Pimple 2 implemented in C
+
+* PHP >= 5.3
+* Not tested under Windows, might work
+
+Install
+=======
+
+ > phpize
+ > ./configure
+ > make
+ > make install
diff --git a/vendor/pimple/pimple/ext/pimple/config.m4 b/vendor/pimple/pimple/ext/pimple/config.m4
new file mode 100644
index 00000000..c9ba17dd
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/config.m4
@@ -0,0 +1,63 @@
+dnl $Id$
+dnl config.m4 for extension pimple
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+dnl If your extension references something external, use with:
+
+dnl PHP_ARG_WITH(pimple, for pimple support,
+dnl Make sure that the comment is aligned:
+dnl [ --with-pimple Include pimple support])
+
+dnl Otherwise use enable:
+
+PHP_ARG_ENABLE(pimple, whether to enable pimple support,
+dnl Make sure that the comment is aligned:
+[ --enable-pimple Enable pimple support])
+
+if test "$PHP_PIMPLE" != "no"; then
+ dnl Write more examples of tests here...
+
+ dnl # --with-pimple -> check with-path
+ dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
+ dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this
+ dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter
+ dnl PIMPLE_DIR=$PHP_PIMPLE
+ dnl else # search default path list
+ dnl AC_MSG_CHECKING([for pimple files in default path])
+ dnl for i in $SEARCH_PATH ; do
+ dnl if test -r $i/$SEARCH_FOR; then
+ dnl PIMPLE_DIR=$i
+ dnl AC_MSG_RESULT(found in $i)
+ dnl fi
+ dnl done
+ dnl fi
+ dnl
+ dnl if test -z "$PIMPLE_DIR"; then
+ dnl AC_MSG_RESULT([not found])
+ dnl AC_MSG_ERROR([Please reinstall the pimple distribution])
+ dnl fi
+
+ dnl # --with-pimple -> add include path
+ dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include)
+
+ dnl # --with-pimple -> check for lib and symbol presence
+ dnl LIBNAME=pimple # you may want to change this
+ dnl LIBSYMBOL=pimple # you most likely want to change this
+
+ dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+ dnl [
+ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD)
+ dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ])
+ dnl ],[
+ dnl AC_MSG_ERROR([wrong pimple lib version or lib not found])
+ dnl ],[
+ dnl -L$PIMPLE_DIR/lib -lm
+ dnl ])
+ dnl
+ dnl PHP_SUBST(PIMPLE_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared)
+fi
diff --git a/vendor/pimple/pimple/ext/pimple/config.w32 b/vendor/pimple/pimple/ext/pimple/config.w32
new file mode 100644
index 00000000..39857b32
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/config.w32
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+// If your extension references something external, use ARG_WITH
+// ARG_WITH("pimple", "for pimple support", "no");
+
+// Otherwise, use ARG_ENABLE
+// ARG_ENABLE("pimple", "enable pimple support", "no");
+
+if (PHP_PIMPLE != "no") {
+ EXTENSION("pimple", "pimple.c");
+}
+
diff --git a/vendor/pimple/pimple/ext/pimple/php_pimple.h b/vendor/pimple/pimple/ext/pimple/php_pimple.h
new file mode 100644
index 00000000..49431f08
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/php_pimple.h
@@ -0,0 +1,121 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 Fabien Potencier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PHP_PIMPLE_H
+#define PHP_PIMPLE_H
+
+extern zend_module_entry pimple_module_entry;
+#define phpext_pimple_ptr &pimple_module_entry
+
+#ifdef PHP_WIN32
+# define PHP_PIMPLE_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_PIMPLE_API __attribute__ ((visibility("default")))
+#else
+# define PHP_PIMPLE_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#define PIMPLE_VERSION "3.0.2"
+#define PIMPLE_NS "Pimple"
+
+#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5
+#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10
+
+zend_module_entry *get_module(void);
+
+PHP_MINIT_FUNCTION(pimple);
+PHP_MINFO_FUNCTION(pimple);
+
+PHP_METHOD(Pimple, __construct);
+PHP_METHOD(Pimple, factory);
+PHP_METHOD(Pimple, protect);
+PHP_METHOD(Pimple, raw);
+PHP_METHOD(Pimple, extend);
+PHP_METHOD(Pimple, keys);
+PHP_METHOD(Pimple, register);
+PHP_METHOD(Pimple, offsetSet);
+PHP_METHOD(Pimple, offsetUnset);
+PHP_METHOD(Pimple, offsetGet);
+PHP_METHOD(Pimple, offsetExists);
+
+PHP_METHOD(PimpleClosure, invoker);
+
+typedef struct _pimple_bucket_value {
+ zval *value; /* Must be the first element */
+ zval *raw;
+ zend_object_handle handle_num;
+ enum {
+ PIMPLE_IS_PARAM = 0,
+ PIMPLE_IS_SERVICE = 2
+ } type;
+ zend_bool initialized;
+ zend_fcall_info_cache fcc;
+} pimple_bucket_value;
+
+typedef struct _pimple_object {
+ zend_object zobj;
+ HashTable values;
+ HashTable factories;
+ HashTable protected;
+} pimple_object;
+
+typedef struct _pimple_closure_object {
+ zend_object zobj;
+ zval *callable;
+ zval *factory;
+} pimple_closure_object;
+
+static const char sensiolabs_logo[] = "";
+
+static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
+static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
+
+static void pimple_bucket_dtor(pimple_bucket_value *bucket);
+static void pimple_free_bucket(pimple_bucket_value *bucket);
+
+static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
+static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC);
+static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC);
+static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC);
+static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC);
+static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC);
+
+static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC);
+static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC);
+static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC);
+static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
+
+#ifdef ZTS
+#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v)
+#else
+#define PIMPLE_G(v) (pimple_globals.v)
+#endif
+
+#endif /* PHP_PIMPLE_H */
+
diff --git a/vendor/pimple/pimple/ext/pimple/pimple.c b/vendor/pimple/pimple/ext/pimple/pimple.c
new file mode 100644
index 00000000..239c01d6
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/pimple.c
@@ -0,0 +1,922 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 Fabien Potencier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_pimple.h"
+#include "pimple_compat.h"
+#include "zend_interfaces.h"
+#include "zend.h"
+#include "Zend/zend_closures.h"
+#include "ext/spl/spl_exceptions.h"
+#include "Zend/zend_exceptions.h"
+#include "main/php_output.h"
+#include "SAPI.h"
+
+static zend_class_entry *pimple_ce;
+static zend_object_handlers pimple_object_handlers;
+static zend_class_entry *pimple_closure_ce;
+static zend_class_entry *pimple_serviceprovider_ce;
+static zend_object_handlers pimple_closure_object_handlers;
+static zend_internal_function pimple_closure_invoker_function;
+
+#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \
+ ulong index; \
+ pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \
+
+#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \
+ if (ce != pimple_ce) { \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \
+ if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \
+ pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
+ } \
+ zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \
+ if (function->common.scope != ce) { \
+ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
+ } \
+ } else { \
+ pimple_object_handlers.read_dimension = pimple_object_read_dimension; \
+ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
+ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
+ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
+ }\
+ } while(0);
+
+#define PIMPLE_CALL_CB do { \
+ zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \
+ fci.size = sizeof(fci); \
+ fci.object_ptr = retval->fcc.object_ptr; \
+ fci.function_name = retval->value; \
+ fci.no_separation = 1; \
+ fci.retval_ptr_ptr = &retval_ptr_ptr; \
+\
+ zend_call_function(&fci, &retval->fcc TSRMLS_CC); \
+ efree(fci.params); \
+ if (EG(exception)) { \
+ return EG(uninitialized_zval_ptr); \
+ } \
+ } while(0);
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
+ZEND_ARG_ARRAY_INFO(0, value, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2)
+ZEND_ARG_INFO(0, offset)
+ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1)
+ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1)
+ZEND_ARG_INFO(0, id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2)
+ZEND_ARG_INFO(0, id)
+ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1)
+ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0)
+ZEND_ARG_ARRAY_INFO(0, values, 1)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1)
+ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry pimple_ce_functions[] = {
+ PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC)
+
+ PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC)
+ PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = {
+ PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register)
+ PHP_FE_END
+};
+
+static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC)
+{
+ zend_object_std_dtor(&obj->zobj TSRMLS_CC);
+ if (obj->factory) {
+ zval_ptr_dtor(&obj->factory);
+ }
+ if (obj->callable) {
+ zval_ptr_dtor(&obj->callable);
+ }
+ efree(obj);
+}
+
+static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC)
+{
+ zend_hash_destroy(&obj->factories);
+ zend_hash_destroy(&obj->protected);
+ zend_hash_destroy(&obj->values);
+ zend_object_std_dtor(&obj->zobj TSRMLS_CC);
+ efree(obj);
+}
+
+static void pimple_free_bucket(pimple_bucket_value *bucket)
+{
+ if (bucket->raw) {
+ zval_ptr_dtor(&bucket->raw);
+ }
+}
+
+static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ pimple_closure_object *pimple_closure_obj = NULL;
+
+ pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object));
+ ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce);
+
+ pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor;
+ retval.handlers = &pimple_closure_object_handlers;
+ retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC);
+
+ return retval;
+}
+
+static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC)
+{
+ zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated");
+
+ return NULL;
+}
+
+static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC)
+{
+ *zobj_ptr = obj;
+ *ce_ptr = Z_OBJCE_P(obj);
+ *fptr_ptr = (zend_function *)&pimple_closure_invoker_function;
+
+ return SUCCESS;
+}
+
+static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ pimple_object *pimple_obj = NULL;
+ zend_function *function = NULL;
+
+ pimple_obj = emalloc(sizeof(pimple_object));
+ ZEND_OBJ_INIT(&pimple_obj->zobj, ce);
+
+ PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS
+
+ retval.handlers = &pimple_object_handlers;
+ retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC);
+
+ zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+ zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+ zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
+
+ return retval;
+}
+
+static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value pimple_value = {0}, *found_value = NULL;
+ ulong hash;
+
+ pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC);
+
+ if (!offset) {/* $p[] = 'foo' when not overloaded */
+ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(value);
+ return;
+ }
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value);
+ if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
+ pimple_free_bucket(&pimple_value);
+ zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset));
+ return;
+ }
+ if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
+ pimple_free_bucket(&pimple_value);
+ return;
+ }
+ Z_ADDREF_P(value);
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value);
+ if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
+ pimple_free_bucket(&pimple_value);
+ zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index);
+ return;
+ }
+ if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
+ pimple_free_bucket(&pimple_value);
+ return;
+ }
+ Z_ADDREF_P(value);
+ break;
+ case IS_NULL: /* $p[] = 'foo' when overloaded */
+ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(value);
+ break;
+ default:
+ pimple_free_bucket(&pimple_value);
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+}
+
+static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ zend_hash_index_del(&pimple_obj->values, index);
+ zend_hash_index_del(&pimple_obj->factories, index);
+ zend_hash_index_del(&pimple_obj->protected, index);
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+}
+
+static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value *retval = NULL;
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) {
+ switch (check_empty) {
+ case 0: /* isset */
+ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */
+ case 1: /* empty */
+ default:
+ return zend_is_true(retval->value);
+ }
+ }
+ return 0;
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) {
+ switch (check_empty) {
+ case 0: /* isset */
+ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/
+ case 1: /* empty */
+ default:
+ return zend_is_true(retval->value);
+ }
+ }
+ return 0;
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ return 0;
+ }
+}
+
+static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
+{
+ FETCH_DIM_HANDLERS_VARS
+
+ pimple_bucket_value *retval = NULL;
+ zend_fcall_info fci = {0};
+ zval *retval_ptr_ptr = NULL;
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
+ return EG(uninitialized_zval_ptr);
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) {
+ return EG(uninitialized_zval_ptr);
+ }
+ break;
+ case IS_NULL: /* $p[][3] = 'foo' first dim access */
+ return EG(uninitialized_zval_ptr);
+ break;
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ return EG(uninitialized_zval_ptr);
+ }
+
+ if(retval->type == PIMPLE_IS_PARAM) {
+ return retval->value;
+ }
+
+ if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) {
+ /* Service is protected, return the value every time */
+ return retval->value;
+ }
+
+ if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) {
+ /* Service is a factory, call it everytime and never cache its result */
+ PIMPLE_CALL_CB
+ Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */
+ return retval_ptr_ptr;
+ }
+
+ if (retval->initialized == 1) {
+ /* Service has already been called, return its cached value */
+ return retval->value;
+ }
+
+ ALLOC_INIT_ZVAL(retval->raw);
+ MAKE_COPY_ZVAL(&retval->value, retval->raw);
+
+ PIMPLE_CALL_CB
+
+ retval->initialized = 1;
+ zval_ptr_dtor(&retval->value);
+ retval->value = retval_ptr_ptr;
+
+ return retval->value;
+}
+
+static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
+{
+ if (Z_TYPE_P(_zval) != IS_OBJECT) {
+ return FAILURE;
+ }
+
+ if (_pimple_bucket_value->fcc.called_scope) {
+ return SUCCESS;
+ }
+
+ if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) {
+ _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope;
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+
+static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
+{
+ _pimple_bucket_value->value = _zval;
+
+ if (Z_TYPE_P(_zval) != IS_OBJECT) {
+ return PIMPLE_IS_PARAM;
+ }
+
+ if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) {
+ _pimple_bucket_value->type = PIMPLE_IS_SERVICE;
+ _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval);
+ }
+
+ return PIMPLE_IS_SERVICE;
+}
+
+static void pimple_bucket_dtor(pimple_bucket_value *bucket)
+{
+ zval_ptr_dtor(&bucket->value);
+ pimple_free_bucket(bucket);
+}
+
+PHP_METHOD(Pimple, protect)
+{
+ zval *protected = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value bucket = {0};
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) {
+ return;
+ }
+
+ if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC);
+ return;
+ }
+
+ pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC);
+ pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
+ Z_ADDREF_P(protected);
+ RETURN_ZVAL(protected, 1 , 0);
+ } else {
+ pimple_free_bucket(&bucket);
+ }
+ RETURN_FALSE;
+}
+
+PHP_METHOD(Pimple, raw)
+{
+ zval *offset = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value *value = NULL;
+ ulong index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
+ RETURN_NULL();
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
+ RETURN_NULL();
+ }
+ break;
+ case IS_NULL:
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+
+ if (value->raw) {
+ RETVAL_ZVAL(value->raw, 1, 0);
+ } else {
+ RETVAL_ZVAL(value->value, 1, 0);
+ }
+}
+
+PHP_METHOD(Pimple, extend)
+{
+ zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL;
+ pimple_bucket_value bucket = {0}, *value = NULL;
+ pimple_object *pobj = NULL;
+ pimple_closure_object *pcobj = NULL;
+ ulong index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_STRING:
+ if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
+ RETURN_NULL();
+ }
+ if (value->type != PIMPLE_IS_SERVICE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset));
+ RETURN_NULL();
+ }
+ break;
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_LONG:
+ if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ index = (ulong)Z_DVAL_P(offset);
+ } else {
+ index = Z_LVAL_P(offset);
+ }
+ if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index);
+ RETURN_NULL();
+ }
+ if (value->type != PIMPLE_IS_SERVICE) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index);
+ RETURN_NULL();
+ }
+ break;
+ case IS_NULL:
+ default:
+ zend_error(E_WARNING, "Unsupported offset type");
+ }
+
+ if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
+ RETURN_NULL();
+ }
+ pimple_free_bucket(&bucket);
+
+ ALLOC_INIT_ZVAL(pimple_closure_obj);
+ object_init_ex(pimple_closure_obj, pimple_closure_ce);
+
+ pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC);
+ pcobj->callable = callable;
+ pcobj->factory = value->value;
+ Z_ADDREF_P(callable);
+ Z_ADDREF_P(value->value);
+
+ if (zend_hash_index_exists(&pobj->factories, value->handle_num)) {
+ pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC);
+ zend_hash_index_del(&pobj->factories, value->handle_num);
+ zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL);
+ Z_ADDREF_P(pimple_closure_obj);
+ }
+
+ pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC);
+
+ RETVAL_ZVAL(pimple_closure_obj, 1, 1);
+}
+
+PHP_METHOD(Pimple, keys)
+{
+ HashPosition pos;
+ pimple_object *pobj = NULL;
+ zval **value = NULL;
+ zval *endval = NULL;
+ char *str_index = NULL;
+ int str_len;
+ ulong num_index;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ array_init_size(return_value, zend_hash_num_elements(&pobj->values));
+
+ zend_hash_internal_pointer_reset_ex(&pobj->values, &pos);
+
+ while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) {
+ MAKE_STD_ZVAL(endval);
+ switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) {
+ case HASH_KEY_IS_STRING:
+ ZVAL_STRINGL(endval, str_index, str_len - 1, 1);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
+ break;
+ case HASH_KEY_IS_LONG:
+ ZVAL_LONG(endval, num_index);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
+ break;
+ }
+ zend_hash_move_forward_ex(&pobj->values, &pos);
+ }
+}
+
+PHP_METHOD(Pimple, factory)
+{
+ zval *factory = NULL;
+ pimple_object *pobj = NULL;
+ pimple_bucket_value bucket = {0};
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) {
+ return;
+ }
+
+ if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) {
+ pimple_free_bucket(&bucket);
+ zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
+ return;
+ }
+
+ pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC);
+ pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
+ Z_ADDREF_P(factory);
+ RETURN_ZVAL(factory, 1 , 0);
+ } else {
+ pimple_free_bucket(&bucket);
+ }
+
+ RETURN_FALSE;
+}
+
+PHP_METHOD(Pimple, offsetSet)
+{
+ zval *offset = NULL, *value = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) {
+ return;
+ }
+
+ pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC);
+}
+
+PHP_METHOD(Pimple, offsetGet)
+{
+ zval *offset = NULL, *retval = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC);
+
+ RETVAL_ZVAL(retval, 1, 0);
+}
+
+PHP_METHOD(Pimple, offsetUnset)
+{
+ zval *offset = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ pimple_object_unset_dimension(getThis(), offset TSRMLS_CC);
+}
+
+PHP_METHOD(Pimple, offsetExists)
+{
+ zval *offset = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
+ return;
+ }
+
+ RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC));
+}
+
+PHP_METHOD(Pimple, register)
+{
+ zval *provider;
+ zval **data;
+ zval *retval = NULL;
+ zval key;
+
+ HashTable *array = NULL;
+ HashPosition pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) {
+ return;
+ }
+
+ RETVAL_ZVAL(getThis(), 1, 0);
+
+ zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis());
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+
+ if (!array) {
+ return;
+ }
+
+ zend_hash_internal_pointer_reset_ex(array, &pos);
+
+ while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) {
+ zend_hash_get_current_key_zval_ex(array, &key, &pos);
+ pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC);
+ zend_hash_move_forward_ex(array, &pos);
+ }
+}
+
+PHP_METHOD(Pimple, __construct)
+{
+ zval *values = NULL, **pData = NULL, offset;
+ HashPosition pos;
+ char *str_index = NULL;
+ zend_uint str_length;
+ ulong num_index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) {
+ return;
+ }
+
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
+ while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) {
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos);
+ zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos);
+ INIT_ZVAL(offset);
+ if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) {
+ ZVAL_LONG(&offset, num_index);
+ } else {
+ ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0);
+ }
+ pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos);
+ }
+}
+
+/*
+ * This is PHP code snippet handling extend()s calls :
+
+ $extended = function ($c) use ($callable, $factory) {
+ return $callable($factory($c), $c);
+ };
+
+ */
+PHP_METHOD(PimpleClosure, invoker)
+{
+ pimple_closure_object *pcobj = NULL;
+ zval *arg = NULL, *retval = NULL, *newretval = NULL;
+ zend_fcall_info fci = {0};
+ zval **args[2];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+ return;
+ }
+
+ pcobj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ fci.function_name = pcobj->factory;
+ args[0] = &arg;
+ zend_fcall_info_argp(&fci TSRMLS_CC, 1, args);
+ fci.retval_ptr_ptr = &retval;
+ fci.size = sizeof(fci);
+
+ if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
+ efree(fci.params);
+ return; /* Should here return default zval */
+ }
+
+ efree(fci.params);
+ memset(&fci, 0, sizeof(fci));
+ fci.size = sizeof(fci);
+
+ fci.function_name = pcobj->callable;
+ args[0] = &retval;
+ args[1] = &arg;
+ zend_fcall_info_argp(&fci TSRMLS_CC, 2, args);
+ fci.retval_ptr_ptr = &newretval;
+
+ if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
+ efree(fci.params);
+ zval_ptr_dtor(&retval);
+ return;
+ }
+
+ efree(fci.params);
+ zval_ptr_dtor(&retval);
+
+ RETVAL_ZVAL(newretval, 1 ,1);
+}
+
+PHP_MINIT_FUNCTION(pimple)
+{
+ zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce;
+ INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions);
+ INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL);
+ INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions);
+
+ tmp_pimple_ce.create_object = pimple_object_create;
+ tmp_pimple_closure_ce.create_object = pimple_closure_object_create;
+
+ pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC);
+ zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess);
+
+ pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC);
+ pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
+
+ pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC);
+
+ memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers()));
+ pimple_object_handlers = std_object_handlers;
+ pimple_closure_object_handlers.get_closure = pimple_closure_get_closure;
+
+ pimple_closure_invoker_function.function_name = "Pimple closure internal invoker";
+ pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE;
+ pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker);
+ pimple_closure_invoker_function.num_args = 1;
+ pimple_closure_invoker_function.required_num_args = 1;
+ pimple_closure_invoker_function.scope = pimple_closure_ce;
+ pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION;
+ pimple_closure_invoker_function.module = &pimple_module_entry;
+
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(pimple)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled");
+ php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION);
+ php_info_print_table_end();
+
+ php_info_print_box_start(0);
+ php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC);
+ if (!sapi_module.phpinfo_as_text) {
+ php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC);
+ }
+ php_info_print_box_end();
+}
+
+zend_module_entry pimple_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "pimple",
+ NULL,
+ PHP_MINIT(pimple),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(pimple),
+ PIMPLE_VERSION,
+ STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_PIMPLE
+ZEND_GET_MODULE(pimple)
+#endif
diff --git a/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/vendor/pimple/pimple/ext/pimple/pimple_compat.h
new file mode 100644
index 00000000..d234e174
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/pimple_compat.h
@@ -0,0 +1,81 @@
+
+/*
+ * This file is part of Pimple.
+ *
+ * Copyright (c) 2014 Fabien Potencier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PIMPLE_COMPAT_H_
+#define PIMPLE_COMPAT_H_
+
+#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
+
+#define PHP_5_0_X_API_NO 220040412
+#define PHP_5_1_X_API_NO 220051025
+#define PHP_5_2_X_API_NO 220060519
+#define PHP_5_3_X_API_NO 220090626
+#define PHP_5_4_X_API_NO 220100525
+#define PHP_5_5_X_API_NO 220121212
+#define PHP_5_6_X_API_NO 220131226
+
+#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
+#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
+
+#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
+#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
+
+#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO
+#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
+
+#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO
+#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+
+#if IS_PHP_53
+#define object_properties_init(obj, ce) do { \
+ zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \
+ } while (0);
+#endif
+
+#define ZEND_OBJ_INIT(obj, ce) do { \
+ zend_object_std_init(obj, ce TSRMLS_CC); \
+ object_properties_init((obj), (ce)); \
+ } while(0);
+
+#if IS_PHP_53 || IS_PHP_54
+static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
+ Bucket *p;
+
+ p = pos ? (*pos) : ht->pInternalPointer;
+
+ if (!p) {
+ Z_TYPE_P(key) = IS_NULL;
+ } else if (p->nKeyLength) {
+ Z_TYPE_P(key) = IS_STRING;
+ Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1);
+ Z_STRLEN_P(key) = p->nKeyLength - 1;
+ } else {
+ Z_TYPE_P(key) = IS_LONG;
+ Z_LVAL_P(key) = p->h;
+ }
+}
+#endif
+
+#endif /* PIMPLE_COMPAT_H_ */
diff --git a/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/vendor/pimple/pimple/ext/pimple/tests/001.phpt
new file mode 100644
index 00000000..0809ea23
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/001.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test for read_dim/write_dim handlers
+--SKIPIF--
+
+--FILE--
+
+
+--EXPECTF--
+foo
+42
+foo2
+foo99
+baz
+strstr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/vendor/pimple/pimple/ext/pimple/tests/002.phpt
new file mode 100644
index 00000000..7b56d2c1
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/002.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Test for constructor
+--SKIPIF--
+
+--FILE--
+'foo'));
+var_dump($p[42]);
+?>
+--EXPECT--
+NULL
+string(3) "foo"
diff --git a/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/vendor/pimple/pimple/ext/pimple/tests/003.phpt
new file mode 100644
index 00000000..a22cfa35
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/003.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Test empty dimensions
+--SKIPIF--
+
+--FILE--
+
+--EXPECT--
+int(42)
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/vendor/pimple/pimple/ext/pimple/tests/004.phpt
new file mode 100644
index 00000000..1e1d2513
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/004.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test has/unset dim handlers
+--SKIPIF--
+
+--FILE--
+
+--EXPECT--
+int(42)
+NULL
+bool(true)
+bool(false)
+bool(true)
+bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/vendor/pimple/pimple/ext/pimple/tests/005.phpt
new file mode 100644
index 00000000..0479ee05
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/005.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test simple class inheritance
+--SKIPIF--
+
+--FILE--
+someAttr;
+?>
+--EXPECT--
+string(3) "hit"
+foo
+fooAttr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/vendor/pimple/pimple/ext/pimple/tests/006.phpt
new file mode 100644
index 00000000..cfe8a119
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/006.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Test complex class inheritance
+--SKIPIF--
+
+--FILE--
+ 'bar', 88 => 'baz');
+
+$p = new TestPimple($defaultValues);
+$p[42] = 'foo';
+var_dump($p[42]);
+var_dump($p[0]);
+?>
+--EXPECT--
+string(13) "hit offsetset"
+string(27) "hit offsetget in TestPimple"
+string(25) "hit offsetget in MyPimple"
+string(3) "foo"
+string(27) "hit offsetget in TestPimple"
+string(25) "hit offsetget in MyPimple"
+string(3) "baz"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/vendor/pimple/pimple/ext/pimple/tests/007.phpt
new file mode 100644
index 00000000..5aac6838
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/007.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Test for read_dim/write_dim handlers
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+foo
+42
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/vendor/pimple/pimple/ext/pimple/tests/008.phpt
new file mode 100644
index 00000000..db7eeec4
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/008.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Test frozen services
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/vendor/pimple/pimple/ext/pimple/tests/009.phpt
new file mode 100644
index 00000000..bb05ea29
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/009.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Test service is called as callback, and only once
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/vendor/pimple/pimple/ext/pimple/tests/010.phpt
new file mode 100644
index 00000000..badce014
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/010.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test service is called as callback for every callback type
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+callme
+called
+Foo::bar
+array(2) {
+ [0]=>
+ string(3) "Foo"
+ [1]=>
+ string(3) "bar"
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/vendor/pimple/pimple/ext/pimple/tests/011.phpt
new file mode 100644
index 00000000..6682ab8e
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/011.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test service callback throwing an exception
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+all right!
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/vendor/pimple/pimple/ext/pimple/tests/012.phpt
new file mode 100644
index 00000000..4c6ac486
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/012.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Test service factory
+--SKIPIF--
+
+--FILE--
+factory($f = function() { var_dump('called-1'); return 'ret-1';});
+
+$p[] = $f;
+
+$p[] = function () { var_dump('called-2'); return 'ret-2'; };
+
+var_dump($p[0]);
+var_dump($p[0]);
+var_dump($p[1]);
+var_dump($p[1]);
+?>
+--EXPECTF--
+string(8) "called-1"
+string(5) "ret-1"
+string(8) "called-1"
+string(5) "ret-1"
+string(8) "called-2"
+string(5) "ret-2"
+string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/vendor/pimple/pimple/ext/pimple/tests/013.phpt
new file mode 100644
index 00000000..f419958c
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/013.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Test keys()
+--SKIPIF--
+
+--FILE--
+keys());
+
+$p['foo'] = 'bar';
+$p[] = 'foo';
+
+var_dump($p->keys());
+
+unset($p['foo']);
+
+var_dump($p->keys());
+?>
+--EXPECTF--
+array(0) {
+}
+array(2) {
+ [0]=>
+ string(3) "foo"
+ [1]=>
+ int(0)
+}
+array(1) {
+ [0]=>
+ int(0)
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/vendor/pimple/pimple/ext/pimple/tests/014.phpt
new file mode 100644
index 00000000..ac937213
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/014.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test raw()
+--SKIPIF--
+
+--FILE--
+raw('foo'));
+var_dump($p[42]);
+
+unset($p['foo']);
+
+try {
+ $p->raw('foo');
+ echo "expected exception";
+} catch (InvalidArgumentException $e) { }
+--EXPECTF--
+string(8) "called-2"
+string(5) "ret-2"
+object(Closure)#%i (0) {
+}
+string(8) "called-2"
+string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/vendor/pimple/pimple/ext/pimple/tests/015.phpt
new file mode 100644
index 00000000..314f008a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/015.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test protect()
+--SKIPIF--
+
+--FILE--
+protect($f);
+
+var_dump($p['foo']);
+--EXPECTF--
+object(Closure)#%i (0) {
+}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/vendor/pimple/pimple/ext/pimple/tests/016.phpt
new file mode 100644
index 00000000..e55edb0a
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/016.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test extend()
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */
+
+var_dump($c('param'));
+--EXPECTF--
+string(5) "param"
+string(3) "foo"
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/vendor/pimple/pimple/ext/pimple/tests/017.phpt
new file mode 100644
index 00000000..bac23ce0
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/017.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test extend() with exception in service extension
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { throw new BadMethodCallException; });
+
+try {
+ $p[12];
+ echo "Exception expected";
+} catch (BadMethodCallException $e) { }
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
new file mode 100644
index 00000000..8f881d6e
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test extend() with exception in service factory
+--SKIPIF--
+
+--FILE--
+extend(12, function ($w) { return 'foobar'; });
+
+try {
+ $p[12];
+ echo "Exception expected";
+} catch (BadMethodCallException $e) { }
+--EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/vendor/pimple/pimple/ext/pimple/tests/018.phpt
new file mode 100644
index 00000000..27c12a14
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/018.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test register()
+--SKIPIF--
+
+--FILE--
+register(new Foo, array(42 => 'bar'));
+
+var_dump($p[42]);
+--EXPECTF--
+object(Pimple\Container)#1 (0) {
+}
+string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/vendor/pimple/pimple/ext/pimple/tests/019.phpt
new file mode 100644
index 00000000..28a9aeca
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/019.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test register() returns static and is a fluent interface
+--SKIPIF--
+
+--FILE--
+register(new Foo));
+--EXPECTF--
+bool(true)
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
new file mode 100644
index 00000000..8f983e65
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
@@ -0,0 +1,51 @@
+factory($factory);
+
+$p['factory'] = $factory;
+
+echo $p['factory'];
+echo $p['factory'];
+echo $p['factory'];
+
+}
+
+echo microtime(true) - $time;
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
new file mode 100644
index 00000000..aec541f0
--- /dev/null
+++ b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
@@ -0,0 +1,25 @@
+
diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist
new file mode 100644
index 00000000..5c8d487f
--- /dev/null
+++ b/vendor/pimple/pimple/phpunit.xml.dist
@@ -0,0 +1,14 @@
+
+
+
+
+
+ ./src/Pimple/Tests
+
+
+
diff --git a/vendor/pimple/pimple/src/Pimple/Container.php b/vendor/pimple/pimple/src/Pimple/Container.php
new file mode 100644
index 00000000..c976431e
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Container.php
@@ -0,0 +1,282 @@
+factories = new \SplObjectStorage();
+ $this->protected = new \SplObjectStorage();
+
+ foreach ($values as $key => $value) {
+ $this->offsetSet($key, $value);
+ }
+ }
+
+ /**
+ * Sets a parameter or an object.
+ *
+ * Objects must be defined as Closures.
+ *
+ * Allowing any PHP callable leads to difficult to debug problems
+ * as function names (strings) are callable (creating a function with
+ * the same name as an existing parameter would break your container).
+ *
+ * @param string $id The unique identifier for the parameter or object
+ * @param mixed $value The value of the parameter or a closure to define an object
+ *
+ * @throws \RuntimeException Prevent override of a frozen service
+ */
+ public function offsetSet($id, $value)
+ {
+ if (isset($this->frozen[$id])) {
+ throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id));
+ }
+
+ $this->values[$id] = $value;
+ $this->keys[$id] = true;
+ }
+
+ /**
+ * Gets a parameter or an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return mixed The value of the parameter or an object
+ *
+ * @throws \InvalidArgumentException if the identifier is not defined
+ */
+ public function offsetGet($id)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
+ }
+
+ if (
+ isset($this->raw[$id])
+ || !is_object($this->values[$id])
+ || isset($this->protected[$this->values[$id]])
+ || !method_exists($this->values[$id], '__invoke')
+ ) {
+ return $this->values[$id];
+ }
+
+ if (isset($this->factories[$this->values[$id]])) {
+ return $this->values[$id]($this);
+ }
+
+ $raw = $this->values[$id];
+ $val = $this->values[$id] = $raw($this);
+ $this->raw[$id] = $raw;
+
+ $this->frozen[$id] = true;
+
+ return $val;
+ }
+
+ /**
+ * Checks if a parameter or an object is set.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return bool
+ */
+ public function offsetExists($id)
+ {
+ return isset($this->keys[$id]);
+ }
+
+ /**
+ * Unsets a parameter or an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ */
+ public function offsetUnset($id)
+ {
+ if (isset($this->keys[$id])) {
+ if (is_object($this->values[$id])) {
+ unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);
+ }
+
+ unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);
+ }
+ }
+
+ /**
+ * Marks a callable as being a factory service.
+ *
+ * @param callable $callable A service definition to be used as a factory
+ *
+ * @return callable The passed callable
+ *
+ * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
+ */
+ public function factory($callable)
+ {
+ if (!method_exists($callable, '__invoke')) {
+ throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.');
+ }
+
+ $this->factories->attach($callable);
+
+ return $callable;
+ }
+
+ /**
+ * Protects a callable from being interpreted as a service.
+ *
+ * This is useful when you want to store a callable as a parameter.
+ *
+ * @param callable $callable A callable to protect from being evaluated
+ *
+ * @return callable The passed callable
+ *
+ * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
+ */
+ public function protect($callable)
+ {
+ if (!method_exists($callable, '__invoke')) {
+ throw new \InvalidArgumentException('Callable is not a Closure or invokable object.');
+ }
+
+ $this->protected->attach($callable);
+
+ return $callable;
+ }
+
+ /**
+ * Gets a parameter or the closure defining an object.
+ *
+ * @param string $id The unique identifier for the parameter or object
+ *
+ * @return mixed The value of the parameter or the closure defining an object
+ *
+ * @throws \InvalidArgumentException if the identifier is not defined
+ */
+ public function raw($id)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
+ }
+
+ if (isset($this->raw[$id])) {
+ return $this->raw[$id];
+ }
+
+ return $this->values[$id];
+ }
+
+ /**
+ * Extends an object definition.
+ *
+ * Useful when you want to extend an existing object definition,
+ * without necessarily loading that object.
+ *
+ * @param string $id The unique identifier for the object
+ * @param callable $callable A service definition to extend the original
+ *
+ * @return callable The wrapped callable
+ *
+ * @throws \InvalidArgumentException if the identifier is not defined or not a service definition
+ */
+ public function extend($id, $callable)
+ {
+ if (!isset($this->keys[$id])) {
+ throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
+ }
+
+ if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) {
+ throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id));
+ }
+
+ if (!is_object($callable) || !method_exists($callable, '__invoke')) {
+ throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.');
+ }
+
+ $factory = $this->values[$id];
+
+ $extended = function ($c) use ($callable, $factory) {
+ return $callable($factory($c), $c);
+ };
+
+ if (isset($this->factories[$factory])) {
+ $this->factories->detach($factory);
+ $this->factories->attach($extended);
+ }
+
+ return $this[$id] = $extended;
+ }
+
+ /**
+ * Returns all defined value names.
+ *
+ * @return array An array of value names
+ */
+ public function keys()
+ {
+ return array_keys($this->values);
+ }
+
+ /**
+ * Registers a service provider.
+ *
+ * @param ServiceProviderInterface $provider A ServiceProviderInterface instance
+ * @param array $values An array of values that customizes the provider
+ *
+ * @return static
+ */
+ public function register(ServiceProviderInterface $provider, array $values = array())
+ {
+ $provider->register($this);
+
+ foreach ($values as $key => $value) {
+ $this[$key] = $value;
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php
new file mode 100644
index 00000000..c004594b
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php
@@ -0,0 +1,46 @@
+value = $value;
+
+ return $service;
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php
new file mode 100644
index 00000000..33cd4e54
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php
@@ -0,0 +1,34 @@
+factory(function () {
+ return new Service();
+ });
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php
new file mode 100644
index 00000000..d71b184d
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php
@@ -0,0 +1,35 @@
+
+ */
+class Service
+{
+ public $value;
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
new file mode 100644
index 00000000..8e5c4c73
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
@@ -0,0 +1,76 @@
+
+ */
+class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase
+{
+ public function testProvider()
+ {
+ $pimple = new Container();
+
+ $pimpleServiceProvider = new Fixtures\PimpleServiceProvider();
+ $pimpleServiceProvider->register($pimple);
+
+ $this->assertEquals('value', $pimple['param']);
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+
+ $serviceOne = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+
+ public function testProviderWithRegisterMethod()
+ {
+ $pimple = new Container();
+
+ $pimple->register(new Fixtures\PimpleServiceProvider(), array(
+ 'anotherParameter' => 'anotherValue',
+ ));
+
+ $this->assertEquals('value', $pimple['param']);
+ $this->assertEquals('anotherValue', $pimple['anotherParameter']);
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+
+ $serviceOne = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['factory'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+}
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
new file mode 100644
index 00000000..918f620d
--- /dev/null
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
@@ -0,0 +1,440 @@
+
+ */
+class PimpleTest extends \PHPUnit_Framework_TestCase
+{
+ public function testWithString()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+
+ $this->assertEquals('value', $pimple['param']);
+ }
+
+ public function testWithClosure()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']);
+ }
+
+ public function testServicesShouldBeDifferent()
+ {
+ $pimple = new Container();
+ $pimple['service'] = $pimple->factory(function () {
+ return new Fixtures\Service();
+ });
+
+ $serviceOne = $pimple['service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ }
+
+ public function testShouldPassContainerAsParameter()
+ {
+ $pimple = new Container();
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+ $pimple['container'] = function ($container) {
+ return $container;
+ };
+
+ $this->assertNotSame($pimple, $pimple['service']);
+ $this->assertSame($pimple, $pimple['container']);
+ }
+
+ public function testIsset()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ $pimple['null'] = null;
+
+ $this->assertTrue(isset($pimple['param']));
+ $this->assertTrue(isset($pimple['service']));
+ $this->assertTrue(isset($pimple['null']));
+ $this->assertFalse(isset($pimple['non_existent']));
+ }
+
+ public function testConstructorInjection()
+ {
+ $params = array('param' => 'value');
+ $pimple = new Container($params);
+
+ $this->assertSame($params['param'], $pimple['param']);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testOffsetGetValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ echo $pimple['foo'];
+ }
+
+ public function testOffsetGetHonorsNullValues()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = null;
+ $this->assertNull($pimple['foo']);
+ }
+
+ public function testUnset()
+ {
+ $pimple = new Container();
+ $pimple['param'] = 'value';
+ $pimple['service'] = function () {
+ return new Fixtures\Service();
+ };
+
+ unset($pimple['param'], $pimple['service']);
+ $this->assertFalse(isset($pimple['param']));
+ $this->assertFalse(isset($pimple['service']));
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testShare($service)
+ {
+ $pimple = new Container();
+ $pimple['shared_service'] = $service;
+
+ $serviceOne = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+
+ $serviceTwo = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+
+ $this->assertSame($serviceOne, $serviceTwo);
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testProtect($service)
+ {
+ $pimple = new Container();
+ $pimple['protected'] = $pimple->protect($service);
+
+ $this->assertSame($service, $pimple['protected']);
+ }
+
+ public function testGlobalFunctionNameAsParameterValue()
+ {
+ $pimple = new Container();
+ $pimple['global_function'] = 'strlen';
+ $this->assertSame('strlen', $pimple['global_function']);
+ }
+
+ public function testRaw()
+ {
+ $pimple = new Container();
+ $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; });
+ $this->assertSame($definition, $pimple->raw('service'));
+ }
+
+ public function testRawHonorsNullValues()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = null;
+ $this->assertNull($pimple->raw('foo'));
+ }
+
+ public function testFluentRegister()
+ {
+ $pimple = new Container();
+ $this->assertSame($pimple, $pimple->register($this->getMock('Pimple\ServiceProviderInterface')));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testRawValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->raw('foo');
+ }
+
+ /**
+ * @dataProvider serviceDefinitionProvider
+ */
+ public function testExtend($service)
+ {
+ $pimple = new Container();
+ $pimple['shared_service'] = function () {
+ return new Fixtures\Service();
+ };
+ $pimple['factory_service'] = $pimple->factory(function () {
+ return new Fixtures\Service();
+ });
+
+ $pimple->extend('shared_service', $service);
+ $serviceOne = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+ $serviceTwo = $pimple['shared_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+ $this->assertSame($serviceOne, $serviceTwo);
+ $this->assertSame($serviceOne->value, $serviceTwo->value);
+
+ $pimple->extend('factory_service', $service);
+ $serviceOne = $pimple['factory_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne);
+ $serviceTwo = $pimple['factory_service'];
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo);
+ $this->assertNotSame($serviceOne, $serviceTwo);
+ $this->assertNotSame($serviceOne->value, $serviceTwo->value);
+ }
+
+ public function testExtendDoesNotLeakWithFactories()
+ {
+ if (extension_loaded('pimple')) {
+ $this->markTestSkipped('Pimple extension does not support this test');
+ }
+ $pimple = new Container();
+
+ $pimple['foo'] = $pimple->factory(function () { return; });
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; });
+ unset($pimple['foo']);
+
+ $p = new \ReflectionProperty($pimple, 'values');
+ $p->setAccessible(true);
+ $this->assertEmpty($p->getValue($pimple));
+
+ $p = new \ReflectionProperty($pimple, 'factories');
+ $p->setAccessible(true);
+ $this->assertCount(0, $p->getValue($pimple));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" is not defined.
+ */
+ public function testExtendValidatesKeyIsPresent()
+ {
+ $pimple = new Container();
+ $pimple->extend('foo', function () {});
+ }
+
+ public function testKeys()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = 123;
+ $pimple['bar'] = 123;
+
+ $this->assertEquals(array('foo', 'bar'), $pimple->keys());
+ }
+
+ /** @test */
+ public function settingAnInvokableObjectShouldTreatItAsFactory()
+ {
+ $pimple = new Container();
+ $pimple['invokable'] = new Fixtures\Invokable();
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']);
+ }
+
+ /** @test */
+ public function settingNonInvokableObjectShouldTreatItAsParameter()
+ {
+ $pimple = new Container();
+ $pimple['non_invokable'] = new Fixtures\NonInvokable();
+
+ $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Service definition is not a Closure or invokable object.
+ */
+ public function testFactoryFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->factory($service);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Callable is not a Closure or invokable object.
+ */
+ public function testProtectFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple->protect($service);
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Identifier "foo" does not contain an object definition.
+ */
+ public function testExtendFailsForKeysNotContainingServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = $service;
+ $pimple->extend('foo', function () {});
+ }
+
+ /**
+ * @dataProvider badServiceDefinitionProvider
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Extension service definition is not a Closure or invokable object.
+ */
+ public function testExtendFailsForInvalidServiceDefinitions($service)
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {};
+ $pimple->extend('foo', $service);
+ }
+
+ /**
+ * Provider for invalid service definitions.
+ */
+ public function badServiceDefinitionProvider()
+ {
+ return array(
+ array(123),
+ array(new Fixtures\NonInvokable()),
+ );
+ }
+
+ /**
+ * Provider for service definitions.
+ */
+ public function serviceDefinitionProvider()
+ {
+ return array(
+ array(function ($value) {
+ $service = new Fixtures\Service();
+ $service->value = $value;
+
+ return $service;
+ }),
+ array(new Fixtures\Invokable()),
+ );
+ }
+
+ public function testDefiningNewServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['bar'] = function () {
+ return 'bar';
+ };
+ $this->assertSame('bar', $pimple['bar']);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot override frozen service "foo".
+ */
+ public function testOverridingServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['foo'] = function () {
+ return 'bar';
+ };
+ }
+
+ public function testRemovingServiceAfterFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $foo = $pimple['foo'];
+
+ unset($pimple['foo']);
+ $pimple['foo'] = function () {
+ return 'bar';
+ };
+ $this->assertSame('bar', $pimple['foo']);
+ }
+
+ public function testExtendingService()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
+ return "$foo.bar";
+ });
+ $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
+ return "$foo.baz";
+ });
+ $this->assertSame('foo.bar.baz', $pimple['foo']);
+ }
+
+ public function testExtendingServiceAfterOtherServiceFreeze()
+ {
+ $pimple = new Container();
+ $pimple['foo'] = function () {
+ return 'foo';
+ };
+ $pimple['bar'] = function () {
+ return 'bar';
+ };
+ $foo = $pimple['foo'];
+
+ $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) {
+ return "$bar.baz";
+ });
+ $this->assertSame('bar.baz', $pimple['bar']);
+ }
+}
diff --git a/vendor/psr/log/.gitignore b/vendor/psr/log/.gitignore
new file mode 100644
index 00000000..22d0d82f
--- /dev/null
+++ b/vendor/psr/log/.gitignore
@@ -0,0 +1 @@
+vendor
diff --git a/vendor/psr/log/LICENSE b/vendor/psr/log/LICENSE
new file mode 100644
index 00000000..474c952b
--- /dev/null
+++ b/vendor/psr/log/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 PHP Framework Interoperability Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/psr/log/Psr/Log/AbstractLogger.php b/vendor/psr/log/Psr/Log/AbstractLogger.php
new file mode 100644
index 00000000..90e721af
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/AbstractLogger.php
@@ -0,0 +1,128 @@
+log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/vendor/psr/log/Psr/Log/InvalidArgumentException.php
new file mode 100644
index 00000000..67f852d1
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/InvalidArgumentException.php
@@ -0,0 +1,7 @@
+logger = $logger;
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php
new file mode 100644
index 00000000..5ea72438
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/LoggerInterface.php
@@ -0,0 +1,123 @@
+log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ abstract public function log($level, $message, array $context = array());
+}
diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php
new file mode 100644
index 00000000..d8cd682c
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/NullLogger.php
@@ -0,0 +1,28 @@
+logger) { }`
+ * blocks.
+ */
+class NullLogger extends AbstractLogger
+{
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function log($level, $message, array $context = array())
+ {
+ // noop
+ }
+}
diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
new file mode 100644
index 00000000..a0391a52
--- /dev/null
+++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
@@ -0,0 +1,140 @@
+ ".
+ *
+ * Example ->error('Foo') would yield "error Foo".
+ *
+ * @return string[]
+ */
+ abstract public function getLogs();
+
+ public function testImplements()
+ {
+ $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
+ }
+
+ /**
+ * @dataProvider provideLevelsAndMessages
+ */
+ public function testLogsAtAllLevels($level, $message)
+ {
+ $logger = $this->getLogger();
+ $logger->{$level}($message, array('user' => 'Bob'));
+ $logger->log($level, $message, array('user' => 'Bob'));
+
+ $expected = array(
+ $level.' message of level '.$level.' with context: Bob',
+ $level.' message of level '.$level.' with context: Bob',
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function provideLevelsAndMessages()
+ {
+ return array(
+ LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
+ LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
+ LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
+ LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
+ LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
+ LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
+ LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
+ LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
+ );
+ }
+
+ /**
+ * @expectedException \Psr\Log\InvalidArgumentException
+ */
+ public function testThrowsOnInvalidLevel()
+ {
+ $logger = $this->getLogger();
+ $logger->log('invalid level', 'Foo');
+ }
+
+ public function testContextReplacement()
+ {
+ $logger = $this->getLogger();
+ $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
+
+ $expected = array('info {Message {nothing} Bob Bar a}');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testObjectCastToString()
+ {
+ if (method_exists($this, 'createPartialMock')) {
+ $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
+ } else {
+ $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
+ }
+ $dummy->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('DUMMY'));
+
+ $this->getLogger()->warning($dummy);
+
+ $expected = array('warning DUMMY');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextCanContainAnything()
+ {
+ $context = array(
+ 'bool' => true,
+ 'null' => null,
+ 'string' => 'Foo',
+ 'int' => 0,
+ 'float' => 0.5,
+ 'nested' => array('with object' => new DummyTest),
+ 'object' => new \DateTime,
+ 'resource' => fopen('php://memory', 'r'),
+ );
+
+ $this->getLogger()->warning('Crazy context data', $context);
+
+ $expected = array('warning Crazy context data');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextExceptionKeyCanBeExceptionOrOtherValues()
+ {
+ $logger = $this->getLogger();
+ $logger->warning('Random message', array('exception' => 'oops'));
+ $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
+
+ $expected = array(
+ 'warning Random message',
+ 'critical Uncaught Exception!'
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+}
+
+class DummyTest
+{
+ public function __toString()
+ {
+ }
+}
diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md
new file mode 100644
index 00000000..574bc1cb
--- /dev/null
+++ b/vendor/psr/log/README.md
@@ -0,0 +1,45 @@
+PSR Log
+=======
+
+This repository holds all interfaces/classes/traits related to
+[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).
+
+Note that this is not a logger of its own. It is merely an interface that
+describes a logger. See the specification for more details.
+
+Usage
+-----
+
+If you need a logger, you can use the interface like this:
+
+```php
+logger = $logger;
+ }
+
+ public function doSomething()
+ {
+ if ($this->logger) {
+ $this->logger->info('Doing work');
+ }
+
+ // do something useful
+ }
+}
+```
+
+You can then pick one of the implementations of the interface to get a logger.
+
+If you want to implement the interface, you can require this package and
+implement `Psr\Log\LoggerInterface` in your code. Please read the
+[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
+for details.
diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json
new file mode 100644
index 00000000..87934d70
--- /dev/null
+++ b/vendor/psr/log/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "psr/log",
+ "description": "Common interface for logging libraries",
+ "keywords": ["psr", "psr-3", "log"],
+ "homepage": "https://github.com/php-fig/log",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/vendor/ramsey/array_column/.gitignore b/vendor/ramsey/array_column/.gitignore
new file mode 100644
index 00000000..7e8f330b
--- /dev/null
+++ b/vendor/ramsey/array_column/.gitignore
@@ -0,0 +1,6 @@
+.DS_Store
+phpunit.xml
+composer.lock
+build
+vendor
+*.phar
diff --git a/vendor/ramsey/array_column/.travis.yml b/vendor/ramsey/array_column/.travis.yml
new file mode 100644
index 00000000..ffc234e7
--- /dev/null
+++ b/vendor/ramsey/array_column/.travis.yml
@@ -0,0 +1,26 @@
+language: php
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+
+before_script:
+ - travis_retry composer self-update
+ - travis_retry composer install --no-interaction --prefer-source
+
+script:
+ - mkdir -p build/logs
+ - ./vendor/bin/parallel-lint src tests
+ - ./vendor/bin/phpunit --coverage-text
+ - ./vendor/bin/phpcs src --standard=psr2 -sp
+
+after_script:
+ - php vendor/bin/coveralls
+
+matrix:
+ allow_failures:
+ - php: hhvm
diff --git a/vendor/ramsey/array_column/CHANGELOG.md b/vendor/ramsey/array_column/CHANGELOG.md
new file mode 100644
index 00000000..1dd01361
--- /dev/null
+++ b/vendor/ramsey/array_column/CHANGELOG.md
@@ -0,0 +1,37 @@
+# array_column() Changelog
+
+## 1.1.3
+
+_Released 2015-03-20_
+
+* Changing package name from "rhumsaa/array_column" to "ramsey/array_column"
+* Updated Travis CI build config to test more versions of PHP
+* Updated Travis CI config to lint and check PSR-2 coding standards
+* Added project badges
+* Added CHANGELOG
+
+## 1.1.2
+
+_Released 2013-07-22_
+
+* Remove unnecessary conditionals
+* Whitespace changes
+
+## 1.1.1
+
+_Released 2013-07-06_
+
+* Documentation updates
+
+## 1.1.0
+
+_Released 2013-07-06_
+
+* Catching up array_column() library functionality and tests with PHP 5.5.0
+* Set Travis CI to run tests on PHP 5.5
+
+## 1.0.0
+
+_Released 2013-03-22_
+
+* Initial release of userland library
diff --git a/vendor/ramsey/array_column/LICENSE b/vendor/ramsey/array_column/LICENSE
new file mode 100644
index 00000000..d099612d
--- /dev/null
+++ b/vendor/ramsey/array_column/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013-2015 Ben Ramsey (http://benramsey.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/ramsey/array_column/README.md b/vendor/ramsey/array_column/README.md
new file mode 100644
index 00000000..24b5b73f
--- /dev/null
+++ b/vendor/ramsey/array_column/README.md
@@ -0,0 +1,91 @@
+# array_column() for PHP
+
+[![Build Status](https://travis-ci.org/ramsey/array_column.svg?branch=master)](https://travis-ci.org/ramsey/array_column)
+[![Coverage Status](https://coveralls.io/repos/ramsey/array_column/badge.svg?branch=master)](https://coveralls.io/r/ramsey/array_column)
+[![Latest Stable Version](https://poser.pugx.org/ramsey/array_column/v/stable.svg)](https://packagist.org/packages/ramsey/array_column)
+[![Total Downloads](https://poser.pugx.org/ramsey/array_column/downloads.svg)](https://packagist.org/packages/ramsey/array_column)
+[![Latest Unstable Version](https://poser.pugx.org/ramsey/array_column/v/unstable.svg)](https://packagist.org/packages/ramsey/array_column)
+[![License](https://poser.pugx.org/ramsey/array_column/license.svg)](https://packagist.org/packages/ramsey/array_column)
+
+This simple library provides functionality for [`array_column()`](http://php.net/array_column)
+to versions of PHP earlier than 5.5. It mimics the functionality of the built-in
+function in every way.
+
+
+## Usage
+
+```
+array array_column(array $input, mixed $columnKey[, mixed $indexKey])
+```
+
+Given a multi-dimensional array of data, `array_column()` returns the values
+from a single column of the input array, identified by the `$columnKey`.
+Optionally, you may provide an `$indexKey` to index the values in the returned
+array by the values from the `$indexKey` column in the input array.
+
+For example, using the following array of data, we tell `array_column()` to
+return an array of just the last names, indexed by their record IDs.
+
+``` php
+ 2135,
+ 'first_name' => 'John',
+ 'last_name' => 'Doe'
+ ),
+ array(
+ 'id' => 3245,
+ 'first_name' => 'Sally',
+ 'last_name' => 'Smith'
+ ),
+ array(
+ 'id' => 5342,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Jones'
+ ),
+ array(
+ 'id' => 5623,
+ 'first_name' => 'Peter',
+ 'last_name' => 'Doe'
+ )
+);
+
+$lastNames = array_column($records, 'last_name', 'id');
+```
+
+If we call `print_r()` on `$lastNames`, you'll see a resulting array that looks
+a bit like this:
+
+``` text
+Array
+(
+ [2135] => Doe
+ [3245] => Smith
+ [5342] => Jones
+ [5623] => Doe
+)
+```
+
+
+## Installation
+
+The easiest way to install this library is to use [Composer](https://getcomposer.org/):
+
+```
+php composer.phar require ramsey/array_column
+```
+
+Then, when you run `composer install`, everything will fall magically into place,
+and the `array_column()` function will be available to your project, as long as
+you are including Composer's autoloader.
+
+_However, you do not need Composer to use this library._
+
+This library has no dependencies and should work on older versions of PHP.
+Download the code and include `src/array_column.php` in your project, and all
+should work fine.
+
+When you are ready to run your project on PHP 5.5, everything should
+continue to run well without conflicts, even if this library remains included
+in your project.
diff --git a/vendor/ramsey/array_column/composer.json b/vendor/ramsey/array_column/composer.json
new file mode 100644
index 00000000..2316b225
--- /dev/null
+++ b/vendor/ramsey/array_column/composer.json
@@ -0,0 +1,27 @@
+{
+ "name": "ramsey/array_column",
+ "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.",
+ "type": "library",
+ "keywords": ["array", "column", "array_column"],
+ "homepage": "https://github.com/ramsey/array_column",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "homepage": "http://benramsey.com"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/array_column/issues",
+ "source": "https://github.com/ramsey/array_column"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5",
+ "squizlabs/php_codesniffer": "~2.2",
+ "jakub-onderka/php-parallel-lint": "0.8.*",
+ "satooshi/php-coveralls": "0.6.*"
+ },
+ "autoload": {
+ "files": ["src/array_column.php"]
+ }
+}
diff --git a/vendor/ramsey/array_column/phpunit.xml.dist b/vendor/ramsey/array_column/phpunit.xml.dist
new file mode 100644
index 00000000..61da3c17
--- /dev/null
+++ b/vendor/ramsey/array_column/phpunit.xml.dist
@@ -0,0 +1,21 @@
+
+
+
+
+ ./tests
+
+
+
+
+ ./src
+
+
+
+
+
+
+
+
diff --git a/vendor/ramsey/array_column/src/array_column.php b/vendor/ramsey/array_column/src/array_column.php
new file mode 100644
index 00000000..1e7fa99f
--- /dev/null
+++ b/vendor/ramsey/array_column/src/array_column.php
@@ -0,0 +1,115 @@
+recordSet = array(
+ array(
+ 'id' => 1,
+ 'first_name' => 'John',
+ 'last_name' => 'Doe'
+ ),
+ array(
+ 'id' => 2,
+ 'first_name' => 'Sally',
+ 'last_name' => 'Smith'
+ ),
+ array(
+ 'id' => 3,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Jones'
+ ),
+ );
+
+ $fh = fopen(__FILE__, 'r', true);
+
+ $this->multiDataTypes = array(
+ array(
+ 'id' => 1,
+ 'value' => new stdClass
+ ),
+ array(
+ 'id' => 2,
+ 'value' => 34.2345
+ ),
+ array(
+ 'id' => 3,
+ 'value' => true
+ ),
+ array(
+ 'id' => 4,
+ 'value' => false
+ ),
+ array(
+ 'id' => 5,
+ 'value' => null
+ ),
+ array(
+ 'id' => 6,
+ 'value' => 1234
+ ),
+ array(
+ 'id' => 7,
+ 'value' => 'Foo'
+ ),
+ array(
+ 'id' => 8,
+ 'value' => $fh
+ ),
+ );
+
+ $this->numericColumns = array(
+ array('aaa', '111'),
+ array('bbb', '222'),
+ array('ccc', '333', -1 => 'ddd'),
+ );
+
+ $this->mismatchedColumns = array(
+ array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'),
+ array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'),
+ array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'),
+ );
+ }
+
+ public function testFirstNameColumnFromRecordset()
+ {
+ $expected = array('John', 'Sally', 'Jane');
+ $this->assertEquals($expected, array_column($this->recordSet, 'first_name'));
+ }
+
+ public function testIdColumnFromRecordset()
+ {
+ $expected = array(1, 2, 3);
+ $this->assertEquals($expected, array_column($this->recordSet, 'id'));
+ }
+
+ public function testLastNameColumnKeyedByIdColumnFromRecordset()
+ {
+ $expected = array(1 => 'Doe', 2 => 'Smith', 3 => 'Jones');
+ $this->assertEquals($expected, array_column($this->recordSet, 'last_name', 'id'));
+ }
+
+ public function testLastNameColumnKeyedByFirstNameColumnFromRecordset()
+ {
+ $expected = array('John' => 'Doe', 'Sally' => 'Smith', 'Jane' => 'Jones');
+ $this->assertEquals($expected, array_column($this->recordSet, 'last_name', 'first_name'));
+ }
+
+ public function testValueColumnWithMultipleDataTypes()
+ {
+ $expected = array();
+ foreach ($this->multiDataTypes as $row) {
+ $expected[] = $row['value'];
+ }
+ $this->assertEquals($expected, array_column($this->multiDataTypes, 'value'));
+ }
+
+ public function testValueColumnKeyedByIdWithMultipleDataTypes()
+ {
+ $expected = array();
+ foreach ($this->multiDataTypes as $row) {
+ $expected[$row['id']] = $row['value'];
+ }
+ $this->assertEquals($expected, array_column($this->multiDataTypes, 'value', 'id'));
+ }
+
+ public function testNumericColumnKeys1()
+ {
+ $expected = array('111', '222', '333');
+ $this->assertEquals($expected, array_column($this->numericColumns, 1));
+ }
+
+ public function testNumericColumnKeys2()
+ {
+ $expected = array('aaa' => '111', 'bbb' => '222', 'ccc' => '333');
+ $this->assertEquals($expected, array_column($this->numericColumns, 1, 0));
+ }
+
+ public function testNumericColumnKeys3()
+ {
+ $expected = array('aaa' => '111', 'bbb' => '222', 'ccc' => '333');
+ $this->assertEquals($expected, array_column($this->numericColumns, 1, 0.123));
+ }
+
+ public function testNumericColumnKeys4()
+ {
+ $expected = array(0 => '111', 1 => '222', 'ddd' => '333');
+ $this->assertEquals($expected, array_column($this->numericColumns, 1, -1));
+ }
+
+ public function testFailureToFindColumn1()
+ {
+ $this->assertEquals(array(), array_column($this->numericColumns, 2));
+ }
+
+ public function testFailureToFindColumn2()
+ {
+ $this->assertEquals(array(), array_column($this->numericColumns, 'foo'));
+ }
+
+ public function testFailureToFindColumn3()
+ {
+ $expected = array('aaa', 'bbb', 'ccc');
+ $this->assertEquals($expected, array_column($this->numericColumns, 0, 'foo'));
+ }
+
+ public function testFailureToFindColumn4()
+ {
+ $this->assertEquals(array(), array_column($this->numericColumns, 3.14));
+ }
+
+ public function testSingleDimensionalArray()
+ {
+ $singleDimension = array('foo', 'bar', 'baz');
+ $this->assertEquals(array(), array_column($singleDimension, 1));
+ }
+
+ public function testMismatchedColumns1()
+ {
+ $expected = array('qux');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'c'));
+ }
+
+ public function testMismatchedColumns2()
+ {
+ $expected = array('baz' => 'qux');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'c', 'a'));
+ }
+
+ public function testMismatchedColumns3()
+ {
+ $expected = array('foo', 'aaa' => 'baz', 'eee');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'a', 'd'));
+ }
+
+ public function testMismatchedColumns4()
+ {
+ $expected = array('bbb' => 'foo', 'baz', 'ggg' => 'eee');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'a', 'e'));
+ }
+
+ public function testMismatchedColumns5()
+ {
+ $expected = array('bar', 'fff');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'b'));
+ }
+
+ public function testMismatchedColumns6()
+ {
+ $expected = array('foo' => 'bar', 'eee' => 'fff');
+ $this->assertEquals($expected, array_column($this->mismatchedColumns, 'b', 'a'));
+ }
+
+ public function testObjectConvertedToString()
+ {
+ $f = new Foo();
+ $b = new Bar();
+ $this->assertEquals(array('Doe', 'Smith', 'Jones'), array_column($this->recordSet, $f));
+ $this->assertEquals(array('John' => 'Doe', 'Sally' => 'Smith', 'Jane' => 'Jones'), array_column($this->recordSet, $f, $b));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column() expects at least 2 parameters, 0 given
+ */
+ public function testFunctionWithZeroArgs()
+ {
+ $foo = array_column();
+ }
+
+ public function testFunctionWithZeroArgsReturnValue()
+ {
+ $foo = @array_column();
+ $this->assertNull($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column() expects at least 2 parameters, 1 given
+ */
+ public function testFunctionWithOneArg()
+ {
+ $foo = array_column(array());
+ }
+
+ public function testFunctionWithOneArgReturnValue()
+ {
+ $foo = @array_column(array());
+ $this->assertNull($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column() expects parameter 1 to be array, string given
+ */
+ public function testFunctionWithStringAsFirstArg()
+ {
+ $foo = array_column('foo', 0);
+ }
+
+ public function testFunctionWithStringAsFirstArgReturnValue()
+ {
+ $foo = @array_column('foo', 0);
+ $this->assertNull($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column() expects parameter 1 to be array, integer given
+ */
+ public function testFunctionWithIntAsFirstArg()
+ {
+ $foo = array_column(1, 'foo');
+ }
+
+ public function testFunctionWithIntAsFirstArgReturnValue()
+ {
+ $foo = @array_column(1, 'foo');
+ $this->assertNull($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column(): The column key should be either a string or an integer
+ */
+ public function testFunctionWithColumnKeyAsBool()
+ {
+ $foo = array_column(array(), true);
+ }
+
+ public function testFunctionWithColumnKeyAsBoolReturnValue()
+ {
+ $foo = @array_column(array(), true);
+ $this->assertFalse($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column(): The column key should be either a string or an integer
+ */
+ public function testFunctionWithColumnKeyAsArray()
+ {
+ $foo = array_column(array(), array());
+ }
+
+ public function testFunctionWithColumnKeyAsArrayReturnValue()
+ {
+ $foo = @array_column(array(), array());
+ $this->assertFalse($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column(): The index key should be either a string or an integer
+ */
+ public function testFunctionWithIndexKeyAsBool()
+ {
+ $foo = array_column(array(), 'foo', true);
+ }
+
+ public function testFunctionWithIndexKeyAsBoolReturnValue()
+ {
+ $foo = @array_column(array(), 'foo', true);
+ $this->assertFalse($foo);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error_Warning
+ * @expectedExceptionMessage array_column(): The index key should be either a string or an integer
+ */
+ public function testFunctionWithIndexKeyAsArray()
+ {
+ $foo = array_column(array(), 'foo', array());
+ }
+
+ public function testFunctionWithIndexKeyAsArrayReturnValue()
+ {
+ $foo = @array_column(array(), 'foo', array());
+ $this->assertFalse($foo);
+ }
+
+ /**
+ * @link https://bugs.php.net/bug.php?id=64493
+ */
+ public function testBugRequest64493()
+ {
+ // Array from Bug Request #64493 test script
+ $rows = array(
+ 456 => array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'),
+ 457 => array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'),
+ );
+
+ // pass null as second parameter to get back all columns indexed by third parameter
+ $expected1 = array(
+ 3 => array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'),
+ 5 => array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'),
+ );
+ $this->assertEquals($expected1, array_column($rows, null, 'id'));
+
+ // pass null as second parameter and bogus third param to get back zero-indexed array of all columns
+ $expected2 = array(
+ array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'),
+ array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'),
+ );
+ $this->assertEquals($expected2, array_column($rows, null, 'foo'));
+
+ // pass null as second parameter and no third param to get back array_values(input) (same as $expected2)
+ $this->assertEquals($expected2, array_column($rows, null));
+ }
+
+ public function testObjectCast()
+ {
+ $columnKey = new ColumnKeyClass();
+ $indexKey = new IndexKeyClass();
+ $value = new ValueClass();
+
+ $records = array(
+ array(
+ 'id' => $value,
+ 'first_name' => 'John',
+ 'last_name' => 'XXX'
+ ),
+ array(
+ 'id' => 3245,
+ 'first_name' => 'Sally',
+ 'last_name' => 'Smith'
+ ),
+ );
+
+ $expected = array(
+ 2135 => 'John',
+ 3245 => 'Sally',
+ );
+
+ $this->assertEquals($expected, array_column($records, $columnKey, $indexKey));
+ }
+}
+
+class Foo
+{
+ public function __toString()
+ {
+ return 'last_name';
+ }
+}
+
+class Bar
+{
+ public function __toString()
+ {
+ return 'first_name';
+ }
+}
+
+class ColumnKeyClass
+{
+ function __toString() { return 'first_name'; }
+}
+
+class IndexKeyClass
+{
+ function __toString() { return 'id'; }
+}
+
+class ValueClass
+{
+ function __toString() { return '2135'; }
+}
diff --git a/vendor/ramsey/array_column/tests/bootstrap.php b/vendor/ramsey/array_column/tests/bootstrap.php
new file mode 100644
index 00000000..97eabbac
--- /dev/null
+++ b/vendor/ramsey/array_column/tests/bootstrap.php
@@ -0,0 +1,5 @@
+=5.3.3"
+ },
+ "require-dev": {
+ "mockery/mockery": "~0.9.1",
+ "symfony/phpunit-bridge": "~3.2"
+ },
+ "autoload": {
+ "files": ["lib/swift_required.php"]
+ },
+ "autoload-dev": {
+ "psr-0": {
+ "Swift_": "tests/unit"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.4-dev"
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/doc/headers.rst b/vendor/swiftmailer/swiftmailer/doc/headers.rst
new file mode 100644
index 00000000..6aec23ff
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/headers.rst
@@ -0,0 +1,742 @@
+Message Headers
+===============
+
+Sometimes you'll want to add your own headers to a message or modify/remove
+headers that are already present. You work with the message's HeaderSet to do
+this.
+
+Header Basics
+-------------
+
+All MIME entities in Swift Mailer -- including the message itself --
+store their headers in a single object called a HeaderSet. This HeaderSet is
+retrieved with the ``getHeaders()`` method.
+
+As mentioned in the previous chapter, everything that forms a part of a message
+in Swift Mailer is a MIME entity that is represented by an instance of
+``Swift_Mime_MimeEntity``. This includes -- most notably -- the message object
+itself, attachments, MIME parts and embedded images. Each of these MIME entities
+consists of a body and a set of headers that describe the body.
+
+For all of the "standard" headers in these MIME entities, such as the
+``Content-Type``, there are named methods for working with them, such as
+``setContentType()`` and ``getContentType()``. This is because headers are a
+moderately complex area of the library. Each header has a slightly different
+required structure that it must meet in order to comply with the standards that
+govern email (and that are checked by spam blockers etc).
+
+You fetch the HeaderSet from a MIME entity like so:
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ // Fetch the HeaderSet from a Message object
+ $headers = $message->getHeaders();
+
+ $attachment = Swift_Attachment::fromPath('document.pdf');
+
+ // Fetch the HeaderSet from an attachment object
+ $headers = $attachment->getHeaders();
+
+The job of the HeaderSet is to contain and manage instances of Header objects.
+Depending upon the MIME entity the HeaderSet came from, the contents of the
+HeaderSet will be different, since an attachment for example has a different
+set of headers to those in a message.
+
+You can find out what the HeaderSet contains with a quick loop, dumping out
+the names of the headers:
+
+.. code-block:: php
+
+ foreach ($headers->getAll() as $header) {
+ printf("%s
\n", $header->getFieldName());
+ }
+
+ /*
+ Content-Transfer-Encoding
+ Content-Type
+ MIME-Version
+ Date
+ Message-ID
+ From
+ Subject
+ To
+ */
+
+You can also dump out the rendered HeaderSet by calling its ``toString()``
+method:
+
+.. code-block:: php
+
+ echo $headers->toString();
+
+ /*
+ Message-ID: <1234869991.499a9ee7f1d5e@swift.generated>
+ Date: Tue, 17 Feb 2009 22:26:31 +1100
+ Subject: Awesome subject!
+ From: sender@example.org
+ To: recipient@example.org
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=utf-8
+ Content-Transfer-Encoding: quoted-printable
+ */
+
+Where the complexity comes in is when you want to modify an existing header.
+This complexity comes from the fact that each header can be of a slightly
+different type (such as a Date header, or a header that contains email
+addresses, or a header that has key-value parameters on it!). Each header in the
+HeaderSet is an instance of ``Swift_Mime_Header``. They all have common
+functionality, but knowing exactly what type of header you're working with will
+allow you a little more control.
+
+You can determine the type of header by comparing the return value of its
+``getFieldType()`` method with the constants ``TYPE_TEXT``,
+``TYPE_PARAMETERIZED``, ``TYPE_DATE``, ``TYPE_MAILBOX``, ``TYPE_ID`` and
+``TYPE_PATH`` which are defined in ``Swift_Mime_Header``.
+
+
+.. code-block:: php
+
+ foreach ($headers->getAll() as $header) {
+ switch ($header->getFieldType()) {
+ case Swift_Mime_Header::TYPE_TEXT: $type = 'text';
+ break;
+ case Swift_Mime_Header::TYPE_PARAMETERIZED: $type = 'parameterized';
+ break;
+ case Swift_Mime_Header::TYPE_MAILBOX: $type = 'mailbox';
+ break;
+ case Swift_Mime_Header::TYPE_DATE: $type = 'date';
+ break;
+ case Swift_Mime_Header::TYPE_ID: $type = 'ID';
+ break;
+ case Swift_Mime_Header::TYPE_PATH: $type = 'path';
+ break;
+ }
+ printf("%s: is a %s header
\n", $header->getFieldName(), $type);
+ }
+
+ /*
+ Content-Transfer-Encoding: is a text header
+ Content-Type: is a parameterized header
+ MIME-Version: is a text header
+ Date: is a date header
+ Message-ID: is a ID header
+ From: is a mailbox header
+ Subject: is a text header
+ To: is a mailbox header
+ */
+
+Headers can be removed from the set, modified within the set, or added to the
+set.
+
+The following sections show you how to work with the HeaderSet and explain the
+details of each implementation of ``Swift_Mime_Header`` that may
+exist within the HeaderSet.
+
+Header Types
+------------
+
+Because all headers are modeled on different data (dates, addresses, text!)
+there are different types of Header in Swift Mailer. Swift Mailer attempts to
+categorize all possible MIME headers into more general groups, defined by a
+small number of classes.
+
+Text Headers
+~~~~~~~~~~~~
+
+Text headers are the simplest type of Header. They contain textual information
+with no special information included within it -- for example the Subject
+header in a message.
+
+There's nothing particularly interesting about a text header, though it is
+probably the one you'd opt to use if you need to add a custom header to a
+message. It represents text just like you'd think it does. If the text
+contains characters that are not permitted in a message header (such as new
+lines, or non-ascii characters) then the header takes care of encoding the
+text so that it can be used.
+
+No header -- including text headers -- in Swift Mailer is vulnerable to
+header-injection attacks. Swift Mailer breaks any attempt at header injection by
+encoding the dangerous data into a non-dangerous form.
+
+It's easy to add a new text header to a HeaderSet. You do this by calling the
+HeaderSet's ``addTextHeader()`` method.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addTextHeader('Your-Header-Name', 'the header value');
+
+Changing the value of an existing text header is done by calling it's
+``setValue()`` method.
+
+.. code-block:: php
+
+ $subject = $message->getHeaders()->get('Subject');
+
+ $subject->setValue('new subject');
+
+When output via ``toString()``, a text header produces something like the
+following:
+
+.. code-block:: php
+
+ $subject = $message->getHeaders()->get('Subject');
+
+ $subject->setValue('amazing subject line');
+
+ echo $subject->toString();
+
+ /*
+
+ Subject: amazing subject line
+
+ */
+
+If the header contains any characters that are outside of the US-ASCII range
+however, they will be encoded. This is nothing to be concerned about since
+mail clients will decode them back.
+
+.. code-block:: php
+
+ $subject = $message->getHeaders()->get('Subject');
+
+ $subject->setValue('contains – dash');
+
+ echo $subject->toString();
+
+ /*
+
+ Subject: contains =?utf-8?Q?=E2=80=93?= dash
+
+ */
+
+Parameterized Headers
+~~~~~~~~~~~~~~~~~~~~~
+
+Parameterized headers are text headers that contain key-value parameters
+following the textual content. The Content-Type header of a message is a
+parameterized header since it contains charset information after the content
+type.
+
+The parameterized header type is a special type of text header. It extends the
+text header by allowing additional information to follow it. All of the methods
+from text headers are available in addition to the methods described here.
+
+Adding a parameterized header to a HeaderSet is done by using the
+``addParameterizedHeader()`` method which takes a text value like
+``addTextHeader()`` but it also accepts an associative array of
+key-value parameters.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addParameterizedHeader(
+ 'Header-Name', 'header value',
+ array('foo' => 'bar')
+ );
+
+To change the text value of the header, call it's ``setValue()`` method just as
+you do with text headers.
+
+To change the parameters in the header, call the header's ``setParameters()``
+method or the ``setParameter()`` method (note the pluralization).
+
+.. code-block:: php
+
+ $type = $message->getHeaders()->get('Content-Type');
+
+ // setParameters() takes an associative array
+ $type->setParameters(array(
+ 'name' => 'file.txt',
+ 'charset' => 'iso-8859-1'
+ ));
+
+ // setParameter() takes two args for $key and $value
+ $type->setParameter('charset', 'iso-8859-1');
+
+When output via ``toString()``, a parameterized header produces something like
+the following:
+
+.. code-block:: php
+
+ $type = $message->getHeaders()->get('Content-Type');
+
+ $type->setValue('text/html');
+ $type->setParameter('charset', 'utf-8');
+
+ echo $type->toString();
+
+ /*
+
+ Content-Type: text/html; charset=utf-8
+
+ */
+
+If the header contains any characters that are outside of the US-ASCII range
+however, they will be encoded, just like they are for text headers. This is
+nothing to be concerned about since mail clients will decode them back.
+Likewise, if the parameters contain any non-ascii characters they will be
+encoded so that they can be transmitted safely.
+
+.. code-block:: php
+
+ $attachment = Swift_Attachment::newInstance();
+
+ $disp = $attachment->getHeaders()->get('Content-Disposition');
+
+ $disp->setValue('attachment');
+ $disp->setParameter('filename', 'report–may.pdf');
+
+ echo $disp->toString();
+
+ /*
+
+ Content-Disposition: attachment; filename*=utf-8''report%E2%80%93may.pdf
+
+ */
+
+Date Headers
+~~~~~~~~~~~~
+
+Date headers contains an RFC 2822 formatted date (i.e. what PHP's ``date('r')``
+returns). They are used anywhere a date or time is needed to be presented as a
+message header.
+
+The data on which a date header is modeled is simply a UNIX timestamp such as
+that returned by ``time()`` or ``strtotime()``. The timestamp is used to create
+a correctly structured RFC 2822 formatted date such as
+``Tue, 17 Feb 2009 22:26:31 +1100``.
+
+The obvious place this header type is used is in the ``Date:`` header of the
+message itself.
+
+It's easy to add a new date header to a HeaderSet. You do this by calling
+the HeaderSet's ``addDateHeader()`` method.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addDateHeader('Your-Header-Name', strtotime('3 days ago'));
+
+Changing the value of an existing date header is done by calling it's
+``setTimestamp()`` method.
+
+.. code-block:: php
+
+ $date = $message->getHeaders()->get('Date');
+
+ $date->setTimestamp(time());
+
+When output via ``toString()``, a date header produces something like the
+following:
+
+.. code-block:: php
+
+ $date = $message->getHeaders()->get('Date');
+
+ echo $date->toString();
+
+ /*
+
+ Date: Wed, 18 Feb 2009 13:35:02 +1100
+
+ */
+
+Mailbox (e-mail address) Headers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Mailbox headers contain one or more email addresses, possibly with
+personalized names attached to them. The data on which they are modeled is
+represented by an associative array of email addresses and names.
+
+Mailbox headers are probably the most complex header type to understand in
+Swift Mailer because they accept their input as an array which can take various
+forms, as described in the previous chapter.
+
+All of the headers that contain e-mail addresses in a message -- with the
+exception of ``Return-Path:`` which has a stricter syntax -- use this header
+type. That is, ``To:``, ``From:`` etc.
+
+You add a new mailbox header to a HeaderSet by calling the HeaderSet's
+``addMailboxHeader()`` method.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addMailboxHeader('Your-Header-Name', array(
+ 'person1@example.org' => 'Person Name One',
+ 'person2@example.org',
+ 'person3@example.org',
+ 'person4@example.org' => 'Another named person'
+ ));
+
+Changing the value of an existing mailbox header is done by calling it's
+``setNameAddresses()`` method.
+
+.. code-block:: php
+
+ $to = $message->getHeaders()->get('To');
+
+ $to->setNameAddresses(array(
+ 'joe@example.org' => 'Joe Bloggs',
+ 'john@example.org' => 'John Doe',
+ 'no-name@example.org'
+ ));
+
+If you don't wish to concern yourself with the complicated accepted input
+formats accepted by ``setNameAddresses()`` as described in the previous chapter
+and you only want to set one or more addresses (not names) then you can just
+use the ``setAddresses()`` method instead.
+
+.. code-block:: php
+
+ $to = $message->getHeaders()->get('To');
+
+ $to->setAddresses(array(
+ 'joe@example.org',
+ 'john@example.org',
+ 'no-name@example.org'
+ ));
+
+.. note::
+
+ Both methods will accept the above input format in practice.
+
+If all you want to do is set a single address in the header, you can use a
+string as the input parameter to ``setAddresses()`` and/or
+``setNameAddresses()``.
+
+.. code-block:: php
+
+ $to = $message->getHeaders()->get('To');
+
+ $to->setAddresses('joe-bloggs@example.org');
+
+When output via ``toString()``, a mailbox header produces something like the
+following:
+
+.. code-block:: php
+
+ $to = $message->getHeaders()->get('To');
+
+ $to->setNameAddresses(array(
+ 'person1@example.org' => 'Name of Person',
+ 'person2@example.org',
+ 'person3@example.org' => 'Another Person'
+ ));
+
+ echo $to->toString();
+
+ /*
+
+ To: Name of Person , person2@example.org, Another Person
+
+
+ */
+
+ID Headers
+~~~~~~~~~~
+
+ID headers contain identifiers for the entity (or the message). The most
+notable ID header is the Message-ID header on the message itself.
+
+An ID that exists inside an ID header looks more-or-less less like an email
+address. For example, ``<1234955437.499becad62ec2@example.org>``.
+The part to the left of the @ sign is usually unique, based on the current time
+and some random factor. The part on the right is usually a domain name.
+
+Any ID passed to the header's ``setId()`` method absolutely MUST conform to
+this structure, otherwise you'll get an Exception thrown at you by Swift Mailer
+(a ``Swift_RfcComplianceException``). This is to ensure that the generated
+email complies with relevant RFC documents and therefore is less likely to be
+blocked as spam.
+
+It's easy to add a new ID header to a HeaderSet. You do this by calling
+the HeaderSet's ``addIdHeader()`` method.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addIdHeader('Your-Header-Name', '123456.unqiue@example.org');
+
+Changing the value of an existing date header is done by calling its
+``setId()`` method.
+
+.. code-block:: php
+
+ $msgId = $message->getHeaders()->get('Message-ID');
+
+ $msgId->setId(time() . '.' . uniqid('thing') . '@example.org');
+
+When output via ``toString()``, an ID header produces something like the
+following:
+
+.. code-block:: php
+
+ $msgId = $message->getHeaders()->get('Message-ID');
+
+ echo $msgId->toString();
+
+ /*
+
+ Message-ID: <1234955437.499becad62ec2@example.org>
+
+ */
+
+Path Headers
+~~~~~~~~~~~~
+
+Path headers are like very-restricted mailbox headers. They contain a single
+email address with no associated name. The Return-Path header of a message is
+a path header.
+
+You add a new path header to a HeaderSet by calling the HeaderSet's
+``addPathHeader()`` method.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $headers = $message->getHeaders();
+
+ $headers->addPathHeader('Your-Header-Name', 'person@example.org');
+
+
+Changing the value of an existing path header is done by calling its
+``setAddress()`` method.
+
+.. code-block:: php
+
+ $return = $message->getHeaders()->get('Return-Path');
+
+ $return->setAddress('my-address@example.org');
+
+When output via ``toString()``, a path header produces something like the
+following:
+
+.. code-block:: php
+
+ $return = $message->getHeaders()->get('Return-Path');
+
+ $return->setAddress('person@example.org');
+
+ echo $return->toString();
+
+ /*
+
+ Return-Path:
+
+ */
+
+Header Operations
+-----------------
+
+Working with the headers in a message involves knowing how to use the methods
+on the HeaderSet and on the individual Headers within the HeaderSet.
+
+Adding new Headers
+~~~~~~~~~~~~~~~~~~
+
+New headers can be added to the HeaderSet by using one of the provided
+``add..Header()`` methods.
+
+To add a header to a MIME entity (such as the message):
+
+Get the HeaderSet from the entity by via its ``getHeaders()`` method.
+
+* Add the header to the HeaderSet by calling one of the ``add..Header()``
+ methods.
+
+The added header will appear in the message when it is sent.
+
+.. code-block:: php
+
+ // Adding a custom header to a message
+ $message = Swift_Message::newInstance();
+ $headers = $message->getHeaders();
+ $headers->addTextHeader('X-Mine', 'something here');
+
+ // Adding a custom header to an attachment
+ $attachment = Swift_Attachment::fromPath('/path/to/doc.pdf');
+ $attachment->getHeaders()->addDateHeader('X-Created-Time', time());
+
+Retrieving Headers
+~~~~~~~~~~~~~~~~~~
+
+Headers are retrieved through the HeaderSet's ``get()`` and ``getAll()``
+methods.
+
+To get a header, or several headers from a MIME entity:
+
+* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
+
+* Get the header(s) from the HeaderSet by calling either ``get()`` or
+ ``getAll()``.
+
+When using ``get()`` a single header is returned that matches the name (case
+insensitive) that is passed to it. When using ``getAll()`` with a header name,
+an array of headers with that name are returned. Calling ``getAll()`` with no
+arguments returns an array of all headers present in the entity.
+
+.. note::
+
+ It's valid for some headers to appear more than once in a message (e.g.
+ the Received header). For this reason ``getAll()`` exists to fetch all
+ headers with a specified name. In addition, ``get()`` accepts an optional
+ numerical index, starting from zero to specify which header you want more
+ specifically.
+
+.. note::
+
+ If you want to modify the contents of the header and you don't know for
+ sure what type of header it is then you may need to check the type by
+ calling its ``getFieldType()`` method.
+
+ .. code-block:: php
+
+ $headers = $message->getHeaders();
+
+ // Get the To: header
+ $toHeader = $headers->get('To');
+
+ // Get all headers named "X-Foo"
+ $fooHeaders = $headers->getAll('X-Foo');
+
+ // Get the second header named "X-Foo"
+ $foo = $headers->get('X-Foo', 1);
+
+ // Get all headers that are present
+ $all = $headers->getAll();
+
+Check if a Header Exists
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can check if a named header is present in a HeaderSet by calling its
+``has()`` method.
+
+To check if a header exists:
+
+* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
+
+* Call the HeaderSet's ``has()`` method specifying the header you're looking
+ for.
+
+If the header exists, ``true`` will be returned or ``false`` if not.
+
+.. note::
+
+ It's valid for some headers to appear more than once in a message (e.g.
+ the Received header). For this reason ``has()`` accepts an optional
+ numerical index, starting from zero to specify which header you want to
+ check more specifically.
+
+ .. code-block:: php
+
+ $headers = $message->getHeaders();
+
+ // Check if the To: header exists
+ if ($headers->has('To')) {
+ echo 'To: exists';
+ }
+
+ // Check if an X-Foo header exists twice (i.e. check for the 2nd one)
+ if ($headers->has('X-Foo', 1)) {
+ echo 'Second X-Foo header exists';
+ }
+
+Removing Headers
+~~~~~~~~~~~~~~~~
+
+Removing a Header from the HeaderSet is done by calling the HeaderSet's
+``remove()`` or ``removeAll()`` methods.
+
+To remove an existing header:
+
+* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
+
+* Call the HeaderSet's ``remove()`` or ``removeAll()`` methods specifying the
+ header you want to remove.
+
+When calling ``remove()`` a single header will be removed. When calling
+``removeAll()`` all headers with the given name will be removed. If no headers
+exist with the given name, no errors will occur.
+
+.. note::
+
+ It's valid for some headers to appear more than once in a message (e.g.
+ the Received header). For this reason ``remove()`` accepts an optional
+ numerical index, starting from zero to specify which header you want to
+ check more specifically. For the same reason, ``removeAll()`` exists to
+ remove all headers that have the given name.
+
+ .. code-block:: php
+
+ $headers = $message->getHeaders();
+
+ // Remove the Subject: header
+ $headers->remove('Subject');
+
+ // Remove all X-Foo headers
+ $headers->removeAll('X-Foo');
+
+ // Remove only the second X-Foo header
+ $headers->remove('X-Foo', 1);
+
+Modifying a Header's Content
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To change a Header's content you should know what type of header it is and then
+call it's appropriate setter method. All headers also have a
+``setFieldBodyModel()`` method that accepts a mixed parameter and delegates to
+the correct setter.
+
+To modify an existing header:
+
+* Get the HeaderSet from the entity by via its ``getHeaders()`` method.
+
+* Get the Header by using the HeaderSet's ``get()``.
+
+* Call the Header's appropriate setter method or call the header's
+ ``setFieldBodyModel()`` method.
+
+The header will be updated inside the HeaderSet and the changes will be seen
+when the message is sent.
+
+.. code-block:: php
+
+ $headers = $message->getHeaders();
+
+ // Change the Subject: header
+ $subj = $headers->get('Subject');
+ $subj->setValue('new subject here');
+
+ // Change the To: header
+ $to = $headers->get('To');
+ $to->setNameAddresses(array(
+ 'person@example.org' => 'Person',
+ 'thing@example.org'
+ ));
+
+ // Using the setFieldBodyModel() just delegates to the correct method
+ // So here to calls setNameAddresses()
+ $to->setFieldBodyModel(array(
+ 'person@example.org' => 'Person',
+ 'thing@example.org'
+ ));
diff --git a/vendor/swiftmailer/swiftmailer/doc/help-resources.rst b/vendor/swiftmailer/swiftmailer/doc/help-resources.rst
new file mode 100644
index 00000000..42089359
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/help-resources.rst
@@ -0,0 +1,44 @@
+Getting Help
+============
+
+There are a number of ways you can get help when using Swift Mailer, depending
+upon the nature of your problem. For bug reports and feature requests create a
+new ticket in GitHub. For general advice ask on the Google Group
+(swiftmailer).
+
+Submitting Bugs & Feature Requests
+----------------------------------
+
+Bugs and feature requests should be posted on GitHub.
+
+If you post a bug or request a feature in the forum, or on the Google Group
+you will most likely be asked to create a ticket in `GitHub`_ since it is
+simply not feasible to manage such requests from a number of a different
+sources.
+
+When you go to GitHub you will be asked to create a username and password
+before you can create a ticket. This is free and takes very little time.
+
+When you create your ticket, do not assign it to any milestones. A developer
+will assess your ticket and re-assign it as needed.
+
+If your ticket is reporting a bug present in the current version, which was
+not present in the previous version please include the tag "regression" in
+your ticket.
+
+GitHub will update you when work is performed on your ticket.
+
+Ask on the Google Group
+-----------------------
+
+You can seek advice at Google Groups, within the "swiftmailer" `group`_.
+
+You can post messages to this group if you want help, or there's something you
+wish to discuss with the developers and with other users.
+
+This is probably the fastest way to get help since it is primarily email-based
+for most users, though bug reports should not be posted here since they may
+not be resolved.
+
+.. _`GitHub`: https://github.com/swiftmailer/swiftmailer/issues
+.. _`group`: http://groups.google.com/group/swiftmailer
diff --git a/vendor/swiftmailer/swiftmailer/doc/including-the-files.rst b/vendor/swiftmailer/swiftmailer/doc/including-the-files.rst
new file mode 100644
index 00000000..978dca20
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/including-the-files.rst
@@ -0,0 +1,46 @@
+Including Swift Mailer (Autoloading)
+====================================
+
+If you are using Composer, Swift Mailer will be automatically autoloaded.
+
+If not, you can use the built-in autoloader by requiring the
+``swift_required.php`` file::
+
+ require_once '/path/to/swift-mailer/lib/swift_required.php';
+
+ /* rest of code goes here */
+
+If you want to override the default Swift Mailer configuration, call the
+``init()`` method on the ``Swift`` class and pass it a valid PHP callable (a
+PHP function name, a PHP 5.3 anonymous function, ...)::
+
+ require_once '/path/to/swift-mailer/lib/swift_required.php';
+
+ function swiftmailer_configurator() {
+ // configure Swift Mailer
+
+ Swift_DependencyContainer::getInstance()->...
+ Swift_Preferences::getInstance()->...
+ }
+
+ Swift::init('swiftmailer_configurator');
+
+ /* rest of code goes here */
+
+The advantage of using the ``init()`` method is that your code will be
+executed only if you use Swift Mailer in your script.
+
+.. note::
+
+ While Swift Mailer's autoloader is designed to play nicely with other
+ autoloaders, sometimes you may have a need to avoid using Swift Mailer's
+ autoloader and use your own instead. Include the ``swift_init.php``
+ instead of the ``swift_required.php`` if you need to do this. The very
+ minimum include is the ``swift_init.php`` file since Swift Mailer will not
+ work without the dependency injection this file sets up:
+
+ .. code-block:: php
+
+ require_once '/path/to/swift-mailer/lib/swift_init.php';
+
+ /* rest of code goes here */
diff --git a/vendor/swiftmailer/swiftmailer/doc/index.rst b/vendor/swiftmailer/swiftmailer/doc/index.rst
new file mode 100644
index 00000000..a1a0a924
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/index.rst
@@ -0,0 +1,16 @@
+Swiftmailer
+===========
+
+.. toctree::
+ :maxdepth: 2
+
+ introduction
+ overview
+ installing
+ help-resources
+ including-the-files
+ messages
+ headers
+ sending
+ plugins
+ japanese
diff --git a/vendor/swiftmailer/swiftmailer/doc/installing.rst b/vendor/swiftmailer/swiftmailer/doc/installing.rst
new file mode 100644
index 00000000..557211d4
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/installing.rst
@@ -0,0 +1,89 @@
+Installing the Library
+======================
+
+Installing with Composer
+------------------------
+
+The recommended way to install Swiftmailer is via Composer:
+
+.. code-block:: bash
+
+ $ php composer.phar require swiftmailer/swiftmailer @stable
+
+Installing from Git
+-------------------
+
+It's possible to download and install Swift Mailer directly from github.com if
+you want to keep up-to-date with ease.
+
+Swift Mailer's source code is kept in a git repository at github.com so you
+can get the source directly from the repository.
+
+.. note::
+
+ You do not need to have git installed to use Swift Mailer from GitHub. If
+ you don't have git installed, go to `GitHub`_ and click the "Download"
+ button.
+
+Cloning the Repository
+~~~~~~~~~~~~~~~~~~~~~~
+
+The repository can be cloned from git://github.com/swiftmailer/swiftmailer.git
+using the ``git clone`` command.
+
+You will need to have ``git`` installed before you can use the
+``git clone`` command.
+
+To clone the repository:
+
+* Open your favorite terminal environment (command line).
+
+* Move to the directory you want to clone to.
+
+* Run the command ``git clone git://github.com/swiftmailer/swiftmailer.git
+ swiftmailer``.
+
+The source code will be downloaded into a directory called "swiftmailer".
+
+The example shows the process on a UNIX-like system such as Linux, BSD or Mac
+OS X.
+
+.. code-block:: bash
+
+ $ cd source_code/
+ $ git clone git://github.com/swiftmailer/swiftmailer.git swiftmailer
+ Initialized empty Git repository in /Users/chris/source_code/swiftmailer/.git/
+ remote: Counting objects: 6815, done.
+ remote: Compressing objects: 100% (2761/2761), done.
+ remote: Total 6815 (delta 3641), reused 6326 (delta 3286)
+ Receiving objects: 100% (6815/6815), 4.35 MiB | 162 KiB/s, done.
+ Resolving deltas: 100% (3641/3641), done.
+ Checking out files: 100% (1847/1847), done.
+ $ cd swiftmailer/
+ $ ls
+ CHANGES LICENSE ...
+ $
+
+Troubleshooting
+---------------
+
+Swift Mailer does not work when used with function overloading as implemented
+by ``mbstring`` (``mbstring.func_overload`` set to ``2``). A workaround is to
+temporarily change the internal encoding to ``ASCII`` when sending an email:
+
+.. code-block:: php
+
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
+ {
+ $mbEncoding = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
+ // Create your message and send it with Swift Mailer
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+.. _`GitHub`: http://github.com/swiftmailer/swiftmailer
diff --git a/vendor/swiftmailer/swiftmailer/doc/introduction.rst b/vendor/swiftmailer/swiftmailer/doc/introduction.rst
new file mode 100644
index 00000000..a85336b7
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/introduction.rst
@@ -0,0 +1,135 @@
+Introduction
+============
+
+Swift Mailer is a component-based library for sending e-mails from PHP
+applications.
+
+Organization of this Book
+-------------------------
+
+This book has been written so that those who need information quickly are able
+to find what they need, and those who wish to learn more advanced topics can
+read deeper into each chapter.
+
+The book begins with an overview of Swift Mailer, discussing what's included
+in the package and preparing you for the remainder of the book.
+
+It is possible to read this user guide just like any other book (from
+beginning to end). Each chapter begins with a discussion of the contents it
+contains, followed by a short code sample designed to give you a head start.
+As you get further into a chapter you will learn more about Swift Mailer's
+capabilities, but often you will be able to head directly to the topic you
+wish to learn about.
+
+Throughout this book you will be presented with code samples, which most
+people should find ample to implement Swift Mailer appropriately in their own
+projects. We will also use diagrams where appropriate, and where we believe
+readers may find it helpful we will discuss some related theory, including
+reference to certain documents you are able to find online.
+
+Code Samples
+------------
+
+Code samples presented in this book will be displayed on a different colored
+background in a monospaced font. Samples are not to be taken as copy & paste
+code snippets.
+
+Code examples are used through the book to clarify what is written in text.
+They will sometimes be usable as-is, but they should always be taken as
+outline/pseudo code only.
+
+A code sample will look like this::
+
+ class AClass
+ {
+ ...
+ }
+
+ // A Comment
+ $obj = new AClass($arg1, $arg2, ... );
+
+ /* A note about another way of doing something
+ $obj = AClass::newInstance($arg1, $arg2, ... );
+
+ */
+
+The presence of 3 dots ``...`` in a code sample indicates that we have left
+out a chunk of the code for brevity, they are not actually part of the code.
+
+We will often place multi-line comments ``/* ... */`` in the code so that we
+can show alternative ways of achieving the same result.
+
+You should read the code examples given and try to understand them. They are
+kept concise so that you are not overwhelmed with information.
+
+History of Swift Mailer
+-----------------------
+
+Swift Mailer began back in 2005 as a one-class project for sending mail over
+SMTP. It has since grown into the flexible component-based library that is in
+development today.
+
+Chris Corbyn first posted Swift Mailer on a web forum asking for comments from
+other developers. It was never intended as a fully supported open source
+project, but members of the forum began to adopt it and make use of it.
+
+Very quickly feature requests were coming for the ability to add attachments
+and use SMTP authentication, along with a number of other "obvious" missing
+features. Considering the only alternative was PHPMailer it seemed like a good
+time to bring some fresh tools to the table. Chris began working towards a
+more component based, PHP5-like approach unlike the existing single-class,
+legacy PHP4 approach taken by PHPMailer.
+
+Members of the forum offered a lot of advice and critique on the code as he
+worked through this project and released versions 2 and 3 of the library in
+2005 and 2006, which by then had been broken down into smaller classes
+offering more flexibility and supporting plugins. To this day the Swift Mailer
+team still receive a lot of feature requests from users both on the forum and
+in by email.
+
+Until 2008 Chris was the sole developer of Swift Mailer, but entering 2009 he
+gained the support of two experienced developers well-known to him: Paul
+Annesley and Christopher Thompson. This has been an extremely welcome change.
+
+As of September 2009, Chris handed over the maintenance of Swift Mailer to
+Fabien Potencier.
+
+Now 2009 and in its fourth major version Swift Mailer is more object-oriented
+and flexible than ever, both from a usability standpoint and from a
+development standpoint.
+
+By no means is Swift Mailer ready to call "finished". There are still many
+features that can be added to the library along with the constant refactoring
+that happens behind the scenes.
+
+It's a Library!
+---------------
+
+Swift Mailer is not an application - it's a library.
+
+To most experienced developers this is probably an obvious point to make, but
+it's certainly worth mentioning. Many people often contact us having gotten
+the completely wrong end of the stick in terms of what Swift Mailer is
+actually for.
+
+It's not an application. It does not have a graphical user interface. It
+cannot be opened in your web browser directly.
+
+It's a library (or a framework if you like). It provides a whole lot of
+classes that do some very complicated things, so that you don't have to. You
+"use" Swift Mailer within an application so that your application can have the
+ability to send emails.
+
+The component-based structure of the library means that you are free to
+implement it in a number of different ways and that you can pick and choose
+what you want to use.
+
+An application on the other hand (such as a blog or a forum) is already "put
+together" in a particular way, (usually) provides a graphical user interface
+and most likely doesn't offer a great deal of integration with your own
+application.
+
+Embrace the structure of the library and use the components it offers to your
+advantage. Learning what the components do, rather than blindly copying and
+pasting existing code will put you in a great position to build a powerful
+application!
diff --git a/vendor/swiftmailer/swiftmailer/doc/japanese.rst b/vendor/swiftmailer/swiftmailer/doc/japanese.rst
new file mode 100644
index 00000000..34afa7b8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/japanese.rst
@@ -0,0 +1,22 @@
+Using Swift Mailer for Japanese Emails
+======================================
+
+To send emails in Japanese, you need to tweak the default configuration.
+
+After requiring the Swift Mailer autoloader (by including the
+``swift_required.php`` file), call the ``Swift::init()`` method with the
+following code::
+
+ require_once '/path/to/swift-mailer/lib/swift_required.php';
+
+ Swift::init(function () {
+ Swift_DependencyContainer::getInstance()
+ ->register('mime.qpheaderencoder')
+ ->asAliasOf('mime.base64headerencoder');
+
+ Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
+ });
+
+ /* rest of code goes here */
+
+That's all!
diff --git a/vendor/swiftmailer/swiftmailer/doc/messages.rst b/vendor/swiftmailer/swiftmailer/doc/messages.rst
new file mode 100644
index 00000000..fb5e7fc3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/messages.rst
@@ -0,0 +1,1061 @@
+Creating Messages
+=================
+
+Creating messages in Swift Mailer is done by making use of the various MIME
+entities provided with the library. Complex messages can be quickly created
+with very little effort.
+
+Quick Reference for Creating a Message
+---------------------------------------
+
+You can think of creating a Message as being similar to the steps you perform
+when you click the Compose button in your mail client. You give it a subject,
+specify some recipients, add any attachments and write your message.
+
+To create a Message:
+
+* Call the ``newInstance()`` method of ``Swift_Message``.
+
+* Set your sender address (``From:``) with ``setFrom()`` or ``setSender()``.
+
+* Set a subject line with ``setSubject()``.
+
+* Set recipients with ``setTo()``, ``setCc()`` and/or ``setBcc()``.
+
+* Set a body with ``setBody()``.
+
+* Add attachments with ``attach()``.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the message
+ $message = Swift_Message::newInstance()
+
+ // Give the message a subject
+ ->setSubject('Your subject')
+
+ // Set the From address with an associative array
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+
+ // Set the To addresses with an associative array
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+
+ // Give it a body
+ ->setBody('Here is the message itself')
+
+ // And optionally an alternative body
+ ->addPart('Here is the message itself
', 'text/html')
+
+ // Optionally add any attachments
+ ->attach(Swift_Attachment::fromPath('my-document.pdf'))
+ ;
+
+Message Basics
+--------------
+
+A message is a container for anything you want to send to somebody else. There
+are several basic aspects of a message that you should know.
+
+An e-mail message is made up of several relatively simple entities that are
+combined in different ways to achieve different results. All of these entities
+have the same fundamental outline but serve a different purpose. The Message
+itself can be defined as a MIME entity, an Attachment is a MIME entity, all
+MIME parts are MIME entities -- and so on!
+
+The basic units of each MIME entity -- be it the Message itself, or an
+Attachment -- are its Headers and its body:
+
+.. code-block:: text
+
+ Header-Name: A header value
+ Other-Header: Another value
+
+ The body content itself
+
+The Headers of a MIME entity, and its body must conform to some strict
+standards defined by various RFC documents. Swift Mailer ensures that these
+specifications are followed by using various types of object, including
+Encoders and different Header types to generate the entity.
+
+The Structure of a Message
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Of all of the MIME entities, a message -- ``Swift_Message``
+is the largest and most complex. It has many properties that can be updated
+and it can contain other MIME entities -- attachments for example --
+nested inside it.
+
+A Message has a lot of different Headers which are there to present
+information about the message to the recipients' mail client. Most of these
+headers will be familiar to the majority of users, but we'll list the basic
+ones. Although it's possible to work directly with the Headers of a Message
+(or other MIME entity), the standard Headers have accessor methods provided to
+abstract away the complex details for you. For example, although the Date on a
+message is written with a strict format, you only need to pass a UNIX
+timestamp to ``setDate()``.
+
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| Header | Description | Accessors |
++===============================+====================================================================================================================================+=============================================+
+| ``Message-ID`` | Identifies this message with a unique ID, usually containing the domain name and time generated | ``getId()`` / ``setId()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Return-Path`` | Specifies where bounces should go (Swift Mailer reads this for other uses) | ``getReturnPath()`` / ``setReturnPath()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``From`` | Specifies the address of the person who the message is from. This can be multiple addresses if multiple people wrote the message. | ``getFrom()`` / ``setFrom()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Sender`` | Specifies the address of the person who physically sent the message (higher precedence than ``From:``) | ``getSender()`` / ``setSender()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``To`` | Specifies the addresses of the intended recipients | ``getTo()`` / ``setTo()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Cc`` | Specifies the addresses of recipients who will be copied in on the message | ``getCc()`` / ``setCc()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Bcc`` | Specifies the addresses of recipients who the message will be blind-copied to. Other recipients will not be aware of these copies. | ``getBcc()`` / ``setBcc()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Reply-To`` | Specifies the address where replies are sent to | ``getReplyTo()`` / ``setReplyTo()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Subject`` | Specifies the subject line that is displayed in the recipients' mail client | ``getSubject()`` / ``setSubject()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Date`` | Specifies the date at which the message was sent | ``getDate()`` / ``setDate()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Content-Type`` | Specifies the format of the message (usually text/plain or text/html) | ``getContentType()`` / ``setContentType()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+| ``Content-Transfer-Encoding`` | Specifies the encoding scheme in the message | ``getEncoder()`` / ``setEncoder()`` |
++-------------------------------+------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+
+
+Working with a Message Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Although there are a lot of available methods on a message object, you only
+need to make use of a small subset of them. Usually you'll use
+``setSubject()``, ``setTo()`` and
+``setFrom()`` before setting the body of your message with
+``setBody()``.
+
+Calling methods is simple. You just call them like functions, but using the
+object operator "``->``" to do so. If you've created
+a message object and called it ``$message`` then you'd set a
+subject on it like so:
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ $message = Swift_Message::newInstance();
+ $message->setSubject('My subject');
+
+All MIME entities (including a message) have a ``toString()``
+method that you can call if you want to take a look at what is going to be
+sent. For example, if you ``echo
+$message->toString();`` you would see something like this:
+
+.. code-block:: bash
+
+ Message-ID: <1230173678.4952f5eeb1432@swift.generated>
+ Date: Thu, 25 Dec 2008 13:54:38 +1100
+ Subject: Example subject
+ From: Chris Corbyn
+ To: Receiver Name
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=utf-8
+ Content-Transfer-Encoding: quoted-printable
+
+ Here is the message
+
+We'll take a closer look at the methods you use to create your message in the
+following sections.
+
+Adding Content to Your Message
+------------------------------
+
+Rich content can be added to messages in Swift Mailer with relative ease by
+calling methods such as ``setSubject()``, ``setBody()``, ``addPart()`` and
+``attach()``.
+
+Setting the Subject Line
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The subject line, displayed in the recipients' mail client can be set with the
+``setSubject()`` method, or as a parameter to ``Swift_Message::newInstance()``.
+
+To set the subject of your Message:
+
+* Call the ``setSubject()`` method of the Message, or specify it at the time
+ you create the message.
+
+ .. code-block:: php
+
+ // Pass it as a parameter when you create the message
+ $message = Swift_Message::newInstance('My amazing subject');
+
+ // Or set it after like this
+ $message->setSubject('My amazing subject');
+
+Setting the Body Content
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The body of the message -- seen when the user opens the message --
+is specified by calling the ``setBody()`` method. If an alternative body is to
+be included ``addPart()`` can be used.
+
+The body of a message is the main part that is read by the user. Often people
+want to send a message in HTML format (``text/html``), other
+times people want to send in plain text (``text/plain``), or
+sometimes people want to send both versions and allow the recipient to choose
+how they view the message.
+
+As a rule of thumb, if you're going to send a HTML email, always include a
+plain-text equivalent of the same content so that users who prefer to read
+plain text can do so.
+
+To set the body of your Message:
+
+* Call the ``setBody()`` method of the Message, or specify it at the time you
+ create the message.
+
+* Add any alternative bodies with ``addPart()``.
+
+If the recipient's mail client offers preferences for displaying text vs. HTML
+then the mail client will present that part to the user where available. In
+other cases the mail client will display the "best" part it can - usually HTML
+if you've included HTML.
+
+.. code-block:: php
+
+ // Pass it as a parameter when you create the message
+ $message = Swift_Message::newInstance('Subject here', 'My amazing body');
+
+ // Or set it after like this
+ $message->setBody('My amazing body', 'text/html');
+
+ // Add alternative parts with addPart()
+ $message->addPart('My amazing body in plain text', 'text/plain');
+
+Attaching Files
+---------------
+
+Attachments are downloadable parts of a message and can be added by calling
+the ``attach()`` method on the message. You can add attachments that exist on
+disk, or you can create attachments on-the-fly.
+
+Attachments are actually an interesting area of Swift Mailer and something
+that could put a lot of power at your fingertips if you grasp the concept
+behind the way a message is held together.
+
+Although we refer to files sent over e-mails as "attachments" -- because
+they're attached to the message -- lots of other parts of the message are
+actually "attached" even if we don't refer to these parts as attachments.
+
+File attachments are created by the ``Swift_Attachment`` class
+and then attached to the message via the ``attach()`` method on
+it. For all of the "every day" MIME types such as all image formats, word
+documents, PDFs and spreadsheets you don't need to explicitly set the
+content-type of the attachment, though it would do no harm to do so. For less
+common formats you should set the content-type -- which we'll cover in a
+moment.
+
+Attaching Existing Files
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Files that already exist, either on disk or at a URL can be attached to a
+message with just one line of code, using ``Swift_Attachment::fromPath()``.
+
+You can attach files that exist locally, or if your PHP installation has
+``allow_url_fopen`` turned on you can attach files from other
+websites.
+
+To attach an existing file:
+
+* Create an attachment with ``Swift_Attachment::fromPath()``.
+
+* Add the attachment to the message with ``attach()``.
+
+The attachment will be presented to the recipient as a downloadable file with
+the same filename as the one you attached.
+
+.. code-block:: php
+
+ // Create the attachment
+ // * Note that you can technically leave the content-type parameter out
+ $attachment = Swift_Attachment::fromPath('/path/to/image.jpg', 'image/jpeg');
+
+ // Attach it to the message
+ $message->attach($attachment);
+
+
+ // The two statements above could be written in one line instead
+ $message->attach(Swift_Attachment::fromPath('/path/to/image.jpg'));
+
+
+ // You can attach files from a URL if allow_url_fopen is on in php.ini
+ $message->attach(Swift_Attachment::fromPath('http://site.tld/logo.png'));
+
+Setting the Filename
+~~~~~~~~~~~~~~~~~~~~
+
+Usually you don't need to explicitly set the filename of an attachment because
+the name of the attached file will be used by default, but if you want to set
+the filename you use the ``setFilename()`` method of the Attachment.
+
+To change the filename of an attachment:
+
+* Call its ``setFilename()`` method.
+
+The attachment will be attached in the normal way, but meta-data sent inside
+the email will rename the file to something else.
+
+.. code-block:: php
+
+ // Create the attachment and call its setFilename() method
+ $attachment = Swift_Attachment::fromPath('/path/to/image.jpg')
+ ->setFilename('cool.jpg');
+
+
+ // Because there's a fluid interface, you can do this in one statement
+ $message->attach(
+ Swift_Attachment::fromPath('/path/to/image.jpg')->setFilename('cool.jpg')
+ );
+
+Attaching Dynamic Content
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Files that are generated at runtime, such as PDF documents or images created
+via GD can be attached directly to a message without writing them out to disk.
+Use the standard ``Swift_Attachment::newInstance()`` method.
+
+To attach dynamically created content:
+
+* Create your content as you normally would.
+
+* Create an attachment with ``Swift_Attachment::newInstance()``, specifying
+ the source data of your content along with a name and the content-type.
+
+* Add the attachment to the message with ``attach()``.
+
+The attachment will be presented to the recipient as a downloadable file
+with the filename and content-type you specify.
+
+.. note::
+
+ If you would usually write the file to disk anyway you should just attach
+ it with ``Swift_Attachment::fromPath()`` since this will use less memory:
+
+ .. code-block:: php
+
+ // Create your file contents in the normal way, but don't write them to disk
+ $data = create_my_pdf_data();
+
+ // Create the attachment with your data
+ $attachment = Swift_Attachment::newInstance($data, 'my-file.pdf', 'application/pdf');
+
+ // Attach it to the message
+ $message->attach($attachment);
+
+
+ // You can alternatively use method chaining to build the attachment
+ $attachment = Swift_Attachment::newInstance()
+ ->setFilename('my-file.pdf')
+ ->setContentType('application/pdf')
+ ->setBody($data)
+ ;
+
+Changing the Disposition
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Attachments just appear as files that can be saved to the Desktop if desired.
+You can make attachment appear inline where possible by using the
+``setDisposition()`` method of an attachment.
+
+To make an attachment appear inline:
+
+* Call its ``setDisposition()`` method.
+
+The attachment will be displayed within the email viewing window if the mail
+client knows how to display it.
+
+.. note::
+
+ If you try to create an inline attachment for a non-displayable file type
+ such as a ZIP file, the mail client should just present the attachment as
+ normal:
+
+ .. code-block:: php
+
+ // Create the attachment and call its setDisposition() method
+ $attachment = Swift_Attachment::fromPath('/path/to/image.jpg')
+ ->setDisposition('inline');
+
+
+ // Because there's a fluid interface, you can do this in one statement
+ $message->attach(
+ Swift_Attachment::fromPath('/path/to/image.jpg')->setDisposition('inline')
+ );
+
+Embedding Inline Media Files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Often people want to include an image or other content inline with a HTML
+message. It's easy to do this with HTML linking to remote resources, but this
+approach is usually blocked by mail clients. Swift Mailer allows you to embed
+your media directly into the message.
+
+Mail clients usually block downloads from remote resources because this
+technique was often abused as a mean of tracking who opened an email. If
+you're sending a HTML email and you want to include an image in the message
+another approach you can take is to embed the image directly.
+
+Swift Mailer makes embedding files into messages extremely streamlined. You
+embed a file by calling the ``embed()`` method of the message,
+which returns a value you can use in a ``src`` or
+``href`` attribute in your HTML.
+
+Just like with attachments, it's possible to embed dynamically generated
+content without having an existing file available.
+
+The embedded files are sent in the email as a special type of attachment that
+has a unique ID used to reference them within your HTML attributes. On mail
+clients that do not support embedded files they may appear as attachments.
+
+Although this is commonly done for images, in theory it will work for any
+displayable (or playable) media type. Support for other media types (such as
+video) is dependent on the mail client however.
+
+Embedding Existing Files
+........................
+
+Files that already exist, either on disk or at a URL can be embedded in a
+message with just one line of code, using ``Swift_EmbeddedFile::fromPath()``.
+
+You can embed files that exist locally, or if your PHP installation has
+``allow_url_fopen`` turned on you can embed files from other websites.
+
+To embed an existing file:
+
+* Create a message object with ``Swift_Message::newInstance()``.
+
+* Set the body as HTML, and embed a file at the correct point in the message with ``embed()``.
+
+The file will be displayed with the message inline with the HTML wherever its ID
+is used as a ``src`` attribute.
+
+.. note::
+
+ ``Swift_Image`` and ``Swift_EmbeddedFile`` are just aliases of one
+ another. ``Swift_Image`` exists for semantic purposes.
+
+.. note::
+
+ You can embed files in two stages if you prefer. Just capture the return
+ value of ``embed()`` in a variable and use that as the ``src`` attribute.
+
+ .. code-block:: php
+
+ // Create the message
+ $message = Swift_Message::newInstance('My subject');
+
+ // Set the body
+ $message->setBody(
+ '' .
+ ' ' .
+ ' ' .
+ ' Here is an image ' .
+ ' Rest of message' .
+ ' ' .
+ '',
+ 'text/html' // Mark the content-type as HTML
+ );
+
+ // You can embed files from a URL if allow_url_fopen is on in php.ini
+ $message->setBody(
+ '' .
+ ' ' .
+ ' ' .
+ ' Here is an image ' .
+ ' Rest of message' .
+ ' ' .
+ '',
+ 'text/html'
+ );
+
+
+ // If placing the embed() code inline becomes cumbersome
+ // it's easy to do this in two steps
+ $cid = $message->embed(Swift_Image::fromPath('image.png'));
+
+ $message->setBody(
+ '' .
+ ' ' .
+ ' ' .
+ ' Here is an image ' .
+ ' Rest of message' .
+ ' ' .
+ '',
+ 'text/html' // Mark the content-type as HTML
+ );
+
+Embedding Dynamic Content
+.........................
+
+Images that are generated at runtime, such as images created via GD can be
+embedded directly to a message without writing them out to disk. Use the
+standard ``Swift_Image::newInstance()`` method.
+
+To embed dynamically created content:
+
+* Create a message object with ``Swift_Message::newInstance()``.
+
+* Set the body as HTML, and embed a file at the correct point in the message
+ with ``embed()``. You will need to specify a filename and a content-type.
+
+The file will be displayed with the message inline with the HTML wherever its ID
+is used as a ``src`` attribute.
+
+.. note::
+
+ ``Swift_Image`` and ``Swift_EmbeddedFile`` are just aliases of one
+ another. ``Swift_Image`` exists for semantic purposes.
+
+.. note::
+
+ You can embed files in two stages if you prefer. Just capture the return
+ value of ``embed()`` in a variable and use that as the ``src`` attribute.
+
+ .. code-block:: php
+
+ // Create your file contents in the normal way, but don't write them to disk
+ $img_data = create_my_image_data();
+
+ // Create the message
+ $message = Swift_Message::newInstance('My subject');
+
+ // Set the body
+ $message->setBody(
+ '' .
+ ' ' .
+ ' ' .
+ ' Here is an image ' .
+ ' Rest of message' .
+ ' ' .
+ '',
+ 'text/html' // Mark the content-type as HTML
+ );
+
+
+ // If placing the embed() code inline becomes cumbersome
+ // it's easy to do this in two steps
+ $cid = $message->embed(Swift_Image::newInstance($img_data, 'image.jpg', 'image/jpeg'));
+
+ $message->setBody(
+ '' .
+ ' ' .
+ ' ' .
+ ' Here is an image ' .
+ ' Rest of message' .
+ ' ' .
+ '',
+ 'text/html' // Mark the content-type as HTML
+ );
+
+Adding Recipients to Your Message
+---------------------------------
+
+Recipients are specified within the message itself via ``setTo()``, ``setCc()``
+and ``setBcc()``. Swift Mailer reads these recipients from the message when it
+gets sent so that it knows where to send the message to.
+
+Message recipients are one of three types:
+
+* ``To:`` recipients -- the primary recipients (required)
+
+* ``Cc:`` recipients -- receive a copy of the message (optional)
+
+* ``Bcc:`` recipients -- hidden from other recipients (optional)
+
+Each type can contain one, or several addresses. It's possible to list only
+the addresses of the recipients, or you can personalize the address by
+providing the real name of the recipient.
+
+Make sure to add only valid email addresses as recipients. If you try to add an
+invalid email address with ``setTo()``, ``setCc()`` or ``setBcc()``, Swift
+Mailer will throw a ``Swift_RfcComplianceException``.
+
+If you add recipients automatically based on a data source that may contain
+invalid email addresses, you can prevent possible exceptions by validating the
+addresses using ``Swift_Validate::email($email)`` and only adding addresses
+that validate. Another way would be to wrap your ``setTo()``, ``setCc()`` and
+``setBcc()`` calls in a try-catch block and handle the
+``Swift_RfcComplianceException`` in the catch block.
+
+.. sidebar:: Syntax for Addresses
+
+ If you only wish to refer to a single email address (for example your
+ ``From:`` address) then you can just use a string.
+
+ .. code-block:: php
+
+ $message->setFrom('some@address.tld');
+
+ If you want to include a name then you must use an associative array.
+
+ .. code-block:: php
+
+ $message->setFrom(array('some@address.tld' => 'The Name'));
+
+ If you want to include multiple addresses then you must use an array.
+
+ .. code-block:: php
+
+ $message->setTo(array('some@address.tld', 'other@address.tld'));
+
+ You can mix personalized (addresses with a name) and non-personalized
+ addresses in the same list by mixing the use of associative and
+ non-associative array syntax.
+
+ .. code-block:: php
+
+ $message->setTo(array(
+ 'recipient-with-name@example.org' => 'Recipient Name One',
+ 'no-name@example.org', // Note that this is not a key-value pair
+ 'named-recipient@example.org' => 'Recipient Name Two'
+ ));
+
+Setting ``To:`` Recipients
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``To:`` recipients are required in a message and are set with the
+``setTo()`` or ``addTo()`` methods of the message.
+
+To set ``To:`` recipients, create the message object using either
+``new Swift_Message( ... )`` or ``Swift_Message::newInstance( ... )``,
+then call the ``setTo()`` method with a complete array of addresses, or use the
+``addTo()`` method to iteratively add recipients.
+
+The ``setTo()`` method accepts input in various formats as described earlier in
+this chapter. The ``addTo()`` method takes either one or two parameters. The
+first being the email address and the second optional parameter being the name
+of the recipient.
+
+``To:`` recipients are visible in the message headers and will be
+seen by the other recipients.
+
+.. note::
+
+ Multiple calls to ``setTo()`` will not add new recipients -- each
+ call overrides the previous calls. If you want to iteratively add
+ recipients, use the ``addTo()`` method.
+
+ .. code-block:: php
+
+ // Using setTo() to set all recipients in one go
+ $message->setTo(array(
+ 'person1@example.org',
+ 'person2@otherdomain.org' => 'Person 2 Name',
+ 'person3@example.org',
+ 'person4@example.org',
+ 'person5@example.org' => 'Person 5 Name'
+ ));
+
+ // Using addTo() to add recipients iteratively
+ $message->addTo('person1@example.org');
+ $message->addTo('person2@example.org', 'Person 2 Name');
+
+Setting ``Cc:`` Recipients
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``Cc:`` recipients are set with the ``setCc()`` or ``addCc()`` methods of the
+message.
+
+To set ``Cc:`` recipients, create the message object using either
+``new Swift_Message( ... )`` or ``Swift_Message::newInstance( ... )``, then call
+the ``setCc()`` method with a complete array of addresses, or use the
+``addCc()`` method to iteratively add recipients.
+
+The ``setCc()`` method accepts input in various formats as described earlier in
+this chapter. The ``addCc()`` method takes either one or two parameters. The
+first being the email address and the second optional parameter being the name
+of the recipient.
+
+``Cc:`` recipients are visible in the message headers and will be
+seen by the other recipients.
+
+.. note::
+
+ Multiple calls to ``setCc()`` will not add new recipients -- each
+ call overrides the previous calls. If you want to iteratively add Cc:
+ recipients, use the ``addCc()`` method.
+
+ .. code-block:: php
+
+ // Using setCc() to set all recipients in one go
+ $message->setCc(array(
+ 'person1@example.org',
+ 'person2@otherdomain.org' => 'Person 2 Name',
+ 'person3@example.org',
+ 'person4@example.org',
+ 'person5@example.org' => 'Person 5 Name'
+ ));
+
+ // Using addCc() to add recipients iteratively
+ $message->addCc('person1@example.org');
+ $message->addCc('person2@example.org', 'Person 2 Name');
+
+Setting ``Bcc:`` Recipients
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``Bcc:`` recipients receive a copy of the message without anybody else knowing
+it, and are set with the ``setBcc()`` or ``addBcc()`` methods of the message.
+
+To set ``Bcc:`` recipients, create the message object using either ``new
+Swift_Message( ... )`` or ``Swift_Message::newInstance( ... )``, then call the
+``setBcc()`` method with a complete array of addresses, or use
+the ``addBcc()`` method to iteratively add recipients.
+
+The ``setBcc()`` method accepts input in various formats as described earlier in
+this chapter. The ``addBcc()`` method takes either one or two parameters. The
+first being the email address and the second optional parameter being the name
+of the recipient.
+
+Only the individual ``Bcc:`` recipient will see their address in the message
+headers. Other recipients (including other ``Bcc:`` recipients) will not see the
+address.
+
+.. note::
+
+ Multiple calls to ``setBcc()`` will not add new recipients -- each
+ call overrides the previous calls. If you want to iteratively add Bcc:
+ recipients, use the ``addBcc()`` method.
+
+ .. code-block:: php
+
+ // Using setBcc() to set all recipients in one go
+ $message->setBcc(array(
+ 'person1@example.org',
+ 'person2@otherdomain.org' => 'Person 2 Name',
+ 'person3@example.org',
+ 'person4@example.org',
+ 'person5@example.org' => 'Person 5 Name'
+ ));
+
+ // Using addBcc() to add recipients iteratively
+ $message->addBcc('person1@example.org');
+ $message->addBcc('person2@example.org', 'Person 2 Name');
+
+Specifying Sender Details
+-------------------------
+
+An email must include information about who sent it. Usually this is managed
+by the ``From:`` address, however there are other options.
+
+The sender information is contained in three possible places:
+
+* ``From:`` -- the address(es) of who wrote the message (required)
+
+* ``Sender:`` -- the address of the single person who sent the message
+ (optional)
+
+* ``Return-Path:`` -- the address where bounces should go to (optional)
+
+You must always include a ``From:`` address by using ``setFrom()`` on the
+message. Swift Mailer will use this as the default ``Return-Path:`` unless
+otherwise specified.
+
+The ``Sender:`` address exists because the person who actually sent the email
+may not be the person who wrote the email. It has a higher precedence than the
+``From:`` address and will be used as the ``Return-Path:`` unless otherwise
+specified.
+
+Setting the ``From:`` Address
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A ``From:`` address is required and is set with the ``setFrom()`` method of the
+message. ``From:`` addresses specify who actually wrote the email, and usually who sent it.
+
+What most people probably don't realise is that you can have more than one
+``From:`` address if more than one person wrote the email -- for example if an
+email was put together by a committee.
+
+To set the ``From:`` address(es):
+
+* Call the ``setFrom()`` method on the Message.
+
+The ``From:`` address(es) are visible in the message headers and
+will be seen by the recipients.
+
+.. note::
+
+ If you set multiple ``From:`` addresses then you absolutely must set a
+ ``Sender:`` address to indicate who physically sent the message.
+
+ .. code-block:: php
+
+ // Set a single From: address
+ $message->setFrom('your@address.tld');
+
+ // Set a From: address including a name
+ $message->setFrom(array('your@address.tld' => 'Your Name'));
+
+ // Set multiple From: addresses if multiple people wrote the email
+ $message->setFrom(array(
+ 'person1@example.org' => 'Sender One',
+ 'person2@example.org' => 'Sender Two'
+ ));
+
+Setting the ``Sender:`` Address
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A ``Sender:`` address specifies who sent the message and is set with the
+``setSender()`` method of the message.
+
+To set the ``Sender:`` address:
+
+* Call the ``setSender()`` method on the Message.
+
+The ``Sender:`` address is visible in the message headers and will be seen by
+the recipients.
+
+This address will be used as the ``Return-Path:`` unless otherwise specified.
+
+.. note::
+
+ If you set multiple ``From:`` addresses then you absolutely must set a
+ ``Sender:`` address to indicate who physically sent the message.
+
+You must not set more than one sender address on a message because it's not
+possible for more than one person to send a single message.
+
+.. code-block:: php
+
+ $message->setSender('your@address.tld');
+
+Setting the ``Return-Path:`` (Bounce) Address
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``Return-Path:`` address specifies where bounce notifications should
+be sent and is set with the ``setReturnPath()`` method of the message.
+
+You can only have one ``Return-Path:`` and it must not include
+a personal name.
+
+To set the ``Return-Path:`` address:
+
+* Call the ``setReturnPath()`` method on the Message.
+
+Bounce notifications will be sent to this address.
+
+.. code-block:: php
+
+ $message->setReturnPath('bounces@address.tld');
+
+
+Signed/Encrypted Message
+------------------------
+
+To increase the integrity/security of a message it is possible to sign and/or
+encrypt an message using one or multiple signers.
+
+S/MIME
+~~~~~~
+
+S/MIME can sign and/or encrypt a message using the OpenSSL extension.
+
+When signing a message, the signer creates a signature of the entire content of the message (including attachments).
+
+The certificate and private key must be PEM encoded, and can be either created using for example OpenSSL or
+obtained at an official Certificate Authority (CA).
+
+**The recipient must have the CA certificate in the list of trusted issuers in order to verify the signature.**
+
+**Make sure the certificate supports emailProtection.**
+
+When using OpenSSL this can done by the including the *-addtrust emailProtection* parameter when creating the certificate.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $smimeSigner = Swift_Signers_SMimeSigner::newInstance();
+ $smimeSigner->setSignCertificate('/path/to/certificate.pem', '/path/to/private-key.pem');
+ $message->attachSigner($smimeSigner);
+
+When the private key is secured using a passphrase use the following instead.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $smimeSigner = Swift_Signers_SMimeSigner::newInstance();
+ $smimeSigner->setSignCertificate('/path/to/certificate.pem', array('/path/to/private-key.pem', 'passphrase'));
+ $message->attachSigner($smimeSigner);
+
+By default the signature is added as attachment,
+making the message still readable for mailing agents not supporting signed messages.
+
+Storing the message as binary is also possible but not recommended.
+
+.. code-block:: php
+
+ $smimeSigner->setSignCertificate('/path/to/certificate.pem', '/path/to/private-key.pem', PKCS7_BINARY);
+
+When encrypting the message (also known as enveloping), the entire message (including attachments)
+is encrypted using a certificate, and the recipient can then decrypt the message using corresponding private key.
+
+Encrypting ensures nobody can read the contents of the message without the private key.
+
+Normally the recipient provides a certificate for encrypting and keeping the decryption key private.
+
+Using both signing and encrypting is also possible.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance();
+
+ $smimeSigner = Swift_Signers_SMimeSigner::newInstance();
+ $smimeSigner->setSignCertificate('/path/to/sign-certificate.pem', '/path/to/private-key.pem');
+ $smimeSigner->setEncryptCertificate('/path/to/encrypt-certificate.pem');
+ $message->attachSigner($smimeSigner);
+
+The used encryption cipher can be set as the second parameter of setEncryptCertificate()
+
+See http://php.net/manual/openssl.ciphers for a list of supported ciphers.
+
+By default the message is first signed and then encrypted, this can be changed by adding.
+
+.. code-block:: php
+
+ $smimeSigner->setSignThenEncrypt(false);
+
+**Changing this is not recommended as most mail agents don't support this none-standard way.**
+
+Only when having trouble with sign then encrypt method, this should be changed.
+
+Requesting a Read Receipt
+-------------------------
+
+It is possible to request a read-receipt to be sent to an address when the
+email is opened. To request a read receipt set the address with
+``setReadReceiptTo()``.
+
+To request a read receipt:
+
+* Set the address you want the receipt to be sent to with the
+ ``setReadReceiptTo()`` method on the Message.
+
+When the email is opened, if the mail client supports it a notification will be sent to this address.
+
+.. note::
+
+ Read receipts won't work for the majority of recipients since many mail
+ clients auto-disable them. Those clients that will send a read receipt
+ will make the user aware that one has been requested.
+
+ .. code-block:: php
+
+ $message->setReadReceiptTo('your@address.tld');
+
+Setting the Character Set
+-------------------------
+
+The character set of the message (and it's MIME parts) is set with the
+``setCharset()`` method. You can also change the global default of UTF-8 by
+working with the ``Swift_Preferences`` class.
+
+Swift Mailer will default to the UTF-8 character set unless otherwise
+overridden. UTF-8 will work in most instances since it includes all of the
+standard US keyboard characters in addition to most international characters.
+
+It is absolutely vital however that you know what character set your message
+(or it's MIME parts) are written in otherwise your message may be received
+completely garbled.
+
+There are two places in Swift Mailer where you can change the character set:
+
+* In the ``Swift_Preferences`` class
+
+* On each individual message and/or MIME part
+
+To set the character set of your Message:
+
+* Change the global UTF-8 setting by calling
+ ``Swift_Preferences::setCharset()``; or
+
+* Call the ``setCharset()`` method on the message or the MIME part.
+
+ .. code-block:: php
+
+ // Approach 1: Change the global setting (suggested)
+ Swift_Preferences::getInstance()->setCharset('iso-8859-2');
+
+ // Approach 2: Call the setCharset() method of the message
+ $message = Swift_Message::newInstance()
+ ->setCharset('iso-8859-2');
+
+ // Approach 3: Specify the charset when setting the body
+ $message->setBody('My body', 'text/html', 'iso-8859-2');
+
+ // Approach 4: Specify the charset for each part added
+ $message->addPart('My part', 'text/plain', 'iso-8859-2');
+
+Setting the Line Length
+-----------------------
+
+The length of lines in a message can be changed by using the ``setMaxLineLength()`` method on the message. It should be kept to less than
+1000 characters.
+
+Swift Mailer defaults to using 78 characters per line in a message. This is
+done for historical reasons and so that the message can be easily viewed in
+plain-text terminals.
+
+To change the maximum length of lines in your Message:
+
+* Call the ``setMaxLineLength()`` method on the Message.
+
+Lines that are longer than the line length specified will be wrapped between
+words.
+
+.. note::
+
+ You should never set a maximum length longer than 1000 characters
+ according to RFC 2822. Doing so could have unspecified side-effects such
+ as truncating parts of your message when it is transported between SMTP
+ servers.
+
+ .. code-block:: php
+
+ $message->setMaxLineLength(1000);
+
+Setting the Message Priority
+----------------------------
+
+You can change the priority of the message with ``setPriority()``. Setting the
+priority will not change the way your email is sent -- it is purely an
+indicative setting for the recipient.
+
+The priority of a message is an indication to the recipient what significance
+it has. Swift Mailer allows you to set the priority by calling the
+``setPriority`` method. This method takes an integer value between 1 and 5:
+
+* `Swift_Mime_SimpleMessage::PRIORITY_HIGHEST`: 1
+* `Swift_Mime_SimpleMessage::PRIORITY_HIGH`: 2
+* `Swift_Mime_SimpleMessage::PRIORITY_NORMAL`: 3
+* `Swift_Mime_SimpleMessage::PRIORITY_LOW`: 4
+* `Swift_Mime_SimpleMessage::PRIORITY_LOWEST`: 5
+
+To set the message priority:
+
+* Set the priority as an integer between 1 and 5 with the ``setPriority()``
+ method on the Message.
+
+.. code-block:: php
+
+ // Indicate "High" priority
+ $message->setPriority(2);
+
+ // Or use the constant to be more explicit
+ $message->setPriority(Swift_Mime_SimpleMessage::PRIORITY_HIGH);
diff --git a/vendor/swiftmailer/swiftmailer/doc/overview.rst b/vendor/swiftmailer/swiftmailer/doc/overview.rst
new file mode 100644
index 00000000..ebfe0083
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/overview.rst
@@ -0,0 +1,159 @@
+Library Overview
+================
+
+Most features (and more) of your every day mail client software are provided
+by Swift Mailer, using object-oriented PHP code as the interface.
+
+In this chapter we will take a short tour of the various components, which put
+together form the Swift Mailer library as a whole. You will learn key
+terminology used throughout the rest of this book and you will gain a little
+understanding of the classes you will work with as you integrate Swift Mailer
+into your application.
+
+This chapter is intended to prepare you for the information contained in the
+subsequent chapters of this book. You may choose to skip this chapter if you
+are fairly technically minded, though it is likely to save you some time in
+the long run if you at least read between the lines here.
+
+System Requirements
+-------------------
+
+The basic requirements to operate Swift Mailer are extremely minimal and
+easily achieved. Historically, Swift Mailer has supported both PHP 4 and PHP 5
+by following a parallel development workflow. Now in it's fourth major
+version, and Swift Mailer operates on servers running PHP 5.3.3 or higher.
+
+The library aims to work with as many PHP 5 projects as possible:
+
+* PHP 5.3.3 or higher, with the SPL extension (standard)
+
+* Limited network access to connect to remote SMTP servers
+
+* 8 MB or more memory limit (Swift Mailer uses around 2 MB)
+
+Component Breakdown
+-------------------
+
+Swift Mailer is made up of many classes. Each of these classes can be grouped
+into a general "component" group which describes the task it is designed to
+perform.
+
+We'll take a brief look at the components which form Swift Mailer in this
+section of the book.
+
+The Mailer
+~~~~~~~~~~
+
+The mailer class, ``Swift_Mailer`` is the central class in the library where
+all of the other components meet one another. ``Swift_Mailer`` acts as a sort
+of message dispatcher, communicating with the underlying Transport to deliver
+your Message to all intended recipients.
+
+If you were to dig around in the source code for Swift Mailer you'd notice
+that ``Swift_Mailer`` itself is pretty bare. It delegates to other objects for
+most tasks and in theory, if you knew the internals of Swift Mailer well you
+could by-pass this class entirely. We wouldn't advise doing such a thing
+however -- there are reasons this class exists:
+
+* for consistency, regardless of the Transport used
+
+* to provide abstraction from the internals in the event internal API changes
+ are made
+
+* to provide convenience wrappers around aspects of the internal API
+
+An instance of ``Swift_Mailer`` is created by the developer before sending any
+Messages.
+
+Transports
+~~~~~~~~~~
+
+Transports are the classes in Swift Mailer that are responsible for
+communicating with a service in order to deliver a Message. There are several
+types of Transport in Swift Mailer, all of which implement the Swift_Transport
+interface and offer underlying start(), stop() and send() methods.
+
+Typically you will not need to know how a Transport works under-the-surface,
+you will only need to know how to create an instance of one, and which one to
+use for your environment.
+
++---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+| Class | Features | Pros/cons |
++=================================+=============================================================================================+===============================================================================================================================================+
+| ``Swift_SmtpTransport`` | Sends messages over SMTP; Supports Authentication; Supports Encryption | Very portable; Pleasingly predictable results; Provides good feedback |
++---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+| ``Swift_SendmailTransport`` | Communicates with a locally installed ``sendmail`` executable (Linux/UNIX) | Quick time-to-run; Provides less-accurate feedback than SMTP; Requires ``sendmail`` installation |
++---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+| ``Swift_LoadBalancedTransport`` | Cycles through a collection of the other Transports to manage load-reduction | Provides graceful fallback if one Transport fails (e.g. an SMTP server is down); Keeps the load on remote services down by spreading the work |
++---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+| ``Swift_FailoverTransport`` | Works in conjunction with a collection of the other Transports to provide high-availability | Provides graceful fallback if one Transport fails (e.g. an SMTP server is down) |
++---------------------------------+---------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+
+MIME Entities
+~~~~~~~~~~~~~
+
+Everything that forms part of a Message is called a MIME Entity. All MIME
+entities in Swift Mailer share a common set of features. There are various
+types of MIME entity that serve different purposes such as Attachments and
+MIME parts.
+
+An e-mail message is made up of several relatively simple entities that are
+combined in different ways to achieve different results. All of these entities
+have the same fundamental outline but serve a different purpose. The Message
+itself can be defined as a MIME entity, an Attachment is a MIME entity, all
+MIME parts are MIME entities -- and so on!
+
+The basic units of each MIME entity -- be it the Message itself, or an
+Attachment -- are its Headers and its body:
+
+.. code-block:: text
+
+ Other-Header: Another value
+
+ The body content itself
+
+The Headers of a MIME entity, and its body must conform to some strict
+standards defined by various RFC documents. Swift Mailer ensures that these
+specifications are followed by using various types of object, including
+Encoders and different Header types to generate the entity.
+
+Each MIME component implements the base ``Swift_Mime_MimeEntity`` interface,
+which offers methods for retrieving Headers, adding new Headers, changing the
+Encoder, updating the body and so on!
+
+All MIME entities have one Header in common -- the Content-Type Header,
+updated with the entity's ``setContentType()`` method.
+
+Encoders
+~~~~~~~~
+
+Encoders are used to transform the content of Messages generated in Swift
+Mailer into a format that is safe to send across the internet and that
+conforms to RFC specifications.
+
+Generally speaking you will not need to interact with the Encoders in Swift
+Mailer -- the correct settings will be handled by the library itself.
+However they are probably worth a brief mention in the event that you do want
+to play with them.
+
+Both the Headers and the body of all MIME entities (including the Message
+itself) use Encoders to ensure the data they contain can be sent over the
+internet without becoming corrupted or misinterpreted.
+
+There are two types of Encoder: Base64 and Quoted-Printable.
+
+Plugins
+~~~~~~~
+
+Plugins exist to extend, or modify the behaviour of Swift Mailer. They respond
+to Events that are fired within the Transports during sending.
+
+There are a number of Plugins provided as part of the base Swift Mailer
+package and they all follow a common interface to respond to Events fired
+within the library. Interfaces are provided to "listen" to each type of Event
+fired and to act as desired when a listened-to Event occurs.
+
+Although several plugins are provided with Swift Mailer out-of-the-box, the
+Events system has been specifically designed to make it easy for experienced
+object-oriented developers to write their own plugins in order to achieve
+goals that may not be possible with the base library.
diff --git a/vendor/swiftmailer/swiftmailer/doc/plugins.rst b/vendor/swiftmailer/swiftmailer/doc/plugins.rst
new file mode 100644
index 00000000..16ae3356
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/plugins.rst
@@ -0,0 +1,385 @@
+Plugins
+=======
+
+Plugins are provided with Swift Mailer and can be used to extend the behavior
+of the library in situations where using simple class inheritance would be more complex.
+
+AntiFlood Plugin
+----------------
+
+Many SMTP servers have limits on the number of messages that may be sent
+during any single SMTP connection. The AntiFlood plugin provides a way to stay
+within this limit while still managing a large number of emails.
+
+A typical limit for a single connection is 100 emails. If the server you
+connect to imposes such a limit, it expects you to disconnect after that
+number of emails has been sent. You could manage this manually within a loop,
+but the AntiFlood plugin provides the necessary wrapper code so that you don't
+need to worry about this logic.
+
+Regardless of limits imposed by the server, it's usually a good idea to be
+conservative with the resources of the SMTP server. Sending will become
+sluggish if the server is being over-used so using the AntiFlood plugin will
+not be a bad idea even if no limits exist.
+
+The AntiFlood plugin's logic is basically to disconnect and the immediately
+re-connect with the SMTP server every X number of emails sent, where X is a
+number you specify to the plugin.
+
+You can also specify a time period in seconds that Swift Mailer should pause
+for between the disconnect/re-connect process. It's a good idea to pause for a
+short time (say 30 seconds every 100 emails) simply to give the SMTP server a
+chance to process its queue and recover some resources.
+
+Using the AntiFlood Plugin
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The AntiFlood Plugin -- like all plugins -- is added with the Mailer class's
+``registerPlugin()`` method. It takes two constructor parameters: the number of
+emails to pause after, and optionally the number of seconds to pause for.
+
+To use the AntiFlood plugin:
+
+* Create an instance of the Mailer using any Transport you choose.
+
+* Create an instance of the ``Swift_Plugins_AntiFloodPlugin`` class, passing
+ in one or two constructor parameters.
+
+* Register the plugin using the Mailer's ``registerPlugin()`` method.
+
+* Continue using Swift Mailer to send messages as normal.
+
+When Swift Mailer sends messages it will count the number of messages that
+have been sent since the last re-connect. Once the number hits your specified
+threshold it will disconnect and re-connect, optionally pausing for a
+specified amount of time.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Mailer using any Transport
+ $mailer = Swift_Mailer::newInstance(
+ Swift_SmtpTransport::newInstance('smtp.example.org', 25)
+ );
+
+ // Use AntiFlood to re-connect after 100 emails
+ $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100));
+
+ // And specify a time in seconds to pause for (30 secs)
+ $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
+
+ // Continue sending as normal
+ for ($lotsOfRecipients as $recipient) {
+ ...
+
+ $mailer->send( ... );
+ }
+
+Throttler Plugin
+----------------
+
+If your SMTP server has restrictions in place to limit the rate at which you
+send emails, then your code will need to be aware of this rate-limiting. The
+Throttler plugin makes Swift Mailer run at a rate-limited speed.
+
+Many shared hosts don't open their SMTP servers as a free-for-all. Usually
+they have policies in place (probably to discourage spammers) that only allow
+you to send a fixed number of emails per-hour/day.
+
+The Throttler plugin supports two modes of rate-limiting and with each, you
+will need to do that math to figure out the values you want. The plugin can
+limit based on the number of emails per minute, or the number of
+bytes-transferred per-minute.
+
+Using the Throttler Plugin
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Throttler Plugin -- like all plugins -- is added with the Mailer class'
+``registerPlugin()`` method. It has two required constructor parameters that
+tell it how to do its rate-limiting.
+
+To use the Throttler plugin:
+
+* Create an instance of the Mailer using any Transport you choose.
+
+* Create an instance of the ``Swift_Plugins_ThrottlerPlugin`` class, passing
+ the number of emails, or bytes you wish to limit by, along with the mode
+ you're using.
+
+* Register the plugin using the Mailer's ``registerPlugin()`` method.
+
+* Continue using Swift Mailer to send messages as normal.
+
+When Swift Mailer sends messages it will keep track of the rate at which sending
+messages is occurring. If it realises that sending is happening too fast, it
+will cause your program to ``sleep()`` for enough time to average out the rate.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Mailer using any Transport
+ $mailer = Swift_Mailer::newInstance(
+ Swift_SmtpTransport::newInstance('smtp.example.org', 25)
+ );
+
+ // Rate limit to 100 emails per-minute
+ $mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
+ 100, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE
+ ));
+
+ // Rate limit to 10MB per-minute
+ $mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
+ 1024 * 1024 * 10, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE
+ ));
+
+ // Continue sending as normal
+ for ($lotsOfRecipients as $recipient) {
+ ...
+
+ $mailer->send( ... );
+ }
+
+Logger Plugin
+-------------
+
+The Logger plugins helps with debugging during the process of sending. It can
+help to identify why an SMTP server is rejecting addresses, or any other
+hard-to-find problems that may arise.
+
+The Logger plugin comes in two parts. There's the plugin itself, along with
+one of a number of possible Loggers that you may choose to use. For example,
+the logger may output messages directly in realtime, or it may capture
+messages in an array.
+
+One other notable feature is the way in which the Logger plugin changes
+Exception messages. If Exceptions are being thrown but the error message does
+not provide conclusive information as to the source of the problem (such as an
+ambiguous SMTP error) the Logger plugin includes the entire SMTP transcript in
+the error message so that debugging becomes a simpler task.
+
+There are a few available Loggers included with Swift Mailer, but writing your
+own implementation is incredibly simple and is achieved by creating a short
+class that implements the ``Swift_Plugins_Logger`` interface.
+
+* ``Swift_Plugins_Loggers_ArrayLogger``: Keeps a collection of log messages
+ inside an array. The array content can be cleared or dumped out to the
+ screen.
+
+* ``Swift_Plugins_Loggers_EchoLogger``: Prints output to the screen in
+ realtime. Handy for very rudimentary debug output.
+
+Using the Logger Plugin
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The Logger Plugin -- like all plugins -- is added with the Mailer class'
+``registerPlugin()`` method. It accepts an instance of ``Swift_Plugins_Logger``
+in its constructor.
+
+To use the Logger plugin:
+
+* Create an instance of the Mailer using any Transport you choose.
+
+* Create an instance of the a Logger implementation of
+ ``Swift_Plugins_Logger``.
+
+* Create an instance of the ``Swift_Plugins_LoggerPlugin`` class, passing the
+ created Logger instance to its constructor.
+
+* Register the plugin using the Mailer's ``registerPlugin()`` method.
+
+* Continue using Swift Mailer to send messages as normal.
+
+* Dump the contents of the log with the logger's ``dump()`` method.
+
+When Swift Mailer sends messages it will keep a log of all the interactions
+with the underlying Transport being used. Depending upon the Logger that has
+been used the behaviour will differ, but all implementations offer a way to
+get the contents of the log.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Mailer using any Transport
+ $mailer = Swift_Mailer::newInstance(
+ Swift_SmtpTransport::newInstance('smtp.example.org', 25)
+ );
+
+ // To use the ArrayLogger
+ $logger = new Swift_Plugins_Loggers_ArrayLogger();
+ $mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
+
+ // Or to use the Echo Logger
+ $logger = new Swift_Plugins_Loggers_EchoLogger();
+ $mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
+
+ // Continue sending as normal
+ for ($lotsOfRecipients as $recipient) {
+ ...
+
+ $mailer->send( ... );
+ }
+
+ // Dump the log contents
+ // NOTE: The EchoLogger dumps in realtime so dump() does nothing for it
+ echo $logger->dump();
+
+Decorator Plugin
+----------------
+
+Often there's a need to send the same message to multiple recipients, but with
+tiny variations such as the recipient's name being used inside the message
+body. The Decorator plugin aims to provide a solution for allowing these small
+differences.
+
+The decorator plugin works by intercepting the sending process of Swift
+Mailer, reading the email address in the To: field and then looking up a set
+of replacements for a template.
+
+While the use of this plugin is simple, it is probably the most commonly
+misunderstood plugin due to the way in which it works. The typical mistake
+users make is to try registering the plugin multiple times (once for each
+recipient) -- inside a loop for example. This is incorrect.
+
+The Decorator plugin should be registered just once, but containing the list
+of all recipients prior to sending. It will use this list of recipients to
+find the required replacements during sending.
+
+Using the Decorator Plugin
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To use the Decorator plugin, simply create an associative array of replacements
+based on email addresses and then use the mailer's ``registerPlugin()`` method
+to add the plugin.
+
+First create an associative array of replacements based on the email addresses
+you'll be sending the message to.
+
+.. note::
+
+ The replacements array becomes a 2-dimensional array whose keys are the
+ email addresses and whose values are an associative array of replacements
+ for that email address. The curly braces used in this example can be any
+ type of syntax you choose, provided they match the placeholders in your
+ email template.
+
+ .. code-block:: php
+
+ $replacements = array();
+ foreach ($users as $user) {
+ $replacements[$user['email']] = array(
+ '{username}'=>$user['username'],
+ '{password}'=>$user['password']
+ );
+ }
+
+Now create an instance of the Decorator plugin using this array of replacements
+and then register it with the Mailer. Do this only once!
+
+.. code-block:: php
+
+ $decorator = new Swift_Plugins_DecoratorPlugin($replacements);
+
+ $mailer->registerPlugin($decorator);
+
+When you create your message, replace elements in the body (and/or the subject
+line) with your placeholders.
+
+.. code-block:: php
+
+ $message = Swift_Message::newInstance()
+ ->setSubject('Important notice for {username}')
+ ->setBody(
+ "Hello {username}, we have reset your password to {password}\n" .
+ "Please log in and change it at your earliest convenience."
+ )
+ ;
+
+ foreach ($users as $user) {
+ $message->addTo($user['email']);
+ }
+
+When you send this message to each of your recipients listed in your
+``$replacements`` array they will receive a message customized for just
+themselves. For example, the message used above when received may appear like
+this to one user:
+
+.. code-block:: text
+
+ Subject: Important notice for smilingsunshine2009
+
+ Hello smilingsunshine2009, we have reset your password to rainyDays
+ Please log in and change it at your earliest convenience.
+
+While another use may receive the message as:
+
+.. code-block:: text
+
+ Subject: Important notice for billy-bo-bob
+
+ Hello billy-bo-bob, we have reset your password to dancingOctopus
+ Please log in and change it at your earliest convenience.
+
+While the decorator plugin provides a means to solve this problem, there are
+various ways you could tackle this problem without the need for a plugin.
+We're trying to come up with a better way ourselves and while we have several
+(obvious) ideas we don't quite have the perfect solution to go ahead and
+implement it. Watch this space.
+
+Providing Your Own Replacements Lookup for the Decorator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Filling an array with replacements may not be the best solution for providing
+replacement information to the decorator. If you have a more elegant algorithm
+that performs replacement lookups on-the-fly you may provide your own
+implementation.
+
+Providing your own replacements lookup implementation for the Decorator is
+simply a matter of passing an instance of ``Swift_Plugins_Decorator_Replacements`` to the decorator plugin's constructor,
+rather than passing in an array.
+
+The Replacements interface is very simple to implement since it has just one
+method: ``getReplacementsFor($address)``.
+
+Imagine you want to look up replacements from a database on-the-fly, you might
+provide an implementation that does this. You need to create a small class.
+
+.. code-block:: php
+
+ class DbReplacements implements Swift_Plugins_Decorator_Replacements {
+ public function getReplacementsFor($address) {
+ $sql = sprintf(
+ "SELECT * FROM user WHERE email = '%s'",
+ mysql_real_escape_string($address)
+ );
+
+ $result = mysql_query($sql);
+
+ if ($row = mysql_fetch_assoc($result)) {
+ return array(
+ '{username}'=>$row['username'],
+ '{password}'=>$row['password']
+ );
+ }
+ }
+ }
+
+Now all you need to do is pass an instance of your class into the Decorator
+plugin's constructor instead of passing an array.
+
+.. code-block:: php
+
+ $decorator = new Swift_Plugins_DecoratorPlugin(new DbReplacements());
+
+ $mailer->registerPlugin($decorator);
+
+For each message sent, the plugin will call your class' ``getReplacementsFor()``
+method to find the array of replacements it needs.
+
+.. note::
+
+ If your lookup algorithm is case sensitive, you should transform the
+ ``$address`` argument as appropriate -- for example by passing it
+ through ``strtolower()``.
diff --git a/vendor/swiftmailer/swiftmailer/doc/sending.rst b/vendor/swiftmailer/swiftmailer/doc/sending.rst
new file mode 100644
index 00000000..f340404c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/doc/sending.rst
@@ -0,0 +1,571 @@
+Sending Messages
+================
+
+Quick Reference for Sending a Message
+-------------------------------------
+
+Sending a message is very straightforward. You create a Transport, use it to
+create the Mailer, then you use the Mailer to send the message.
+
+To send a Message:
+
+* Create a Transport from one of the provided Transports --
+ ``Swift_SmtpTransport``, ``Swift_SendmailTransport``
+ or one of the aggregate Transports.
+
+* Create an instance of the ``Swift_Mailer`` class, using the Transport as
+ it's constructor parameter.
+
+* Create a Message.
+
+* Send the message via the ``send()`` method on the Mailer object.
+
+.. caution::
+
+ The ``Swift_SmtpTransport`` and ``Swift_SendmailTransport`` transports use
+ ``proc_*`` PHP functions, which might not be available on your PHP
+ installation. You can easily check if that's the case by running the
+ following PHP script: ``setUsername('your username')
+ ->setPassword('your password')
+ ;
+
+ /*
+ You could alternatively use a different transport such as Sendmail:
+
+ // Sendmail
+ $transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
+ */
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ // Create a message
+ $message = Swift_Message::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself')
+ ;
+
+ // Send the message
+ $result = $mailer->send($message);
+
+Transport Types
+~~~~~~~~~~~~~~~
+
+A Transport is the component which actually does the sending. You need to
+provide a Transport object to the Mailer class and there are several possible
+options.
+
+Typically you will not need to know how a Transport works under-the-surface,
+you will only need to know how to create an instance of one, and which one to
+use for your environment.
+
+The SMTP Transport
+..................
+
+The SMTP Transport sends messages over the (standardized) Simple Message
+Transfer Protocol. It can deal with encryption and authentication.
+
+The SMTP Transport, ``Swift_SmtpTransport`` is without doubt the most commonly
+used Transport because it will work on 99% of web servers (I just made that
+number up, but you get the idea). All the server needs is the ability to
+connect to a remote (or even local) SMTP server on the correct port number
+(usually 25).
+
+SMTP servers often require users to authenticate with a username and password
+before any mail can be sent to other domains. This is easily achieved using
+Swift Mailer with the SMTP Transport.
+
+SMTP is a protocol -- in other words it's a "way" of communicating a job
+to be done (i.e. sending a message). The SMTP protocol is the fundamental
+basis on which messages are delivered all over the internet 7 days a week, 365
+days a year. For this reason it's the most "direct" method of sending messages
+you can use and it's the one that will give you the most power and feedback
+(such as delivery failures) when using Swift Mailer.
+
+Because SMTP is generally run as a remote service (i.e. you connect to it over
+the network/internet) it's extremely portable from server-to-server. You can
+easily store the SMTP server address and port number in a configuration file
+within your application and adjust the settings accordingly if the code is
+moved or if the SMTP server is changed.
+
+Some SMTP servers -- Google for example -- use encryption for security reasons.
+Swift Mailer supports using both SSL and TLS encryption settings.
+
+Using the SMTP Transport
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The SMTP Transport is easy to use. Most configuration options can be set with
+the constructor.
+
+To use the SMTP Transport you need to know which SMTP server your code needs
+to connect to. Ask your web host if you're not sure. Lots of people ask me who
+to connect to -- I really can't answer that since it's a setting that's
+extremely specific to your hosting environment.
+
+To use the SMTP Transport:
+
+* Call ``Swift_SmtpTransport::newInstance()`` with the SMTP server name and
+ optionally with a port number (defaults to 25).
+
+* Use the returned object to create the Mailer.
+
+A connection to the SMTP server will be established upon the first call to
+``send()``.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport
+ $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25);
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ /*
+ It's also possible to use multiple method calls
+
+ $transport = Swift_SmtpTransport::newInstance()
+ ->setHost('smtp.example.org')
+ ->setPort(25)
+ ;
+ */
+
+Encrypted SMTP
+^^^^^^^^^^^^^^
+
+You can use SSL or TLS encryption with the SMTP Transport by specifying it as
+a parameter or with a method call.
+
+To use encryption with the SMTP Transport:
+
+* Pass the encryption setting as a third parameter to
+ ``Swift_SmtpTransport::newInstance()``; or
+
+* Call the ``setEncryption()`` method on the Transport.
+
+A connection to the SMTP server will be established upon the first call to
+``send()``. The connection will be initiated with the correct encryption
+settings.
+
+.. note::
+
+ For SSL or TLS encryption to work your PHP installation must have
+ appropriate OpenSSL transports wrappers. You can check if "tls" and/or
+ "ssl" are present in your PHP installation by using the PHP function
+ ``stream_get_transports()``
+
+ .. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport
+ $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 587, 'ssl');
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ /*
+ It's also possible to use multiple method calls
+
+ $transport = Swift_SmtpTransport::newInstance()
+ ->setHost('smtp.example.org')
+ ->setPort(587)
+ ->setEncryption('ssl')
+ ;
+ */
+
+SMTP with a Username and Password
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Some servers require authentication. You can provide a username and password
+with ``setUsername()`` and ``setPassword()`` methods.
+
+To use a username and password with the SMTP Transport:
+
+* Create the Transport with ``Swift_SmtpTransport::newInstance()``.
+
+* Call the ``setUsername()`` and ``setPassword()`` methods on the Transport.
+
+Your username and password will be used to authenticate upon first connect
+when ``send()`` are first used on the Mailer.
+
+If authentication fails, an Exception of type ``Swift_TransportException`` will
+be thrown.
+
+.. note::
+
+ If you need to know early whether or not authentication has failed and an
+ Exception is going to be thrown, call the ``start()`` method on the
+ created Transport.
+
+ .. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport the call setUsername() and setPassword()
+ $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
+ ->setUsername('username')
+ ->setPassword('password')
+ ;
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+The Sendmail Transport
+......................
+
+The Sendmail Transport sends messages by communicating with a locally
+installed MTA -- such as ``sendmail``.
+
+The Sendmail Transport, ``Swift_SendmailTransport`` does not directly connect to
+any remote services. It is designed for Linux servers that have ``sendmail``
+installed. The Transport starts a local ``sendmail`` process and sends messages
+to it. Usually the ``sendmail`` process will respond quickly as it spools your
+messages to disk before sending them.
+
+The Transport is named the Sendmail Transport for historical reasons
+(``sendmail`` was the "standard" UNIX tool for sending e-mail for years). It
+will send messages using other transfer agents such as Exim or Postfix despite
+its name, provided they have the relevant sendmail wrappers so that they can be
+started with the correct command-line flags.
+
+It's a common misconception that because the Sendmail Transport returns a
+result very quickly it must therefore deliver messages to recipients quickly
+-- this is not true. It's not slow by any means, but it's certainly not
+faster than SMTP when it comes to getting messages to the intended recipients.
+This is because sendmail itself sends the messages over SMTP once they have
+been quickly spooled to disk.
+
+The Sendmail Transport has the potential to be just as smart of the SMTP
+Transport when it comes to notifying Swift Mailer about which recipients were
+rejected, but in reality the majority of locally installed ``sendmail``
+instances are not configured well enough to provide any useful feedback. As such
+Swift Mailer may report successful deliveries where they did in fact fail before
+they even left your server.
+
+You can run the Sendmail Transport in two different modes specified by command
+line flags:
+
+* "``-bs``" runs in SMTP mode so theoretically it will act like the SMTP
+ Transport
+
+* "``-t``" runs in piped mode with no feedback, but theoretically faster,
+ though not advised
+
+You can think of the Sendmail Transport as a sort of asynchronous SMTP Transport
+-- though if you have problems with delivery failures you should try using the
+SMTP Transport instead. Swift Mailer isn't doing the work here, it's simply
+passing the work to somebody else (i.e. ``sendmail``).
+
+Using the Sendmail Transport
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To use the Sendmail Transport you simply need to call
+``Swift_SendmailTransport::newInstance()`` with the command as a parameter.
+
+To use the Sendmail Transport you need to know where ``sendmail`` or another MTA
+exists on the server. Swift Mailer uses a default value of
+``/usr/sbin/sendmail``, which should work on most systems.
+
+You specify the entire command as a parameter (i.e. including the command line
+flags). Swift Mailer supports operational modes of "``-bs``" (default) and
+"``-t``".
+
+.. note::
+
+ If you run sendmail in "``-t``" mode you will get no feedback as to whether
+ or not sending has succeeded. Use "``-bs``" unless you have a reason not to.
+
+To use the Sendmail Transport:
+
+* Call ``Swift_SendmailTransport::newInstance()`` with the command, including
+ the correct command line flags. The default is to use ``/usr/sbin/sendmail
+ -bs`` if this is not specified.
+
+* Use the returned object to create the Mailer.
+
+A sendmail process will be started upon the first call to ``send()``. If the
+process cannot be started successfully an Exception of type
+``Swift_TransportException`` will be thrown.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport
+ $transport = Swift_SendmailTransport::newInstance('/usr/sbin/exim -bs');
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+The Mail Transport
+..................
+
+The Mail Transport sends messages by delegating to PHP's internal
+``mail()`` function.
+
+In my experience -- and others' -- the ``mail()`` function is not particularly
+predictable, or helpful.
+
+Quite notably, the ``mail()`` function behaves entirely differently between
+Linux and Windows servers. On linux it uses ``sendmail``, but on Windows it uses
+SMTP.
+
+In order for the ``mail()`` function to even work at all ``php.ini`` needs to be
+configured correctly, specifying the location of sendmail or of an SMTP server.
+
+The problem with ``mail()`` is that it "tries" to simplify things to the point
+that it actually makes things more complex due to poor interface design. The
+developers of Swift Mailer have gone to a lot of effort to make the Mail
+Transport work with a reasonable degree of consistency.
+
+Serious drawbacks when using this Transport are:
+
+* Unpredictable message headers
+
+* Lack of feedback regarding delivery failures
+
+* Lack of support for several plugins that require real-time delivery feedback
+
+It's a last resort, and we say that with a passion!
+
+Available Methods for Sending Messages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Mailer class offers two methods for sending Messages -- ``send()``.
+Each behaves in a slightly different way.
+
+When a message is sent in Swift Mailer, the Mailer class communicates with
+whichever Transport class you have chosen to use.
+
+Each recipient in the message should either be accepted or rejected by the
+Transport. For example, if the domain name on the email address is not
+reachable the SMTP Transport may reject the address because it cannot process
+it. Whichever method you use -- ``send()`` -- Swift Mailer will return
+an integer indicating the number of accepted recipients.
+
+.. note::
+
+ It's possible to find out which recipients were rejected -- we'll cover that
+ later in this chapter.
+
+Using the ``send()`` Method
+...........................
+
+The ``send()`` method of the ``Swift_Mailer`` class sends a message using
+exactly the same logic as your Desktop mail client would use. Just pass it a
+Message and get a result.
+
+To send a Message with ``send()``:
+
+* Create a Transport from one of the provided Transports --
+ ``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
+ or one of the aggregate Transports.
+
+* Create an instance of the ``Swift_Mailer`` class, using the Transport as
+ it's constructor parameter.
+
+* Create a Message.
+
+* Send the message via the ``send()`` method on the Mailer object.
+
+The message will be sent just like it would be sent if you used your mail
+client. An integer is returned which includes the number of successful
+recipients. If none of the recipients could be sent to then zero will be
+returned, which equates to a boolean ``false``. If you set two
+``To:`` recipients and three ``Bcc:`` recipients in the message and all of the
+recipients are delivered to successfully then the value 5 will be returned.
+
+.. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport
+ $transport = Swift_SmtpTransport::newInstance('localhost', 25);
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ // Create a message
+ $message = Swift_Message::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself')
+ ;
+
+ // Send the message
+ $numSent = $mailer->send($message);
+
+ printf("Sent %d messages\n", $numSent);
+
+ /* Note that often that only the boolean equivalent of the
+ return value is of concern (zero indicates FALSE)
+
+ if ($mailer->send($message))
+ {
+ echo "Sent\n";
+ }
+ else
+ {
+ echo "Failed\n";
+ }
+
+ */
+
+Sending Emails in Batch
+.......................
+
+If you want to send a separate message to each recipient so that only their
+own address shows up in the ``To:`` field, follow the following recipe:
+
+* Create a Transport from one of the provided Transports --
+ ``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
+ or one of the aggregate Transports.
+
+* Create an instance of the ``Swift_Mailer`` class, using the Transport as
+ it's constructor parameter.
+
+* Create a Message.
+
+* Iterate over the recipients and send message via the ``send()`` method on
+ the Mailer object.
+
+Each recipient of the messages receives a different copy with only their own
+email address on the ``To:`` field.
+
+Make sure to add only valid email addresses as recipients. If you try to add an
+invalid email address with ``setTo()``, ``setCc()`` or ``setBcc()``, Swift
+Mailer will throw a ``Swift_RfcComplianceException``.
+
+If you add recipients automatically based on a data source that may contain
+invalid email addresses, you can prevent possible exceptions by validating the
+addresses using ``Swift_Validate::email($email)`` and only adding addresses
+that validate. Another way would be to wrap your ``setTo()``, ``setCc()`` and
+``setBcc()`` calls in a try-catch block and handle the
+``Swift_RfcComplianceException`` in the catch block.
+
+Handling invalid addresses properly is especially important when sending emails
+in large batches since a single invalid address might cause an unhandled
+exception and stop the execution or your script early.
+
+.. note::
+
+ In the following example, two emails are sent. One to each of
+ ``receiver@domain.org`` and ``other@domain.org``. These recipients will
+ not be aware of each other.
+
+ .. code-block:: php
+
+ require_once 'lib/swift_required.php';
+
+ // Create the Transport
+ $transport = Swift_SmtpTransport::newInstance('localhost', 25);
+
+ // Create the Mailer using your created Transport
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ // Create a message
+ $message = Swift_Message::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setBody('Here is the message itself')
+ ;
+
+ // Send the message
+ $failedRecipients = array();
+ $numSent = 0;
+ $to = array('receiver@domain.org', 'other@domain.org' => 'A name');
+
+ foreach ($to as $address => $name)
+ {
+ if (is_int($address)) {
+ $message->setTo($name);
+ } else {
+ $message->setTo(array($address => $name));
+ }
+
+ $numSent += $mailer->send($message, $failedRecipients);
+ }
+
+ printf("Sent %d messages\n", $numSent);
+
+Finding out Rejected Addresses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It's possible to get a list of addresses that were rejected by the Transport
+by using a by-reference parameter to ``send()``.
+
+As Swift Mailer attempts to send the message to each address given to it, if a
+recipient is rejected it will be added to the array. You can pass an existing
+array, otherwise one will be created by-reference.
+
+Collecting the list of recipients that were rejected can be useful in
+circumstances where you need to "prune" a mailing list for example when some
+addresses cannot be delivered to.
+
+Getting Failures By-reference
+.............................
+
+Collecting delivery failures by-reference with the ``send()`` method is as
+simple as passing a variable name to the method call.
+
+To get failed recipients by-reference:
+
+* Pass a by-reference variable name to the ``send()`` method of the Mailer
+ class.
+
+If the Transport rejects any of the recipients, the culprit addresses will be
+added to the array provided by-reference.
+
+.. note::
+
+ If the variable name does not yet exist, it will be initialized as an
+ empty array and then failures will be added to that array. If the variable
+ already exists it will be type-cast to an array and failures will be added
+ to it.
+
+ .. code-block:: php
+
+ $mailer = Swift_Mailer::newInstance( ... );
+
+ $message = Swift_Message::newInstance( ... )
+ ->setFrom( ... )
+ ->setTo(array(
+ 'receiver@bad-domain.org' => 'Receiver Name',
+ 'other@domain.org' => 'A name',
+ 'other-receiver@bad-domain.org' => 'Other Name'
+ ))
+ ->setBody( ... )
+ ;
+
+ // Pass a variable name to the send() method
+ if (!$mailer->send($message, $failures))
+ {
+ echo "Failures:";
+ print_r($failures);
+ }
+
+ /*
+ Failures:
+ Array (
+ 0 => receiver@bad-domain.org,
+ 1 => other-receiver@bad-domain.org
+ )
+ */
diff --git a/vendor/swiftmailer/swiftmailer/doc/uml/Encoders.graffle b/vendor/swiftmailer/swiftmailer/doc/uml/Encoders.graffle
new file mode 100644
index 00000000..f895752b
Binary files /dev/null and b/vendor/swiftmailer/swiftmailer/doc/uml/Encoders.graffle differ
diff --git a/vendor/swiftmailer/swiftmailer/doc/uml/Mime.graffle b/vendor/swiftmailer/swiftmailer/doc/uml/Mime.graffle
new file mode 100644
index 00000000..e1e33cbf
Binary files /dev/null and b/vendor/swiftmailer/swiftmailer/doc/uml/Mime.graffle differ
diff --git a/vendor/swiftmailer/swiftmailer/doc/uml/Transports.graffle b/vendor/swiftmailer/swiftmailer/doc/uml/Transports.graffle
new file mode 100644
index 00000000..5670e2b6
Binary files /dev/null and b/vendor/swiftmailer/swiftmailer/doc/uml/Transports.graffle differ
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
new file mode 100644
index 00000000..82c381b7
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
@@ -0,0 +1,80 @@
+createDependenciesFor('mime.attachment')
+ );
+
+ $this->setBody($data);
+ $this->setFilename($filename);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new Attachment.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public static function newInstance($data = null, $filename = null, $contentType = null)
+ {
+ return new self($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new Attachment from a filesystem path.
+ *
+ * @param string $path
+ * @param string $contentType optional
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public static function fromPath($path, $contentType = null)
+ {
+ return self::newInstance()->setFile(
+ new Swift_ByteStream_FileByteStream($path),
+ $contentType
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php
new file mode 100644
index 00000000..a7b0e3a6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php
@@ -0,0 +1,181 @@
+_filters[$key] = $filter;
+ }
+
+ /**
+ * Remove an already present StreamFilter based on its $key.
+ *
+ * @param string $key
+ */
+ public function removeFilter($key)
+ {
+ unset($this->_filters[$key]);
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ *
+ * @throws Swift_IoException
+ *
+ * @return int
+ */
+ public function write($bytes)
+ {
+ $this->_writeBuffer .= $bytes;
+ foreach ($this->_filters as $filter) {
+ if ($filter->shouldBuffer($this->_writeBuffer)) {
+ return;
+ }
+ }
+ $this->_doWrite($this->_writeBuffer);
+
+ return ++$this->_sequence;
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ */
+ public function commit()
+ {
+ $this->_doWrite($this->_writeBuffer);
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ if ($this->_writeBuffer !== '') {
+ $stream->write($this->_writeBuffer);
+ }
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ */
+ public function flushBuffers()
+ {
+ if ($this->_writeBuffer !== '') {
+ $this->_doWrite($this->_writeBuffer);
+ }
+ $this->_flush();
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+
+ /** Run $bytes through all filters */
+ private function _filter($bytes)
+ {
+ foreach ($this->_filters as $filter) {
+ $bytes = $filter->filter($bytes);
+ }
+
+ return $bytes;
+ }
+
+ /** Just write the bytes to the stream */
+ private function _doWrite($bytes)
+ {
+ $this->_commit($this->_filter($bytes));
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+
+ $this->_writeBuffer = '';
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php
new file mode 100644
index 00000000..ef05a6d5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php
@@ -0,0 +1,182 @@
+_array = $stack;
+ $this->_arraySize = count($stack);
+ } elseif (is_string($stack)) {
+ $this->write($stack);
+ } else {
+ $this->_array = array();
+ }
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the
+ * remaining bytes are given instead. If no bytes are remaining at all, boolean
+ * false is returned.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_offset == $this->_arraySize) {
+ return false;
+ }
+
+ // Don't use array slice
+ $end = $length + $this->_offset;
+ $end = $this->_arraySize < $end ? $this->_arraySize : $end;
+ $ret = '';
+ for (; $this->_offset < $end; ++$this->_offset) {
+ $ret .= $this->_array[$this->_offset];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ */
+ public function write($bytes)
+ {
+ $to_add = str_split($bytes);
+ foreach ($to_add as $value) {
+ $this->_array[] = $value;
+ }
+ $this->_arraySize = count($this->_array);
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param int $byteOffset
+ *
+ * @return bool
+ */
+ public function setReadPointer($byteOffset)
+ {
+ if ($byteOffset > $this->_arraySize) {
+ $byteOffset = $this->_arraySize;
+ } elseif ($byteOffset < 0) {
+ $byteOffset = 0;
+ }
+
+ $this->_offset = $byteOffset;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ */
+ public function flushBuffers()
+ {
+ $this->_offset = 0;
+ $this->_array = array();
+ $this->_arraySize = 0;
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php
new file mode 100644
index 00000000..9ed85231
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php
@@ -0,0 +1,231 @@
+_path = $path;
+ $this->_mode = $writable ? 'w+b' : 'rb';
+
+ if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
+ $this->_quotes = true;
+ }
+ }
+
+ /**
+ * Get the complete path to the file.
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the
+ * remaining bytes are given instead. If no bytes are remaining at all, boolean
+ * false is returned.
+ *
+ * @param int $length
+ *
+ * @throws Swift_IoException
+ *
+ * @return string|bool
+ */
+ public function read($length)
+ {
+ $fp = $this->_getReadHandle();
+ if (!feof($fp)) {
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ $bytes = fread($fp, $length);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_offset = ftell($fp);
+
+ // If we read one byte after reaching the end of the file
+ // feof() will return false and an empty string is returned
+ if ($bytes === '' && feof($fp)) {
+ $this->_resetReadHandle();
+
+ return false;
+ }
+
+ return $bytes;
+ }
+
+ $this->_resetReadHandle();
+
+ return false;
+ }
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param int $byteOffset
+ *
+ * @return bool
+ */
+ public function setReadPointer($byteOffset)
+ {
+ if (isset($this->_reader)) {
+ $this->_seekReadStreamToPosition($byteOffset);
+ }
+ $this->_offset = $byteOffset;
+ }
+
+ /** Just write the bytes to the file */
+ protected function _commit($bytes)
+ {
+ fwrite($this->_getWriteHandle(), $bytes);
+ $this->_resetReadHandle();
+ }
+
+ /** Not used */
+ protected function _flush()
+ {
+ }
+
+ /** Get the resource for reading */
+ private function _getReadHandle()
+ {
+ if (!isset($this->_reader)) {
+ $pointer = @fopen($this->_path, 'rb');
+ if (!$pointer) {
+ throw new Swift_IoException(
+ 'Unable to open file for reading ['.$this->_path.']'
+ );
+ }
+ $this->_reader = $pointer;
+ if ($this->_offset != 0) {
+ $this->_getReadStreamSeekableStatus();
+ $this->_seekReadStreamToPosition($this->_offset);
+ }
+ }
+
+ return $this->_reader;
+ }
+
+ /** Get the resource for writing */
+ private function _getWriteHandle()
+ {
+ if (!isset($this->_writer)) {
+ if (!$this->_writer = fopen($this->_path, $this->_mode)) {
+ throw new Swift_IoException(
+ 'Unable to open file for writing ['.$this->_path.']'
+ );
+ }
+ }
+
+ return $this->_writer;
+ }
+
+ /** Force a reload of the resource for reading */
+ private function _resetReadHandle()
+ {
+ if (isset($this->_reader)) {
+ fclose($this->_reader);
+ $this->_reader = null;
+ }
+ }
+
+ /** Check if ReadOnly Stream is seekable */
+ private function _getReadStreamSeekableStatus()
+ {
+ $metas = stream_get_meta_data($this->_reader);
+ $this->_seekable = $metas['seekable'];
+ }
+
+ /** Streams in a readOnly stream ensuring copy if needed */
+ private function _seekReadStreamToPosition($offset)
+ {
+ if ($this->_seekable === null) {
+ $this->_getReadStreamSeekableStatus();
+ }
+ if ($this->_seekable === false) {
+ $currentPos = ftell($this->_reader);
+ if ($currentPos < $offset) {
+ $toDiscard = $offset - $currentPos;
+ fread($this->_reader, $toDiscard);
+
+ return;
+ }
+ $this->_copyReadStream();
+ }
+ fseek($this->_reader, $offset, SEEK_SET);
+ }
+
+ /** Copy a readOnly Stream to ensure seekability */
+ private function _copyReadStream()
+ {
+ if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) {
+ /* We have opened a php:// Stream Should work without problem */
+ } elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
+ /* We have opened a tmpfile */
+ } else {
+ throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
+ }
+ $currentPos = ftell($this->_reader);
+ fclose($this->_reader);
+ $source = fopen($this->_path, 'rb');
+ if (!$source) {
+ throw new Swift_IoException('Unable to open file for copying ['.$this->_path.']');
+ }
+ fseek($tmpFile, 0, SEEK_SET);
+ while (!feof($source)) {
+ fwrite($tmpFile, fread($source, 4096));
+ }
+ fseek($tmpFile, $currentPos, SEEK_SET);
+ fclose($source);
+ $this->_reader = $tmpFile;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php
new file mode 100644
index 00000000..1c9a80c0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php
@@ -0,0 +1,42 @@
+getPath())) === false) {
+ throw new Swift_IoException('Failed to get temporary file content.');
+ }
+
+ return $content;
+ }
+
+ public function __destruct()
+ {
+ if (file_exists($this->getPath())) {
+ @unlink($this->getPath());
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php
new file mode 100644
index 00000000..3d5e854a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php
@@ -0,0 +1,67 @@
+
+ */
+interface Swift_CharacterReader
+{
+ const MAP_TYPE_INVALID = 0x01;
+ const MAP_TYPE_FIXED_LEN = 0x02;
+ const MAP_TYPE_POSITIONS = 0x03;
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars);
+
+ /**
+ * Returns the mapType, see constants.
+ *
+ * @return int
+ */
+ public function getMapType();
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ *
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param integer[] $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size);
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * For fixed width character sets this should be the number of octets-per-character.
+ * For multibyte character sets this will probably be 1.
+ *
+ * @return int
+ */
+ public function getInitialByteSize();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php
new file mode 100644
index 00000000..6a18e1dd
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php
@@ -0,0 +1,97 @@
+
+ */
+class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader
+{
+ /**
+ * The number of bytes in a single character.
+ *
+ * @var int
+ */
+ private $_width;
+
+ /**
+ * Creates a new GenericFixedWidthReader using $width bytes per character.
+ *
+ * @param int $width
+ */
+ public function __construct($width)
+ {
+ $this->_width = $width;
+ }
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
+ {
+ $strlen = strlen($string);
+ // % and / are CPU intensive, so, maybe find a better way
+ $ignored = $strlen % $this->_width;
+ $ignoredChars = $ignored ? substr($string, -$ignored) : '';
+ $currentMap = $this->_width;
+
+ return ($strlen - $ignored) / $this->_width;
+ }
+
+ /**
+ * Returns the mapType.
+ *
+ * @return int
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_FIXED_LEN;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ *
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ $needed = $this->_width - $size;
+
+ return $needed > -1 ? $needed : -1;
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return $this->_width;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php
new file mode 100644
index 00000000..67da48f6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php
@@ -0,0 +1,84 @@
+ "\x07F") {
+ // Invalid char
+ $currentMap[$i + $startOffset] = $string[$i];
+ }
+ }
+
+ return $strlen;
+ }
+
+ /**
+ * Returns mapType.
+ *
+ * @return int mapType
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_INVALID;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ $byte = reset($bytes);
+ if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) {
+ return 0;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php
new file mode 100644
index 00000000..7379bda2
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php
@@ -0,0 +1,176 @@
+
+ */
+class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
+{
+ /** Pre-computed for optimization */
+ private static $length_map = array(
+ // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x0N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x2N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x4N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x6N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x8N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xAN
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBN
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xCN
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDN
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEN
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0, // 0xFN
+ );
+
+ private static $s_length_map = array(
+ "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1,
+ "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1,
+ "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1,
+ "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1,
+ "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1,
+ "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1,
+ "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1,
+ "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1,
+ "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1,
+ "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1,
+ "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1,
+ "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1,
+ "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1,
+ "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1,
+ "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1,
+ "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1,
+ "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0,
+ "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0,
+ "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0,
+ "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0,
+ "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0,
+ "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0,
+ "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0,
+ "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0,
+ "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2,
+ "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2,
+ "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2,
+ "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2,
+ "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3,
+ "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3,
+ "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4,
+ "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0,
+ );
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
+ {
+ if (!isset($currentMap['i']) || !isset($currentMap['p'])) {
+ $currentMap['p'] = $currentMap['i'] = array();
+ }
+
+ $strlen = strlen($string);
+ $charPos = count($currentMap['p']);
+ $foundChars = 0;
+ $invalid = false;
+ for ($i = 0; $i < $strlen; ++$i) {
+ $char = $string[$i];
+ $size = self::$s_length_map[$char];
+ if ($size == 0) {
+ /* char is invalid, we must wait for a resync */
+ $invalid = true;
+ continue;
+ } else {
+ if ($invalid == true) {
+ /* We mark the chars as invalid and start a new char */
+ $currentMap['p'][$charPos + $foundChars] = $startOffset + $i;
+ $currentMap['i'][$charPos + $foundChars] = true;
+ ++$foundChars;
+ $invalid = false;
+ }
+ if (($i + $size) > $strlen) {
+ $ignoredChars = substr($string, $i);
+ break;
+ }
+ for ($j = 1; $j < $size; ++$j) {
+ $char = $string[$i + $j];
+ if ($char > "\x7F" && $char < "\xC0") {
+ // Valid - continue parsing
+ } else {
+ /* char is invalid, we must wait for a resync */
+ $invalid = true;
+ continue 2;
+ }
+ }
+ /* Ok we got a complete char here */
+ $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size;
+ $i += $j - 1;
+ ++$foundChars;
+ }
+ }
+
+ return $foundChars;
+ }
+
+ /**
+ * Returns mapType.
+ *
+ * @return int mapType
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_POSITIONS;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ if ($size < 1) {
+ return -1;
+ }
+ $needed = self::$length_map[$bytes[0]] - $size;
+
+ return $needed > -1 ? $needed : -1;
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php
new file mode 100644
index 00000000..15b6c692
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php
@@ -0,0 +1,26 @@
+init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ public function init()
+ {
+ if (count(self::$_map) > 0) {
+ return;
+ }
+
+ $prefix = 'Swift_CharacterReader_';
+
+ $singleByte = array(
+ 'class' => $prefix.'GenericFixedWidthReader',
+ 'constructor' => array(1),
+ );
+
+ $doubleByte = array(
+ 'class' => $prefix.'GenericFixedWidthReader',
+ 'constructor' => array(2),
+ );
+
+ $fourBytes = array(
+ 'class' => $prefix.'GenericFixedWidthReader',
+ 'constructor' => array(4),
+ );
+
+ // Utf-8
+ self::$_map['utf-?8'] = array(
+ 'class' => $prefix.'Utf8Reader',
+ 'constructor' => array(),
+ );
+
+ //7-8 bit charsets
+ self::$_map['(us-)?ascii'] = $singleByte;
+ self::$_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte;
+ self::$_map['windows-?125[0-9]'] = $singleByte;
+ self::$_map['cp-?[0-9]+'] = $singleByte;
+ self::$_map['ansi'] = $singleByte;
+ self::$_map['macintosh'] = $singleByte;
+ self::$_map['koi-?7'] = $singleByte;
+ self::$_map['koi-?8-?.+'] = $singleByte;
+ self::$_map['mik'] = $singleByte;
+ self::$_map['(cork|t1)'] = $singleByte;
+ self::$_map['v?iscii'] = $singleByte;
+
+ //16 bits
+ self::$_map['(ucs-?2|utf-?16)'] = $doubleByte;
+
+ //32 bits
+ self::$_map['(ucs-?4|utf-?32)'] = $fourBytes;
+
+ // Fallback
+ self::$_map['.*'] = $singleByte;
+ }
+
+ /**
+ * Returns a CharacterReader suitable for the charset applied.
+ *
+ * @param string $charset
+ *
+ * @return Swift_CharacterReader
+ */
+ public function getReaderFor($charset)
+ {
+ $charset = trim(strtolower($charset));
+ foreach (self::$_map as $pattern => $spec) {
+ $re = '/^'.$pattern.'$/D';
+ if (preg_match($re, $charset)) {
+ if (!array_key_exists($pattern, self::$_loaded)) {
+ $reflector = new ReflectionClass($spec['class']);
+ if ($reflector->getConstructor()) {
+ $reader = $reflector->newInstanceArgs($spec['constructor']);
+ } else {
+ $reader = $reflector->newInstance();
+ }
+ self::$_loaded[$pattern] = $reader;
+ }
+
+ return self::$_loaded[$pattern];
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php
new file mode 100644
index 00000000..717924f5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php
@@ -0,0 +1,89 @@
+setCharacterReaderFactory($factory);
+ $this->setCharacterSet($charset);
+ }
+
+ /**
+ * Set the character set used in this CharacterStream.
+ *
+ * @param string $charset
+ */
+ public function setCharacterSet($charset)
+ {
+ $this->_charset = $charset;
+ $this->_charReader = null;
+ }
+
+ /**
+ * Set the CharacterReaderFactory for multi charset support.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ */
+ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
+ {
+ $this->_charReaderFactory = $factory;
+ }
+
+ /**
+ * Overwrite this character stream using the byte sequence in the byte stream.
+ *
+ * @param Swift_OutputByteStream $os output stream to read from
+ */
+ public function importByteStream(Swift_OutputByteStream $os)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory
+ ->getReaderFor($this->_charset);
+ }
+
+ $startLength = $this->_charReader->getInitialByteSize();
+ while (false !== $bytes = $os->read($startLength)) {
+ $c = array();
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $c[] = self::$_byteMap[$bytes[$i]];
+ }
+ $size = count($c);
+ $need = $this->_charReader
+ ->validateByteSequence($c, $size);
+ if ($need > 0 &&
+ false !== $bytes = $os->read($need)) {
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $c[] = self::$_byteMap[$bytes[$i]];
+ }
+ }
+ $this->_array[] = $c;
+ ++$this->_array_size;
+ }
+ }
+
+ /**
+ * Import a string a bytes into this CharacterStream, overwriting any existing
+ * data in the stream.
+ *
+ * @param string $string
+ */
+ public function importString($string)
+ {
+ $this->flushContents();
+ $this->write($string);
+ }
+
+ /**
+ * Read $length characters from the stream and move the internal pointer
+ * $length further into the stream.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_offset == $this->_array_size) {
+ return false;
+ }
+
+ // Don't use array slice
+ $arrays = array();
+ $end = $length + $this->_offset;
+ for ($i = $this->_offset; $i < $end; ++$i) {
+ if (!isset($this->_array[$i])) {
+ break;
+ }
+ $arrays[] = $this->_array[$i];
+ }
+ $this->_offset += $i - $this->_offset; // Limit function calls
+ $chars = false;
+ foreach ($arrays as $array) {
+ $chars .= implode('', array_map('chr', $array));
+ }
+
+ return $chars;
+ }
+
+ /**
+ * Read $length characters from the stream and return a 1-dimensional array
+ * containing there octet values.
+ *
+ * @param int $length
+ *
+ * @return integer[]
+ */
+ public function readBytes($length)
+ {
+ if ($this->_offset == $this->_array_size) {
+ return false;
+ }
+ $arrays = array();
+ $end = $length + $this->_offset;
+ for ($i = $this->_offset; $i < $end; ++$i) {
+ if (!isset($this->_array[$i])) {
+ break;
+ }
+ $arrays[] = $this->_array[$i];
+ }
+ $this->_offset += ($i - $this->_offset); // Limit function calls
+
+ return call_user_func_array('array_merge', $arrays);
+ }
+
+ /**
+ * Write $chars to the end of the stream.
+ *
+ * @param string $chars
+ */
+ public function write($chars)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory->getReaderFor(
+ $this->_charset);
+ }
+
+ $startLength = $this->_charReader->getInitialByteSize();
+
+ $fp = fopen('php://memory', 'w+b');
+ fwrite($fp, $chars);
+ unset($chars);
+ fseek($fp, 0, SEEK_SET);
+
+ $buffer = array(0);
+ $buf_pos = 1;
+ $buf_len = 1;
+ $has_datas = true;
+ do {
+ $bytes = array();
+ // Buffer Filing
+ if ($buf_len - $buf_pos < $startLength) {
+ $buf = array_splice($buffer, $buf_pos);
+ $new = $this->_reloadBuffer($fp, 100);
+ if ($new) {
+ $buffer = array_merge($buf, $new);
+ $buf_len = count($buffer);
+ $buf_pos = 0;
+ } else {
+ $has_datas = false;
+ }
+ }
+ if ($buf_len - $buf_pos > 0) {
+ $size = 0;
+ for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) {
+ ++$size;
+ $bytes[] = $buffer[$buf_pos++];
+ }
+ $need = $this->_charReader->validateByteSequence(
+ $bytes, $size);
+ if ($need > 0) {
+ if ($buf_len - $buf_pos < $need) {
+ $new = $this->_reloadBuffer($fp, $need);
+
+ if ($new) {
+ $buffer = array_merge($buffer, $new);
+ $buf_len = count($buffer);
+ }
+ }
+ for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) {
+ $bytes[] = $buffer[$buf_pos++];
+ }
+ }
+ $this->_array[] = $bytes;
+ ++$this->_array_size;
+ }
+ } while ($has_datas);
+
+ fclose($fp);
+ }
+
+ /**
+ * Move the internal pointer to $charOffset in the stream.
+ *
+ * @param int $charOffset
+ */
+ public function setPointer($charOffset)
+ {
+ if ($charOffset > $this->_array_size) {
+ $charOffset = $this->_array_size;
+ } elseif ($charOffset < 0) {
+ $charOffset = 0;
+ }
+ $this->_offset = $charOffset;
+ }
+
+ /**
+ * Empty the stream and reset the internal pointer.
+ */
+ public function flushContents()
+ {
+ $this->_offset = 0;
+ $this->_array = array();
+ $this->_array_size = 0;
+ }
+
+ private function _reloadBuffer($fp, $len)
+ {
+ if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) {
+ $buf = array();
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $buf[] = self::$_byteMap[$bytes[$i]];
+ }
+
+ return $buf;
+ }
+
+ return false;
+ }
+
+ private static function _initializeMaps()
+ {
+ if (!isset(self::$_charMap)) {
+ self::$_charMap = array();
+ for ($byte = 0; $byte < 256; ++$byte) {
+ self::$_charMap[$byte] = chr($byte);
+ }
+ self::$_byteMap = array_flip(self::$_charMap);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php
new file mode 100644
index 00000000..58bd140f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php
@@ -0,0 +1,267 @@
+
+ */
+class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
+{
+ /**
+ * The char reader (lazy-loaded) for the current charset.
+ *
+ * @var Swift_CharacterReader
+ */
+ private $_charReader;
+
+ /**
+ * A factory for creating CharacterReader instances.
+ *
+ * @var Swift_CharacterReaderFactory
+ */
+ private $_charReaderFactory;
+
+ /**
+ * The character set this stream is using.
+ *
+ * @var string
+ */
+ private $_charset;
+
+ /**
+ * The data's stored as-is.
+ *
+ * @var string
+ */
+ private $_datas = '';
+
+ /**
+ * Number of bytes in the stream.
+ *
+ * @var int
+ */
+ private $_datasSize = 0;
+
+ /**
+ * Map.
+ *
+ * @var mixed
+ */
+ private $_map;
+
+ /**
+ * Map Type.
+ *
+ * @var int
+ */
+ private $_mapType = 0;
+
+ /**
+ * Number of characters in the stream.
+ *
+ * @var int
+ */
+ private $_charCount = 0;
+
+ /**
+ * Position in the stream.
+ *
+ * @var int
+ */
+ private $_currentPos = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ * @param string $charset
+ */
+ public function __construct(Swift_CharacterReaderFactory $factory, $charset)
+ {
+ $this->setCharacterReaderFactory($factory);
+ $this->setCharacterSet($charset);
+ }
+
+ /* -- Changing parameters of the stream -- */
+
+ /**
+ * Set the character set used in this CharacterStream.
+ *
+ * @param string $charset
+ */
+ public function setCharacterSet($charset)
+ {
+ $this->_charset = $charset;
+ $this->_charReader = null;
+ $this->_mapType = 0;
+ }
+
+ /**
+ * Set the CharacterReaderFactory for multi charset support.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ */
+ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
+ {
+ $this->_charReaderFactory = $factory;
+ }
+
+ /**
+ * @see Swift_CharacterStream::flushContents()
+ */
+ public function flushContents()
+ {
+ $this->_datas = null;
+ $this->_map = null;
+ $this->_charCount = 0;
+ $this->_currentPos = 0;
+ $this->_datasSize = 0;
+ }
+
+ /**
+ * @see Swift_CharacterStream::importByteStream()
+ *
+ * @param Swift_OutputByteStream $os
+ */
+ public function importByteStream(Swift_OutputByteStream $os)
+ {
+ $this->flushContents();
+ $blocks = 512;
+ $os->setReadPointer(0);
+ while (false !== ($read = $os->read($blocks))) {
+ $this->write($read);
+ }
+ }
+
+ /**
+ * @see Swift_CharacterStream::importString()
+ *
+ * @param string $string
+ */
+ public function importString($string)
+ {
+ $this->flushContents();
+ $this->write($string);
+ }
+
+ /**
+ * @see Swift_CharacterStream::read()
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_currentPos >= $this->_charCount) {
+ return false;
+ }
+ $ret = false;
+ $length = $this->_currentPos + $length > $this->_charCount ? $this->_charCount - $this->_currentPos : $length;
+ switch ($this->_mapType) {
+ case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
+ $len = $length * $this->_map;
+ $ret = substr($this->_datas,
+ $this->_currentPos * $this->_map,
+ $len);
+ $this->_currentPos += $length;
+ break;
+
+ case Swift_CharacterReader::MAP_TYPE_INVALID:
+ $ret = '';
+ for (; $this->_currentPos < $length; ++$this->_currentPos) {
+ if (isset($this->_map[$this->_currentPos])) {
+ $ret .= '?';
+ } else {
+ $ret .= $this->_datas[$this->_currentPos];
+ }
+ }
+ break;
+
+ case Swift_CharacterReader::MAP_TYPE_POSITIONS:
+ $end = $this->_currentPos + $length;
+ $end = $end > $this->_charCount ? $this->_charCount : $end;
+ $ret = '';
+ $start = 0;
+ if ($this->_currentPos > 0) {
+ $start = $this->_map['p'][$this->_currentPos - 1];
+ }
+ $to = $start;
+ for (; $this->_currentPos < $end; ++$this->_currentPos) {
+ if (isset($this->_map['i'][$this->_currentPos])) {
+ $ret .= substr($this->_datas, $start, $to - $start).'?';
+ $start = $this->_map['p'][$this->_currentPos];
+ } else {
+ $to = $this->_map['p'][$this->_currentPos];
+ }
+ }
+ $ret .= substr($this->_datas, $start, $to - $start);
+ break;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @see Swift_CharacterStream::readBytes()
+ *
+ * @param int $length
+ *
+ * @return int[]
+ */
+ public function readBytes($length)
+ {
+ $read = $this->read($length);
+ if ($read !== false) {
+ $ret = array_map('ord', str_split($read, 1));
+
+ return $ret;
+ }
+
+ return false;
+ }
+
+ /**
+ * @see Swift_CharacterStream::setPointer()
+ *
+ * @param int $charOffset
+ */
+ public function setPointer($charOffset)
+ {
+ if ($this->_charCount < $charOffset) {
+ $charOffset = $this->_charCount;
+ }
+ $this->_currentPos = $charOffset;
+ }
+
+ /**
+ * @see Swift_CharacterStream::write()
+ *
+ * @param string $chars
+ */
+ public function write($chars)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory->getReaderFor(
+ $this->_charset);
+ $this->_map = array();
+ $this->_mapType = $this->_charReader->getMapType();
+ }
+ $ignored = '';
+ $this->_datas .= $chars;
+ $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored);
+ if ($ignored !== false) {
+ $this->_datasSize = strlen($this->_datas) - strlen($ignored);
+ } else {
+ $this->_datasSize = strlen($this->_datas);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php
new file mode 100644
index 00000000..4ae5bacf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php
@@ -0,0 +1,63 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base class for Spools (implements time and message limits).
+ *
+ * @author Fabien Potencier
+ */
+abstract class Swift_ConfigurableSpool implements Swift_Spool
+{
+ /** The maximum number of messages to send per flush */
+ private $_message_limit;
+
+ /** The time limit per flush */
+ private $_time_limit;
+
+ /**
+ * Sets the maximum number of messages to send per flush.
+ *
+ * @param int $limit
+ */
+ public function setMessageLimit($limit)
+ {
+ $this->_message_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the maximum number of messages to send per flush.
+ *
+ * @return int The limit
+ */
+ public function getMessageLimit()
+ {
+ return $this->_message_limit;
+ }
+
+ /**
+ * Sets the time limit (in seconds) per flush.
+ *
+ * @param int $limit The limit
+ */
+ public function setTimeLimit($limit)
+ {
+ $this->_time_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the time limit (in seconds) per flush.
+ *
+ * @return int The limit
+ */
+ public function getTimeLimit()
+ {
+ return $this->_time_limit;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php
new file mode 100644
index 00000000..8c1074a3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php
@@ -0,0 +1,373 @@
+_store);
+ }
+
+ /**
+ * Test if an item is registered in this container with the given name.
+ *
+ * @see register()
+ *
+ * @param string $itemName
+ *
+ * @return bool
+ */
+ public function has($itemName)
+ {
+ return array_key_exists($itemName, $this->_store)
+ && isset($this->_store[$itemName]['lookupType']);
+ }
+
+ /**
+ * Lookup the item with the given $itemName.
+ *
+ * @see register()
+ *
+ * @param string $itemName
+ *
+ * @throws Swift_DependencyException If the dependency is not found
+ *
+ * @return mixed
+ */
+ public function lookup($itemName)
+ {
+ if (!$this->has($itemName)) {
+ throw new Swift_DependencyException(
+ 'Cannot lookup dependency "'.$itemName.'" since it is not registered.'
+ );
+ }
+
+ switch ($this->_store[$itemName]['lookupType']) {
+ case self::TYPE_ALIAS:
+ return $this->_createAlias($itemName);
+ case self::TYPE_VALUE:
+ return $this->_getValue($itemName);
+ case self::TYPE_INSTANCE:
+ return $this->_createNewInstance($itemName);
+ case self::TYPE_SHARED:
+ return $this->_createSharedInstance($itemName);
+ }
+ }
+
+ /**
+ * Create an array of arguments passed to the constructor of $itemName.
+ *
+ * @param string $itemName
+ *
+ * @return array
+ */
+ public function createDependenciesFor($itemName)
+ {
+ $args = array();
+ if (isset($this->_store[$itemName]['args'])) {
+ $args = $this->_resolveArgs($this->_store[$itemName]['args']);
+ }
+
+ return $args;
+ }
+
+ /**
+ * Register a new dependency with $itemName.
+ *
+ * This method returns the current DependencyContainer instance because it
+ * requires the use of the fluid interface to set the specific details for the
+ * dependency.
+ *
+ * @see asNewInstanceOf(), asSharedInstanceOf(), asValue()
+ *
+ * @param string $itemName
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function register($itemName)
+ {
+ $this->_store[$itemName] = array();
+ $this->_endPoint = &$this->_store[$itemName];
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a literal value.
+ *
+ * {@link register()} must be called before this will work.
+ *
+ * @param mixed $value
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asValue($value)
+ {
+ $endPoint = &$this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_VALUE;
+ $endPoint['value'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as an alias of another item.
+ *
+ * @param string $lookup
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asAliasOf($lookup)
+ {
+ $endPoint = &$this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_ALIAS;
+ $endPoint['ref'] = $lookup;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a new instance of $className.
+ *
+ * {@link register()} must be called before this will work.
+ * Any arguments can be set with {@link withDependencies()},
+ * {@link addConstructorValue()} or {@link addConstructorLookup()}.
+ *
+ * @see withDependencies(), addConstructorValue(), addConstructorLookup()
+ *
+ * @param string $className
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asNewInstanceOf($className)
+ {
+ $endPoint = &$this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_INSTANCE;
+ $endPoint['className'] = $className;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a shared instance of $className.
+ *
+ * {@link register()} must be called before this will work.
+ *
+ * @param string $className
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asSharedInstanceOf($className)
+ {
+ $endPoint = &$this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_SHARED;
+ $endPoint['className'] = $className;
+
+ return $this;
+ }
+
+ /**
+ * Specify a list of injected dependencies for the previously registered item.
+ *
+ * This method takes an array of lookup names.
+ *
+ * @see addConstructorValue(), addConstructorLookup()
+ *
+ * @param array $lookups
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function withDependencies(array $lookups)
+ {
+ $endPoint = &$this->_getEndPoint();
+ $endPoint['args'] = array();
+ foreach ($lookups as $lookup) {
+ $this->addConstructorLookup($lookup);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Specify a literal (non looked up) value for the constructor of the
+ * previously registered item.
+ *
+ * @see withDependencies(), addConstructorLookup()
+ *
+ * @param mixed $value
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function addConstructorValue($value)
+ {
+ $endPoint = &$this->_getEndPoint();
+ if (!isset($endPoint['args'])) {
+ $endPoint['args'] = array();
+ }
+ $endPoint['args'][] = array('type' => 'value', 'item' => $value);
+
+ return $this;
+ }
+
+ /**
+ * Specify a dependency lookup for the constructor of the previously
+ * registered item.
+ *
+ * @see withDependencies(), addConstructorValue()
+ *
+ * @param string $lookup
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function addConstructorLookup($lookup)
+ {
+ $endPoint = &$this->_getEndPoint();
+ if (!isset($this->_endPoint['args'])) {
+ $endPoint['args'] = array();
+ }
+ $endPoint['args'][] = array('type' => 'lookup', 'item' => $lookup);
+
+ return $this;
+ }
+
+ /** Get the literal value with $itemName */
+ private function _getValue($itemName)
+ {
+ return $this->_store[$itemName]['value'];
+ }
+
+ /** Resolve an alias to another item */
+ private function _createAlias($itemName)
+ {
+ return $this->lookup($this->_store[$itemName]['ref']);
+ }
+
+ /** Create a fresh instance of $itemName */
+ private function _createNewInstance($itemName)
+ {
+ $reflector = new ReflectionClass($this->_store[$itemName]['className']);
+ if ($reflector->getConstructor()) {
+ return $reflector->newInstanceArgs(
+ $this->createDependenciesFor($itemName)
+ );
+ }
+
+ return $reflector->newInstance();
+ }
+
+ /** Create and register a shared instance of $itemName */
+ private function _createSharedInstance($itemName)
+ {
+ if (!isset($this->_store[$itemName]['instance'])) {
+ $this->_store[$itemName]['instance'] = $this->_createNewInstance($itemName);
+ }
+
+ return $this->_store[$itemName]['instance'];
+ }
+
+ /** Get the current endpoint in the store */
+ private function &_getEndPoint()
+ {
+ if (!isset($this->_endPoint)) {
+ throw new BadMethodCallException(
+ 'Component must first be registered by calling register()'
+ );
+ }
+
+ return $this->_endPoint;
+ }
+
+ /** Get an argument list with dependencies resolved */
+ private function _resolveArgs(array $args)
+ {
+ $resolved = array();
+ foreach ($args as $argDefinition) {
+ switch ($argDefinition['type']) {
+ case 'lookup':
+ $resolved[] = $this->_lookupRecursive($argDefinition['item']);
+ break;
+ case 'value':
+ $resolved[] = $argDefinition['item'];
+ break;
+ }
+ }
+
+ return $resolved;
+ }
+
+ /** Resolve a single dependency with an collections */
+ private function _lookupRecursive($item)
+ {
+ if (is_array($item)) {
+ $collection = array();
+ foreach ($item as $k => $v) {
+ $collection[$k] = $this->_lookupRecursive($v);
+ }
+
+ return $collection;
+ }
+
+ return $this->lookup($item);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php
new file mode 100644
index 00000000..799d38d8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php
@@ -0,0 +1,27 @@
+createDependenciesFor('mime.embeddedfile')
+ );
+
+ $this->setBody($data);
+ $this->setFilename($filename);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new EmbeddedFile.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ *
+ * @return Swift_Mime_EmbeddedFile
+ */
+ public static function newInstance($data = null, $filename = null, $contentType = null)
+ {
+ return new self($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new EmbeddedFile from a filesystem path.
+ *
+ * @param string $path
+ *
+ * @return Swift_Mime_EmbeddedFile
+ */
+ public static function fromPath($path)
+ {
+ return self::newInstance()->setFile(
+ new Swift_ByteStream_FileByteStream($path)
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php
new file mode 100644
index 00000000..2073abca
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php
@@ -0,0 +1,28 @@
+= $maxLineLength || 76 < $maxLineLength) {
+ $maxLineLength = 76;
+ }
+
+ $encodedString = base64_encode($string);
+ $firstLine = '';
+
+ if (0 != $firstLineOffset) {
+ $firstLine = substr(
+ $encodedString, 0, $maxLineLength - $firstLineOffset
+ )."\r\n";
+ $encodedString = substr(
+ $encodedString, $maxLineLength - $firstLineOffset
+ );
+ }
+
+ return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n"));
+ }
+
+ /**
+ * Does nothing.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php
new file mode 100644
index 00000000..8a81fe39
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php
@@ -0,0 +1,300 @@
+ '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04',
+ 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09',
+ 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E',
+ 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13',
+ 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18',
+ 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D',
+ 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22',
+ 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27',
+ 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C',
+ 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31',
+ 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36',
+ 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B',
+ 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40',
+ 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45',
+ 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A',
+ 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F',
+ 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54',
+ 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59',
+ 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E',
+ 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63',
+ 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68',
+ 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D',
+ 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72',
+ 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77',
+ 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C',
+ 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81',
+ 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86',
+ 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B',
+ 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90',
+ 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95',
+ 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A',
+ 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F',
+ 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4',
+ 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9',
+ 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE',
+ 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3',
+ 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8',
+ 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD',
+ 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2',
+ 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7',
+ 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC',
+ 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1',
+ 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6',
+ 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB',
+ 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0',
+ 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5',
+ 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA',
+ 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF',
+ 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4',
+ 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9',
+ 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE',
+ 255 => '=FF',
+ );
+
+ protected static $_safeMapShare = array();
+
+ /**
+ * A map of non-encoded ascii characters.
+ *
+ * @var string[]
+ */
+ protected $_safeMap = array();
+
+ /**
+ * Creates a new QpEncoder for the given CharacterStream.
+ *
+ * @param Swift_CharacterStream $charStream to use for reading characters
+ * @param Swift_StreamFilter $filter if input should be canonicalized
+ */
+ public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null)
+ {
+ $this->_charStream = $charStream;
+ if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
+ } else {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ $this->_filter = $filter;
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter');
+ }
+
+ public function __wakeup()
+ {
+ if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
+ } else {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this);
+ }
+
+ protected function initSafeMap()
+ {
+ foreach (array_merge(
+ array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) {
+ $this->_safeMap[$byte] = chr($byte);
+ }
+ }
+
+ /**
+ * Takes an unencoded string and produces a QP encoded string from it.
+ *
+ * QP encoded strings have a maximum line length of 76 characters.
+ * If the first line needs to be shorter, indicate the difference with
+ * $firstLineOffset.
+ *
+ * @param string $string to encode
+ * @param int $firstLineOffset, optional
+ * @param int $maxLineLength, optional 0 indicates the default of 76 chars
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($maxLineLength > 76 || $maxLineLength <= 0) {
+ $maxLineLength = 76;
+ }
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ $lines = array();
+ $lNo = 0;
+ $lines[$lNo] = '';
+ $currentLine = &$lines[$lNo++];
+ $size = $lineLen = 0;
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importString($string);
+
+ // Fetching more than 4 chars at one is slower, as is fetching fewer bytes
+ // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6
+ // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes
+ while (false !== $bytes = $this->_nextSequence()) {
+ // If we're filtering the input
+ if (isset($this->_filter)) {
+ // If we can't filter because we need more bytes
+ while ($this->_filter->shouldBuffer($bytes)) {
+ // Then collect bytes into the buffer
+ if (false === $moreBytes = $this->_nextSequence(1)) {
+ break;
+ }
+
+ foreach ($moreBytes as $b) {
+ $bytes[] = $b;
+ }
+ }
+ // And filter them
+ $bytes = $this->_filter->filter($bytes);
+ }
+
+ $enc = $this->_encodeByteSequence($bytes, $size);
+
+ $i = strpos($enc, '=0D=0A');
+ $newLineLength = $lineLen + ($i === false ? $size : $i);
+
+ if ($currentLine && $newLineLength >= $thisLineLength) {
+ $lines[$lNo] = '';
+ $currentLine = &$lines[$lNo++];
+ $thisLineLength = $maxLineLength;
+ $lineLen = 0;
+ }
+
+ $currentLine .= $enc;
+
+ if ($i === false) {
+ $lineLen += $size;
+ } else {
+ // 6 is the length of '=0D=0A'.
+ $lineLen = $size - strrpos($enc, '=0D=0A') - 6;
+ }
+ }
+
+ return $this->_standardize(implode("=\r\n", $lines));
+ }
+
+ /**
+ * Updates the charset used.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charStream->setCharacterSet($charset);
+ }
+
+ /**
+ * Encode the given byte array into a verbatim QP form.
+ *
+ * @param integer[] $bytes
+ * @param int $size
+ *
+ * @return string
+ */
+ protected function _encodeByteSequence(array $bytes, &$size)
+ {
+ $ret = '';
+ $size = 0;
+ foreach ($bytes as $b) {
+ if (isset($this->_safeMap[$b])) {
+ $ret .= $this->_safeMap[$b];
+ ++$size;
+ } else {
+ $ret .= self::$_qpMap[$b];
+ $size += 3;
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Get the next sequence of bytes to read from the char stream.
+ *
+ * @param int $size number of bytes to read
+ *
+ * @return integer[]
+ */
+ protected function _nextSequence($size = 4)
+ {
+ return $this->_charStream->readBytes($size);
+ }
+
+ /**
+ * Make sure CRLF is correct and HT/SPACE are in valid places.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ protected function _standardize($string)
+ {
+ $string = str_replace(array("\t=0D=0A", ' =0D=0A', '=0D=0A'),
+ array("=09\r\n", "=20\r\n", "\r\n"), $string
+ );
+ switch ($end = ord(substr($string, -1))) {
+ case 0x09:
+ case 0x20:
+ $string = substr_replace($string, self::$_qpMap[$end], -1);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->_charStream = clone $this->_charStream;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php
new file mode 100644
index 00000000..b0215e88
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php
@@ -0,0 +1,92 @@
+_charStream = $charStream;
+ }
+
+ /**
+ * Takes an unencoded string and produces a string encoded according to
+ * RFC 2231 from it.
+ *
+ * @param string $string
+ * @param int $firstLineOffset
+ * @param int $maxLineLength optional, 0 indicates the default of 75 bytes
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $lines = array();
+ $lineCount = 0;
+ $lines[] = '';
+ $currentLine = &$lines[$lineCount++];
+
+ if (0 >= $maxLineLength) {
+ $maxLineLength = 75;
+ }
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importString($string);
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ while (false !== $char = $this->_charStream->read(4)) {
+ $encodedChar = rawurlencode($char);
+ if (0 != strlen($currentLine)
+ && strlen($currentLine.$encodedChar) > $thisLineLength) {
+ $lines[] = '';
+ $currentLine = &$lines[$lineCount++];
+ $thisLineLength = $maxLineLength;
+ }
+ $currentLine .= $encodedChar;
+ }
+
+ return implode("\r\n", $lines);
+ }
+
+ /**
+ * Updates the charset used.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charStream->setCharacterSet($charset);
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->_charStream = clone $this->_charStream;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php
new file mode 100644
index 00000000..253977b6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php
@@ -0,0 +1,64 @@
+lookup($key);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php
new file mode 100644
index 00000000..7dc381d9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php
@@ -0,0 +1,65 @@
+_command = $command;
+ $this->_successCodes = $successCodes;
+ }
+
+ /**
+ * Get the command which was sent to the server.
+ *
+ * @return string
+ */
+ public function getCommand()
+ {
+ return $this->_command;
+ }
+
+ /**
+ * Get the numeric response codes which indicate success for this command.
+ *
+ * @return integer[]
+ */
+ public function getSuccessCodes()
+ {
+ return $this->_successCodes;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php
new file mode 100644
index 00000000..7545404e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php
@@ -0,0 +1,24 @@
+_source = $source;
+ }
+
+ /**
+ * Get the source object of this event.
+ *
+ * @return object
+ */
+ public function getSource()
+ {
+ return $this->_source;
+ }
+
+ /**
+ * Prevent this Event from bubbling any further up the stack.
+ *
+ * @param bool $cancel, optional
+ */
+ public function cancelBubble($cancel = true)
+ {
+ $this->_bubbleCancelled = $cancel;
+ }
+
+ /**
+ * Returns true if this Event will not bubble any further up the stack.
+ *
+ * @return bool
+ */
+ public function bubbleCancelled()
+ {
+ return $this->_bubbleCancelled;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php
new file mode 100644
index 00000000..2e92ba94
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php
@@ -0,0 +1,65 @@
+_response = $response;
+ $this->_valid = $valid;
+ }
+
+ /**
+ * Get the response which was received from the server.
+ *
+ * @return string
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Get the success status of this Event.
+ *
+ * @return bool
+ */
+ public function isValid()
+ {
+ return $this->_valid;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php
new file mode 100644
index 00000000..c40919d2
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php
@@ -0,0 +1,24 @@
+_message = $message;
+ $this->_result = self::RESULT_PENDING;
+ }
+
+ /**
+ * Get the Transport used to send the Message.
+ *
+ * @return Swift_Transport
+ */
+ public function getTransport()
+ {
+ return $this->getSource();
+ }
+
+ /**
+ * Get the Message being sent.
+ *
+ * @return Swift_Mime_Message
+ */
+ public function getMessage()
+ {
+ return $this->_message;
+ }
+
+ /**
+ * Set the array of addresses that failed in sending.
+ *
+ * @param array $recipients
+ */
+ public function setFailedRecipients($recipients)
+ {
+ $this->_failedRecipients = $recipients;
+ }
+
+ /**
+ * Get an recipient addresses which were not accepted for delivery.
+ *
+ * @return string[]
+ */
+ public function getFailedRecipients()
+ {
+ return $this->_failedRecipients;
+ }
+
+ /**
+ * Set the result of sending.
+ *
+ * @param int $result
+ */
+ public function setResult($result)
+ {
+ $this->_result = $result;
+ }
+
+ /**
+ * Get the result of this Event.
+ *
+ * The return value is a bitmask from
+ * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED}
+ *
+ * @return int
+ */
+ public function getResult()
+ {
+ return $this->_result;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php
new file mode 100644
index 00000000..d922e1bf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php
@@ -0,0 +1,31 @@
+_eventMap = array(
+ 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener',
+ 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener',
+ 'Swift_Events_SendEvent' => 'Swift_Events_SendListener',
+ 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener',
+ 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener',
+ );
+ }
+
+ /**
+ * Create a new SendEvent for $source and $message.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_Mime_Message
+ *
+ * @return Swift_Events_SendEvent
+ */
+ public function createSendEvent(Swift_Transport $source, Swift_Mime_Message $message)
+ {
+ return new Swift_Events_SendEvent($source, $message);
+ }
+
+ /**
+ * Create a new CommandEvent for $source and $command.
+ *
+ * @param Swift_Transport $source
+ * @param string $command That will be executed
+ * @param array $successCodes That are needed
+ *
+ * @return Swift_Events_CommandEvent
+ */
+ public function createCommandEvent(Swift_Transport $source, $command, $successCodes = array())
+ {
+ return new Swift_Events_CommandEvent($source, $command, $successCodes);
+ }
+
+ /**
+ * Create a new ResponseEvent for $source and $response.
+ *
+ * @param Swift_Transport $source
+ * @param string $response
+ * @param bool $valid If the response is valid
+ *
+ * @return Swift_Events_ResponseEvent
+ */
+ public function createResponseEvent(Swift_Transport $source, $response, $valid)
+ {
+ return new Swift_Events_ResponseEvent($source, $response, $valid);
+ }
+
+ /**
+ * Create a new TransportChangeEvent for $source.
+ *
+ * @param Swift_Transport $source
+ *
+ * @return Swift_Events_TransportChangeEvent
+ */
+ public function createTransportChangeEvent(Swift_Transport $source)
+ {
+ return new Swift_Events_TransportChangeEvent($source);
+ }
+
+ /**
+ * Create a new TransportExceptionEvent for $source.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_TransportException $ex
+ *
+ * @return Swift_Events_TransportExceptionEvent
+ */
+ public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex)
+ {
+ return new Swift_Events_TransportExceptionEvent($source, $ex);
+ }
+
+ /**
+ * Bind an event listener to this dispatcher.
+ *
+ * @param Swift_Events_EventListener $listener
+ */
+ public function bindEventListener(Swift_Events_EventListener $listener)
+ {
+ foreach ($this->_listeners as $l) {
+ // Already loaded
+ if ($l === $listener) {
+ return;
+ }
+ }
+ $this->_listeners[] = $listener;
+ }
+
+ /**
+ * Dispatch the given Event to all suitable listeners.
+ *
+ * @param Swift_Events_EventObject $evt
+ * @param string $target method
+ */
+ public function dispatchEvent(Swift_Events_EventObject $evt, $target)
+ {
+ $this->_prepareBubbleQueue($evt);
+ $this->_bubble($evt, $target);
+ }
+
+ /** Queue listeners on a stack ready for $evt to be bubbled up it */
+ private function _prepareBubbleQueue(Swift_Events_EventObject $evt)
+ {
+ $this->_bubbleQueue = array();
+ $evtClass = get_class($evt);
+ foreach ($this->_listeners as $listener) {
+ if (array_key_exists($evtClass, $this->_eventMap)
+ && ($listener instanceof $this->_eventMap[$evtClass])) {
+ $this->_bubbleQueue[] = $listener;
+ }
+ }
+ }
+
+ /** Bubble $evt up the stack calling $target() on each listener */
+ private function _bubble(Swift_Events_EventObject $evt, $target)
+ {
+ if (!$evt->bubbleCancelled() && $listener = array_shift($this->_bubbleQueue)) {
+ $listener->$target($evt);
+ $this->_bubble($evt, $target);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php
new file mode 100644
index 00000000..a8972fda
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php
@@ -0,0 +1,27 @@
+getSource();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php
new file mode 100644
index 00000000..253165de
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php
@@ -0,0 +1,45 @@
+_exception = $ex;
+ }
+
+ /**
+ * Get the TransportException thrown.
+ *
+ * @return Swift_TransportException
+ */
+ public function getException()
+ {
+ return $this->_exception;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php
new file mode 100644
index 00000000..cc3c0993
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php
@@ -0,0 +1,24 @@
+createDependenciesFor('transport.failover')
+ );
+
+ $this->setTransports($transports);
+ }
+
+ /**
+ * Create a new FailoverTransport instance.
+ *
+ * @param Swift_Transport[] $transports
+ *
+ * @return Swift_FailoverTransport
+ */
+ public static function newInstance($transports = array())
+ {
+ return new self($transports);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php
new file mode 100644
index 00000000..c82c5dbf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php
@@ -0,0 +1,208 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages on the filesystem.
+ *
+ * @author Fabien Potencier
+ * @author Xavier De Cock
+ */
+class Swift_FileSpool extends Swift_ConfigurableSpool
+{
+ /** The spool directory */
+ private $_path;
+
+ /**
+ * File WriteRetry Limit.
+ *
+ * @var int
+ */
+ private $_retryLimit = 10;
+
+ /**
+ * Create a new FileSpool.
+ *
+ * @param string $path
+ *
+ * @throws Swift_IoException
+ */
+ public function __construct($path)
+ {
+ $this->_path = $path;
+
+ if (!file_exists($this->_path)) {
+ if (!mkdir($this->_path, 0777, true)) {
+ throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->_path));
+ }
+ }
+ }
+
+ /**
+ * Tests if this Spool mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Spool mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Spool mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Allow to manage the enqueuing retry limit.
+ *
+ * Default, is ten and allows over 64^20 different fileNames
+ *
+ * @param int $limit
+ */
+ public function setRetryLimit($limit)
+ {
+ $this->_retryLimit = $limit;
+ }
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @throws Swift_IoException
+ *
+ * @return bool
+ */
+ public function queueMessage(Swift_Mime_Message $message)
+ {
+ $ser = serialize($message);
+ $fileName = $this->_path.'/'.$this->getRandomString(10);
+ for ($i = 0; $i < $this->_retryLimit; ++$i) {
+ /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */
+ $fp = @fopen($fileName.'.message', 'x');
+ if (false !== $fp) {
+ if (false === fwrite($fp, $ser)) {
+ return false;
+ }
+
+ return fclose($fp);
+ } else {
+ /* The file already exists, we try a longer fileName */
+ $fileName .= $this->getRandomString(1);
+ }
+ }
+
+ throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->_path));
+ }
+
+ /**
+ * Execute a recovery if for any reason a process is sending for too long.
+ *
+ * @param int $timeout in second Defaults is for very slow smtp responses
+ */
+ public function recover($timeout = 900)
+ {
+ foreach (new DirectoryIterator($this->_path) as $file) {
+ $file = $file->getRealPath();
+
+ if (substr($file, -16) == '.message.sending') {
+ $lockedtime = filectime($file);
+ if ((time() - $lockedtime) > $timeout) {
+ rename($file, substr($file, 0, -8));
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent e-mail's
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+ {
+ $directoryIterator = new DirectoryIterator($this->_path);
+
+ /* Start the transport only if there are queued files to send */
+ if (!$transport->isStarted()) {
+ foreach ($directoryIterator as $file) {
+ if (substr($file->getRealPath(), -8) == '.message') {
+ $transport->start();
+ break;
+ }
+ }
+ }
+
+ $failedRecipients = (array) $failedRecipients;
+ $count = 0;
+ $time = time();
+ foreach ($directoryIterator as $file) {
+ $file = $file->getRealPath();
+
+ if (substr($file, -8) != '.message') {
+ continue;
+ }
+
+ /* We try a rename, it's an atomic operation, and avoid locking the file */
+ if (rename($file, $file.'.sending')) {
+ $message = unserialize(file_get_contents($file.'.sending'));
+
+ $count += $transport->send($message, $failedRecipients);
+
+ unlink($file.'.sending');
+ } else {
+ /* This message has just been catched by another process */
+ continue;
+ }
+
+ if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) {
+ break;
+ }
+
+ if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) {
+ break;
+ }
+ }
+
+ return $count;
+ }
+
+ /**
+ * Returns a random string needed to generate a fileName for the queue.
+ *
+ * @param int $count
+ *
+ * @return string
+ */
+ protected function getRandomString($count)
+ {
+ // This string MUST stay FS safe, avoid special chars
+ $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
+ $ret = '';
+ $strlen = strlen($base);
+ for ($i = 0; $i < $count; ++$i) {
+ $ret .= $base[((int) rand(0, $strlen - 1))];
+ }
+
+ return $ret;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php
new file mode 100644
index 00000000..0b24db1c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php
@@ -0,0 +1,24 @@
+setFile(
+ new Swift_ByteStream_FileByteStream($path)
+ );
+
+ return $image;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php
new file mode 100644
index 00000000..56efc759
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php
@@ -0,0 +1,75 @@
+_stream = $stream;
+ }
+
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ */
+ public function setString($nsKey, $itemKey, $string, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $this->_contents[$nsKey][$itemKey] = $string;
+ break;
+ case self::MODE_APPEND:
+ if (!$this->hasKey($nsKey, $itemKey)) {
+ $this->_contents[$nsKey][$itemKey] = '';
+ }
+ $this->_contents[$nsKey][$itemKey] .= $string;
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode ['.$mode.'] used to set nsKey='.
+ $nsKey.', itemKey='.$itemKey
+ );
+ }
+ }
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $this->clearKey($nsKey, $itemKey);
+ case self::MODE_APPEND:
+ if (!$this->hasKey($nsKey, $itemKey)) {
+ $this->_contents[$nsKey][$itemKey] = '';
+ }
+ while (false !== $bytes = $os->read(8192)) {
+ $this->_contents[$nsKey][$itemKey] .= $bytes;
+ }
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode ['.$mode.'] used to set nsKey='.
+ $nsKey.', itemKey='.$itemKey
+ );
+ }
+ }
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $writeThrough
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
+ {
+ $is = clone $this->_stream;
+ $is->setKeyCache($this);
+ $is->setNsKey($nsKey);
+ $is->setItemKey($itemKey);
+ if (isset($writeThrough)) {
+ $is->setWriteThroughStream($writeThrough);
+ }
+
+ return $is;
+ }
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return string
+ */
+ public function getString($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+ if ($this->hasKey($nsKey, $itemKey)) {
+ return $this->_contents[$nsKey][$itemKey];
+ }
+ }
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
+ {
+ $this->_prepareCache($nsKey);
+ $is->write($this->getString($nsKey, $itemKey));
+ }
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+
+ return array_key_exists($itemKey, $this->_contents[$nsKey]);
+ }
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey)
+ {
+ unset($this->_contents[$nsKey][$itemKey]);
+ }
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey)
+ {
+ unset($this->_contents[$nsKey]);
+ }
+
+ /**
+ * Initialize the namespace of $nsKey if needed.
+ *
+ * @param string $nsKey
+ */
+ private function _prepareCache($nsKey)
+ {
+ if (!array_key_exists($nsKey, $this->_contents)) {
+ $this->_contents[$nsKey] = array();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php
new file mode 100644
index 00000000..453f50a1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php
@@ -0,0 +1,321 @@
+_stream = $stream;
+ $this->_path = $path;
+
+ if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
+ $this->_quotes = true;
+ }
+ }
+
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ *
+ * @throws Swift_IoException
+ */
+ public function setString($nsKey, $itemKey, $string, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ break;
+ case self::MODE_APPEND:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode ['.$mode.'] used to set nsKey='.
+ $nsKey.', itemKey='.$itemKey
+ );
+ break;
+ }
+ fwrite($fp, $string);
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ *
+ * @throws Swift_IoException
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ break;
+ case self::MODE_APPEND:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode ['.$mode.'] used to set nsKey='.
+ $nsKey.', itemKey='.$itemKey
+ );
+ break;
+ }
+ while (false !== $bytes = $os->read(8192)) {
+ fwrite($fp, $bytes);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $writeThrough
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
+ {
+ $is = clone $this->_stream;
+ $is->setKeyCache($this);
+ $is->setNsKey($nsKey);
+ $is->setItemKey($itemKey);
+ if (isset($writeThrough)) {
+ $is->setWriteThroughStream($writeThrough);
+ }
+
+ return $is;
+ }
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @throws Swift_IoException
+ *
+ * @return string
+ */
+ public function getString($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ $str = '';
+ while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
+ $str .= $bytes;
+ }
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+
+ return $str;
+ }
+ }
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
+ {
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
+ $is->write($bytes);
+ }
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+ }
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey)
+ {
+ return is_file($this->_path.'/'.$nsKey.'/'.$itemKey);
+ }
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey)
+ {
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $this->_freeHandle($nsKey, $itemKey);
+ unlink($this->_path.'/'.$nsKey.'/'.$itemKey);
+ }
+ }
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey)
+ {
+ if (array_key_exists($nsKey, $this->_keys)) {
+ foreach ($this->_keys[$nsKey] as $itemKey => $null) {
+ $this->clearKey($nsKey, $itemKey);
+ }
+ if (is_dir($this->_path.'/'.$nsKey)) {
+ rmdir($this->_path.'/'.$nsKey);
+ }
+ unset($this->_keys[$nsKey]);
+ }
+ }
+
+ /**
+ * Initialize the namespace of $nsKey if needed.
+ *
+ * @param string $nsKey
+ */
+ private function _prepareCache($nsKey)
+ {
+ $cacheDir = $this->_path.'/'.$nsKey;
+ if (!is_dir($cacheDir)) {
+ if (!mkdir($cacheDir)) {
+ throw new Swift_IoException('Failed to create cache directory '.$cacheDir);
+ }
+ $this->_keys[$nsKey] = array();
+ }
+ }
+
+ /**
+ * Get a file handle on the cache item.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param int $position
+ *
+ * @return resource
+ */
+ private function _getHandle($nsKey, $itemKey, $position)
+ {
+ if (!isset($this->_keys[$nsKey][$itemKey])) {
+ $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b';
+ $fp = fopen($this->_path.'/'.$nsKey.'/'.$itemKey, $openMode);
+ $this->_keys[$nsKey][$itemKey] = $fp;
+ }
+ if (self::POSITION_START == $position) {
+ fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET);
+ } elseif (self::POSITION_END == $position) {
+ fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END);
+ }
+
+ return $this->_keys[$nsKey][$itemKey];
+ }
+
+ private function _freeHandle($nsKey, $itemKey)
+ {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_CURRENT);
+ fclose($fp);
+ $this->_keys[$nsKey][$itemKey] = null;
+ }
+
+ /**
+ * Destructor.
+ */
+ public function __destruct()
+ {
+ foreach ($this->_keys as $nsKey => $null) {
+ $this->clearAll($nsKey);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php
new file mode 100644
index 00000000..af80bdca
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php
@@ -0,0 +1,51 @@
+_keyCache = $keyCache;
+ }
+
+ /**
+ * Specify a stream to write through for each write().
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function setWriteThroughStream(Swift_InputByteStream $is)
+ {
+ $this->_writeThrough = $is;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ * @param Swift_InputByteStream $is optional
+ */
+ public function write($bytes, Swift_InputByteStream $is = null)
+ {
+ $this->_keyCache->setString(
+ $this->_nsKey, $this->_itemKey, $bytes, Swift_KeyCache::MODE_APPEND
+ );
+ if (isset($is)) {
+ $is->write($bytes);
+ }
+ if (isset($this->_writeThrough)) {
+ $this->_writeThrough->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ */
+ public function flushBuffers()
+ {
+ $this->_keyCache->clearKey($this->_nsKey, $this->_itemKey);
+ }
+
+ /**
+ * Set the nsKey which will be written to.
+ *
+ * @param string $nsKey
+ */
+ public function setNsKey($nsKey)
+ {
+ $this->_nsKey = $nsKey;
+ }
+
+ /**
+ * Set the itemKey which will be written to.
+ *
+ * @param string $itemKey
+ */
+ public function setItemKey($itemKey)
+ {
+ $this->_itemKey = $itemKey;
+ }
+
+ /**
+ * Any implementation should be cloneable, allowing the clone to access a
+ * separate $nsKey and $itemKey.
+ */
+ public function __clone()
+ {
+ $this->_writeThrough = null;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php
new file mode 100644
index 00000000..fdba9df5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php
@@ -0,0 +1,45 @@
+createDependenciesFor('transport.loadbalanced')
+ );
+
+ $this->setTransports($transports);
+ }
+
+ /**
+ * Create a new LoadBalancedTransport instance.
+ *
+ * @param array $transports
+ *
+ * @return Swift_LoadBalancedTransport
+ */
+ public static function newInstance($transports = array())
+ {
+ return new self($transports);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php
new file mode 100644
index 00000000..994df3ec
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php
@@ -0,0 +1,47 @@
+createDependenciesFor('transport.mail')
+ );
+
+ $this->setExtraParams($extraParams);
+ }
+
+ /**
+ * Create a new MailTransport instance.
+ *
+ * @param string $extraParams To be passed to mail()
+ *
+ * @return Swift_MailTransport
+ */
+ public static function newInstance($extraParams = '-f%s')
+ {
+ return new self($extraParams);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php
new file mode 100644
index 00000000..64115462
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php
@@ -0,0 +1,114 @@
+_transport = $transport;
+ }
+
+ /**
+ * Create a new Mailer instance.
+ *
+ * @param Swift_Transport $transport
+ *
+ * @return Swift_Mailer
+ */
+ public static function newInstance(Swift_Transport $transport)
+ {
+ return new self($transport);
+ }
+
+ /**
+ * Create a new class instance of one of the message services.
+ *
+ * For example 'mimepart' would create a 'message.mimepart' instance
+ *
+ * @param string $service
+ *
+ * @return object
+ */
+ public function createMessage($service = 'message')
+ {
+ return Swift_DependencyContainer::getInstance()
+ ->lookup('message.'.$service);
+ }
+
+ /**
+ * Send the given Message like it would be sent in a mail client.
+ *
+ * All recipients (with the exception of Bcc) will be able to see the other
+ * recipients this message was sent to.
+ *
+ * Recipient/sender data will be retrieved from the Message object.
+ *
+ * The return value is the number of recipients who were accepted for
+ * delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param array $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of successful recipients. Can be 0 which indicates failure
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+
+ if (!$this->_transport->isStarted()) {
+ $this->_transport->start();
+ }
+
+ $sent = 0;
+
+ try {
+ $sent = $this->_transport->send($message, $failedRecipients);
+ } catch (Swift_RfcComplianceException $e) {
+ foreach ($message->getTo() as $address => $name) {
+ $failedRecipients[] = $address;
+ }
+ }
+
+ return $sent;
+ }
+
+ /**
+ * Register a plugin using a known unique key (e.g. myPlugin).
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_transport->registerPlugin($plugin);
+ }
+
+ /**
+ * The Transport used to send messages.
+ *
+ * @return Swift_Transport
+ */
+ public function getTransport()
+ {
+ return $this->_transport;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php
new file mode 100644
index 00000000..e3e6cad0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php
@@ -0,0 +1,55 @@
+_recipients = $recipients;
+ }
+
+ /**
+ * Returns true only if there are more recipients to send to.
+ *
+ * @return bool
+ */
+ public function hasNext()
+ {
+ return !empty($this->_recipients);
+ }
+
+ /**
+ * Returns an array where the keys are the addresses of recipients and the
+ * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL).
+ *
+ * @return array
+ */
+ public function nextRecipient()
+ {
+ return array_splice($this->_recipients, 0, 1);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php
new file mode 100644
index 00000000..650f3ec3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php
@@ -0,0 +1,32 @@
+ 'Foo') or ('foo@bar' => NULL).
+ *
+ * @return array
+ */
+ public function nextRecipient();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php
new file mode 100644
index 00000000..2cafb675
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php
@@ -0,0 +1,110 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in memory.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_MemorySpool implements Swift_Spool
+{
+ protected $messages = array();
+ private $flushRetries = 3;
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * @param int $retries
+ */
+ public function setFlushRetries($retries)
+ {
+ $this->flushRetries = $retries;
+ }
+
+ /**
+ * Stores a message in the queue.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return bool Whether the operation has succeeded
+ */
+ public function queueMessage(Swift_Mime_Message $message)
+ {
+ //clone the message to make sure it is not changed while in the queue
+ $this->messages[] = clone $message;
+
+ return true;
+ }
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+ {
+ if (!$this->messages) {
+ return 0;
+ }
+
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+
+ $count = 0;
+ $retries = $this->flushRetries;
+ while ($retries--) {
+ try {
+ while ($message = array_pop($this->messages)) {
+ $count += $transport->send($message, $failedRecipients);
+ }
+ } catch (Swift_TransportException $exception) {
+ if ($retries) {
+ // re-queue the message at the end of the queue to give a chance
+ // to the other messages to be sent, in case the failure was due to
+ // this message and not just the transport failing
+ array_unshift($this->messages, $message);
+
+ // wait half a second before we try again
+ usleep(500000);
+ } else {
+ throw $exception;
+ }
+ }
+ }
+
+ return $count;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php
new file mode 100644
index 00000000..a6bb6593
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php
@@ -0,0 +1,291 @@
+createDependenciesFor('mime.message')
+ );
+
+ if (!isset($charset)) {
+ $charset = Swift_DependencyContainer::getInstance()
+ ->lookup('properties.charset');
+ }
+ $this->setSubject($subject);
+ $this->setBody($body);
+ $this->setCharset($charset);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new Message.
+ *
+ * @param string $subject
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return $this
+ */
+ public static function newInstance($subject = null, $body = null, $contentType = null, $charset = null)
+ {
+ return new self($subject, $body, $contentType, $charset);
+ }
+
+ /**
+ * Add a MimePart to this Message.
+ *
+ * @param string|Swift_OutputByteStream $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return $this
+ */
+ public function addPart($body, $contentType = null, $charset = null)
+ {
+ return $this->attach(Swift_MimePart::newInstance(
+ $body, $contentType, $charset
+ ));
+ }
+
+ /**
+ * Detach a signature handler from a message.
+ *
+ * @param Swift_Signer $signer
+ *
+ * @return $this
+ */
+ public function attachSigner(Swift_Signer $signer)
+ {
+ if ($signer instanceof Swift_Signers_HeaderSigner) {
+ $this->headerSigners[] = $signer;
+ } elseif ($signer instanceof Swift_Signers_BodySigner) {
+ $this->bodySigners[] = $signer;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Attach a new signature handler to the message.
+ *
+ * @param Swift_Signer $signer
+ *
+ * @return $this
+ */
+ public function detachSigner(Swift_Signer $signer)
+ {
+ if ($signer instanceof Swift_Signers_HeaderSigner) {
+ foreach ($this->headerSigners as $k => $headerSigner) {
+ if ($headerSigner === $signer) {
+ unset($this->headerSigners[$k]);
+
+ return $this;
+ }
+ }
+ } elseif ($signer instanceof Swift_Signers_BodySigner) {
+ foreach ($this->bodySigners as $k => $bodySigner) {
+ if ($bodySigner === $signer) {
+ unset($this->bodySigners[$k]);
+
+ return $this;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get this message as a complete string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ if (empty($this->headerSigners) && empty($this->bodySigners)) {
+ return parent::toString();
+ }
+
+ $this->saveMessage();
+
+ $this->doSign();
+
+ $string = parent::toString();
+
+ $this->restoreMessage();
+
+ return $string;
+ }
+
+ /**
+ * Write this message to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ if (empty($this->headerSigners) && empty($this->bodySigners)) {
+ parent::toByteStream($is);
+
+ return;
+ }
+
+ $this->saveMessage();
+
+ $this->doSign();
+
+ parent::toByteStream($is);
+
+ $this->restoreMessage();
+ }
+
+ public function __wakeup()
+ {
+ Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message');
+ }
+
+ /**
+ * loops through signers and apply the signatures.
+ */
+ protected function doSign()
+ {
+ foreach ($this->bodySigners as $signer) {
+ $altered = $signer->getAlteredHeaders();
+ $this->saveHeaders($altered);
+ $signer->signMessage($this);
+ }
+
+ foreach ($this->headerSigners as $signer) {
+ $altered = $signer->getAlteredHeaders();
+ $this->saveHeaders($altered);
+ $signer->reset();
+
+ $signer->setHeaders($this->getHeaders());
+
+ $signer->startBody();
+ $this->_bodyToByteStream($signer);
+ $signer->endBody();
+
+ $signer->addSignature($this->getHeaders());
+ }
+ }
+
+ /**
+ * save the message before any signature is applied.
+ */
+ protected function saveMessage()
+ {
+ $this->savedMessage = array('headers' => array());
+ $this->savedMessage['body'] = $this->getBody();
+ $this->savedMessage['children'] = $this->getChildren();
+ if (count($this->savedMessage['children']) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $this->savedMessage['children']));
+ $this->setBody('');
+ }
+ }
+
+ /**
+ * save the original headers.
+ *
+ * @param array $altered
+ */
+ protected function saveHeaders(array $altered)
+ {
+ foreach ($altered as $head) {
+ $lc = strtolower($head);
+
+ if (!isset($this->savedMessage['headers'][$lc])) {
+ $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head);
+ }
+ }
+ }
+
+ /**
+ * Remove or restore altered headers.
+ */
+ protected function restoreHeaders()
+ {
+ foreach ($this->savedMessage['headers'] as $name => $savedValue) {
+ $headers = $this->getHeaders()->getAll($name);
+
+ foreach ($headers as $key => $value) {
+ if (!isset($savedValue[$key])) {
+ $this->getHeaders()->remove($name, $key);
+ }
+ }
+ }
+ }
+
+ /**
+ * Restore message body.
+ */
+ protected function restoreMessage()
+ {
+ $this->setBody($this->savedMessage['body']);
+ $this->setChildren($this->savedMessage['children']);
+
+ $this->restoreHeaders();
+ $this->savedMessage = array();
+ }
+
+ /**
+ * Clone Message Signers.
+ *
+ * @see Swift_Mime_SimpleMimeEntity::__clone()
+ */
+ public function __clone()
+ {
+ parent::__clone();
+ foreach ($this->bodySigners as $key => $bodySigner) {
+ $this->bodySigners[$key] = clone $bodySigner;
+ }
+
+ foreach ($this->headerSigners as $key => $headerSigner) {
+ $this->headerSigners[$key] = clone $headerSigner;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php
new file mode 100644
index 00000000..46a5e8da
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php
@@ -0,0 +1,149 @@
+setDisposition('attachment');
+ $this->setContentType('application/octet-stream');
+ $this->_mimeTypes = $mimeTypes;
+ }
+
+ /**
+ * Get the nesting level used for this attachment.
+ *
+ * Always returns {@link LEVEL_MIXED}.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_MIXED;
+ }
+
+ /**
+ * Get the Content-Disposition of this attachment.
+ *
+ * By default attachments have a disposition of "attachment".
+ *
+ * @return string
+ */
+ public function getDisposition()
+ {
+ return $this->_getHeaderFieldModel('Content-Disposition');
+ }
+
+ /**
+ * Set the Content-Disposition of this attachment.
+ *
+ * @param string $disposition
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setDisposition($disposition)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Disposition', $disposition)) {
+ $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the filename of this attachment when downloaded.
+ *
+ * @return string
+ */
+ public function getFilename()
+ {
+ return $this->_getHeaderParameter('Content-Disposition', 'filename');
+ }
+
+ /**
+ * Set the filename of this attachment.
+ *
+ * @param string $filename
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setFilename($filename)
+ {
+ $this->_setHeaderParameter('Content-Disposition', 'filename', $filename);
+ $this->_setHeaderParameter('Content-Type', 'name', $filename);
+
+ return $this;
+ }
+
+ /**
+ * Get the file size of this attachment.
+ *
+ * @return int
+ */
+ public function getSize()
+ {
+ return $this->_getHeaderParameter('Content-Disposition', 'size');
+ }
+
+ /**
+ * Set the file size of this attachment.
+ *
+ * @param int $size
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setSize($size)
+ {
+ $this->_setHeaderParameter('Content-Disposition', 'size', $size);
+
+ return $this;
+ }
+
+ /**
+ * Set the file that this attachment is for.
+ *
+ * @param Swift_FileStream $file
+ * @param string $contentType optional
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setFile(Swift_FileStream $file, $contentType = null)
+ {
+ $this->setFilename(basename($file->getPath()));
+ $this->setBody($file, $contentType);
+ if (!isset($contentType)) {
+ $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1));
+
+ if (array_key_exists($extension, $this->_mimeTypes)) {
+ $this->setContentType($this->_mimeTypes[$extension]);
+ }
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php
new file mode 100644
index 00000000..b49c3a87
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php
@@ -0,0 +1,24 @@
+= $maxLineLength || 76 < $maxLineLength) {
+ $maxLineLength = 76;
+ }
+
+ $remainder = 0;
+ $base64ReadBufferRemainderBytes = null;
+
+ // To reduce memory usage, the output buffer is streamed to the input buffer like so:
+ // Output Stream => base64encode => wrap line length => Input Stream
+ // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data)
+ // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream.
+ // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the
+ // chunk of bytes read in the next iteration.
+ // When the OutputStream is empty, we must flush any remainder bytes.
+ while (true) {
+ $readBytes = $os->read(8192);
+ $atEOF = ($readBytes === false);
+
+ if ($atEOF) {
+ $streamTheseBytes = $base64ReadBufferRemainderBytes;
+ } else {
+ $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes;
+ }
+ $base64ReadBufferRemainderBytes = null;
+ $bytesLength = strlen($streamTheseBytes);
+
+ if ($bytesLength === 0) { // no data left to encode
+ break;
+ }
+
+ // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data
+ // and carry over remainder 1-2 bytes to the next loop iteration
+ if (!$atEOF) {
+ $excessBytes = $bytesLength % 3;
+ if ($excessBytes !== 0) {
+ $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes);
+ $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes);
+ }
+ }
+
+ $encoded = base64_encode($streamTheseBytes);
+ $encodedTransformed = '';
+ $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset;
+
+ while ($thisMaxLineLength < strlen($encoded)) {
+ $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n";
+ $firstLineOffset = 0;
+ $encoded = substr($encoded, $thisMaxLineLength);
+ $thisMaxLineLength = $maxLineLength;
+ $remainder = 0;
+ }
+
+ if (0 < $remainingLength = strlen($encoded)) {
+ $remainder += $remainingLength;
+ $encodedTransformed .= $encoded;
+ $encoded = null;
+ }
+
+ $is->write($encodedTransformed);
+
+ if ($atEOF) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ * Returns the string 'base64'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'base64';
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
new file mode 100644
index 00000000..710b5ac9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
@@ -0,0 +1,123 @@
+charset = $charset ? $charset : 'utf-8';
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * Encode $in to $out.
+ *
+ * @param Swift_OutputByteStream $os to read from
+ * @param Swift_InputByteStream $is to write to
+ * @param int $firstLineOffset
+ * @param int $maxLineLength 0 indicates the default length for this encoding
+ *
+ * @throws RuntimeException
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->charset !== 'utf-8') {
+ throw new RuntimeException(
+ sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset));
+ }
+
+ $string = '';
+
+ while (false !== $bytes = $os->read(8192)) {
+ $string .= $bytes;
+ }
+
+ $is->write($this->encodeString($string));
+ }
+
+ /**
+ * Get the MIME name of this content encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset if first line needs to be shorter
+ * @param int $maxLineLength 0 indicates the default length for this encoding
+ *
+ * @throws RuntimeException
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->charset !== 'utf-8') {
+ throw new RuntimeException(
+ sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset));
+ }
+
+ return $this->_standardize(quoted_printable_encode($string));
+ }
+
+ /**
+ * Make sure CRLF is correct and HT/SPACE are in valid places.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ protected function _standardize($string)
+ {
+ // transform CR or LF to CRLF
+ $string = preg_replace('~=0D(?!=0A)|(?_name = $name;
+ $this->_canonical = $canonical;
+ }
+
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength - 0 means no wrapping will occur
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->_canonical) {
+ $string = $this->_canonicalize($string);
+ }
+
+ return $this->_safeWordWrap($string, $maxLineLength, "\r\n");
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * @param Swift_OutputByteStream $os
+ * @param Swift_InputByteStream $is
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength optional, 0 means no wrapping will occur
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $leftOver = '';
+ while (false !== $bytes = $os->read(8192)) {
+ $toencode = $leftOver.$bytes;
+ if ($this->_canonical) {
+ $toencode = $this->_canonicalize($toencode);
+ }
+ $wrapped = $this->_safeWordWrap($toencode, $maxLineLength, "\r\n");
+ $lastLinePos = strrpos($wrapped, "\r\n");
+ $leftOver = substr($wrapped, $lastLinePos);
+ $wrapped = substr($wrapped, 0, $lastLinePos);
+
+ $is->write($wrapped);
+ }
+ if (strlen($leftOver)) {
+ $is->write($leftOver);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Not used.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+
+ /**
+ * A safer (but weaker) wordwrap for unicode.
+ *
+ * @param string $string
+ * @param int $length
+ * @param string $le
+ *
+ * @return string
+ */
+ private function _safeWordwrap($string, $length = 75, $le = "\r\n")
+ {
+ if (0 >= $length) {
+ return $string;
+ }
+
+ $originalLines = explode($le, $string);
+
+ $lines = array();
+ $lineCount = 0;
+
+ foreach ($originalLines as $originalLine) {
+ $lines[] = '';
+ $currentLine = &$lines[$lineCount++];
+
+ //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine);
+ $chunks = preg_split('/(?<=\s)/', $originalLine);
+
+ foreach ($chunks as $chunk) {
+ if (0 != strlen($currentLine)
+ && strlen($currentLine.$chunk) > $length) {
+ $lines[] = '';
+ $currentLine = &$lines[$lineCount++];
+ }
+ $currentLine .= $chunk;
+ }
+ }
+
+ return implode("\r\n", $lines);
+ }
+
+ /**
+ * Canonicalize string input (fix CRLF).
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ private function _canonicalize($string)
+ {
+ return str_replace(
+ array("\r\n", "\r", "\n"),
+ array("\n", "\n", "\r\n"),
+ $string
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
new file mode 100644
index 00000000..5cc907b8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
@@ -0,0 +1,134 @@
+_dotEscape = $dotEscape;
+ parent::__construct($charStream, $filter);
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter', '_dotEscape');
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this).($this->_dotEscape ? '.dotEscape' : '');
+ }
+
+ protected function initSafeMap()
+ {
+ parent::initSafeMap();
+ if ($this->_dotEscape) {
+ /* Encode . as =2e for buggy remote servers */
+ unset($this->_safeMap[0x2e]);
+ }
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * QP encoded strings have a maximum line length of 76 characters.
+ * If the first line needs to be shorter, indicate the difference with
+ * $firstLineOffset.
+ *
+ * @param Swift_OutputByteStream $os output stream
+ * @param Swift_InputByteStream $is input stream
+ * @param int $firstLineOffset
+ * @param int $maxLineLength
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($maxLineLength > 76 || $maxLineLength <= 0) {
+ $maxLineLength = 76;
+ }
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importByteStream($os);
+
+ $currentLine = '';
+ $prepend = '';
+ $size = $lineLen = 0;
+
+ while (false !== $bytes = $this->_nextSequence()) {
+ // If we're filtering the input
+ if (isset($this->_filter)) {
+ // If we can't filter because we need more bytes
+ while ($this->_filter->shouldBuffer($bytes)) {
+ // Then collect bytes into the buffer
+ if (false === $moreBytes = $this->_nextSequence(1)) {
+ break;
+ }
+
+ foreach ($moreBytes as $b) {
+ $bytes[] = $b;
+ }
+ }
+ // And filter them
+ $bytes = $this->_filter->filter($bytes);
+ }
+
+ $enc = $this->_encodeByteSequence($bytes, $size);
+
+ $i = strpos($enc, '=0D=0A');
+ $newLineLength = $lineLen + ($i === false ? $size : $i);
+
+ if ($currentLine && $newLineLength >= $thisLineLength) {
+ $is->write($prepend.$this->_standardize($currentLine));
+ $currentLine = '';
+ $prepend = "=\r\n";
+ $thisLineLength = $maxLineLength;
+ $lineLen = 0;
+ }
+
+ $currentLine .= $enc;
+
+ if ($i === false) {
+ $lineLen += $size;
+ } else {
+ // 6 is the length of '=0D=0A'.
+ $lineLen = $size - strrpos($enc, '=0D=0A') - 6;
+ }
+ }
+ if (strlen($currentLine)) {
+ $is->write($prepend.$this->_standardize($currentLine));
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ * Returns the string 'quoted-printable'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php
new file mode 100644
index 00000000..3214e1cf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php
@@ -0,0 +1,98 @@
+
+ */
+class Swift_Mime_ContentEncoder_QpContentEncoderProxy implements Swift_Mime_ContentEncoder
+{
+ /**
+ * @var Swift_Mime_ContentEncoder_QpContentEncoder
+ */
+ private $safeEncoder;
+
+ /**
+ * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder
+ */
+ private $nativeEncoder;
+
+ /**
+ * @var null|string
+ */
+ private $charset;
+
+ /**
+ * Constructor.
+ *
+ * @param Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder
+ * @param Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder
+ * @param string|null $charset
+ */
+ public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset)
+ {
+ $this->safeEncoder = $safeEncoder;
+ $this->nativeEncoder = $nativeEncoder;
+ $this->charset = $charset;
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->safeEncoder = clone $this->safeEncoder;
+ $this->nativeEncoder = clone $this->nativeEncoder;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function charsetChanged($charset)
+ {
+ $this->charset = $charset;
+ $this->safeEncoder->charsetChanged($charset);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength);
+ }
+
+ /**
+ * @return Swift_Mime_ContentEncoder
+ */
+ private function getEncoder()
+ {
+ return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
new file mode 100644
index 00000000..0b8526e3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
@@ -0,0 +1,64 @@
+
+ */
+class Swift_Mime_ContentEncoder_RawContentEncoder implements Swift_Mime_ContentEncoder
+{
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength ignored
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return $string;
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * @param Swift_OutputByteStream $in
+ * @param Swift_InputByteStream $out
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength ignored
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ while (false !== ($bytes = $os->read(8192))) {
+ $is->write($bytes);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'raw';
+ }
+
+ /**
+ * Not used.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php
new file mode 100644
index 00000000..6af75712
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php
@@ -0,0 +1,45 @@
+setDisposition('inline');
+ $this->setId($this->getId());
+ }
+
+ /**
+ * Get the nesting level of this EmbeddedFile.
+ *
+ * Returns {@see LEVEL_RELATED}.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_RELATED;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php
new file mode 100644
index 00000000..cc44a6ef
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php
@@ -0,0 +1,24 @@
+init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ protected function init()
+ {
+ if (count(self::$_specials) > 0) {
+ return;
+ }
+
+ self::$_specials = array(
+ '(', ')', '<', '>', '[', ']',
+ ':', ';', '@', ',', '.', '"',
+ );
+
+ /*** Refer to RFC 2822 for ABNF grammar ***/
+
+ // All basic building blocks
+ self::$_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]';
+ self::$_grammar['WSP'] = '[ \t]';
+ self::$_grammar['CRLF'] = '(?:\r\n)';
+ self::$_grammar['FWS'] = '(?:(?:'.self::$_grammar['WSP'].'*'.
+ self::$_grammar['CRLF'].')?'.self::$_grammar['WSP'].')';
+ self::$_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]';
+ self::$_grammar['quoted-pair'] = '(?:\\\\'.self::$_grammar['text'].')';
+ self::$_grammar['ctext'] = '(?:'.self::$_grammar['NO-WS-CTL'].
+ '|[\x21-\x27\x2A-\x5B\x5D-\x7E])';
+ // Uses recursive PCRE (?1) -- could be a weak point??
+ self::$_grammar['ccontent'] = '(?:'.self::$_grammar['ctext'].'|'.
+ self::$_grammar['quoted-pair'].'|(?1))';
+ self::$_grammar['comment'] = '(\((?:'.self::$_grammar['FWS'].'|'.
+ self::$_grammar['ccontent'].')*'.self::$_grammar['FWS'].'?\))';
+ self::$_grammar['CFWS'] = '(?:(?:'.self::$_grammar['FWS'].'?'.
+ self::$_grammar['comment'].')*(?:(?:'.self::$_grammar['FWS'].'?'.
+ self::$_grammar['comment'].')|'.self::$_grammar['FWS'].'))';
+ self::$_grammar['qtext'] = '(?:'.self::$_grammar['NO-WS-CTL'].
+ '|[\x21\x23-\x5B\x5D-\x7E])';
+ self::$_grammar['qcontent'] = '(?:'.self::$_grammar['qtext'].'|'.
+ self::$_grammar['quoted-pair'].')';
+ self::$_grammar['quoted-string'] = '(?:'.self::$_grammar['CFWS'].'?"'.
+ '('.self::$_grammar['FWS'].'?'.self::$_grammar['qcontent'].')*'.
+ self::$_grammar['FWS'].'?"'.self::$_grammar['CFWS'].'?)';
+ self::$_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]';
+ self::$_grammar['atom'] = '(?:'.self::$_grammar['CFWS'].'?'.
+ self::$_grammar['atext'].'+'.self::$_grammar['CFWS'].'?)';
+ self::$_grammar['dot-atom-text'] = '(?:'.self::$_grammar['atext'].'+'.
+ '(\.'.self::$_grammar['atext'].'+)*)';
+ self::$_grammar['dot-atom'] = '(?:'.self::$_grammar['CFWS'].'?'.
+ self::$_grammar['dot-atom-text'].'+'.self::$_grammar['CFWS'].'?)';
+ self::$_grammar['word'] = '(?:'.self::$_grammar['atom'].'|'.
+ self::$_grammar['quoted-string'].')';
+ self::$_grammar['phrase'] = '(?:'.self::$_grammar['word'].'+?)';
+ self::$_grammar['no-fold-quote'] = '(?:"(?:'.self::$_grammar['qtext'].
+ '|'.self::$_grammar['quoted-pair'].')*")';
+ self::$_grammar['dtext'] = '(?:'.self::$_grammar['NO-WS-CTL'].
+ '|[\x21-\x5A\x5E-\x7E])';
+ self::$_grammar['no-fold-literal'] = '(?:\[(?:'.self::$_grammar['dtext'].
+ '|'.self::$_grammar['quoted-pair'].')*\])';
+
+ // Message IDs
+ self::$_grammar['id-left'] = '(?:'.self::$_grammar['dot-atom-text'].'|'.
+ self::$_grammar['no-fold-quote'].')';
+ self::$_grammar['id-right'] = '(?:'.self::$_grammar['dot-atom-text'].'|'.
+ self::$_grammar['no-fold-literal'].')';
+
+ // Addresses, mailboxes and paths
+ self::$_grammar['local-part'] = '(?:'.self::$_grammar['dot-atom'].'|'.
+ self::$_grammar['quoted-string'].')';
+ self::$_grammar['dcontent'] = '(?:'.self::$_grammar['dtext'].'|'.
+ self::$_grammar['quoted-pair'].')';
+ self::$_grammar['domain-literal'] = '(?:'.self::$_grammar['CFWS'].'?\[('.
+ self::$_grammar['FWS'].'?'.self::$_grammar['dcontent'].')*?'.
+ self::$_grammar['FWS'].'?\]'.self::$_grammar['CFWS'].'?)';
+ self::$_grammar['domain'] = '(?:'.self::$_grammar['dot-atom'].'|'.
+ self::$_grammar['domain-literal'].')';
+ self::$_grammar['addr-spec'] = '(?:'.self::$_grammar['local-part'].'@'.
+ self::$_grammar['domain'].')';
+ }
+
+ /**
+ * Get the grammar defined for $name token.
+ *
+ * @param string $name exactly as written in the RFC
+ *
+ * @return string
+ */
+ public function getDefinition($name)
+ {
+ if (array_key_exists($name, self::$_grammar)) {
+ return self::$_grammar[$name];
+ }
+
+ throw new Swift_RfcComplianceException(
+ "No such grammar '".$name."' defined."
+ );
+ }
+
+ /**
+ * Returns the tokens defined in RFC 2822 (and some related RFCs).
+ *
+ * @return array
+ */
+ public function getGrammarDefinitions()
+ {
+ return self::$_grammar;
+ }
+
+ /**
+ * Returns the current special characters used in the syntax which need to be escaped.
+ *
+ * @return array
+ */
+ public function getSpecials()
+ {
+ return self::$_specials;
+ }
+
+ /**
+ * Escape special characters in a string (convert to quoted-pairs).
+ *
+ * @param string $token
+ * @param string[] $include additional chars to escape
+ * @param string[] $exclude chars from escaping
+ *
+ * @return string
+ */
+ public function escapeSpecials($token, $include = array(), $exclude = array())
+ {
+ foreach (array_merge(array('\\'), array_diff(self::$_specials, $exclude), $include) as $char) {
+ $token = str_replace($char, '\\'.$char, $token);
+ }
+
+ return $token;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php
new file mode 100644
index 00000000..a8ddd272
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php
@@ -0,0 +1,93 @@
+getName(), "\r\n");
+ mb_internal_encoding($old);
+
+ return $newstring;
+ }
+
+ return parent::encodeString($string, $firstLineOffset, $maxLineLength);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
new file mode 100644
index 00000000..510dd663
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
@@ -0,0 +1,65 @@
+_safeMap[$byte] = chr($byte);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * Returns the string 'Q'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Q';
+ }
+
+ /**
+ * Takes an unencoded string and produces a QP encoded string from it.
+ *
+ * @param string $string string to encode
+ * @param int $firstLineOffset optional
+ * @param int $maxLineLength optional, 0 indicates the default of 76 chars
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return str_replace(array(' ', '=20', "=\r\n"), array('_', '_', "\r\n"),
+ parent::encodeString($string, $firstLineOffset, $maxLineLength)
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php
new file mode 100644
index 00000000..c65f26d7
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php
@@ -0,0 +1,78 @@
+setGrammar($grammar);
+ }
+
+ /**
+ * Set the character set used in this Header.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ $this->clearCachedValueIf($charset != $this->_charset);
+ $this->_charset = $charset;
+ if (isset($this->_encoder)) {
+ $this->_encoder->charsetChanged($charset);
+ }
+ }
+
+ /**
+ * Get the character set used in this Header.
+ *
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->_charset;
+ }
+
+ /**
+ * Set the language used in this Header.
+ *
+ * For example, for US English, 'en-us'.
+ * This can be unspecified.
+ *
+ * @param string $lang
+ */
+ public function setLanguage($lang)
+ {
+ $this->clearCachedValueIf($this->_lang != $lang);
+ $this->_lang = $lang;
+ }
+
+ /**
+ * Get the language used in this Header.
+ *
+ * @return string
+ */
+ public function getLanguage()
+ {
+ return $this->_lang;
+ }
+
+ /**
+ * Set the encoder used for encoding the header.
+ *
+ * @param Swift_Mime_HeaderEncoder $encoder
+ */
+ public function setEncoder(Swift_Mime_HeaderEncoder $encoder)
+ {
+ $this->_encoder = $encoder;
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the encoder used for encoding this Header.
+ *
+ * @return Swift_Mime_HeaderEncoder
+ */
+ public function getEncoder()
+ {
+ return $this->_encoder;
+ }
+
+ /**
+ * Set the grammar used for the header.
+ *
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function setGrammar(Swift_Mime_Grammar $grammar)
+ {
+ $this->_grammar = $grammar;
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the grammar used for this Header.
+ *
+ * @return Swift_Mime_Grammar
+ */
+ public function getGrammar()
+ {
+ return $this->_grammar;
+ }
+
+ /**
+ * Get the name of this header (e.g. charset).
+ *
+ * @return string
+ */
+ public function getFieldName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Set the maximum length of lines in the header (excluding EOL).
+ *
+ * @param int $lineLength
+ */
+ public function setMaxLineLength($lineLength)
+ {
+ $this->clearCachedValueIf($this->_lineLength != $lineLength);
+ $this->_lineLength = $lineLength;
+ }
+
+ /**
+ * Get the maximum permitted length of lines in this Header.
+ *
+ * @return int
+ */
+ public function getMaxLineLength()
+ {
+ return $this->_lineLength;
+ }
+
+ /**
+ * Get this Header rendered as a RFC 2822 compliant string.
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->_tokensToString($this->toTokens());
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return string
+ *
+ * @see toString()
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ // -- Points of extension
+
+ /**
+ * Set the name of this Header field.
+ *
+ * @param string $name
+ */
+ protected function setFieldName($name)
+ {
+ $this->_name = $name;
+ }
+
+ /**
+ * Produces a compliant, formatted RFC 2822 'phrase' based on the string given.
+ *
+ * @param Swift_Mime_Header $header
+ * @param string $string as displayed
+ * @param string $charset of the text
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param bool $shorten the first line to make remove for header name
+ *
+ * @return string
+ */
+ protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false)
+ {
+ // Treat token as exactly what was given
+ $phraseStr = $string;
+ // If it's not valid
+ if (!preg_match('/^'.$this->getGrammar()->getDefinition('phrase').'$/D', $phraseStr)) {
+ // .. but it is just ascii text, try escaping some characters
+ // and make it a quoted-string
+ if (preg_match('/^'.$this->getGrammar()->getDefinition('text').'*$/D', $phraseStr)) {
+ $phraseStr = $this->getGrammar()->escapeSpecials(
+ $phraseStr, array('"'), $this->getGrammar()->getSpecials()
+ );
+ $phraseStr = '"'.$phraseStr.'"';
+ } else {
+ // ... otherwise it needs encoding
+ // Determine space remaining on line if first line
+ if ($shorten) {
+ $usedLength = strlen($header->getFieldName().': ');
+ } else {
+ $usedLength = 0;
+ }
+ $phraseStr = $this->encodeWords($header, $string, $usedLength);
+ }
+ }
+
+ return $phraseStr;
+ }
+
+ /**
+ * Encode needed word tokens within a string of input.
+ *
+ * @param Swift_Mime_Header $header
+ * @param string $input
+ * @param string $usedLength optional
+ *
+ * @return string
+ */
+ protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1)
+ {
+ $value = '';
+
+ $tokens = $this->getEncodableWordTokens($input);
+
+ foreach ($tokens as $token) {
+ // See RFC 2822, Sect 2.2 (really 2.2 ??)
+ if ($this->tokenNeedsEncoding($token)) {
+ // Don't encode starting WSP
+ $firstChar = substr($token, 0, 1);
+ switch ($firstChar) {
+ case ' ':
+ case "\t":
+ $value .= $firstChar;
+ $token = substr($token, 1);
+ }
+
+ if (-1 == $usedLength) {
+ $usedLength = strlen($header->getFieldName().': ') + strlen($value);
+ }
+ $value .= $this->getTokenAsEncodedWord($token, $usedLength);
+
+ $header->setMaxLineLength(76); // Forcefully override
+ } else {
+ $value .= $token;
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Test if a token needs to be encoded or not.
+ *
+ * @param string $token
+ *
+ * @return bool
+ */
+ protected function tokenNeedsEncoding($token)
+ {
+ return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token);
+ }
+
+ /**
+ * Splits a string into tokens in blocks of words which can be encoded quickly.
+ *
+ * @param string $string
+ *
+ * @return string[]
+ */
+ protected function getEncodableWordTokens($string)
+ {
+ $tokens = array();
+
+ $encodedToken = '';
+ // Split at all whitespace boundaries
+ foreach (preg_split('~(?=[\t ])~', $string) as $token) {
+ if ($this->tokenNeedsEncoding($token)) {
+ $encodedToken .= $token;
+ } else {
+ if (strlen($encodedToken) > 0) {
+ $tokens[] = $encodedToken;
+ $encodedToken = '';
+ }
+ $tokens[] = $token;
+ }
+ }
+ if (strlen($encodedToken)) {
+ $tokens[] = $encodedToken;
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Get a token as an encoded word for safe insertion into headers.
+ *
+ * @param string $token token to encode
+ * @param int $firstLineOffset optional
+ *
+ * @return string
+ */
+ protected function getTokenAsEncodedWord($token, $firstLineOffset = 0)
+ {
+ // Adjust $firstLineOffset to account for space needed for syntax
+ $charsetDecl = $this->_charset;
+ if (isset($this->_lang)) {
+ $charsetDecl .= '*'.$this->_lang;
+ }
+ $encodingWrapperLength = strlen(
+ '=?'.$charsetDecl.'?'.$this->_encoder->getName().'??='
+ );
+
+ if ($firstLineOffset >= 75) {
+ //Does this logic need to be here?
+ $firstLineOffset = 0;
+ }
+
+ $encodedTextLines = explode("\r\n",
+ $this->_encoder->encodeString(
+ $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset
+ )
+ );
+
+ if (strtolower($this->_charset) !== 'iso-2022-jp') {
+ // special encoding for iso-2022-jp using mb_encode_mimeheader
+ foreach ($encodedTextLines as $lineNum => $line) {
+ $encodedTextLines[$lineNum] = '=?'.$charsetDecl.
+ '?'.$this->_encoder->getName().
+ '?'.$line.'?=';
+ }
+ }
+
+ return implode("\r\n ", $encodedTextLines);
+ }
+
+ /**
+ * Generates tokens from the given string which include CRLF as individual tokens.
+ *
+ * @param string $token
+ *
+ * @return string[]
+ */
+ protected function generateTokenLines($token)
+ {
+ return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE);
+ }
+
+ /**
+ * Set a value into the cache.
+ *
+ * @param string $value
+ */
+ protected function setCachedValue($value)
+ {
+ $this->_cachedValue = $value;
+ }
+
+ /**
+ * Get the value in the cache.
+ *
+ * @return string
+ */
+ protected function getCachedValue()
+ {
+ return $this->_cachedValue;
+ }
+
+ /**
+ * Clear the cached value if $condition is met.
+ *
+ * @param bool $condition
+ */
+ protected function clearCachedValueIf($condition)
+ {
+ if ($condition) {
+ $this->setCachedValue(null);
+ }
+ }
+
+ /**
+ * Generate a list of all tokens in the final header.
+ *
+ * @param string $string The string to tokenize
+ *
+ * @return array An array of tokens as strings
+ */
+ protected function toTokens($string = null)
+ {
+ if (is_null($string)) {
+ $string = $this->getFieldBody();
+ }
+
+ $tokens = array();
+
+ // Generate atoms; split at all invisible boundaries followed by WSP
+ foreach (preg_split('~(?=[ \t])~', $string) as $token) {
+ $newTokens = $this->generateTokenLines($token);
+ foreach ($newTokens as $newToken) {
+ $tokens[] = $newToken;
+ }
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Takes an array of tokens which appear in the header and turns them into
+ * an RFC 2822 compliant string, adding FWSP where needed.
+ *
+ * @param string[] $tokens
+ *
+ * @return string
+ */
+ private function _tokensToString(array $tokens)
+ {
+ $lineCount = 0;
+ $headerLines = array();
+ $headerLines[] = $this->_name.': ';
+ $currentLine = &$headerLines[$lineCount++];
+
+ // Build all tokens back into compliant header
+ foreach ($tokens as $i => $token) {
+ // Line longer than specified maximum or token was just a new line
+ if (("\r\n" == $token) ||
+ ($i > 0 && strlen($currentLine.$token) > $this->_lineLength)
+ && 0 < strlen($currentLine)) {
+ $headerLines[] = '';
+ $currentLine = &$headerLines[$lineCount++];
+ }
+
+ // Append token to the line
+ if ("\r\n" != $token) {
+ $currentLine .= $token;
+ }
+ }
+
+ // Implode with FWS (RFC 2822, 2.2.3)
+ return implode("\r\n", $headerLines)."\r\n";
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php
new file mode 100644
index 00000000..4fd66742
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php
@@ -0,0 +1,125 @@
+
+ *
+ *
+ *
+ * @param string $name of Header
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_DATE;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a UNIX timestamp.
+ *
+ * @param int $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setTimestamp($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a UNIX timestamp.
+ *
+ * @return mixed
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getTimestamp();
+ }
+
+ /**
+ * Get the UNIX timestamp of the Date in this Header.
+ *
+ * @return int
+ */
+ public function getTimestamp()
+ {
+ return $this->_timestamp;
+ }
+
+ /**
+ * Set the UNIX timestamp of the Date in this Header.
+ *
+ * @param int $timestamp
+ */
+ public function setTimestamp($timestamp)
+ {
+ if (!is_null($timestamp)) {
+ $timestamp = (int) $timestamp;
+ }
+ $this->clearCachedValueIf($this->_timestamp != $timestamp);
+ $this->_timestamp = $timestamp;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ if (isset($this->_timestamp)) {
+ $this->setCachedValue(date('r', $this->_timestamp));
+ }
+ }
+
+ return $this->getCachedValue();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php
new file mode 100644
index 00000000..b114506b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php
@@ -0,0 +1,180 @@
+setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_ID;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string ID, or an array of IDs.
+ *
+ * @param mixed $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setId($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns an array of IDs
+ *
+ * @return array
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getIds();
+ }
+
+ /**
+ * Set the ID used in the value of this header.
+ *
+ * @param string|array $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setId($id)
+ {
+ $this->setIds(is_array($id) ? $id : array($id));
+ }
+
+ /**
+ * Get the ID used in the value of this Header.
+ *
+ * If multiple IDs are set only the first is returned.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ if (count($this->_ids) > 0) {
+ return $this->_ids[0];
+ }
+ }
+
+ /**
+ * Set a collection of IDs to use in the value of this Header.
+ *
+ * @param string[] $ids
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setIds(array $ids)
+ {
+ $actualIds = array();
+
+ foreach ($ids as $id) {
+ $this->_assertValidId($id);
+ $actualIds[] = $id;
+ }
+
+ $this->clearCachedValueIf($this->_ids != $actualIds);
+ $this->_ids = $actualIds;
+ }
+
+ /**
+ * Get the list of IDs used in this Header.
+ *
+ * @return string[]
+ */
+ public function getIds()
+ {
+ return $this->_ids;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@see toString()} for that).
+ *
+ * @see toString()
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ $angleAddrs = array();
+
+ foreach ($this->_ids as $id) {
+ $angleAddrs[] = '<'.$id.'>';
+ }
+
+ $this->setCachedValue(implode(' ', $angleAddrs));
+ }
+
+ return $this->getCachedValue();
+ }
+
+ /**
+ * Throws an Exception if the id passed does not comply with RFC 2822.
+ *
+ * @param string $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ private function _assertValidId($id)
+ {
+ if (!preg_match(
+ '/^'.$this->getGrammar()->getDefinition('id-left').'@'.
+ $this->getGrammar()->getDefinition('id-right').'$/D',
+ $id
+ )) {
+ throw new Swift_RfcComplianceException(
+ 'Invalid ID given <'.$id.'>'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php
new file mode 100644
index 00000000..e54b1c66
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php
@@ -0,0 +1,353 @@
+setFieldName($name);
+ $this->setEncoder($encoder);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_MAILBOX;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string, or an array of addresses.
+ *
+ * @param mixed $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setNameAddresses($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns an associative array like {@link getNameAddresses()}
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return array
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getNameAddresses();
+ }
+
+ /**
+ * Set a list of mailboxes to be shown in this Header.
+ *
+ * The mailboxes can be a simple array of addresses, or an array of
+ * key=>value pairs where (email => personalName).
+ * Example:
+ *
+ * setNameAddresses(array(
+ * 'chris@swiftmailer.org' => 'Chris Corbyn',
+ * 'mark@swiftmailer.org' //No associated personal name
+ * ));
+ * ?>
+ *
+ *
+ * @see __construct()
+ * @see setAddresses()
+ * @see setValue()
+ *
+ * @param string|string[] $mailboxes
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setNameAddresses($mailboxes)
+ {
+ $this->_mailboxes = $this->normalizeMailboxes((array) $mailboxes);
+ $this->setCachedValue(null); //Clear any cached value
+ }
+
+ /**
+ * Get the full mailbox list of this Header as an array of valid RFC 2822 strings.
+ *
+ * Example:
+ *
+ * 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddressStrings());
+ * // array (
+ * // 0 => Chris Corbyn ,
+ * // 1 => Mark Corbyn
+ * // )
+ * ?>
+ *
+ *
+ * @see getNameAddresses()
+ * @see toString()
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return string[]
+ */
+ public function getNameAddressStrings()
+ {
+ return $this->_createNameAddressStrings($this->getNameAddresses());
+ }
+
+ /**
+ * Get all mailboxes in this Header as key=>value pairs.
+ *
+ * The key is the address and the value is the name (or null if none set).
+ * Example:
+ *
+ * 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddresses());
+ * // array (
+ * // chris@swiftmailer.org => Chris Corbyn,
+ * // mark@swiftmailer.org => Mark Corbyn
+ * // )
+ * ?>
+ *
+ *
+ * @see getAddresses()
+ * @see getNameAddressStrings()
+ *
+ * @return string[]
+ */
+ public function getNameAddresses()
+ {
+ return $this->_mailboxes;
+ }
+
+ /**
+ * Makes this Header represent a list of plain email addresses with no names.
+ *
+ * Example:
+ *
+ * setAddresses(
+ * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld')
+ * );
+ * ?>
+ *
+ *
+ * @see setNameAddresses()
+ * @see setValue()
+ *
+ * @param string[] $addresses
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setAddresses($addresses)
+ {
+ $this->setNameAddresses(array_values((array) $addresses));
+ }
+
+ /**
+ * Get all email addresses in this Header.
+ *
+ * @see getNameAddresses()
+ *
+ * @return string[]
+ */
+ public function getAddresses()
+ {
+ return array_keys($this->_mailboxes);
+ }
+
+ /**
+ * Remove one or more addresses from this Header.
+ *
+ * @param string|string[] $addresses
+ */
+ public function removeAddresses($addresses)
+ {
+ $this->setCachedValue(null);
+ foreach ((array) $addresses as $address) {
+ unset($this->_mailboxes[$address]);
+ }
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ // Compute the string value of the header only if needed
+ if (is_null($this->getCachedValue())) {
+ $this->setCachedValue($this->createMailboxListString($this->_mailboxes));
+ }
+
+ return $this->getCachedValue();
+ }
+
+ // -- Points of extension
+
+ /**
+ * Normalizes a user-input list of mailboxes into consistent key=>value pairs.
+ *
+ * @param string[] $mailboxes
+ *
+ * @return string[]
+ */
+ protected function normalizeMailboxes(array $mailboxes)
+ {
+ $actualMailboxes = array();
+
+ foreach ($mailboxes as $key => $value) {
+ if (is_string($key)) {
+ //key is email addr
+ $address = $key;
+ $name = $value;
+ } else {
+ $address = $value;
+ $name = null;
+ }
+ $this->_assertValidAddress($address);
+ $actualMailboxes[$address] = $name;
+ }
+
+ return $actualMailboxes;
+ }
+
+ /**
+ * Produces a compliant, formatted display-name based on the string given.
+ *
+ * @param string $displayName as displayed
+ * @param bool $shorten the first line to make remove for header name
+ *
+ * @return string
+ */
+ protected function createDisplayNameString($displayName, $shorten = false)
+ {
+ return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten);
+ }
+
+ /**
+ * Creates a string form of all the mailboxes in the passed array.
+ *
+ * @param string[] $mailboxes
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return string
+ */
+ protected function createMailboxListString(array $mailboxes)
+ {
+ return implode(', ', $this->_createNameAddressStrings($mailboxes));
+ }
+
+ /**
+ * Redefine the encoding requirements for mailboxes.
+ *
+ * All "specials" must be encoded as the full header value will not be quoted
+ *
+ * @see RFC 2822 3.2.1
+ *
+ * @param string $token
+ *
+ * @return bool
+ */
+ protected function tokenNeedsEncoding($token)
+ {
+ return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token);
+ }
+
+ /**
+ * Return an array of strings conforming the the name-addr spec of RFC 2822.
+ *
+ * @param string[] $mailboxes
+ *
+ * @return string[]
+ */
+ private function _createNameAddressStrings(array $mailboxes)
+ {
+ $strings = array();
+
+ foreach ($mailboxes as $email => $name) {
+ $mailboxStr = $email;
+ if (!is_null($name)) {
+ $nameStr = $this->createDisplayNameString($name, empty($strings));
+ $mailboxStr = $nameStr.' <'.$mailboxStr.'>';
+ }
+ $strings[] = $mailboxStr;
+ }
+
+ return $strings;
+ }
+
+ /**
+ * Throws an Exception if the address passed does not comply with RFC 2822.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException If invalid.
+ */
+ private function _assertValidAddress($address)
+ {
+ if (!preg_match('/^'.$this->getGrammar()->getDefinition('addr-spec').'$/D',
+ $address)) {
+ throw new Swift_RfcComplianceException(
+ 'Address in mailbox given ['.$address.
+ '] does not comply with RFC 2822, 3.6.2.'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php
new file mode 100644
index 00000000..d7495500
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php
@@ -0,0 +1,133 @@
+
+ */
+class Swift_Mime_Headers_OpenDKIMHeader implements Swift_Mime_Header
+{
+ /**
+ * The value of this Header.
+ *
+ * @var string
+ */
+ private $_value;
+
+ /**
+ * The name of this Header.
+ *
+ * @var string
+ */
+ private $_fieldName;
+
+ /**
+ * @param string $name
+ */
+ public function __construct($name)
+ {
+ $this->_fieldName = $name;
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_TEXT;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string for the field value.
+ *
+ * @param string $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setValue($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a string.
+ *
+ * @return string
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Get the (unencoded) value of this header.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Set the (unencoded) value of this header.
+ *
+ * @param string $value
+ */
+ public function setValue($value)
+ {
+ $this->_value = $value;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Get this Header rendered as a RFC 2822 compliant string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->_fieldName.': '.$this->_value;
+ }
+
+ /**
+ * Set the Header FieldName.
+ *
+ * @see Swift_Mime_Header::getFieldName()
+ */
+ public function getFieldName()
+ {
+ return $this->_fieldName;
+ }
+
+ /**
+ * Ignored.
+ */
+ public function setCharset($charset)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php
new file mode 100644
index 00000000..c506daec
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php
@@ -0,0 +1,258 @@
+_paramEncoder = $paramEncoder;
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_PARAMETERIZED;
+ }
+
+ /**
+ * Set the character set used in this Header.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ parent::setCharset($charset);
+ if (isset($this->_paramEncoder)) {
+ $this->_paramEncoder->charsetChanged($charset);
+ }
+ }
+
+ /**
+ * Set the value of $parameter.
+ *
+ * @param string $parameter
+ * @param string $value
+ */
+ public function setParameter($parameter, $value)
+ {
+ $this->setParameters(array_merge($this->getParameters(), array($parameter => $value)));
+ }
+
+ /**
+ * Get the value of $parameter.
+ *
+ * @param string $parameter
+ *
+ * @return string
+ */
+ public function getParameter($parameter)
+ {
+ $params = $this->getParameters();
+
+ return array_key_exists($parameter, $params) ? $params[$parameter] : null;
+ }
+
+ /**
+ * Set an associative array of parameter names mapped to values.
+ *
+ * @param string[] $parameters
+ */
+ public function setParameters(array $parameters)
+ {
+ $this->clearCachedValueIf($this->_params != $parameters);
+ $this->_params = $parameters;
+ }
+
+ /**
+ * Returns an associative array of parameter names mapped to values.
+ *
+ * @return string[]
+ */
+ public function getParameters()
+ {
+ return $this->_params;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody() //TODO: Check caching here
+ {
+ $body = parent::getFieldBody();
+ foreach ($this->_params as $name => $value) {
+ if (!is_null($value)) {
+ // Add the parameter
+ $body .= '; '.$this->_createParameter($name, $value);
+ }
+ }
+
+ return $body;
+ }
+
+ /**
+ * Generate a list of all tokens in the final header.
+ *
+ * This doesn't need to be overridden in theory, but it is for implementation
+ * reasons to prevent potential breakage of attributes.
+ *
+ * @param string $string The string to tokenize
+ *
+ * @return array An array of tokens as strings
+ */
+ protected function toTokens($string = null)
+ {
+ $tokens = parent::toTokens(parent::getFieldBody());
+
+ // Try creating any parameters
+ foreach ($this->_params as $name => $value) {
+ if (!is_null($value)) {
+ // Add the semi-colon separator
+ $tokens[count($tokens) - 1] .= ';';
+ $tokens = array_merge($tokens, $this->generateTokenLines(
+ ' '.$this->_createParameter($name, $value)
+ ));
+ }
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Render a RFC 2047 compliant header parameter from the $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ *
+ * @return string
+ */
+ private function _createParameter($name, $value)
+ {
+ $origValue = $value;
+
+ $encoded = false;
+ // Allow room for parameter name, indices, "=" and DQUOTEs
+ $maxValueLength = $this->getMaxLineLength() - strlen($name.'=*N"";') - 1;
+ $firstLineOffset = 0;
+
+ // If it's not already a valid parameter value...
+ if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
+ // TODO: text, or something else??
+ // ... and it's not ascii
+ if (!preg_match('/^'.$this->getGrammar()->getDefinition('text').'*$/D', $value)) {
+ $encoded = true;
+ // Allow space for the indices, charset and language
+ $maxValueLength = $this->getMaxLineLength() - strlen($name.'*N*="";') - 1;
+ $firstLineOffset = strlen(
+ $this->getCharset()."'".$this->getLanguage()."'"
+ );
+ }
+ }
+
+ // Encode if we need to
+ if ($encoded || strlen($value) > $maxValueLength) {
+ if (isset($this->_paramEncoder)) {
+ $value = $this->_paramEncoder->encodeString(
+ $origValue, $firstLineOffset, $maxValueLength, $this->getCharset()
+ );
+ } else {
+ // We have to go against RFC 2183/2231 in some areas for interoperability
+ $value = $this->getTokenAsEncodedWord($origValue);
+ $encoded = false;
+ }
+ }
+
+ $valueLines = isset($this->_paramEncoder) ? explode("\r\n", $value) : array($value);
+
+ // Need to add indices
+ if (count($valueLines) > 1) {
+ $paramLines = array();
+ foreach ($valueLines as $i => $line) {
+ $paramLines[] = $name.'*'.$i.
+ $this->_getEndOfParameterValue($line, true, $i == 0);
+ }
+
+ return implode(";\r\n ", $paramLines);
+ } else {
+ return $name.$this->_getEndOfParameterValue(
+ $valueLines[0], $encoded, true
+ );
+ }
+ }
+
+ /**
+ * Returns the parameter value from the "=" and beyond.
+ *
+ * @param string $value to append
+ * @param bool $encoded
+ * @param bool $firstLine
+ *
+ * @return string
+ */
+ private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
+ {
+ if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
+ $value = '"'.$value.'"';
+ }
+ $prepend = '=';
+ if ($encoded) {
+ $prepend = '*=';
+ if ($firstLine) {
+ $prepend = '*='.$this->getCharset()."'".$this->getLanguage().
+ "'";
+ }
+ }
+
+ return $prepend.$value;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php
new file mode 100644
index 00000000..2fffc7b4
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php
@@ -0,0 +1,143 @@
+setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_PATH;
+ }
+
+ /**
+ * Set the model for the field body.
+ * This method takes a string for an address.
+ *
+ * @param string $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setAddress($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ * This method returns a string email address.
+ *
+ * @return mixed
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getAddress();
+ }
+
+ /**
+ * Set the Address which should appear in this Header.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setAddress($address)
+ {
+ if (is_null($address)) {
+ $this->_address = null;
+ } elseif ('' == $address) {
+ $this->_address = '';
+ } else {
+ $this->_assertValidAddress($address);
+ $this->_address = $address;
+ }
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the address which is used in this Header (if any).
+ *
+ * Null is returned if no address is set.
+ *
+ * @return string
+ */
+ public function getAddress()
+ {
+ return $this->_address;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ if (isset($this->_address)) {
+ $this->setCachedValue('<'.$this->_address.'>');
+ }
+ }
+
+ return $this->getCachedValue();
+ }
+
+ /**
+ * Throws an Exception if the address passed does not comply with RFC 2822.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException If address is invalid
+ */
+ private function _assertValidAddress($address)
+ {
+ if (!preg_match('/^'.$this->getGrammar()->getDefinition('addr-spec').'$/D',
+ $address)) {
+ throw new Swift_RfcComplianceException(
+ 'Address set in PathHeader does not comply with addr-spec of RFC 2822.'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php
new file mode 100644
index 00000000..86177f14
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php
@@ -0,0 +1,112 @@
+setFieldName($name);
+ $this->setEncoder($encoder);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_TEXT;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string for the field value.
+ *
+ * @param string $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setValue($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a string.
+ *
+ * @return string
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Get the (unencoded) value of this header.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Set the (unencoded) value of this header.
+ *
+ * @param string $value
+ */
+ public function setValue($value)
+ {
+ $this->clearCachedValueIf($this->_value != $value);
+ $this->_value = $value;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ $this->setCachedValue(
+ $this->encodeWords($this, $this->_value)
+ );
+ }
+
+ return $this->getCachedValue();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php
new file mode 100644
index 00000000..9b36d216
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php
@@ -0,0 +1,223 @@
+ 'Real Name').
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $address
+ * @param string $name optional
+ */
+ public function setSender($address, $name = null);
+
+ /**
+ * Get the sender address for this message.
+ *
+ * This has a higher significance than the From address.
+ *
+ * @return string
+ */
+ public function getSender();
+
+ /**
+ * Set the From address of this message.
+ *
+ * It is permissible for multiple From addresses to be set using an array.
+ *
+ * If multiple From addresses are used, you SHOULD set the Sender address and
+ * according to RFC 2822, MUST set the sender address.
+ *
+ * An array can be used if display names are to be provided: i.e.
+ * array('email@address.com' => 'Real Name').
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setFrom($addresses, $name = null);
+
+ /**
+ * Get the From address(es) of this message.
+ *
+ * This method always returns an associative array where the keys are the
+ * addresses.
+ *
+ * @return string[]
+ */
+ public function getFrom();
+
+ /**
+ * Set the Reply-To address(es).
+ *
+ * Any replies from the receiver will be sent to this address.
+ *
+ * It is permissible for multiple reply-to addresses to be set using an array.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setReplyTo($addresses, $name = null);
+
+ /**
+ * Get the Reply-To addresses for this message.
+ *
+ * This method always returns an associative array where the keys provide the
+ * email addresses.
+ *
+ * @return string[]
+ */
+ public function getReplyTo();
+
+ /**
+ * Set the To address(es).
+ *
+ * Recipients set in this field will receive a copy of this message.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setCc()}.
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setTo($addresses, $name = null);
+
+ /**
+ * Get the To addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getTo();
+
+ /**
+ * Set the Cc address(es).
+ *
+ * Recipients set in this field will receive a 'carbon-copy' of this message.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setCc($addresses, $name = null);
+
+ /**
+ * Get the Cc addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getCc();
+
+ /**
+ * Set the Bcc address(es).
+ *
+ * Recipients set in this field will receive a 'blind-carbon-copy' of this
+ * message.
+ *
+ * In other words, they will get the message, but any other recipients of the
+ * message will have no such knowledge of their receipt of it.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setBcc($addresses, $name = null);
+
+ /**
+ * Get the Bcc addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getBcc();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php
new file mode 100644
index 00000000..30f460cd
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php
@@ -0,0 +1,117 @@
+setContentType('text/plain');
+ if (!is_null($charset)) {
+ $this->setCharset($charset);
+ }
+ }
+
+ /**
+ * Set the body of this entity, either as a string, or as an instance of
+ * {@link Swift_OutputByteStream}.
+ *
+ * @param mixed $body
+ * @param string $contentType optional
+ * @param string $charset optional
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setBody($body, $contentType = null, $charset = null)
+ {
+ if (isset($charset)) {
+ $this->setCharset($charset);
+ }
+ $body = $this->_convertString($body);
+
+ parent::setBody($body, $contentType);
+
+ return $this;
+ }
+
+ /**
+ * Get the character set of this entity.
+ *
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->_getHeaderParameter('Content-Type', 'charset');
+ }
+
+ /**
+ * Set the character set of this entity.
+ *
+ * @param string $charset
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setCharset($charset)
+ {
+ $this->_setHeaderParameter('Content-Type', 'charset', $charset);
+ if ($charset !== $this->_userCharset) {
+ $this->_clearCache();
+ }
+ $this->_userCharset = $charset;
+ parent::charsetChanged($charset);
+
+ return $this;
+ }
+
+ /**
+ * Get the format of this entity (i.e. flowed or fixed).
+ *
+ * @return string
+ */
+ public function getFormat()
+ {
+ return $this->_getHeaderParameter('Content-Type', 'format');
+ }
+
+ /**
+ * Set the format of this entity (flowed or fixed).
+ *
+ * @param string $format
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setFormat($format)
+ {
+ $this->_setHeaderParameter('Content-Type', 'format', $format);
+ $this->_userFormat = $format;
+
+ return $this;
+ }
+
+ /**
+ * Test if delsp is being used for this entity.
+ *
+ * @return bool
+ */
+ public function getDelSp()
+ {
+ return 'yes' == $this->_getHeaderParameter('Content-Type', 'delsp') ? true : false;
+ }
+
+ /**
+ * Turn delsp on or off for this entity.
+ *
+ * @param bool $delsp
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setDelSp($delsp = true)
+ {
+ $this->_setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null);
+ $this->_userDelSp = $delsp;
+
+ return $this;
+ }
+
+ /**
+ * Get the nesting level of this entity.
+ *
+ * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return $this->_nestingLevel;
+ }
+
+ /**
+ * Receive notification that the charset has changed on this document, or a
+ * parent document.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->setCharset($charset);
+ }
+
+ /** Fix the content-type and encoding of this entity */
+ protected function _fixHeaders()
+ {
+ parent::_fixHeaders();
+ if (count($this->getChildren())) {
+ $this->_setHeaderParameter('Content-Type', 'charset', null);
+ $this->_setHeaderParameter('Content-Type', 'format', null);
+ $this->_setHeaderParameter('Content-Type', 'delsp', null);
+ } else {
+ $this->setCharset($this->_userCharset);
+ $this->setFormat($this->_userFormat);
+ $this->setDelSp($this->_userDelSp);
+ }
+ }
+
+ /** Set the nesting level of this entity */
+ protected function _setNestingLevel($level)
+ {
+ $this->_nestingLevel = $level;
+ }
+
+ /** Encode charset when charset is not utf-8 */
+ protected function _convertString($string)
+ {
+ $charset = strtolower($this->getCharset());
+ if (!in_array($charset, array('utf-8', 'iso-8859-1', 'iso-8859-15', ''))) {
+ // mb_convert_encoding must be the first one to check, since iconv cannot convert some words.
+ if (function_exists('mb_convert_encoding')) {
+ $string = mb_convert_encoding($string, $charset, 'utf-8');
+ } elseif (function_exists('iconv')) {
+ $string = iconv('utf-8//TRANSLIT//IGNORE', $charset, $string);
+ } else {
+ throw new Swift_SwiftException('No suitable convert encoding function (use UTF-8 as your charset or install the mbstring or iconv extension).');
+ }
+
+ return $string;
+ }
+
+ return $string;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php
new file mode 100644
index 00000000..e15c6ef9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php
@@ -0,0 +1,34 @@
+_encoder = $encoder;
+ $this->_paramEncoder = $paramEncoder;
+ $this->_grammar = $grammar;
+ $this->_charset = $charset;
+ }
+
+ /**
+ * Create a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string|null $addresses
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createMailboxHeader($name, $addresses = null)
+ {
+ $header = new Swift_Mime_Headers_MailboxHeader($name, $this->_encoder, $this->_grammar);
+ if (isset($addresses)) {
+ $header->setFieldBodyModel($addresses);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new Date header using $timestamp (UNIX time).
+ *
+ * @param string $name
+ * @param int|null $timestamp
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createDateHeader($name, $timestamp = null)
+ {
+ $header = new Swift_Mime_Headers_DateHeader($name, $this->_grammar);
+ if (isset($timestamp)) {
+ $header->setFieldBodyModel($timestamp);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createTextHeader($name, $value = null)
+ {
+ $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->_encoder, $this->_grammar);
+ if (isset($value)) {
+ $header->setFieldBodyModel($value);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ *
+ * @return Swift_Mime_ParameterizedHeader
+ */
+ public function createParameterizedHeader($name, $value = null,
+ $params = array())
+ {
+ $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->_encoder, strtolower($name) == 'content-disposition' ? $this->_paramEncoder : null, $this->_grammar);
+ if (isset($value)) {
+ $header->setFieldBodyModel($value);
+ }
+ foreach ($params as $k => $v) {
+ $header->setParameter($k, $v);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createIdHeader($name, $ids = null)
+ {
+ $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->_grammar);
+ if (isset($ids)) {
+ $header->setFieldBodyModel($ids);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createPathHeader($name, $path = null)
+ {
+ $header = new Swift_Mime_Headers_PathHeader($name, $this->_grammar);
+ if (isset($path)) {
+ $header->setFieldBodyModel($path);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charset = $charset;
+ $this->_encoder->charsetChanged($charset);
+ $this->_paramEncoder->charsetChanged($charset);
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->_encoder = clone $this->_encoder;
+ $this->_paramEncoder = clone $this->_paramEncoder;
+ }
+
+ /** Apply the charset to the Header */
+ private function _setHeaderCharset(Swift_Mime_Header $header)
+ {
+ if (isset($this->_charset)) {
+ $header->setCharset($this->_charset);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php
new file mode 100644
index 00000000..e2d0e874
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php
@@ -0,0 +1,414 @@
+_factory = $factory;
+ if (isset($charset)) {
+ $this->setCharset($charset);
+ }
+ }
+
+ /**
+ * Set the charset used by these headers.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ $this->_charset = $charset;
+ $this->_factory->charsetChanged($charset);
+ $this->_notifyHeadersOfCharset($charset);
+ }
+
+ /**
+ * Add a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string $addresses
+ */
+ public function addMailboxHeader($name, $addresses = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createMailboxHeader($name, $addresses));
+ }
+
+ /**
+ * Add a new Date header using $timestamp (UNIX time).
+ *
+ * @param string $name
+ * @param int $timestamp
+ */
+ public function addDateHeader($name, $timestamp = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createDateHeader($name, $timestamp));
+ }
+
+ /**
+ * Add a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ */
+ public function addTextHeader($name, $value = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createTextHeader($name, $value));
+ }
+
+ /**
+ * Add a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ */
+ public function addParameterizedHeader($name, $value = null, $params = array())
+ {
+ $this->_storeHeader($name, $this->_factory->createParameterizedHeader($name, $value, $params));
+ }
+
+ /**
+ * Add a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ */
+ public function addIdHeader($name, $ids = null)
+ {
+ $this->_storeHeader($name, $this->_factory->createIdHeader($name, $ids));
+ }
+
+ /**
+ * Add a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ */
+ public function addPathHeader($name, $path = null)
+ {
+ $this->_storeHeader($name, $this->_factory->createPathHeader($name, $path));
+ }
+
+ /**
+ * Returns true if at least one header with the given $name exists.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return bool
+ */
+ public function has($name, $index = 0)
+ {
+ $lowerName = strtolower($name);
+
+ if (!array_key_exists($lowerName, $this->_headers)) {
+ return false;
+ }
+
+ if (func_num_args() < 2) {
+ // index was not specified, so we only need to check that there is at least one header value set
+ return (bool) count($this->_headers[$lowerName]);
+ }
+
+ return array_key_exists($index, $this->_headers[$lowerName]);
+ }
+
+ /**
+ * Set a header in the HeaderSet.
+ *
+ * The header may be a previously fetched header via {@link get()} or it may
+ * be one that has been created separately.
+ *
+ * If $index is specified, the header will be inserted into the set at this
+ * offset.
+ *
+ * @param Swift_Mime_Header $header
+ * @param int $index
+ */
+ public function set(Swift_Mime_Header $header, $index = 0)
+ {
+ $this->_storeHeader($header->getFieldName(), $header, $index);
+ }
+
+ /**
+ * Get the header with the given $name.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ * Returns NULL if none present.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return Swift_Mime_Header
+ */
+ public function get($name, $index = 0)
+ {
+ $name = strtolower($name);
+
+ if (func_num_args() < 2) {
+ if ($this->has($name)) {
+ $values = array_values($this->_headers[$name]);
+
+ return array_shift($values);
+ }
+ } else {
+ if ($this->has($name, $index)) {
+ return $this->_headers[$name][$index];
+ }
+ }
+ }
+
+ /**
+ * Get all headers with the given $name.
+ *
+ * @param string $name
+ *
+ * @return array
+ */
+ public function getAll($name = null)
+ {
+ if (!isset($name)) {
+ $headers = array();
+ foreach ($this->_headers as $collection) {
+ $headers = array_merge($headers, $collection);
+ }
+
+ return $headers;
+ }
+
+ $lowerName = strtolower($name);
+ if (!array_key_exists($lowerName, $this->_headers)) {
+ return array();
+ }
+
+ return $this->_headers[$lowerName];
+ }
+
+ /**
+ * Return the name of all Headers.
+ *
+ * @return array
+ */
+ public function listAll()
+ {
+ $headers = $this->_headers;
+ if ($this->_canSort()) {
+ uksort($headers, array($this, '_sortHeaders'));
+ }
+
+ return array_keys($headers);
+ }
+
+ /**
+ * Remove the header with the given $name if it's set.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ */
+ public function remove($name, $index = 0)
+ {
+ $lowerName = strtolower($name);
+ unset($this->_headers[$lowerName][$index]);
+ }
+
+ /**
+ * Remove all headers with the given $name.
+ *
+ * @param string $name
+ */
+ public function removeAll($name)
+ {
+ $lowerName = strtolower($name);
+ unset($this->_headers[$lowerName]);
+ }
+
+ /**
+ * Create a new instance of this HeaderSet.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function newInstance()
+ {
+ return new self($this->_factory);
+ }
+
+ /**
+ * Define a list of Header names as an array in the correct order.
+ *
+ * These Headers will be output in the given order where present.
+ *
+ * @param array $sequence
+ */
+ public function defineOrdering(array $sequence)
+ {
+ $this->_order = array_flip(array_map('strtolower', $sequence));
+ }
+
+ /**
+ * Set a list of header names which must always be displayed when set.
+ *
+ * Usually headers without a field value won't be output unless set here.
+ *
+ * @param array $names
+ */
+ public function setAlwaysDisplayed(array $names)
+ {
+ $this->_required = array_flip(array_map('strtolower', $names));
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->setCharset($charset);
+ }
+
+ /**
+ * Returns a string with a representation of all headers.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $string = '';
+ $headers = $this->_headers;
+ if ($this->_canSort()) {
+ uksort($headers, array($this, '_sortHeaders'));
+ }
+ foreach ($headers as $collection) {
+ foreach ($collection as $header) {
+ if ($this->_isDisplayed($header) || $header->getFieldBody() != '') {
+ $string .= $header->toString();
+ }
+ }
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return string
+ *
+ * @see toString()
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /** Save a Header to the internal collection */
+ private function _storeHeader($name, Swift_Mime_Header $header, $offset = null)
+ {
+ if (!isset($this->_headers[strtolower($name)])) {
+ $this->_headers[strtolower($name)] = array();
+ }
+ if (!isset($offset)) {
+ $this->_headers[strtolower($name)][] = $header;
+ } else {
+ $this->_headers[strtolower($name)][$offset] = $header;
+ }
+ }
+
+ /** Test if the headers can be sorted */
+ private function _canSort()
+ {
+ return count($this->_order) > 0;
+ }
+
+ /** uksort() algorithm for Header ordering */
+ private function _sortHeaders($a, $b)
+ {
+ $lowerA = strtolower($a);
+ $lowerB = strtolower($b);
+ $aPos = array_key_exists($lowerA, $this->_order) ? $this->_order[$lowerA] : -1;
+ $bPos = array_key_exists($lowerB, $this->_order) ? $this->_order[$lowerB] : -1;
+
+ if (-1 === $aPos && -1 === $bPos) {
+ // just be sure to be determinist here
+ return $a > $b ? -1 : 1;
+ }
+
+ if ($aPos == -1) {
+ return 1;
+ } elseif ($bPos == -1) {
+ return -1;
+ }
+
+ return $aPos < $bPos ? -1 : 1;
+ }
+
+ /** Test if the given Header is always displayed */
+ private function _isDisplayed(Swift_Mime_Header $header)
+ {
+ return array_key_exists(strtolower($header->getFieldName()), $this->_required);
+ }
+
+ /** Notify all Headers of the new charset */
+ private function _notifyHeadersOfCharset($charset)
+ {
+ foreach ($this->_headers as $headerGroup) {
+ foreach ($headerGroup as $header) {
+ $header->setCharset($charset);
+ }
+ }
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->_factory = clone $this->_factory;
+ foreach ($this->_headers as $groupKey => $headerGroup) {
+ foreach ($headerGroup as $key => $header) {
+ $this->_headers[$groupKey][$key] = clone $header;
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php
new file mode 100644
index 00000000..72d40cee
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php
@@ -0,0 +1,655 @@
+getHeaders()->defineOrdering(array(
+ 'Return-Path',
+ 'Received',
+ 'DKIM-Signature',
+ 'DomainKey-Signature',
+ 'Sender',
+ 'Message-ID',
+ 'Date',
+ 'Subject',
+ 'From',
+ 'Reply-To',
+ 'To',
+ 'Cc',
+ 'Bcc',
+ 'MIME-Version',
+ 'Content-Type',
+ 'Content-Transfer-Encoding',
+ ));
+ $this->getHeaders()->setAlwaysDisplayed(array('Date', 'Message-ID', 'From'));
+ $this->getHeaders()->addTextHeader('MIME-Version', '1.0');
+ $this->setDate(time());
+ $this->setId($this->getId());
+ $this->getHeaders()->addMailboxHeader('From');
+ }
+
+ /**
+ * Always returns {@link LEVEL_TOP} for a message instance.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_TOP;
+ }
+
+ /**
+ * Set the subject of this message.
+ *
+ * @param string $subject
+ *
+ * @return $this
+ */
+ public function setSubject($subject)
+ {
+ if (!$this->_setHeaderFieldModel('Subject', $subject)) {
+ $this->getHeaders()->addTextHeader('Subject', $subject);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the subject of this message.
+ *
+ * @return string
+ */
+ public function getSubject()
+ {
+ return $this->_getHeaderFieldModel('Subject');
+ }
+
+ /**
+ * Set the date at which this message was created.
+ *
+ * @param int $date
+ *
+ * @return $this
+ */
+ public function setDate($date)
+ {
+ if (!$this->_setHeaderFieldModel('Date', $date)) {
+ $this->getHeaders()->addDateHeader('Date', $date);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the date at which this message was created.
+ *
+ * @return int
+ */
+ public function getDate()
+ {
+ return $this->_getHeaderFieldModel('Date');
+ }
+
+ /**
+ * Set the return-path (the bounce address) of this message.
+ *
+ * @param string $address
+ *
+ * @return $this
+ */
+ public function setReturnPath($address)
+ {
+ if (!$this->_setHeaderFieldModel('Return-Path', $address)) {
+ $this->getHeaders()->addPathHeader('Return-Path', $address);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the return-path (bounce address) of this message.
+ *
+ * @return string
+ */
+ public function getReturnPath()
+ {
+ return $this->_getHeaderFieldModel('Return-Path');
+ }
+
+ /**
+ * Set the sender of this message.
+ *
+ * This does not override the From field, but it has a higher significance.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setSender($address, $name = null)
+ {
+ if (!is_array($address) && isset($name)) {
+ $address = array($address => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Sender', (array) $address)) {
+ $this->getHeaders()->addMailboxHeader('Sender', (array) $address);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the sender of this message.
+ *
+ * @return string
+ */
+ public function getSender()
+ {
+ return $this->_getHeaderFieldModel('Sender');
+ }
+
+ /**
+ * Add a From: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function addFrom($address, $name = null)
+ {
+ $current = $this->getFrom();
+ $current[$address] = $name;
+
+ return $this->setFrom($current);
+ }
+
+ /**
+ * Set the from address of this message.
+ *
+ * You may pass an array of addresses if this message is from multiple people.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param string|array $addresses
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setFrom($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('From', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('From', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the from address of this message.
+ *
+ * @return mixed
+ */
+ public function getFrom()
+ {
+ return $this->_getHeaderFieldModel('From');
+ }
+
+ /**
+ * Add a Reply-To: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function addReplyTo($address, $name = null)
+ {
+ $current = $this->getReplyTo();
+ $current[$address] = $name;
+
+ return $this->setReplyTo($current);
+ }
+
+ /**
+ * Set the reply-to address of this message.
+ *
+ * You may pass an array of addresses if replies will go to multiple people.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setReplyTo($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Reply-To', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the reply-to address of this message.
+ *
+ * @return string
+ */
+ public function getReplyTo()
+ {
+ return $this->_getHeaderFieldModel('Reply-To');
+ }
+
+ /**
+ * Add a To: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function addTo($address, $name = null)
+ {
+ $current = $this->getTo();
+ $current[$address] = $name;
+
+ return $this->setTo($current);
+ }
+
+ /**
+ * Set the to addresses of this message.
+ *
+ * If multiple recipients will receive the message an array should be used.
+ * Example: array('receiver@domain.org', 'other@domain.org' => 'A name')
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setTo($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('To', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('To', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the To addresses of this message.
+ *
+ * @return array
+ */
+ public function getTo()
+ {
+ return $this->_getHeaderFieldModel('To');
+ }
+
+ /**
+ * Add a Cc: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function addCc($address, $name = null)
+ {
+ $current = $this->getCc();
+ $current[$address] = $name;
+
+ return $this->setCc($current);
+ }
+
+ /**
+ * Set the Cc addresses of this message.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setCc($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Cc', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the Cc address of this message.
+ *
+ * @return array
+ */
+ public function getCc()
+ {
+ return $this->_getHeaderFieldModel('Cc');
+ }
+
+ /**
+ * Add a Bcc: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function addBcc($address, $name = null)
+ {
+ $current = $this->getBcc();
+ $current[$address] = $name;
+
+ return $this->setBcc($current);
+ }
+
+ /**
+ * Set the Bcc addresses of this message.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return $this
+ */
+ public function setBcc($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Bcc', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the Bcc addresses of this message.
+ *
+ * @return array
+ */
+ public function getBcc()
+ {
+ return $this->_getHeaderFieldModel('Bcc');
+ }
+
+ /**
+ * Set the priority of this message.
+ *
+ * The value is an integer where 1 is the highest priority and 5 is the lowest.
+ *
+ * @param int $priority
+ *
+ * @return $this
+ */
+ public function setPriority($priority)
+ {
+ $priorityMap = array(
+ self::PRIORITY_HIGHEST => 'Highest',
+ self::PRIORITY_HIGH => 'High',
+ self::PRIORITY_NORMAL => 'Normal',
+ self::PRIORITY_LOW => 'Low',
+ self::PRIORITY_LOWEST => 'Lowest',
+ );
+ $pMapKeys = array_keys($priorityMap);
+ if ($priority > max($pMapKeys)) {
+ $priority = max($pMapKeys);
+ } elseif ($priority < min($pMapKeys)) {
+ $priority = min($pMapKeys);
+ }
+ if (!$this->_setHeaderFieldModel('X-Priority',
+ sprintf('%d (%s)', $priority, $priorityMap[$priority]))) {
+ $this->getHeaders()->addTextHeader('X-Priority',
+ sprintf('%d (%s)', $priority, $priorityMap[$priority]));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the priority of this message.
+ *
+ * The returned value is an integer where 1 is the highest priority and 5
+ * is the lowest.
+ *
+ * @return int
+ */
+ public function getPriority()
+ {
+ list($priority) = sscanf($this->_getHeaderFieldModel('X-Priority'),
+ '%[1-5]'
+ );
+
+ return isset($priority) ? $priority : 3;
+ }
+
+ /**
+ * Ask for a delivery receipt from the recipient to be sent to $addresses.
+ *
+ * @param array $addresses
+ *
+ * @return $this
+ */
+ public function setReadReceiptTo($addresses)
+ {
+ if (!$this->_setHeaderFieldModel('Disposition-Notification-To', $addresses)) {
+ $this->getHeaders()
+ ->addMailboxHeader('Disposition-Notification-To', $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the addresses to which a read-receipt will be sent.
+ *
+ * @return string
+ */
+ public function getReadReceiptTo()
+ {
+ return $this->_getHeaderFieldModel('Disposition-Notification-To');
+ }
+
+ /**
+ * Attach a {@link Swift_Mime_MimeEntity} such as an Attachment or MimePart.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return $this
+ */
+ public function attach(Swift_Mime_MimeEntity $entity)
+ {
+ $this->setChildren(array_merge($this->getChildren(), array($entity)));
+
+ return $this;
+ }
+
+ /**
+ * Remove an already attached entity.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return $this
+ */
+ public function detach(Swift_Mime_MimeEntity $entity)
+ {
+ $newChildren = array();
+ foreach ($this->getChildren() as $child) {
+ if ($entity !== $child) {
+ $newChildren[] = $child;
+ }
+ }
+ $this->setChildren($newChildren);
+
+ return $this;
+ }
+
+ /**
+ * Attach a {@link Swift_Mime_MimeEntity} and return it's CID source.
+ * This method should be used when embedding images or other data in a message.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return string
+ */
+ public function embed(Swift_Mime_MimeEntity $entity)
+ {
+ $this->attach($entity);
+
+ return 'cid:'.$entity->getId();
+ }
+
+ /**
+ * Get this message as a complete string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $children));
+ $string = parent::toString();
+ $this->setChildren($children);
+ } else {
+ $string = parent::toString();
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Write this message to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $children));
+ parent::toByteStream($is);
+ $this->setChildren($children);
+ } else {
+ parent::toByteStream($is);
+ }
+ }
+
+ /** @see Swift_Mime_SimpleMimeEntity::_getIdField() */
+ protected function _getIdField()
+ {
+ return 'Message-ID';
+ }
+
+ /** Turn the body of this message into a child of itself if needed */
+ protected function _becomeMimePart()
+ {
+ $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(),
+ $this->_getCache(), $this->_getGrammar(), $this->_userCharset
+ );
+ $part->setContentType($this->_userContentType);
+ $part->setBody($this->getBody());
+ $part->setFormat($this->_userFormat);
+ $part->setDelSp($this->_userDelSp);
+ $part->_setNestingLevel($this->_getTopNestingLevel());
+
+ return $part;
+ }
+
+ /** Get the highest nesting level nested inside this message */
+ private function _getTopNestingLevel()
+ {
+ $highestLevel = $this->getNestingLevel();
+ foreach ($this->getChildren() as $child) {
+ $childLevel = $child->getNestingLevel();
+ if ($highestLevel < $childLevel) {
+ $highestLevel = $childLevel;
+ }
+ }
+
+ return $highestLevel;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php
new file mode 100644
index 00000000..f169584d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php
@@ -0,0 +1,843 @@
+ array(self::LEVEL_TOP, self::LEVEL_MIXED),
+ 'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
+ 'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED),
+ );
+
+ /** A set of filter rules to define what level an entity should be nested at */
+ private $_compoundLevelFilters = array();
+
+ /** The nesting level of this entity */
+ private $_nestingLevel = self::LEVEL_ALTERNATIVE;
+
+ /** A KeyCache instance used during encoding and streaming */
+ private $_cache;
+
+ /** Direct descendants of this entity */
+ private $_immediateChildren = array();
+
+ /** All descendants of this entity */
+ private $_children = array();
+
+ /** The maximum line length of the body of this entity */
+ private $_maxLineLength = 78;
+
+ /** The order in which alternative mime types should appear */
+ private $_alternativePartOrder = array(
+ 'text/plain' => 1,
+ 'text/html' => 2,
+ 'multipart/related' => 3,
+ );
+
+ /** The CID of this entity */
+ private $_id;
+
+ /** The key used for accessing the cache */
+ private $_cacheKey;
+
+ protected $_userContentType;
+
+ /**
+ * Create a new SimpleMimeEntity with $headers, $encoder and $cache.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar)
+ {
+ $this->_cacheKey = md5(uniqid(getmypid().mt_rand(), true));
+ $this->_cache = $cache;
+ $this->_headers = $headers;
+ $this->_grammar = $grammar;
+ $this->setEncoder($encoder);
+ $this->_headers->defineOrdering(array('Content-Type', 'Content-Transfer-Encoding'));
+
+ // This array specifies that, when the entire MIME document contains
+ // $compoundLevel, then for each child within $level, if its Content-Type
+ // is $contentType then it should be treated as if it's level is
+ // $neededLevel instead. I tried to write that unambiguously! :-\
+ // Data Structure:
+ // array (
+ // $compoundLevel => array(
+ // $level => array(
+ // $contentType => $neededLevel
+ // )
+ // )
+ // )
+
+ $this->_compoundLevelFilters = array(
+ (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
+ self::LEVEL_ALTERNATIVE => array(
+ 'text/plain' => self::LEVEL_ALTERNATIVE,
+ 'text/html' => self::LEVEL_RELATED,
+ ),
+ ),
+ );
+
+ $this->_id = $this->getRandomId();
+ }
+
+ /**
+ * Generate a new Content-ID or Message-ID for this MIME entity.
+ *
+ * @return string
+ */
+ public function generateId()
+ {
+ $this->setId($this->getRandomId());
+
+ return $this->_id;
+ }
+
+ /**
+ * Get the {@link Swift_Mime_HeaderSet} for this entity.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function getHeaders()
+ {
+ return $this->_headers;
+ }
+
+ /**
+ * Get the nesting level of this entity.
+ *
+ * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return $this->_nestingLevel;
+ }
+
+ /**
+ * Get the Content-type of this entity.
+ *
+ * @return string
+ */
+ public function getContentType()
+ {
+ return $this->_getHeaderFieldModel('Content-Type');
+ }
+
+ /**
+ * Set the Content-type of this entity.
+ *
+ * @param string $type
+ *
+ * @return $this
+ */
+ public function setContentType($type)
+ {
+ $this->_setContentTypeInHeaders($type);
+ // Keep track of the value so that if the content-type changes automatically
+ // due to added child entities, it can be restored if they are later removed
+ $this->_userContentType = $type;
+
+ return $this;
+ }
+
+ /**
+ * Get the CID of this entity.
+ *
+ * The CID will only be present in headers if a Content-ID header is present.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ $tmp = (array) $this->_getHeaderFieldModel($this->_getIdField());
+
+ return $this->_headers->has($this->_getIdField()) ? current($tmp) : $this->_id;
+ }
+
+ /**
+ * Set the CID of this entity.
+ *
+ * @param string $id
+ *
+ * @return $this
+ */
+ public function setId($id)
+ {
+ if (!$this->_setHeaderFieldModel($this->_getIdField(), $id)) {
+ $this->_headers->addIdHeader($this->_getIdField(), $id);
+ }
+ $this->_id = $id;
+
+ return $this;
+ }
+
+ /**
+ * Get the description of this entity.
+ *
+ * This value comes from the Content-Description header if set.
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->_getHeaderFieldModel('Content-Description');
+ }
+
+ /**
+ * Set the description of this entity.
+ *
+ * This method sets a value in the Content-ID header.
+ *
+ * @param string $description
+ *
+ * @return $this
+ */
+ public function setDescription($description)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Description', $description)) {
+ $this->_headers->addTextHeader('Content-Description', $description);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the maximum line length of the body of this entity.
+ *
+ * @return int
+ */
+ public function getMaxLineLength()
+ {
+ return $this->_maxLineLength;
+ }
+
+ /**
+ * Set the maximum line length of lines in this body.
+ *
+ * Though not enforced by the library, lines should not exceed 1000 chars.
+ *
+ * @param int $length
+ *
+ * @return $this
+ */
+ public function setMaxLineLength($length)
+ {
+ $this->_maxLineLength = $length;
+
+ return $this;
+ }
+
+ /**
+ * Get all children added to this entity.
+ *
+ * @return Swift_Mime_MimeEntity[]
+ */
+ public function getChildren()
+ {
+ return $this->_children;
+ }
+
+ /**
+ * Set all children of this entity.
+ *
+ * @param Swift_Mime_MimeEntity[] $children
+ * @param int $compoundLevel For internal use only
+ *
+ * @return $this
+ */
+ public function setChildren(array $children, $compoundLevel = null)
+ {
+ // TODO: Try to refactor this logic
+
+ $compoundLevel = isset($compoundLevel) ? $compoundLevel : $this->_getCompoundLevel($children);
+ $immediateChildren = array();
+ $grandchildren = array();
+ $newContentType = $this->_userContentType;
+
+ foreach ($children as $child) {
+ $level = $this->_getNeededChildLevel($child, $compoundLevel);
+ if (empty($immediateChildren)) {
+ //first iteration
+ $immediateChildren = array($child);
+ } else {
+ $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
+ if ($nextLevel == $level) {
+ $immediateChildren[] = $child;
+ } elseif ($level < $nextLevel) {
+ // Re-assign immediateChildren to grandchildren
+ $grandchildren = array_merge($grandchildren, $immediateChildren);
+ // Set new children
+ $immediateChildren = array($child);
+ } else {
+ $grandchildren[] = $child;
+ }
+ }
+ }
+
+ if ($immediateChildren) {
+ $lowestLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
+
+ // Determine which composite media type is needed to accommodate the
+ // immediate children
+ foreach ($this->_compositeRanges as $mediaType => $range) {
+ if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) {
+ $newContentType = $mediaType;
+
+ break;
+ }
+ }
+
+ // Put any grandchildren in a subpart
+ if (!empty($grandchildren)) {
+ $subentity = $this->_createChild();
+ $subentity->_setNestingLevel($lowestLevel);
+ $subentity->setChildren($grandchildren, $compoundLevel);
+ array_unshift($immediateChildren, $subentity);
+ }
+ }
+
+ $this->_immediateChildren = $immediateChildren;
+ $this->_children = $children;
+ $this->_setContentTypeInHeaders($newContentType);
+ $this->_fixHeaders();
+ $this->_sortChildren();
+
+ return $this;
+ }
+
+ /**
+ * Get the body of this entity as a string.
+ *
+ * @return string
+ */
+ public function getBody()
+ {
+ return $this->_body instanceof Swift_OutputByteStream ? $this->_readStream($this->_body) : $this->_body;
+ }
+
+ /**
+ * Set the body of this entity, either as a string, or as an instance of
+ * {@link Swift_OutputByteStream}.
+ *
+ * @param mixed $body
+ * @param string $contentType optional
+ *
+ * @return $this
+ */
+ public function setBody($body, $contentType = null)
+ {
+ if ($body !== $this->_body) {
+ $this->_clearCache();
+ }
+
+ $this->_body = $body;
+ if (isset($contentType)) {
+ $this->setContentType($contentType);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the encoder used for the body of this entity.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public function getEncoder()
+ {
+ return $this->_encoder;
+ }
+
+ /**
+ * Set the encoder used for the body of this entity.
+ *
+ * @param Swift_Mime_ContentEncoder $encoder
+ *
+ * @return $this
+ */
+ public function setEncoder(Swift_Mime_ContentEncoder $encoder)
+ {
+ if ($encoder !== $this->_encoder) {
+ $this->_clearCache();
+ }
+
+ $this->_encoder = $encoder;
+ $this->_setEncoding($encoder->getName());
+ $this->_notifyEncoderChanged($encoder);
+
+ return $this;
+ }
+
+ /**
+ * Get the boundary used to separate children in this entity.
+ *
+ * @return string
+ */
+ public function getBoundary()
+ {
+ if (!isset($this->_boundary)) {
+ $this->_boundary = '_=_swift_v4_'.time().'_'.md5(getmypid().mt_rand().uniqid('', true)).'_=_';
+ }
+
+ return $this->_boundary;
+ }
+
+ /**
+ * Set the boundary used to separate children in this entity.
+ *
+ * @param string $boundary
+ *
+ * @throws Swift_RfcComplianceException
+ *
+ * @return $this
+ */
+ public function setBoundary($boundary)
+ {
+ $this->_assertValidBoundary($boundary);
+ $this->_boundary = $boundary;
+
+ return $this;
+ }
+
+ /**
+ * Receive notification that the charset of this entity, or a parent entity
+ * has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_notifyCharsetChanged($charset);
+ }
+
+ /**
+ * Receive notification that the encoder of this entity or a parent entity
+ * has changed.
+ *
+ * @param Swift_Mime_ContentEncoder $encoder
+ */
+ public function encoderChanged(Swift_Mime_ContentEncoder $encoder)
+ {
+ $this->_notifyEncoderChanged($encoder);
+ }
+
+ /**
+ * Get this entire entity as a string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $string = $this->_headers->toString();
+ $string .= $this->_bodyToString();
+
+ return $string;
+ }
+
+ /**
+ * Get this entire entity as a string.
+ *
+ * @return string
+ */
+ protected function _bodyToString()
+ {
+ $string = '';
+
+ if (isset($this->_body) && empty($this->_immediateChildren)) {
+ if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
+ $body = $this->_cache->getString($this->_cacheKey, 'body');
+ } else {
+ $body = "\r\n".$this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength());
+ $this->_cache->setString($this->_cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE);
+ }
+ $string .= $body;
+ }
+
+ if (!empty($this->_immediateChildren)) {
+ foreach ($this->_immediateChildren as $child) {
+ $string .= "\r\n\r\n--".$this->getBoundary()."\r\n";
+ $string .= $child->toString();
+ }
+ $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n";
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Write this entire entity to a {@see Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ $is->write($this->_headers->toString());
+ $is->commit();
+
+ $this->_bodyToByteStream($is);
+ }
+
+ /**
+ * Write this entire entity to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream
+ */
+ protected function _bodyToByteStream(Swift_InputByteStream $is)
+ {
+ if (empty($this->_immediateChildren)) {
+ if (isset($this->_body)) {
+ if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
+ $this->_cache->exportToByteStream($this->_cacheKey, 'body', $is);
+ } else {
+ $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 'body');
+ if ($cacheIs) {
+ $is->bind($cacheIs);
+ }
+
+ $is->write("\r\n");
+
+ if ($this->_body instanceof Swift_OutputByteStream) {
+ $this->_body->setReadPointer(0);
+
+ $this->_encoder->encodeByteStream($this->_body, $is, 0, $this->getMaxLineLength());
+ } else {
+ $is->write($this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()));
+ }
+
+ if ($cacheIs) {
+ $is->unbind($cacheIs);
+ }
+ }
+ }
+ }
+
+ if (!empty($this->_immediateChildren)) {
+ foreach ($this->_immediateChildren as $child) {
+ $is->write("\r\n\r\n--".$this->getBoundary()."\r\n");
+ $child->toByteStream($is);
+ }
+ $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n");
+ }
+ }
+
+ /**
+ * Get the name of the header that provides the ID of this entity.
+ */
+ protected function _getIdField()
+ {
+ return 'Content-ID';
+ }
+
+ /**
+ * Get the model data (usually an array or a string) for $field.
+ */
+ protected function _getHeaderFieldModel($field)
+ {
+ if ($this->_headers->has($field)) {
+ return $this->_headers->get($field)->getFieldBodyModel();
+ }
+ }
+
+ /**
+ * Set the model data for $field.
+ */
+ protected function _setHeaderFieldModel($field, $model)
+ {
+ if ($this->_headers->has($field)) {
+ $this->_headers->get($field)->setFieldBodyModel($model);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the parameter value of $parameter on $field header.
+ */
+ protected function _getHeaderParameter($field, $parameter)
+ {
+ if ($this->_headers->has($field)) {
+ return $this->_headers->get($field)->getParameter($parameter);
+ }
+ }
+
+ /**
+ * Set the parameter value of $parameter on $field header.
+ */
+ protected function _setHeaderParameter($field, $parameter, $value)
+ {
+ if ($this->_headers->has($field)) {
+ $this->_headers->get($field)->setParameter($parameter, $value);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Re-evaluate what content type and encoding should be used on this entity.
+ */
+ protected function _fixHeaders()
+ {
+ if (count($this->_immediateChildren)) {
+ $this->_setHeaderParameter('Content-Type', 'boundary',
+ $this->getBoundary()
+ );
+ $this->_headers->remove('Content-Transfer-Encoding');
+ } else {
+ $this->_setHeaderParameter('Content-Type', 'boundary', null);
+ $this->_setEncoding($this->_encoder->getName());
+ }
+ }
+
+ /**
+ * Get the KeyCache used in this entity.
+ *
+ * @return Swift_KeyCache
+ */
+ protected function _getCache()
+ {
+ return $this->_cache;
+ }
+
+ /**
+ * Get the grammar used for validation.
+ *
+ * @return Swift_Mime_Grammar
+ */
+ protected function _getGrammar()
+ {
+ return $this->_grammar;
+ }
+
+ /**
+ * Empty the KeyCache for this entity.
+ */
+ protected function _clearCache()
+ {
+ $this->_cache->clearKey($this->_cacheKey, 'body');
+ }
+
+ /**
+ * Returns a random Content-ID or Message-ID.
+ *
+ * @return string
+ */
+ protected function getRandomId()
+ {
+ $idLeft = md5(getmypid().'.'.time().'.'.uniqid(mt_rand(), true));
+ $idRight = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated';
+ $id = $idLeft.'@'.$idRight;
+
+ try {
+ $this->_assertValidId($id);
+ } catch (Swift_RfcComplianceException $e) {
+ $id = $idLeft.'@swift.generated';
+ }
+
+ return $id;
+ }
+
+ private function _readStream(Swift_OutputByteStream $os)
+ {
+ $string = '';
+ while (false !== $bytes = $os->read(8192)) {
+ $string .= $bytes;
+ }
+
+ $os->setReadPointer(0);
+
+ return $string;
+ }
+
+ private function _setEncoding($encoding)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) {
+ $this->_headers->addTextHeader('Content-Transfer-Encoding', $encoding);
+ }
+ }
+
+ private function _assertValidBoundary($boundary)
+ {
+ if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) {
+ throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.');
+ }
+ }
+
+ private function _setContentTypeInHeaders($type)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Type', $type)) {
+ $this->_headers->addParameterizedHeader('Content-Type', $type);
+ }
+ }
+
+ private function _setNestingLevel($level)
+ {
+ $this->_nestingLevel = $level;
+ }
+
+ private function _getCompoundLevel($children)
+ {
+ $level = 0;
+ foreach ($children as $child) {
+ $level |= $child->getNestingLevel();
+ }
+
+ return $level;
+ }
+
+ private function _getNeededChildLevel($child, $compoundLevel)
+ {
+ $filter = array();
+ foreach ($this->_compoundLevelFilters as $bitmask => $rules) {
+ if (($compoundLevel & $bitmask) === $bitmask) {
+ $filter = $rules + $filter;
+ }
+ }
+
+ $realLevel = $child->getNestingLevel();
+ $lowercaseType = strtolower($child->getContentType());
+
+ if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) {
+ return $filter[$realLevel][$lowercaseType];
+ }
+
+ return $realLevel;
+ }
+
+ private function _createChild()
+ {
+ return new self($this->_headers->newInstance(), $this->_encoder, $this->_cache, $this->_grammar);
+ }
+
+ private function _notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder)
+ {
+ foreach ($this->_immediateChildren as $child) {
+ $child->encoderChanged($encoder);
+ }
+ }
+
+ private function _notifyCharsetChanged($charset)
+ {
+ $this->_encoder->charsetChanged($charset);
+ $this->_headers->charsetChanged($charset);
+ foreach ($this->_immediateChildren as $child) {
+ $child->charsetChanged($charset);
+ }
+ }
+
+ private function _sortChildren()
+ {
+ $shouldSort = false;
+ foreach ($this->_immediateChildren as $child) {
+ // NOTE: This include alternative parts moved into a related part
+ if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE) {
+ $shouldSort = true;
+ break;
+ }
+ }
+
+ // Sort in order of preference, if there is one
+ if ($shouldSort) {
+ usort($this->_immediateChildren, array($this, '_childSortAlgorithm'));
+ }
+ }
+
+ private function _childSortAlgorithm($a, $b)
+ {
+ $typePrefs = array();
+ $types = array(strtolower($a->getContentType()), strtolower($b->getContentType()));
+
+ foreach ($types as $type) {
+ $typePrefs[] = array_key_exists($type, $this->_alternativePartOrder) ? $this->_alternativePartOrder[$type] : max($this->_alternativePartOrder) + 1;
+ }
+
+ return $typePrefs[0] >= $typePrefs[1] ? 1 : -1;
+ }
+
+ // -- Destructor
+
+ /**
+ * Empties it's own contents from the cache.
+ */
+ public function __destruct()
+ {
+ $this->_cache->clearAll($this->_cacheKey);
+ }
+
+ /**
+ * Throws an Exception if the id passed does not comply with RFC 2822.
+ *
+ * @param string $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ private function _assertValidId($id)
+ {
+ if (!preg_match('/^'.$this->_grammar->getDefinition('id-left').'@'.$this->_grammar->getDefinition('id-right').'$/D', $id)) {
+ throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>');
+ }
+ }
+
+ /**
+ * Make a deep copy of object.
+ */
+ public function __clone()
+ {
+ $this->_headers = clone $this->_headers;
+ $this->_encoder = clone $this->_encoder;
+ $this->_cacheKey = md5(uniqid(getmypid().mt_rand(), true));
+ $children = array();
+ foreach ($this->_children as $pos => $child) {
+ $children[$pos] = clone $child;
+ }
+ $this->setChildren($children);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php
new file mode 100644
index 00000000..215f8db3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php
@@ -0,0 +1,59 @@
+createDependenciesFor('mime.part')
+ );
+
+ if (!isset($charset)) {
+ $charset = Swift_DependencyContainer::getInstance()
+ ->lookup('properties.charset');
+ }
+ $this->setBody($body);
+ $this->setCharset($charset);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new MimePart.
+ *
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public static function newInstance($body = null, $contentType = null, $charset = null)
+ {
+ return new self($body, $contentType, $charset);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php
new file mode 100644
index 00000000..b38e1cf7
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php
@@ -0,0 +1,39 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pretends messages have been sent, but just ignores them.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_NullTransport extends Swift_Transport_NullTransport
+{
+ /**
+ * Create a new NullTransport.
+ */
+ public function __construct()
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_NullTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.null')
+ );
+ }
+
+ /**
+ * Create a new NullTransport instance.
+ *
+ * @return Swift_NullTransport
+ */
+ public static function newInstance()
+ {
+ return new self();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php
new file mode 100644
index 00000000..1f26f9be
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php
@@ -0,0 +1,46 @@
+setThreshold($threshold);
+ $this->setSleepTime($sleep);
+ $this->_sleeper = $sleeper;
+ }
+
+ /**
+ * Set the number of emails to send before restarting.
+ *
+ * @param int $threshold
+ */
+ public function setThreshold($threshold)
+ {
+ $this->_threshold = $threshold;
+ }
+
+ /**
+ * Get the number of emails to send before restarting.
+ *
+ * @return int
+ */
+ public function getThreshold()
+ {
+ return $this->_threshold;
+ }
+
+ /**
+ * Set the number of seconds to sleep for during a restart.
+ *
+ * @param int $sleep time
+ */
+ public function setSleepTime($sleep)
+ {
+ $this->_sleep = $sleep;
+ }
+
+ /**
+ * Get the number of seconds to sleep for during a restart.
+ *
+ * @return int
+ */
+ public function getSleepTime()
+ {
+ return $this->_sleep;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ ++$this->_counter;
+ if ($this->_counter >= $this->_threshold) {
+ $transport = $evt->getTransport();
+ $transport->stop();
+ if ($this->_sleep) {
+ $this->sleep($this->_sleep);
+ }
+ $transport->start();
+ $this->_counter = 0;
+ }
+ }
+
+ /**
+ * Sleep for $seconds.
+ *
+ * @param int $seconds
+ */
+ public function sleep($seconds)
+ {
+ if (isset($this->_sleeper)) {
+ $this->_sleeper->sleep($seconds);
+ } else {
+ sleep($seconds);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php
new file mode 100644
index 00000000..f7e18d0e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php
@@ -0,0 +1,164 @@
+getMessage();
+ $message->toByteStream($this);
+ }
+
+ /**
+ * Invoked immediately following a command being sent.
+ *
+ * @param Swift_Events_CommandEvent $evt
+ */
+ public function commandSent(Swift_Events_CommandEvent $evt)
+ {
+ $command = $evt->getCommand();
+ $this->_out += strlen($command);
+ }
+
+ /**
+ * Invoked immediately following a response coming back.
+ *
+ * @param Swift_Events_ResponseEvent $evt
+ */
+ public function responseReceived(Swift_Events_ResponseEvent $evt)
+ {
+ $response = $evt->getResponse();
+ $this->_in += strlen($response);
+ }
+
+ /**
+ * Called when a message is sent so that the outgoing counter can be increased.
+ *
+ * @param string $bytes
+ */
+ public function write($bytes)
+ {
+ $this->_out += strlen($bytes);
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function flushBuffers()
+ {
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+
+ /**
+ * Get the total number of bytes sent to the server.
+ *
+ * @return int
+ */
+ public function getBytesOut()
+ {
+ return $this->_out;
+ }
+
+ /**
+ * Get the total number of bytes received from the server.
+ *
+ * @return int
+ */
+ public function getBytesIn()
+ {
+ return $this->_in;
+ }
+
+ /**
+ * Reset the internal counters to zero.
+ */
+ public function reset()
+ {
+ $this->_out = 0;
+ $this->_in = 0;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php
new file mode 100644
index 00000000..9f9f08b5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php
@@ -0,0 +1,31 @@
+
+ * $replacements = array(
+ * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"),
+ * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y")
+ * )
+ *
+ *
+ * When using an instance of {@link Swift_Plugins_Decorator_Replacements},
+ * the object should return just the array of replacements for the address
+ * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}.
+ *
+ * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements
+ */
+ public function __construct($replacements)
+ {
+ $this->setReplacements($replacements);
+ }
+
+ /**
+ * Sets replacements.
+ *
+ * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements
+ *
+ * @see __construct()
+ */
+ public function setReplacements($replacements)
+ {
+ if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) {
+ $this->_replacements = (array) $replacements;
+ } else {
+ $this->_replacements = $replacements;
+ }
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $this->_restoreMessage($message);
+ $to = array_keys($message->getTo());
+ $address = array_shift($to);
+ if ($replacements = $this->getReplacementsFor($address)) {
+ $body = $message->getBody();
+ $search = array_keys($replacements);
+ $replace = array_values($replacements);
+ $bodyReplaced = str_replace(
+ $search, $replace, $body
+ );
+ if ($body != $bodyReplaced) {
+ $this->_originalBody = $body;
+ $message->setBody($bodyReplaced);
+ }
+
+ foreach ($message->getHeaders()->getAll() as $header) {
+ $body = $header->getFieldBodyModel();
+ $count = 0;
+ if (is_array($body)) {
+ $bodyReplaced = array();
+ foreach ($body as $key => $value) {
+ $count1 = 0;
+ $count2 = 0;
+ $key = is_string($key) ? str_replace($search, $replace, $key, $count1) : $key;
+ $value = is_string($value) ? str_replace($search, $replace, $value, $count2) : $value;
+ $bodyReplaced[$key] = $value;
+
+ if (!$count && ($count1 || $count2)) {
+ $count = 1;
+ }
+ }
+ } else {
+ $bodyReplaced = str_replace($search, $replace, $body, $count);
+ }
+
+ if ($count) {
+ $this->_originalHeaders[$header->getFieldName()] = $body;
+ $header->setFieldBodyModel($bodyReplaced);
+ }
+ }
+
+ $children = (array) $message->getChildren();
+ foreach ($children as $child) {
+ list($type) = sscanf($child->getContentType(), '%[^/]/%s');
+ if ('text' == $type) {
+ $body = $child->getBody();
+ $bodyReplaced = str_replace(
+ $search, $replace, $body
+ );
+ if ($body != $bodyReplaced) {
+ $child->setBody($bodyReplaced);
+ $this->_originalChildBodies[$child->getId()] = $body;
+ }
+ }
+ }
+ $this->_lastMessage = $message;
+ }
+ }
+
+ /**
+ * Find a map of replacements for the address.
+ *
+ * If this plugin was provided with a delegate instance of
+ * {@link Swift_Plugins_Decorator_Replacements} then the call will be
+ * delegated to it. Otherwise, it will attempt to find the replacements
+ * from the array provided in the constructor.
+ *
+ * If no replacements can be found, an empty value (NULL) is returned.
+ *
+ * @param string $address
+ *
+ * @return array
+ */
+ public function getReplacementsFor($address)
+ {
+ if ($this->_replacements instanceof Swift_Plugins_Decorator_Replacements) {
+ return $this->_replacements->getReplacementsFor($address);
+ }
+
+ return isset($this->_replacements[$address]) ? $this->_replacements[$address] : null;
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->_restoreMessage($evt->getMessage());
+ }
+
+ /** Restore a changed message back to its original state */
+ private function _restoreMessage(Swift_Mime_Message $message)
+ {
+ if ($this->_lastMessage === $message) {
+ if (isset($this->_originalBody)) {
+ $message->setBody($this->_originalBody);
+ $this->_originalBody = null;
+ }
+ if (!empty($this->_originalHeaders)) {
+ foreach ($message->getHeaders()->getAll() as $header) {
+ if (array_key_exists($header->getFieldName(), $this->_originalHeaders)) {
+ $header->setFieldBodyModel($this->_originalHeaders[$header->getFieldName()]);
+ }
+ }
+ $this->_originalHeaders = array();
+ }
+ if (!empty($this->_originalChildBodies)) {
+ $children = (array) $message->getChildren();
+ foreach ($children as $child) {
+ $id = $child->getId();
+ if (array_key_exists($id, $this->_originalChildBodies)) {
+ $child->setBody($this->_originalChildBodies[$id]);
+ }
+ }
+ $this->_originalChildBodies = array();
+ }
+ $this->_lastMessage = null;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php
new file mode 100644
index 00000000..7552b67a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php
@@ -0,0 +1,69 @@
+_sender = $sender;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $headers = $message->getHeaders();
+
+ // save current recipients
+ $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath());
+
+ // replace them with the one to send to
+ $message->setReturnPath($this->_sender);
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+
+ // restore original headers
+ $headers = $message->getHeaders();
+
+ if ($headers->has('X-Swift-Return-Path')) {
+ $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress());
+ $headers->removeAll('X-Swift-Return-Path');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php
new file mode 100644
index 00000000..d9bce893
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php
@@ -0,0 +1,36 @@
+_logger = $logger;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ $this->_logger->add($entry);
+ }
+
+ /**
+ * Clear the log contents.
+ */
+ public function clear()
+ {
+ $this->_logger->clear();
+ }
+
+ /**
+ * Get this log as a string.
+ *
+ * @return string
+ */
+ public function dump()
+ {
+ return $this->_logger->dump();
+ }
+
+ /**
+ * Invoked immediately following a command being sent.
+ *
+ * @param Swift_Events_CommandEvent $evt
+ */
+ public function commandSent(Swift_Events_CommandEvent $evt)
+ {
+ $command = $evt->getCommand();
+ $this->_logger->add(sprintf('>> %s', $command));
+ }
+
+ /**
+ * Invoked immediately following a response coming back.
+ *
+ * @param Swift_Events_ResponseEvent $evt
+ */
+ public function responseReceived(Swift_Events_ResponseEvent $evt)
+ {
+ $response = $evt->getResponse();
+ $this->_logger->add(sprintf('<< %s', $response));
+ }
+
+ /**
+ * Invoked just before a Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf('++ Starting %s', $transportName));
+ }
+
+ /**
+ * Invoked immediately after the Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf('++ %s started', $transportName));
+ }
+
+ /**
+ * Invoked just before a Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf('++ Stopping %s', $transportName));
+ }
+
+ /**
+ * Invoked immediately after the Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf('++ %s stopped', $transportName));
+ }
+
+ /**
+ * Invoked as a TransportException is thrown in the Transport system.
+ *
+ * @param Swift_Events_TransportExceptionEvent $evt
+ */
+ public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt)
+ {
+ $e = $evt->getException();
+ $message = $e->getMessage();
+ $code = $e->getCode();
+ $this->_logger->add(sprintf('!! %s (code: %s)', $message, $code));
+ $message .= PHP_EOL;
+ $message .= 'Log data:'.PHP_EOL;
+ $message .= $this->_logger->dump();
+ $evt->cancelBubble();
+ throw new Swift_TransportException($message, $code, $e->getPrevious());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php
new file mode 100644
index 00000000..865bb0aa
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php
@@ -0,0 +1,72 @@
+_size = $size;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ $this->_log[] = $entry;
+ while (count($this->_log) > $this->_size) {
+ array_shift($this->_log);
+ }
+ }
+
+ /**
+ * Clear the log contents.
+ */
+ public function clear()
+ {
+ $this->_log = array();
+ }
+
+ /**
+ * Get this log as a string.
+ *
+ * @return string
+ */
+ public function dump()
+ {
+ return implode(PHP_EOL, $this->_log);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php
new file mode 100644
index 00000000..3583297a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php
@@ -0,0 +1,58 @@
+_isHtml = $isHtml;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ if ($this->_isHtml) {
+ printf('%s%s%s', htmlspecialchars($entry, ENT_QUOTES), '
', PHP_EOL);
+ } else {
+ printf('%s%s', $entry, PHP_EOL);
+ }
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function clear()
+ {
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function dump()
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php
new file mode 100644
index 00000000..e622cb37
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php
@@ -0,0 +1,74 @@
+messages = array();
+ }
+
+ /**
+ * Get the message list.
+ *
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * Get the message count.
+ *
+ * @return int count
+ */
+ public function countMessages()
+ {
+ return count($this->messages);
+ }
+
+ /**
+ * Empty the message list.
+ */
+ public function clear()
+ {
+ $this->messages = array();
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->messages[] = clone $evt->getMessage();
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php
new file mode 100644
index 00000000..fb99e4c9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php
@@ -0,0 +1,31 @@
+_host = $host;
+ $this->_port = $port;
+ $this->_crypto = $crypto;
+ }
+
+ /**
+ * Create a new PopBeforeSmtpPlugin for $host and $port.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $crypto as "tls" or "ssl"
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public static function newInstance($host, $port = 110, $crypto = null)
+ {
+ return new self($host, $port, $crypto);
+ }
+
+ /**
+ * Set a Pop3Connection to delegate to instead of connecting directly.
+ *
+ * @param Swift_Plugins_Pop_Pop3Connection $connection
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection)
+ {
+ $this->_connection = $connection;
+
+ return $this;
+ }
+
+ /**
+ * Bind this plugin to a specific SMTP transport instance.
+ *
+ * @param Swift_Transport
+ */
+ public function bindSmtp(Swift_Transport $smtp)
+ {
+ $this->_transport = $smtp;
+ }
+
+ /**
+ * Set the connection timeout in seconds (default 10).
+ *
+ * @param int $timeout
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setTimeout($timeout)
+ {
+ $this->_timeout = (int) $timeout;
+
+ return $this;
+ }
+
+ /**
+ * Set the username to use when connecting (if needed).
+ *
+ * @param string $username
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setUsername($username)
+ {
+ $this->_username = $username;
+
+ return $this;
+ }
+
+ /**
+ * Set the password to use when connecting (if needed).
+ *
+ * @param string $password
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setPassword($password)
+ {
+ $this->_password = $password;
+
+ return $this;
+ }
+
+ /**
+ * Connect to the POP3 host and authenticate.
+ *
+ * @throws Swift_Plugins_Pop_Pop3Exception if connection fails
+ */
+ public function connect()
+ {
+ if (isset($this->_connection)) {
+ $this->_connection->connect();
+ } else {
+ if (!isset($this->_socket)) {
+ if (!$socket = fsockopen(
+ $this->_getHostString(), $this->_port, $errno, $errstr, $this->_timeout)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to connect to POP3 host [%s]: %s', $this->_host, $errstr)
+ );
+ }
+ $this->_socket = $socket;
+
+ if (false === $greeting = fgets($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to connect to POP3 host [%s]', trim($greeting))
+ );
+ }
+
+ $this->_assertOk($greeting);
+
+ if ($this->_username) {
+ $this->_command(sprintf("USER %s\r\n", $this->_username));
+ $this->_command(sprintf("PASS %s\r\n", $this->_password));
+ }
+ }
+ }
+ }
+
+ /**
+ * Disconnect from the POP3 host.
+ */
+ public function disconnect()
+ {
+ if (isset($this->_connection)) {
+ $this->_connection->disconnect();
+ } else {
+ $this->_command("QUIT\r\n");
+ if (!fclose($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('POP3 host [%s] connection could not be stopped', $this->_host)
+ );
+ }
+ $this->_socket = null;
+ }
+ }
+
+ /**
+ * Invoked just before a Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ if (isset($this->_transport)) {
+ if ($this->_transport !== $evt->getTransport()) {
+ return;
+ }
+ }
+
+ $this->connect();
+ $this->disconnect();
+ }
+
+ /**
+ * Not used.
+ */
+ public function transportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function transportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ private function _command($command)
+ {
+ if (!fwrite($this->_socket, $command)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to write command [%s] to POP3 host', trim($command))
+ );
+ }
+
+ if (false === $response = fgets($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to read from POP3 host after command [%s]', trim($command))
+ );
+ }
+
+ $this->_assertOk($response);
+
+ return $response;
+ }
+
+ private function _assertOk($response)
+ {
+ if (substr($response, 0, 3) != '+OK') {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('POP3 command failed [%s]', trim($response))
+ );
+ }
+ }
+
+ private function _getHostString()
+ {
+ $host = $this->_host;
+ switch (strtolower($this->_crypto)) {
+ case 'ssl':
+ $host = 'ssl://'.$host;
+ break;
+
+ case 'tls':
+ $host = 'tls://'.$host;
+ break;
+ }
+
+ return $host;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php
new file mode 100644
index 00000000..c3a1f868
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php
@@ -0,0 +1,213 @@
+_recipient = $recipient;
+ $this->_whitelist = $whitelist;
+ }
+
+ /**
+ * Set the recipient of all messages.
+ *
+ * @param mixed $recipient
+ */
+ public function setRecipient($recipient)
+ {
+ $this->_recipient = $recipient;
+ }
+
+ /**
+ * Get the recipient of all messages.
+ *
+ * @return mixed
+ */
+ public function getRecipient()
+ {
+ return $this->_recipient;
+ }
+
+ /**
+ * Set a list of regular expressions to whitelist certain recipients.
+ *
+ * @param array $whitelist
+ */
+ public function setWhitelist(array $whitelist)
+ {
+ $this->_whitelist = $whitelist;
+ }
+
+ /**
+ * Get the whitelist.
+ *
+ * @return array
+ */
+ public function getWhitelist()
+ {
+ return $this->_whitelist;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $headers = $message->getHeaders();
+
+ // conditionally save current recipients
+
+ if ($headers->has('to')) {
+ $headers->addMailboxHeader('X-Swift-To', $message->getTo());
+ }
+
+ if ($headers->has('cc')) {
+ $headers->addMailboxHeader('X-Swift-Cc', $message->getCc());
+ }
+
+ if ($headers->has('bcc')) {
+ $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc());
+ }
+
+ // Filter remaining headers against whitelist
+ $this->_filterHeaderSet($headers, 'To');
+ $this->_filterHeaderSet($headers, 'Cc');
+ $this->_filterHeaderSet($headers, 'Bcc');
+
+ // Add each hard coded recipient
+ $to = $message->getTo();
+ if (null === $to) {
+ $to = array();
+ }
+
+ foreach ((array) $this->_recipient as $recipient) {
+ if (!array_key_exists($recipient, $to)) {
+ $message->addTo($recipient);
+ }
+ }
+ }
+
+ /**
+ * Filter header set against a whitelist of regular expressions.
+ *
+ * @param Swift_Mime_HeaderSet $headerSet
+ * @param string $type
+ */
+ private function _filterHeaderSet(Swift_Mime_HeaderSet $headerSet, $type)
+ {
+ foreach ($headerSet->getAll($type) as $headers) {
+ $headers->setNameAddresses($this->_filterNameAddresses($headers->getNameAddresses()));
+ }
+ }
+
+ /**
+ * Filtered list of addresses => name pairs.
+ *
+ * @param array $recipients
+ *
+ * @return array
+ */
+ private function _filterNameAddresses(array $recipients)
+ {
+ $filtered = array();
+
+ foreach ($recipients as $address => $name) {
+ if ($this->_isWhitelisted($address)) {
+ $filtered[$address] = $name;
+ }
+ }
+
+ return $filtered;
+ }
+
+ /**
+ * Matches address against whitelist of regular expressions.
+ *
+ * @param $recipient
+ *
+ * @return bool
+ */
+ protected function _isWhitelisted($recipient)
+ {
+ if (in_array($recipient, (array) $this->_recipient)) {
+ return true;
+ }
+
+ foreach ($this->_whitelist as $pattern) {
+ if (preg_match($pattern, $recipient)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->_restoreMessage($evt->getMessage());
+ }
+
+ private function _restoreMessage(Swift_Mime_Message $message)
+ {
+ // restore original headers
+ $headers = $message->getHeaders();
+
+ if ($headers->has('X-Swift-To')) {
+ $message->setTo($headers->get('X-Swift-To')->getNameAddresses());
+ $headers->removeAll('X-Swift-To');
+ } else {
+ $message->setTo(null);
+ }
+
+ if ($headers->has('X-Swift-Cc')) {
+ $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses());
+ $headers->removeAll('X-Swift-Cc');
+ }
+
+ if ($headers->has('X-Swift-Bcc')) {
+ $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses());
+ $headers->removeAll('X-Swift-Bcc');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php
new file mode 100644
index 00000000..0f21b7d6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php
@@ -0,0 +1,32 @@
+_reporter = $reporter;
+ }
+
+ /**
+ * Not used.
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $failures = array_flip($evt->getFailedRecipients());
+ foreach ((array) $message->getTo() as $address => $null) {
+ $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS);
+ }
+ foreach ((array) $message->getCc() as $address => $null) {
+ $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS);
+ }
+ foreach ((array) $message->getBcc() as $address => $null) {
+ $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php
new file mode 100644
index 00000000..cad9d168
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php
@@ -0,0 +1,59 @@
+_failures_cache[$address])) {
+ $this->_failures[] = $address;
+ $this->_failures_cache[$address] = true;
+ }
+ }
+
+ /**
+ * Get an array of addresses for which delivery failed.
+ *
+ * @return array
+ */
+ public function getFailedRecipients()
+ {
+ return $this->_failures;
+ }
+
+ /**
+ * Clear the buffer (empty the list).
+ */
+ public function clear()
+ {
+ $this->_failures = $this->_failures_cache = array();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php
new file mode 100644
index 00000000..c6259355
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php
@@ -0,0 +1,39 @@
+'.PHP_EOL;
+ echo 'PASS '.$address.PHP_EOL;
+ echo ''.PHP_EOL;
+ flush();
+ } else {
+ echo ''.PHP_EOL;
+ echo 'FAIL '.$address.PHP_EOL;
+ echo '
'.PHP_EOL;
+ flush();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php
new file mode 100644
index 00000000..595c0f60
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php
@@ -0,0 +1,24 @@
+_rate = $rate;
+ $this->_mode = $mode;
+ $this->_sleeper = $sleeper;
+ $this->_timer = $timer;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $time = $this->getTimestamp();
+ if (!isset($this->_start)) {
+ $this->_start = $time;
+ }
+ $duration = $time - $this->_start;
+
+ switch ($this->_mode) {
+ case self::BYTES_PER_MINUTE:
+ $sleep = $this->_throttleBytesPerMinute($duration);
+ break;
+ case self::MESSAGES_PER_SECOND:
+ $sleep = $this->_throttleMessagesPerSecond($duration);
+ break;
+ case self::MESSAGES_PER_MINUTE:
+ $sleep = $this->_throttleMessagesPerMinute($duration);
+ break;
+ default:
+ $sleep = 0;
+ break;
+ }
+
+ if ($sleep > 0) {
+ $this->sleep($sleep);
+ }
+ }
+
+ /**
+ * Invoked when a Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ parent::sendPerformed($evt);
+ ++$this->_messages;
+ }
+
+ /**
+ * Sleep for $seconds.
+ *
+ * @param int $seconds
+ */
+ public function sleep($seconds)
+ {
+ if (isset($this->_sleeper)) {
+ $this->_sleeper->sleep($seconds);
+ } else {
+ sleep($seconds);
+ }
+ }
+
+ /**
+ * Get the current UNIX timestamp.
+ *
+ * @return int
+ */
+ public function getTimestamp()
+ {
+ if (isset($this->_timer)) {
+ return $this->_timer->getTimestamp();
+ }
+
+ return time();
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleBytesPerMinute($timePassed)
+ {
+ $expectedDuration = $this->getBytesOut() / ($this->_rate / 60);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleMessagesPerSecond($timePassed)
+ {
+ $expectedDuration = $this->_messages / ($this->_rate);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleMessagesPerMinute($timePassed)
+ {
+ $expectedDuration = $this->_messages / ($this->_rate / 60);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php
new file mode 100644
index 00000000..9c8deb38
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php
@@ -0,0 +1,24 @@
+register('properties.charset')->asValue($charset);
+
+ return $this;
+ }
+
+ /**
+ * Set the directory where temporary files can be saved.
+ *
+ * @param string $dir
+ *
+ * @return Swift_Preferences
+ */
+ public function setTempDir($dir)
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('tempdir')->asValue($dir);
+
+ return $this;
+ }
+
+ /**
+ * Set the type of cache to use (i.e. "disk" or "array").
+ *
+ * @param string $type
+ *
+ * @return Swift_Preferences
+ */
+ public function setCacheType($type)
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('cache')->asAliasOf(sprintf('cache.%s', $type));
+
+ return $this;
+ }
+
+ /**
+ * Set the QuotedPrintable dot escaper preference.
+ *
+ * @param bool $dotEscape
+ *
+ * @return Swift_Preferences
+ */
+ public function setQPDotEscape($dotEscape)
+ {
+ $dotEscape = !empty($dotEscape);
+ Swift_DependencyContainer::getInstance()
+ ->register('mime.qpcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder')
+ ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer'))
+ ->addConstructorValue($dotEscape);
+
+ return $this;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php
new file mode 100644
index 00000000..2897474e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php
@@ -0,0 +1,27 @@
+createDependenciesFor('transport.sendmail')
+ );
+
+ $this->setCommand($command);
+ }
+
+ /**
+ * Create a new SendmailTransport instance.
+ *
+ * @param string $command
+ *
+ * @return Swift_SendmailTransport
+ */
+ public static function newInstance($command = '/usr/sbin/sendmail -bs')
+ {
+ return new self($command);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php
new file mode 100644
index 00000000..2e7a8726
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php
@@ -0,0 +1,23 @@
+
+ *
+ * @deprecated
+ */
+class Swift_SignedMessage extends Swift_Message
+{
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php
new file mode 100644
index 00000000..2d8176d9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php
@@ -0,0 +1,20 @@
+
+ */
+interface Swift_Signer
+{
+ public function reset();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php
new file mode 100644
index 00000000..9ffcef39
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php
@@ -0,0 +1,33 @@
+
+ */
+interface Swift_Signers_BodySigner extends Swift_Signer
+{
+ /**
+ * Change the Swift_Signed_Message to apply the singing.
+ *
+ * @param Swift_Message $message
+ *
+ * @return Swift_Signers_BodySigner
+ */
+ public function signMessage(Swift_Message $message);
+
+ /**
+ * Return the list of header a signer might tamper.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php
new file mode 100644
index 00000000..6ddd4f92
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php
@@ -0,0 +1,698 @@
+
+ */
+class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner
+{
+ /**
+ * PrivateKey.
+ *
+ * @var string
+ */
+ protected $_privateKey;
+
+ /**
+ * DomainName.
+ *
+ * @var string
+ */
+ protected $_domainName;
+
+ /**
+ * Selector.
+ *
+ * @var string
+ */
+ protected $_selector;
+
+ /**
+ * Hash algorithm used.
+ *
+ * @var string
+ */
+ protected $_hashAlgorithm = 'rsa-sha1';
+
+ /**
+ * Body canon method.
+ *
+ * @var string
+ */
+ protected $_bodyCanon = 'simple';
+
+ /**
+ * Header canon method.
+ *
+ * @var string
+ */
+ protected $_headerCanon = 'simple';
+
+ /**
+ * Headers not being signed.
+ *
+ * @var array
+ */
+ protected $_ignoredHeaders = array('return-path' => true);
+
+ /**
+ * Signer identity.
+ *
+ * @var string
+ */
+ protected $_signerIdentity;
+
+ /**
+ * BodyLength.
+ *
+ * @var int
+ */
+ protected $_bodyLen = 0;
+
+ /**
+ * Maximum signedLen.
+ *
+ * @var int
+ */
+ protected $_maxLen = PHP_INT_MAX;
+
+ /**
+ * Embbed bodyLen in signature.
+ *
+ * @var bool
+ */
+ protected $_showLen = false;
+
+ /**
+ * When the signature has been applied (true means time()), false means not embedded.
+ *
+ * @var mixed
+ */
+ protected $_signatureTimestamp = true;
+
+ /**
+ * When will the signature expires false means not embedded, if sigTimestamp is auto
+ * Expiration is relative, otherwhise it's absolute.
+ *
+ * @var int
+ */
+ protected $_signatureExpiration = false;
+
+ /**
+ * Must we embed signed headers?
+ *
+ * @var bool
+ */
+ protected $_debugHeaders = false;
+
+ // work variables
+ /**
+ * Headers used to generate hash.
+ *
+ * @var array
+ */
+ protected $_signedHeaders = array();
+
+ /**
+ * If debugHeaders is set store debugDatas here.
+ *
+ * @var string
+ */
+ private $_debugHeadersData = '';
+
+ /**
+ * Stores the bodyHash.
+ *
+ * @var string
+ */
+ private $_bodyHash = '';
+
+ /**
+ * Stores the signature header.
+ *
+ * @var Swift_Mime_Headers_ParameterizedHeader
+ */
+ protected $_dkimHeader;
+
+ private $_bodyHashHandler;
+
+ private $_headerHash;
+
+ private $_headerCanonData = '';
+
+ private $_bodyCanonEmptyCounter = 0;
+
+ private $_bodyCanonIgnoreStart = 2;
+
+ private $_bodyCanonSpace = false;
+
+ private $_bodyCanonLastChar = null;
+
+ private $_bodyCanonLine = '';
+
+ private $_bound = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ */
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ $this->_privateKey = $privateKey;
+ $this->_domainName = $domainName;
+ $this->_signerIdentity = '@'.$domainName;
+ $this->_selector = $selector;
+ }
+
+ /**
+ * Instanciate DKIMSigner.
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+ /**
+ * Reset the Signer.
+ *
+ * @see Swift_Signer::reset()
+ */
+ public function reset()
+ {
+ $this->_headerHash = null;
+ $this->_signedHeaders = array();
+ $this->_bodyHash = null;
+ $this->_bodyHashHandler = null;
+ $this->_bodyCanonIgnoreStart = 2;
+ $this->_bodyCanonEmptyCounter = 0;
+ $this->_bodyCanonLastChar = null;
+ $this->_bodyCanonSpace = false;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * Writing may not happen immediately if the stream chooses to buffer. If
+ * you want to write these bytes with immediate effect, call {@link commit()}
+ * after calling write().
+ *
+ * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
+ * second, etc etc).
+ *
+ * @param string $bytes
+ *
+ * @throws Swift_IoException
+ *
+ * @return int
+ */
+ public function write($bytes)
+ {
+ $this->_canonicalizeBody($bytes);
+ foreach ($this->_bound as $is) {
+ $is->write($bytes);
+ }
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ */
+ public function commit()
+ {
+ // Nothing to do
+ return;
+ }
+
+ /**
+ * Attach $is to this stream.
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ $this->_bound[] = $is;
+
+ return;
+ }
+
+ /**
+ * Remove an already bound stream.
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ foreach ($this->_bound as $k => $stream) {
+ if ($stream === $is) {
+ unset($this->_bound[$k]);
+
+ return;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ */
+ public function flushBuffers()
+ {
+ $this->reset();
+ }
+
+ /**
+ * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256.
+ *
+ * @param string $hash
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHashAlgorithm($hash)
+ {
+ // Unable to sign with rsa-sha256
+ if ($hash == 'rsa-sha1') {
+ $this->_hashAlgorithm = 'rsa-sha1';
+ } else {
+ $this->_hashAlgorithm = 'rsa-sha256';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the body canonicalization algorithm.
+ *
+ * @param string $canon
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setBodyCanon($canon)
+ {
+ if ($canon == 'relaxed') {
+ $this->_bodyCanon = 'relaxed';
+ } else {
+ $this->_bodyCanon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the header canonicalization algorithm.
+ *
+ * @param string $canon
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHeaderCanon($canon)
+ {
+ if ($canon == 'relaxed') {
+ $this->_headerCanon = 'relaxed';
+ } else {
+ $this->_headerCanon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signer identity.
+ *
+ * @param string $identity
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignerIdentity($identity)
+ {
+ $this->_signerIdentity = $identity;
+
+ return $this;
+ }
+
+ /**
+ * Set the length of the body to sign.
+ *
+ * @param mixed $len (bool or int)
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setBodySignedLen($len)
+ {
+ if ($len === true) {
+ $this->_showLen = true;
+ $this->_maxLen = PHP_INT_MAX;
+ } elseif ($len === false) {
+ $this->_showLen = false;
+ $this->_maxLen = PHP_INT_MAX;
+ } else {
+ $this->_showLen = true;
+ $this->_maxLen = (int) $len;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signature timestamp.
+ *
+ * @param int $time A timestamp
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureTimestamp($time)
+ {
+ $this->_signatureTimestamp = $time;
+
+ return $this;
+ }
+
+ /**
+ * Set the signature expiration timestamp.
+ *
+ * @param int $time A timestamp
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureExpiration($time)
+ {
+ $this->_signatureExpiration = $time;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders.
+ *
+ * @param bool $debug
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ /**
+ * Start Body.
+ */
+ public function startBody()
+ {
+ // Init
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha256':
+ $this->_bodyHashHandler = hash_init('sha256');
+ break;
+ case 'rsa-sha1':
+ $this->_bodyHashHandler = hash_init('sha1');
+ break;
+ }
+ $this->_bodyCanonLine = '';
+ }
+
+ /**
+ * End Body.
+ */
+ public function endBody()
+ {
+ $this->_endOfBody();
+ }
+
+ /**
+ * Returns the list of Headers Tampered by this plugin.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ if ($this->_debugHeaders) {
+ return array('DKIM-Signature', 'X-DebugHash');
+ } else {
+ return array('DKIM-Signature');
+ }
+ }
+
+ /**
+ * Adds an ignored Header.
+ *
+ * @param string $header_name
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function ignoreHeader($header_name)
+ {
+ $this->_ignoredHeaders[strtolower($header_name)] = true;
+
+ return $this;
+ }
+
+ /**
+ * Set the headers to sign.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $this->_headerCanonData = '';
+ // Loop through Headers
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (!isset($this->_ignoredHeaders[strtolower($hName)])) {
+ if ($headers->has($hName)) {
+ $tmp = $headers->getAll($hName);
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $this->_addHeader($header->toString());
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add the signature to the given Headers.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ // Prepare the DKIM-Signature
+ $params = array('v' => '1', 'a' => $this->_hashAlgorithm, 'bh' => base64_encode($this->_bodyHash), 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'i' => $this->_signerIdentity, 's' => $this->_selector);
+ if ($this->_bodyCanon != 'simple') {
+ $params['c'] = $this->_headerCanon.'/'.$this->_bodyCanon;
+ } elseif ($this->_headerCanon != 'simple') {
+ $params['c'] = $this->_headerCanon;
+ }
+ if ($this->_showLen) {
+ $params['l'] = $this->_bodyLen;
+ }
+ if ($this->_signatureTimestamp === true) {
+ $params['t'] = time();
+ if ($this->_signatureExpiration !== false) {
+ $params['x'] = $params['t'] + $this->_signatureExpiration;
+ }
+ } else {
+ if ($this->_signatureTimestamp !== false) {
+ $params['t'] = $this->_signatureTimestamp;
+ }
+ if ($this->_signatureExpiration !== false) {
+ $params['x'] = $this->_signatureExpiration;
+ }
+ }
+ if ($this->_debugHeaders) {
+ $params['z'] = implode('|', $this->_debugHeadersData);
+ }
+ $string = '';
+ foreach ($params as $k => $v) {
+ $string .= $k.'='.$v.'; ';
+ }
+ $string = trim($string);
+ $headers->addTextHeader('DKIM-Signature', $string);
+ // Add the last DKIM-Signature
+ $tmp = $headers->getAll('DKIM-Signature');
+ $this->_dkimHeader = end($tmp);
+ $this->_addHeader(trim($this->_dkimHeader->toString())."\r\n b=", true);
+ $this->_endOfHeaders();
+ if ($this->_debugHeaders) {
+ $headers->addTextHeader('X-DebugHash', base64_encode($this->_headerHash));
+ }
+ $this->_dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->_getEncryptedHash()), 73, ' ')));
+
+ return $this;
+ }
+
+ /* Private helpers */
+
+ protected function _addHeader($header, $is_sig = false)
+ {
+ switch ($this->_headerCanon) {
+ case 'relaxed':
+ // Prepare Header and cascade
+ $exploded = explode(':', $header, 2);
+ $name = strtolower(trim($exploded[0]));
+ $value = str_replace("\r\n", '', $exploded[1]);
+ $value = preg_replace("/[ \t][ \t]+/", ' ', $value);
+ $header = $name.':'.trim($value).($is_sig ? '' : "\r\n");
+ case 'simple':
+ // Nothing to do
+ }
+ $this->_addToHeaderHash($header);
+ }
+
+ /**
+ * @deprecated This method is currently useless in this class but it must be
+ * kept for BC reasons due to its "protected" scope. This method
+ * might be overriden by custom client code.
+ */
+ protected function _endOfHeaders()
+ {
+ }
+
+ protected function _canonicalizeBody($string)
+ {
+ $len = strlen($string);
+ $canon = '';
+ $method = ($this->_bodyCanon == 'relaxed');
+ for ($i = 0; $i < $len; ++$i) {
+ if ($this->_bodyCanonIgnoreStart > 0) {
+ --$this->_bodyCanonIgnoreStart;
+ continue;
+ }
+ switch ($string[$i]) {
+ case "\r":
+ $this->_bodyCanonLastChar = "\r";
+ break;
+ case "\n":
+ if ($this->_bodyCanonLastChar == "\r") {
+ if ($method) {
+ $this->_bodyCanonSpace = false;
+ }
+ if ($this->_bodyCanonLine == '') {
+ ++$this->_bodyCanonEmptyCounter;
+ } else {
+ $this->_bodyCanonLine = '';
+ $canon .= "\r\n";
+ }
+ } else {
+ // Wooops Error
+ // todo handle it but should never happen
+ }
+ break;
+ case ' ':
+ case "\t":
+ if ($method) {
+ $this->_bodyCanonSpace = true;
+ break;
+ }
+ default:
+ if ($this->_bodyCanonEmptyCounter > 0) {
+ $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter);
+ $this->_bodyCanonEmptyCounter = 0;
+ }
+ if ($this->_bodyCanonSpace) {
+ $this->_bodyCanonLine .= ' ';
+ $canon .= ' ';
+ $this->_bodyCanonSpace = false;
+ }
+ $this->_bodyCanonLine .= $string[$i];
+ $canon .= $string[$i];
+ }
+ }
+ $this->_addToBodyHash($canon);
+ }
+
+ protected function _endOfBody()
+ {
+ // Add trailing Line return if last line is non empty
+ if (strlen($this->_bodyCanonLine) > 0) {
+ $this->_addToBodyHash("\r\n");
+ }
+ $this->_bodyHash = hash_final($this->_bodyHashHandler, true);
+ }
+
+ private function _addToBodyHash($string)
+ {
+ $len = strlen($string);
+ if ($len > ($new_len = ($this->_maxLen - $this->_bodyLen))) {
+ $string = substr($string, 0, $new_len);
+ $len = $new_len;
+ }
+ hash_update($this->_bodyHashHandler, $string);
+ $this->_bodyLen += $len;
+ }
+
+ private function _addToHeaderHash($header)
+ {
+ if ($this->_debugHeaders) {
+ $this->_debugHeadersData[] = trim($header);
+ }
+ $this->_headerCanonData .= $header;
+ }
+
+ /**
+ * @throws Swift_SwiftException
+ *
+ * @return string
+ */
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha1':
+ $algorithm = OPENSSL_ALGO_SHA1;
+ break;
+ case 'rsa-sha256':
+ $algorithm = OPENSSL_ALGO_SHA256;
+ break;
+ }
+ $pkeyId = openssl_get_privatekey($this->_privateKey);
+ if (!$pkeyId) {
+ throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']');
+ }
+ if (openssl_sign($this->_headerCanonData, $signature, $pkeyId, $algorithm)) {
+ return $signature;
+ }
+ throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php
new file mode 100644
index 00000000..786cee7b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php
@@ -0,0 +1,525 @@
+
+ */
+class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner
+{
+ /**
+ * PrivateKey.
+ *
+ * @var string
+ */
+ protected $_privateKey;
+
+ /**
+ * DomainName.
+ *
+ * @var string
+ */
+ protected $_domainName;
+
+ /**
+ * Selector.
+ *
+ * @var string
+ */
+ protected $_selector;
+
+ /**
+ * Hash algorithm used.
+ *
+ * @var string
+ */
+ protected $_hashAlgorithm = 'rsa-sha1';
+
+ /**
+ * Canonisation method.
+ *
+ * @var string
+ */
+ protected $_canon = 'simple';
+
+ /**
+ * Headers not being signed.
+ *
+ * @var array
+ */
+ protected $_ignoredHeaders = array();
+
+ /**
+ * Signer identity.
+ *
+ * @var string
+ */
+ protected $_signerIdentity;
+
+ /**
+ * Must we embed signed headers?
+ *
+ * @var bool
+ */
+ protected $_debugHeaders = false;
+
+ // work variables
+ /**
+ * Headers used to generate hash.
+ *
+ * @var array
+ */
+ private $_signedHeaders = array();
+
+ /**
+ * Stores the signature header.
+ *
+ * @var Swift_Mime_Headers_ParameterizedHeader
+ */
+ protected $_domainKeyHeader;
+
+ /**
+ * Hash Handler.
+ *
+ * @var resource|null
+ */
+ private $_hashHandler;
+
+ private $_hash;
+
+ private $_canonData = '';
+
+ private $_bodyCanonEmptyCounter = 0;
+
+ private $_bodyCanonIgnoreStart = 2;
+
+ private $_bodyCanonSpace = false;
+
+ private $_bodyCanonLastChar = null;
+
+ private $_bodyCanonLine = '';
+
+ private $_bound = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ */
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ $this->_privateKey = $privateKey;
+ $this->_domainName = $domainName;
+ $this->_signerIdentity = '@'.$domainName;
+ $this->_selector = $selector;
+ }
+
+ /**
+ * Instanciate DomainKeySigner.
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+ /**
+ * Resets internal states.
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function reset()
+ {
+ $this->_hash = null;
+ $this->_hashHandler = null;
+ $this->_bodyCanonIgnoreStart = 2;
+ $this->_bodyCanonEmptyCounter = 0;
+ $this->_bodyCanonLastChar = null;
+ $this->_bodyCanonSpace = false;
+
+ return $this;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * Writing may not happen immediately if the stream chooses to buffer. If
+ * you want to write these bytes with immediate effect, call {@link commit()}
+ * after calling write().
+ *
+ * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
+ * second, etc etc).
+ *
+ * @param string $bytes
+ *
+ * @throws Swift_IoException
+ *
+ * @return int
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function write($bytes)
+ {
+ $this->_canonicalizeBody($bytes);
+ foreach ($this->_bound as $is) {
+ $is->write($bytes);
+ }
+
+ return $this;
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function commit()
+ {
+ // Nothing to do
+ return $this;
+ }
+
+ /**
+ * Attach $is to this stream.
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ $this->_bound[] = $is;
+
+ return $this;
+ }
+
+ /**
+ * Remove an already bound stream.
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ foreach ($this->_bound as $k => $stream) {
+ if ($stream === $is) {
+ unset($this->_bound[$k]);
+
+ return;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function flushBuffers()
+ {
+ $this->reset();
+
+ return $this;
+ }
+
+ /**
+ * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256.
+ *
+ * @param string $hash
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setHashAlgorithm($hash)
+ {
+ $this->_hashAlgorithm = 'rsa-sha1';
+
+ return $this;
+ }
+
+ /**
+ * Set the canonicalization algorithm.
+ *
+ * @param string $canon simple | nofws defaults to simple
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setCanon($canon)
+ {
+ if ($canon == 'nofws') {
+ $this->_canon = 'nofws';
+ } else {
+ $this->_canon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signer identity.
+ *
+ * @param string $identity
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setSignerIdentity($identity)
+ {
+ $this->_signerIdentity = $identity;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders.
+ *
+ * @param bool $debug
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ /**
+ * Start Body.
+ */
+ public function startBody()
+ {
+ }
+
+ /**
+ * End Body.
+ */
+ public function endBody()
+ {
+ $this->_endOfBody();
+ }
+
+ /**
+ * Returns the list of Headers Tampered by this plugin.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ if ($this->_debugHeaders) {
+ return array('DomainKey-Signature', 'X-DebugHash');
+ }
+
+ return array('DomainKey-Signature');
+ }
+
+ /**
+ * Adds an ignored Header.
+ *
+ * @param string $header_name
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function ignoreHeader($header_name)
+ {
+ $this->_ignoredHeaders[strtolower($header_name)] = true;
+
+ return $this;
+ }
+
+ /**
+ * Set the headers to sign.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $this->_startHash();
+ $this->_canonData = '';
+ // Loop through Headers
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (!isset($this->_ignoredHeaders[strtolower($hName)])) {
+ if ($headers->has($hName)) {
+ $tmp = $headers->getAll($hName);
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $this->_addHeader($header->toString());
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+ $this->_endOfHeaders();
+
+ return $this;
+ }
+
+ /**
+ * Add the signature to the given Headers.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ // Prepare the DomainKey-Signature Header
+ $params = array('a' => $this->_hashAlgorithm, 'b' => chunk_split(base64_encode($this->_getEncryptedHash()), 73, ' '), 'c' => $this->_canon, 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'q' => 'dns', 's' => $this->_selector);
+ $string = '';
+ foreach ($params as $k => $v) {
+ $string .= $k.'='.$v.'; ';
+ }
+ $string = trim($string);
+ $headers->addTextHeader('DomainKey-Signature', $string);
+
+ return $this;
+ }
+
+ /* Private helpers */
+
+ protected function _addHeader($header)
+ {
+ switch ($this->_canon) {
+ case 'nofws':
+ // Prepare Header and cascade
+ $exploded = explode(':', $header, 2);
+ $name = strtolower(trim($exploded[0]));
+ $value = str_replace("\r\n", '', $exploded[1]);
+ $value = preg_replace("/[ \t][ \t]+/", ' ', $value);
+ $header = $name.':'.trim($value)."\r\n";
+ case 'simple':
+ // Nothing to do
+ }
+ $this->_addToHash($header);
+ }
+
+ protected function _endOfHeaders()
+ {
+ $this->_bodyCanonEmptyCounter = 1;
+ }
+
+ protected function _canonicalizeBody($string)
+ {
+ $len = strlen($string);
+ $canon = '';
+ $nofws = ($this->_canon == 'nofws');
+ for ($i = 0; $i < $len; ++$i) {
+ if ($this->_bodyCanonIgnoreStart > 0) {
+ --$this->_bodyCanonIgnoreStart;
+ continue;
+ }
+ switch ($string[$i]) {
+ case "\r":
+ $this->_bodyCanonLastChar = "\r";
+ break;
+ case "\n":
+ if ($this->_bodyCanonLastChar == "\r") {
+ if ($nofws) {
+ $this->_bodyCanonSpace = false;
+ }
+ if ($this->_bodyCanonLine == '') {
+ ++$this->_bodyCanonEmptyCounter;
+ } else {
+ $this->_bodyCanonLine = '';
+ $canon .= "\r\n";
+ }
+ } else {
+ // Wooops Error
+ throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r');
+ }
+ break;
+ case ' ':
+ case "\t":
+ case "\x09": //HTAB
+ if ($nofws) {
+ $this->_bodyCanonSpace = true;
+ break;
+ }
+ default:
+ if ($this->_bodyCanonEmptyCounter > 0) {
+ $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter);
+ $this->_bodyCanonEmptyCounter = 0;
+ }
+ $this->_bodyCanonLine .= $string[$i];
+ $canon .= $string[$i];
+ }
+ }
+ $this->_addToHash($canon);
+ }
+
+ protected function _endOfBody()
+ {
+ if (strlen($this->_bodyCanonLine) > 0) {
+ $this->_addToHash("\r\n");
+ }
+ $this->_hash = hash_final($this->_hashHandler, true);
+ }
+
+ private function _addToHash($string)
+ {
+ $this->_canonData .= $string;
+ hash_update($this->_hashHandler, $string);
+ }
+
+ private function _startHash()
+ {
+ // Init
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha1':
+ $this->_hashHandler = hash_init('sha1');
+ break;
+ }
+ $this->_bodyCanonLine = '';
+ }
+
+ /**
+ * @throws Swift_SwiftException
+ *
+ * @return string
+ */
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ $pkeyId = openssl_get_privatekey($this->_privateKey);
+ if (!$pkeyId) {
+ throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']');
+ }
+ if (openssl_sign($this->_canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) {
+ return $signature;
+ }
+ throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php
new file mode 100644
index 00000000..c75cb08a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php
@@ -0,0 +1,65 @@
+
+ */
+interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream
+{
+ /**
+ * Exclude an header from the signed headers.
+ *
+ * @param string $header_name
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function ignoreHeader($header_name);
+
+ /**
+ * Prepare the Signer to get a new Body.
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function startBody();
+
+ /**
+ * Give the signal that the body has finished streaming.
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function endBody();
+
+ /**
+ * Give the headers already given.
+ *
+ * @param Swift_Mime_SimpleHeaderSet $headers
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers);
+
+ /**
+ * Add the header(s) to the headerSet.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers);
+
+ /**
+ * Return the list of header a signer might tamper.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php
new file mode 100644
index 00000000..3a35ad55
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php
@@ -0,0 +1,190 @@
+
+ */
+class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner
+{
+ private $_peclLoaded = false;
+
+ private $_dkimHandler = null;
+
+ private $dropFirstLF = true;
+
+ const CANON_RELAXED = 1;
+ const CANON_SIMPLE = 2;
+ const SIG_RSA_SHA1 = 3;
+ const SIG_RSA_SHA256 = 4;
+
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ if (!extension_loaded('opendkim')) {
+ throw new Swift_SwiftException('php-opendkim extension not found');
+ }
+
+ $this->_peclLoaded = true;
+
+ parent::__construct($privateKey, $domainName, $selector);
+ }
+
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature');
+ $headerVal = $this->_dkimHandler->getSignatureHeader();
+ if (!$headerVal) {
+ throw new Swift_SwiftException('OpenDKIM Error: '.$this->_dkimHandler->getError());
+ }
+ $header->setValue($headerVal);
+ $headers->set($header);
+
+ return $this;
+ }
+
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $bodyLen = $this->_bodyLen;
+ if (is_bool($bodyLen)) {
+ $bodyLen = -1;
+ }
+ $hash = $this->_hashAlgorithm == 'rsa-sha1' ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256;
+ $bodyCanon = $this->_bodyCanon == 'simple' ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
+ $headerCanon = $this->_headerCanon == 'simple' ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
+ $this->_dkimHandler = new OpenDKIMSign($this->_privateKey, $this->_selector, $this->_domainName, $headerCanon, $bodyCanon, $hash, $bodyLen);
+ // Hardcode signature Margin for now
+ $this->_dkimHandler->setMargin(78);
+
+ if (!is_numeric($this->_signatureTimestamp)) {
+ OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time());
+ } else {
+ if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->_signatureTimestamp)) {
+ throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']');
+ }
+ }
+ if (isset($this->_signerIdentity)) {
+ $this->_dkimHandler->setSigner($this->_signerIdentity);
+ }
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (!isset($this->_ignoredHeaders[strtolower($hName)])) {
+ $tmp = $headers->getAll($hName);
+ if ($headers->has($hName)) {
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $htosign = $header->toString();
+ $this->_dkimHandler->header($htosign);
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ public function startBody()
+ {
+ if (!$this->_peclLoaded) {
+ return parent::startBody();
+ }
+ $this->dropFirstLF = true;
+ $this->_dkimHandler->eoh();
+
+ return $this;
+ }
+
+ public function endBody()
+ {
+ if (!$this->_peclLoaded) {
+ return parent::endBody();
+ }
+ $this->_dkimHandler->eom();
+
+ return $this;
+ }
+
+ public function reset()
+ {
+ $this->_dkimHandler = null;
+ parent::reset();
+
+ return $this;
+ }
+
+ /**
+ * Set the signature timestamp.
+ *
+ * @param int $time
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureTimestamp($time)
+ {
+ $this->_signatureTimestamp = $time;
+
+ return $this;
+ }
+
+ /**
+ * Set the signature expiration timestamp.
+ *
+ * @param int $time
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureExpiration($time)
+ {
+ $this->_signatureExpiration = $time;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders.
+ *
+ * @param bool $debug
+ *
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ // Protected
+
+ protected function _canonicalizeBody($string)
+ {
+ if (!$this->_peclLoaded) {
+ return parent::_canonicalizeBody($string);
+ }
+ if (false && $this->dropFirstLF === true) {
+ if ($string[0] == "\r" && $string[1] == "\n") {
+ $string = substr($string, 2);
+ }
+ }
+ $this->dropFirstLF = false;
+ if (strlen($string)) {
+ $this->_dkimHandler->body($string);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php
new file mode 100644
index 00000000..b267099a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php
@@ -0,0 +1,436 @@
+
+ */
+class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner
+{
+ protected $signCertificate;
+ protected $signPrivateKey;
+ protected $encryptCert;
+ protected $signThenEncrypt = true;
+ protected $signLevel;
+ protected $encryptLevel;
+ protected $signOptions;
+ protected $encryptOptions;
+ protected $encryptCipher;
+ protected $extraCerts = null;
+
+ /**
+ * @var Swift_StreamFilters_StringReplacementFilterFactory
+ */
+ protected $replacementFactory;
+
+ /**
+ * @var Swift_Mime_HeaderFactory
+ */
+ protected $headerFactory;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $signCertificate
+ * @param string|null $signPrivateKey
+ * @param string|null $encryptCertificate
+ */
+ public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null)
+ {
+ if (null !== $signPrivateKey) {
+ $this->setSignCertificate($signCertificate, $signPrivateKey);
+ }
+
+ if (null !== $encryptCertificate) {
+ $this->setEncryptCertificate($encryptCertificate);
+ }
+
+ $this->replacementFactory = Swift_DependencyContainer::getInstance()
+ ->lookup('transport.replacementfactory');
+
+ $this->signOptions = PKCS7_DETACHED;
+
+ // Supported since php5.4
+ if (defined('OPENSSL_CIPHER_AES_128_CBC')) {
+ $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC;
+ } else {
+ $this->encryptCipher = OPENSSL_CIPHER_RC2_128;
+ }
+ }
+
+ /**
+ * Returns an new Swift_Signers_SMimeSigner instance.
+ *
+ * @param string $certificate
+ * @param string $privateKey
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public static function newInstance($certificate = null, $privateKey = null)
+ {
+ return new self($certificate, $privateKey);
+ }
+
+ /**
+ * Set the certificate location to use for signing.
+ *
+ * @link http://www.php.net/manual/en/openssl.pkcs7.flags.php
+ *
+ * @param string $certificate
+ * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead
+ * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign()
+ * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null)
+ {
+ $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate));
+
+ if (null !== $privateKey) {
+ if (is_array($privateKey)) {
+ $this->signPrivateKey = $privateKey;
+ $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0]));
+ } else {
+ $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey));
+ }
+ }
+
+ $this->signOptions = $signOptions;
+ if (null !== $extraCerts) {
+ $this->extraCerts = str_replace('\\', '/', realpath($extraCerts));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the certificate location to use for encryption.
+ *
+ * @link http://www.php.net/manual/en/openssl.pkcs7.flags.php
+ * @link http://nl3.php.net/manual/en/openssl.ciphers.php
+ *
+ * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates.
+ * @param int $cipher
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setEncryptCertificate($recipientCerts, $cipher = null)
+ {
+ if (is_array($recipientCerts)) {
+ $this->encryptCert = array();
+
+ foreach ($recipientCerts as $cert) {
+ $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert));
+ }
+ } else {
+ $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts));
+ }
+
+ if (null !== $cipher) {
+ $this->encryptCipher = $cipher;
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSignCertificate()
+ {
+ return $this->signCertificate;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSignPrivateKey()
+ {
+ return $this->signPrivateKey;
+ }
+
+ /**
+ * Set perform signing before encryption.
+ *
+ * The default is to first sign the message and then encrypt.
+ * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted.
+ * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients.
+ *
+ * @param bool $signThenEncrypt
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setSignThenEncrypt($signThenEncrypt = true)
+ {
+ $this->signThenEncrypt = $signThenEncrypt;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSignThenEncrypt()
+ {
+ return $this->signThenEncrypt;
+ }
+
+ /**
+ * Resets internal states.
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function reset()
+ {
+ return $this;
+ }
+
+ /**
+ * Change the Swift_Message to apply the signing.
+ *
+ * @param Swift_Message $message
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function signMessage(Swift_Message $message)
+ {
+ if (null === $this->signCertificate && null === $this->encryptCert) {
+ return $this;
+ }
+
+ // Store the message using ByteStream to a file{1}
+ // Remove all Children
+ // Sign file{1}, parse the new MIME headers and set them on the primary MimeEntity
+ // Set the singed-body as the new body (without boundary)
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $this->toSMimeByteStream($messageStream, $message);
+ $message->setEncoder(Swift_DependencyContainer::getInstance()->lookup('mime.rawcontentencoder'));
+
+ $message->setChildren(array());
+ $this->streamToMime($messageStream, $message);
+ }
+
+ /**
+ * Return the list of header a signer might tamper.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ return array('Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition');
+ }
+
+ /**
+ * @param Swift_InputByteStream $inputStream
+ * @param Swift_Message $mimeEntity
+ */
+ protected function toSMimeByteStream(Swift_InputByteStream $inputStream, Swift_Message $message)
+ {
+ $mimeEntity = $this->createMessage($message);
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ $mimeEntity->toByteStream($messageStream);
+ $messageStream->commit();
+
+ if (null !== $this->signCertificate && null !== $this->encryptCert) {
+ $temporaryStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if ($this->signThenEncrypt) {
+ $this->messageStreamToSignedByteStream($messageStream, $temporaryStream);
+ $this->messageStreamToEncryptedByteStream($temporaryStream, $inputStream);
+ } else {
+ $this->messageStreamToEncryptedByteStream($messageStream, $temporaryStream);
+ $this->messageStreamToSignedByteStream($temporaryStream, $inputStream);
+ }
+ } elseif ($this->signCertificate !== null) {
+ $this->messageStreamToSignedByteStream($messageStream, $inputStream);
+ } else {
+ $this->messageStreamToEncryptedByteStream($messageStream, $inputStream);
+ }
+ }
+
+ /**
+ * @param Swift_Message $message
+ *
+ * @return Swift_Message
+ */
+ protected function createMessage(Swift_Message $message)
+ {
+ $mimeEntity = new Swift_Message('', $message->getBody(), $message->getContentType(), $message->getCharset());
+ $mimeEntity->setChildren($message->getChildren());
+
+ $messageHeaders = $mimeEntity->getHeaders();
+ $messageHeaders->remove('Message-ID');
+ $messageHeaders->remove('Date');
+ $messageHeaders->remove('Subject');
+ $messageHeaders->remove('MIME-Version');
+ $messageHeaders->remove('To');
+ $messageHeaders->remove('From');
+
+ return $mimeEntity;
+ }
+
+ /**
+ * @param Swift_FileStream $outputStream
+ * @param Swift_InputByteStream $inputStream
+ *
+ * @throws Swift_IoException
+ */
+ protected function messageStreamToSignedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $inputStream)
+ {
+ $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ $args = array($outputStream->getPath(), $signedMessageStream->getPath(), $this->signCertificate, $this->signPrivateKey, array(), $this->signOptions);
+ if (null !== $this->extraCerts) {
+ $args[] = $this->extraCerts;
+ }
+
+ if (!call_user_func_array('openssl_pkcs7_sign', $args)) {
+ throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string()));
+ }
+
+ $this->copyFromOpenSSLOutput($signedMessageStream, $inputStream);
+ }
+
+ /**
+ * @param Swift_FileStream $outputStream
+ * @param Swift_InputByteStream $is
+ *
+ * @throws Swift_IoException
+ */
+ protected function messageStreamToEncryptedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $is)
+ {
+ $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_encrypt($outputStream->getPath(), $encryptedMessageStream->getPath(), $this->encryptCert, array(), 0, $this->encryptCipher)) {
+ throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string()));
+ }
+
+ $this->copyFromOpenSSLOutput($encryptedMessageStream, $is);
+ }
+
+ /**
+ * @param Swift_OutputByteStream $fromStream
+ * @param Swift_InputByteStream $toStream
+ */
+ protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream)
+ {
+ $bufferLength = 4096;
+ $filteredStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
+ $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $filteredStream->write($buffer);
+ }
+
+ $filteredStream->flushBuffers();
+
+ while (false !== ($buffer = $filteredStream->read($bufferLength))) {
+ $toStream->write($buffer);
+ }
+
+ $toStream->commit();
+ }
+
+ /**
+ * Merges an OutputByteStream to Swift_Message.
+ *
+ * @param Swift_OutputByteStream $fromStream
+ * @param Swift_Message $message
+ */
+ protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message)
+ {
+ $bufferLength = 78;
+ $headerData = '';
+
+ $fromStream->setReadPointer(0);
+
+ while (($buffer = $fromStream->read($bufferLength)) !== false) {
+ $headerData .= $buffer;
+
+ if (false !== strpos($buffer, "\r\n\r\n")) {
+ break;
+ }
+ }
+
+ $headersPosEnd = strpos($headerData, "\r\n\r\n");
+ $headerData = trim($headerData);
+ $headerData = substr($headerData, 0, $headersPosEnd);
+ $headerLines = explode("\r\n", $headerData);
+ unset($headerData);
+
+ $headers = array();
+ $currentHeaderName = '';
+
+ foreach ($headerLines as $headerLine) {
+ // Line separated
+ if (ctype_space($headerLines[0]) || false === strpos($headerLine, ':')) {
+ $headers[$currentHeaderName] .= ' '.trim($headerLine);
+ continue;
+ }
+
+ $header = explode(':', $headerLine, 2);
+ $currentHeaderName = strtolower($header[0]);
+ $headers[$currentHeaderName] = trim($header[1]);
+ }
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $messageStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
+ $messageStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
+
+ $messageHeaders = $message->getHeaders();
+
+ // No need to check for 'application/pkcs7-mime', as this is always base64
+ if ('multipart/signed;' === substr($headers['content-type'], 0, 17)) {
+ if (!preg_match('/boundary=("[^"]+"|(?:[^\s]+|$))/is', $headers['content-type'], $contentTypeData)) {
+ throw new Swift_SwiftException('Failed to find Boundary parameter');
+ }
+
+ $boundary = trim($contentTypeData['1'], '"');
+
+ // Skip the header and CRLF CRLF
+ $fromStream->setReadPointer($headersPosEnd + 4);
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $messageStream->write($buffer);
+ }
+
+ $messageStream->commit();
+
+ $messageHeaders->remove('Content-Transfer-Encoding');
+ $message->setContentType($headers['content-type']);
+ $message->setBoundary($boundary);
+ $message->setBody($messageStream);
+ } else {
+ $fromStream->setReadPointer($headersPosEnd + 4);
+
+ if (null === $this->headerFactory) {
+ $this->headerFactory = Swift_DependencyContainer::getInstance()->lookup('mime.headerfactory');
+ }
+
+ $message->setContentType($headers['content-type']);
+ $messageHeaders->set($this->headerFactory->createTextHeader('Content-Transfer-Encoding', $headers['content-transfer-encoding']));
+ $messageHeaders->set($this->headerFactory->createTextHeader('Content-Disposition', $headers['content-disposition']));
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $messageStream->write($buffer);
+ }
+
+ $messageStream->commit();
+ $message->setBody($messageStream);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php
new file mode 100644
index 00000000..62516114
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php
@@ -0,0 +1,58 @@
+createDependenciesFor('transport.smtp')
+ );
+
+ $this->setHost($host);
+ $this->setPort($port);
+ $this->setEncryption($security);
+ }
+
+ /**
+ * Create a new SmtpTransport instance.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $security
+ *
+ * @return Swift_SmtpTransport
+ */
+ public static function newInstance($host = 'localhost', $port = 25, $security = null)
+ {
+ return new self($host, $port, $security);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php
new file mode 100644
index 00000000..c16ab4b3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for spools.
+ *
+ * @author Fabien Potencier
+ */
+interface Swift_Spool
+{
+ /**
+ * Starts this Spool mechanism.
+ */
+ public function start();
+
+ /**
+ * Stops this Spool mechanism.
+ */
+ public function stop();
+
+ /**
+ * Tests if this Spool mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted();
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return bool Whether the operation has succeeded
+ */
+ public function queueMessage(Swift_Mime_Message $message);
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null);
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php
new file mode 100644
index 00000000..cf9bf78f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_SpoolTransport extends Swift_Transport_SpoolTransport
+{
+ /**
+ * Create a new SpoolTransport.
+ *
+ * @param Swift_Spool $spool
+ */
+ public function __construct(Swift_Spool $spool)
+ {
+ $arguments = Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.spool');
+
+ $arguments[] = $spool;
+
+ call_user_func_array(
+ array($this, 'Swift_Transport_SpoolTransport::__construct'),
+ $arguments
+ );
+ }
+
+ /**
+ * Create a new SpoolTransport instance.
+ *
+ * @param Swift_Spool $spool
+ *
+ * @return Swift_SpoolTransport
+ */
+ public static function newInstance(Swift_Spool $spool)
+ {
+ return new self($spool);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php
new file mode 100644
index 00000000..362be2e8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php
@@ -0,0 +1,35 @@
+_search = $search;
+ $this->_index = array();
+ $this->_tree = array();
+ $this->_replace = array();
+ $this->_repSize = array();
+
+ $tree = null;
+ $i = null;
+ $last_size = $size = 0;
+ foreach ($search as $i => $search_element) {
+ if ($tree !== null) {
+ $tree[-1] = min(count($replace) - 1, $i - 1);
+ $tree[-2] = $last_size;
+ }
+ $tree = &$this->_tree;
+ if (is_array($search_element)) {
+ foreach ($search_element as $k => $char) {
+ $this->_index[$char] = true;
+ if (!isset($tree[$char])) {
+ $tree[$char] = array();
+ }
+ $tree = &$tree[$char];
+ }
+ $last_size = $k + 1;
+ $size = max($size, $last_size);
+ } else {
+ $last_size = 1;
+ if (!isset($tree[$search_element])) {
+ $tree[$search_element] = array();
+ }
+ $tree = &$tree[$search_element];
+ $size = max($last_size, $size);
+ $this->_index[$search_element] = true;
+ }
+ }
+ if ($i !== null) {
+ $tree[-1] = min(count($replace) - 1, $i);
+ $tree[-2] = $last_size;
+ $this->_treeMaxLen = $size;
+ }
+ foreach ($replace as $rep) {
+ if (!is_array($rep)) {
+ $rep = array($rep);
+ }
+ $this->_replace[] = $rep;
+ }
+ for ($i = count($this->_replace) - 1; $i >= 0; --$i) {
+ $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
+ $this->_repSize[$i] = count($rep);
+ }
+ }
+
+ /**
+ * Returns true if based on the buffer passed more bytes should be buffered.
+ *
+ * @param array $buffer
+ *
+ * @return bool
+ */
+ public function shouldBuffer($buffer)
+ {
+ $endOfBuffer = end($buffer);
+
+ return isset($this->_index[$endOfBuffer]);
+ }
+
+ /**
+ * Perform the actual replacements on $buffer and return the result.
+ *
+ * @param array $buffer
+ * @param int $_minReplaces
+ *
+ * @return array
+ */
+ public function filter($buffer, $_minReplaces = -1)
+ {
+ if ($this->_treeMaxLen == 0) {
+ return $buffer;
+ }
+
+ $newBuffer = array();
+ $buf_size = count($buffer);
+ $last_size = 0;
+ for ($i = 0; $i < $buf_size; ++$i) {
+ $search_pos = $this->_tree;
+ $last_found = PHP_INT_MAX;
+ // We try to find if the next byte is part of a search pattern
+ for ($j = 0; $j <= $this->_treeMaxLen; ++$j) {
+ // We have a new byte for a search pattern
+ if (isset($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]])) {
+ $search_pos = $search_pos[$buffer[$p]];
+ // We have a complete pattern, save, in case we don't find a better match later
+ if (isset($search_pos[-1]) && $search_pos[-1] < $last_found
+ && $search_pos[-1] > $_minReplaces) {
+ $last_found = $search_pos[-1];
+ $last_size = $search_pos[-2];
+ }
+ }
+ // We got a complete pattern
+ elseif ($last_found !== PHP_INT_MAX) {
+ // Adding replacement datas to output buffer
+ $rep_size = $this->_repSize[$last_found];
+ for ($j = 0; $j < $rep_size; ++$j) {
+ $newBuffer[] = $this->_replace[$last_found][$j];
+ }
+ // We Move cursor forward
+ $i += $last_size - 1;
+ // Edge Case, last position in buffer
+ if ($i >= $buf_size) {
+ $newBuffer[] = $buffer[$i];
+ }
+
+ // We start the next loop
+ continue 2;
+ } else {
+ // this byte is not in a pattern and we haven't found another pattern
+ break;
+ }
+ }
+ // Normal byte, move it to output buffer
+ $newBuffer[] = $buffer[$i];
+ }
+
+ return $newBuffer;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php
new file mode 100644
index 00000000..d0db8b96
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php
@@ -0,0 +1,66 @@
+_search = $search;
+ $this->_replace = $replace;
+ }
+
+ /**
+ * Returns true if based on the buffer passed more bytes should be buffered.
+ *
+ * @param string $buffer
+ *
+ * @return bool
+ */
+ public function shouldBuffer($buffer)
+ {
+ $endOfBuffer = substr($buffer, -1);
+ foreach ((array) $this->_search as $needle) {
+ if (false !== strpos($needle, $endOfBuffer)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Perform the actual replacements on $buffer and return the result.
+ *
+ * @param string $buffer
+ *
+ * @return string
+ */
+ public function filter($buffer)
+ {
+ return str_replace($this->_search, $this->_replace, $buffer);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
new file mode 100644
index 00000000..e98240b5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
@@ -0,0 +1,45 @@
+_filters[$search][$replace])) {
+ if (!isset($this->_filters[$search])) {
+ $this->_filters[$search] = array();
+ }
+
+ if (!isset($this->_filters[$search][$replace])) {
+ $this->_filters[$search][$replace] = array();
+ }
+
+ $this->_filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace);
+ }
+
+ return $this->_filters[$search][$replace];
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php
new file mode 100644
index 00000000..db3d3109
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php
@@ -0,0 +1,29 @@
+_eventDispatcher = $dispatcher;
+ $this->_buffer = $buf;
+ $this->_lookupHostname();
+ }
+
+ /**
+ * Set the name of the local domain which Swift will identify itself as.
+ *
+ * This should be a fully-qualified domain name and should be truly the domain
+ * you're using.
+ *
+ * If your server doesn't have a domain name, use the IP in square
+ * brackets (i.e. [127.0.0.1]).
+ *
+ * @param string $domain
+ *
+ * @return Swift_Transport_AbstractSmtpTransport
+ */
+ public function setLocalDomain($domain)
+ {
+ $this->_domain = $domain;
+
+ return $this;
+ }
+
+ /**
+ * Get the name of the domain Swift will identify as.
+ *
+ * @return string
+ */
+ public function getLocalDomain()
+ {
+ return $this->_domain;
+ }
+
+ /**
+ * Sets the source IP.
+ *
+ * @param string $source
+ */
+ public function setSourceIp($source)
+ {
+ $this->_sourceIp = $source;
+ }
+
+ /**
+ * Returns the IP used to connect to the destination.
+ *
+ * @return string
+ */
+ public function getSourceIp()
+ {
+ return $this->_sourceIp;
+ }
+
+ /**
+ * Start the SMTP connection.
+ */
+ public function start()
+ {
+ if (!$this->_started) {
+ if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted');
+ if ($evt->bubbleCancelled()) {
+ return;
+ }
+ }
+
+ try {
+ $this->_buffer->initialize($this->_getBufferParams());
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ $this->_readGreeting();
+ $this->_doHeloCommand();
+
+ if ($evt) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'transportStarted');
+ }
+
+ $this->_started = true;
+ }
+ }
+
+ /**
+ * Test if an SMTP connection has been established.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return $this->_started;
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $sent = 0;
+ $failedRecipients = (array) $failedRecipients;
+
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if (!$reversePath = $this->_getReversePath($message)) {
+ $this->_throwException(new Swift_TransportException(
+ 'Cannot send message without a sender address'
+ )
+ );
+ }
+
+ $to = (array) $message->getTo();
+ $cc = (array) $message->getCc();
+ $tos = array_merge($to, $cc);
+ $bcc = (array) $message->getBcc();
+
+ $message->setBcc(array());
+
+ try {
+ $sent += $this->_sendTo($message, $reversePath, $tos, $failedRecipients);
+ $sent += $this->_sendBcc($message, $reversePath, $bcc, $failedRecipients);
+ } catch (Exception $e) {
+ $message->setBcc($bcc);
+ throw $e;
+ }
+
+ $message->setBcc($bcc);
+
+ if ($evt) {
+ if ($sent == count($to) + count($cc) + count($bcc)) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ } elseif ($sent > 0) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE);
+ } else {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
+ }
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId(); //Make sure a new Message ID is used
+
+ return $sent;
+ }
+
+ /**
+ * Stop the SMTP connection.
+ */
+ public function stop()
+ {
+ if ($this->_started) {
+ if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped');
+ if ($evt->bubbleCancelled()) {
+ return;
+ }
+ }
+
+ try {
+ $this->executeCommand("QUIT\r\n", array(221));
+ } catch (Swift_TransportException $e) {
+ }
+
+ try {
+ $this->_buffer->terminate();
+
+ if ($evt) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'transportStopped');
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ }
+ $this->_started = false;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+
+ /**
+ * Reset the current mail transaction.
+ */
+ public function reset()
+ {
+ $this->executeCommand("RSET\r\n", array(250));
+ }
+
+ /**
+ * Get the IoBuffer where read/writes are occurring.
+ *
+ * @return Swift_Transport_IoBuffer
+ */
+ public function getBuffer()
+ {
+ return $this->_buffer;
+ }
+
+ /**
+ * Run a command against the buffer, expecting the given response codes.
+ *
+ * If no response codes are given, the response will not be validated.
+ * If codes are given, an exception will be thrown on an invalid response.
+ *
+ * @param string $command
+ * @param int[] $codes
+ * @param string[] $failures An array of failures by-reference
+ *
+ * @return string
+ */
+ public function executeCommand($command, $codes = array(), &$failures = null)
+ {
+ $failures = (array) $failures;
+ $seq = $this->_buffer->write($command);
+ $response = $this->_getFullResponse($seq);
+ if ($evt = $this->_eventDispatcher->createCommandEvent($this, $command, $codes)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'commandSent');
+ }
+ $this->_assertResponseCode($response, $codes);
+
+ return $response;
+ }
+
+ /** Read the opening SMTP greeting */
+ protected function _readGreeting()
+ {
+ $this->_assertResponseCode($this->_getFullResponse(0), array(220));
+ }
+
+ /** Send the HELO welcome */
+ protected function _doHeloCommand()
+ {
+ $this->executeCommand(
+ sprintf("HELO %s\r\n", $this->_domain), array(250)
+ );
+ }
+
+ /** Send the MAIL FROM command */
+ protected function _doMailFromCommand($address)
+ {
+ $this->executeCommand(
+ sprintf("MAIL FROM:<%s>\r\n", $address), array(250)
+ );
+ }
+
+ /** Send the RCPT TO command */
+ protected function _doRcptToCommand($address)
+ {
+ $this->executeCommand(
+ sprintf("RCPT TO:<%s>\r\n", $address), array(250, 251, 252)
+ );
+ }
+
+ /** Send the DATA command */
+ protected function _doDataCommand()
+ {
+ $this->executeCommand("DATA\r\n", array(354));
+ }
+
+ /** Stream the contents of the message over the buffer */
+ protected function _streamMessage(Swift_Mime_Message $message)
+ {
+ $this->_buffer->setWriteTranslations(array("\r\n." => "\r\n.."));
+ try {
+ $message->toByteStream($this->_buffer);
+ $this->_buffer->flushBuffers();
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ $this->_buffer->setWriteTranslations(array());
+ $this->executeCommand("\r\n.\r\n", array(250));
+ }
+
+ /** Determine the best-use reverse path for this message */
+ protected function _getReversePath(Swift_Mime_Message $message)
+ {
+ $return = $message->getReturnPath();
+ $sender = $message->getSender();
+ $from = $message->getFrom();
+ $path = null;
+ if (!empty($return)) {
+ $path = $return;
+ } elseif (!empty($sender)) {
+ // Don't use array_keys
+ reset($sender); // Reset Pointer to first pos
+ $path = key($sender); // Get key
+ } elseif (!empty($from)) {
+ reset($from); // Reset Pointer to first pos
+ $path = key($from); // Get key
+ }
+
+ return $path;
+ }
+
+ /** Throw a TransportException, first sending it to any listeners */
+ protected function _throwException(Swift_TransportException $e)
+ {
+ if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
+ if (!$evt->bubbleCancelled()) {
+ throw $e;
+ }
+ } else {
+ throw $e;
+ }
+ }
+
+ /** Throws an Exception if a response code is incorrect */
+ protected function _assertResponseCode($response, $wanted)
+ {
+ list($code) = sscanf($response, '%3d');
+ $valid = (empty($wanted) || in_array($code, $wanted));
+
+ if ($evt = $this->_eventDispatcher->createResponseEvent($this, $response,
+ $valid)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'responseReceived');
+ }
+
+ if (!$valid) {
+ $this->_throwException(
+ new Swift_TransportException(
+ 'Expected response code '.implode('/', $wanted).' but got code '.
+ '"'.$code.'", with message "'.$response.'"',
+ $code)
+ );
+ }
+ }
+
+ /** Get an entire multi-line response using its sequence number */
+ protected function _getFullResponse($seq)
+ {
+ $response = '';
+ try {
+ do {
+ $line = $this->_buffer->readLine($seq);
+ $response .= $line;
+ } while (null !== $line && false !== $line && ' ' != $line{3});
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ } catch (Swift_IoException $e) {
+ $this->_throwException(
+ new Swift_TransportException(
+ $e->getMessage())
+ );
+ }
+
+ return $response;
+ }
+
+ /** Send an email to the given recipients from the given reverse path */
+ private function _doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients)
+ {
+ $sent = 0;
+ $this->_doMailFromCommand($reversePath);
+ foreach ($recipients as $forwardPath) {
+ try {
+ $this->_doRcptToCommand($forwardPath);
+ ++$sent;
+ } catch (Swift_TransportException $e) {
+ $failedRecipients[] = $forwardPath;
+ }
+ }
+
+ if ($sent != 0) {
+ $this->_doDataCommand();
+ $this->_streamMessage($message);
+ } else {
+ $this->reset();
+ }
+
+ return $sent;
+ }
+
+ /** Send a message to the given To: recipients */
+ private function _sendTo(Swift_Mime_Message $message, $reversePath, array $to, array &$failedRecipients)
+ {
+ if (empty($to)) {
+ return 0;
+ }
+
+ return $this->_doMailTransaction($message, $reversePath, array_keys($to),
+ $failedRecipients);
+ }
+
+ /** Send a message to all Bcc: recipients */
+ private function _sendBcc(Swift_Mime_Message $message, $reversePath, array $bcc, array &$failedRecipients)
+ {
+ $sent = 0;
+ foreach ($bcc as $forwardPath => $name) {
+ $message->setBcc(array($forwardPath => $name));
+ $sent += $this->_doMailTransaction(
+ $message, $reversePath, array($forwardPath), $failedRecipients
+ );
+ }
+
+ return $sent;
+ }
+
+ /** Try to determine the hostname of the server this is run on */
+ private function _lookupHostname()
+ {
+ if (!empty($_SERVER['SERVER_NAME']) && $this->_isFqdn($_SERVER['SERVER_NAME'])) {
+ $this->_domain = $_SERVER['SERVER_NAME'];
+ } elseif (!empty($_SERVER['SERVER_ADDR'])) {
+ // Set the address literal tag (See RFC 5321, section: 4.1.3)
+ if (false === strpos($_SERVER['SERVER_ADDR'], ':')) {
+ $prefix = ''; // IPv4 addresses are not tagged.
+ } else {
+ $prefix = 'IPv6:'; // Adding prefix in case of IPv6.
+ }
+
+ $this->_domain = sprintf('[%s%s]', $prefix, $_SERVER['SERVER_ADDR']);
+ }
+ }
+
+ /** Determine is the $hostname is a fully-qualified name */
+ private function _isFqdn($hostname)
+ {
+ // We could do a really thorough check, but there's really no point
+ if (false !== $dotPos = strpos($hostname, '.')) {
+ return ($dotPos > 0) && ($dotPos != strlen($hostname) - 1);
+ }
+
+ return false;
+ }
+
+ /**
+ * Destructor.
+ */
+ public function __destruct()
+ {
+ $this->stop();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
new file mode 100644
index 00000000..53f721d0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
@@ -0,0 +1,81 @@
+executeCommand("AUTH CRAM-MD5\r\n", array(334));
+ $challenge = base64_decode(substr($challenge, 4));
+ $message = base64_encode(
+ $username.' '.$this->_getResponse($password, $challenge)
+ );
+ $agent->executeCommand(sprintf("%s\r\n", $message), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ /**
+ * Generate a CRAM-MD5 response from a server challenge.
+ *
+ * @param string $secret
+ * @param string $challenge
+ *
+ * @return string
+ */
+ private function _getResponse($secret, $challenge)
+ {
+ if (strlen($secret) > 64) {
+ $secret = pack('H32', md5($secret));
+ }
+
+ if (strlen($secret) < 64) {
+ $secret = str_pad($secret, 64, chr(0));
+ }
+
+ $k_ipad = substr($secret, 0, 64) ^ str_repeat(chr(0x36), 64);
+ $k_opad = substr($secret, 0, 64) ^ str_repeat(chr(0x5C), 64);
+
+ $inner = pack('H32', md5($k_ipad.$challenge));
+ $digest = md5($k_opad.$inner);
+
+ return $digest;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
new file mode 100644
index 00000000..6ab6e333
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
@@ -0,0 +1,51 @@
+executeCommand("AUTH LOGIN\r\n", array(334));
+ $agent->executeCommand(sprintf("%s\r\n", base64_encode($username)), array(334));
+ $agent->executeCommand(sprintf("%s\r\n", base64_encode($password)), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php
new file mode 100644
index 00000000..eb04acf0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php
@@ -0,0 +1,720 @@
+
+ */
+class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ const NTLMSIG = "NTLMSSP\x00";
+ const DESCONST = 'KGS!@#$%';
+
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'NTLM';
+ }
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
+ {
+ if (!function_exists('openssl_random_pseudo_bytes') || !function_exists('openssl_encrypt')) {
+ throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.');
+ }
+
+ if (!function_exists('bcmul')) {
+ throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.');
+ }
+
+ try {
+ // execute AUTH command and filter out the code at the beginning
+ // AUTH NTLM xxxx
+ $response = base64_decode(substr(trim($this->sendMessage1($agent)), 4));
+
+ // extra parameters for our unit cases
+ $timestamp = func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000'));
+ $client = func_num_args() > 4 ? func_get_arg(4) : $this->getRandomBytes(8);
+
+ // Message 3 response
+ $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent);
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ protected function si2bin($si, $bits = 32)
+ {
+ $bin = null;
+ if ($si >= -pow(2, $bits - 1) && ($si <= pow(2, $bits - 1))) {
+ // positive or zero
+ if ($si >= 0) {
+ $bin = base_convert($si, 10, 2);
+ // pad to $bits bit
+ $bin_length = strlen($bin);
+ if ($bin_length < $bits) {
+ $bin = str_repeat('0', $bits - $bin_length).$bin;
+ }
+ } else {
+ // negative
+ $si = -$si - pow(2, $bits);
+ $bin = base_convert($si, 10, 2);
+ $bin_length = strlen($bin);
+ if ($bin_length > $bits) {
+ $bin = str_repeat('1', $bits - $bin_length).$bin;
+ }
+ }
+ }
+
+ return $bin;
+ }
+
+ /**
+ * Send our auth message and returns the response.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ *
+ * @return string SMTP Response
+ */
+ protected function sendMessage1(Swift_Transport_SmtpAgent $agent)
+ {
+ $message = $this->createMessage1();
+
+ return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), array(334));
+ }
+
+ /**
+ * Fetch all details of our response (message 2).
+ *
+ * @param string $response
+ *
+ * @return array our response parsed
+ */
+ protected function parseMessage2($response)
+ {
+ $responseHex = bin2hex($response);
+ $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2;
+ $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2;
+ $challenge = $this->hex2bin(substr($responseHex, 48, 16));
+ $context = $this->hex2bin(substr($responseHex, 64, 16));
+ $targetInfoH = $this->hex2bin(substr($responseHex, 80, 16));
+ $targetName = $this->hex2bin(substr($responseHex, $offset, $length));
+ $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2;
+ $targetInfoBlock = substr($responseHex, $offset);
+ list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock);
+
+ return array(
+ $challenge,
+ $context,
+ $targetInfoH,
+ $targetName,
+ $domainName,
+ $serverName,
+ $DNSDomainName,
+ $DNSServerName,
+ $this->hex2bin($targetInfoBlock),
+ $terminatorByte,
+ );
+ }
+
+ /**
+ * Read the blob information in from message2.
+ *
+ * @param $block
+ *
+ * @return array
+ */
+ protected function readSubBlock($block)
+ {
+ // remove terminatorByte cause it's always the same
+ $block = substr($block, 0, -8);
+
+ $length = strlen($block);
+ $offset = 0;
+ $data = array();
+ while ($offset < $length) {
+ $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256;
+ $offset += 8;
+ $data[] = $this->hex2bin(substr($block, $offset, $blockLength * 2));
+ $offset += $blockLength * 2;
+ }
+
+ if (count($data) == 3) {
+ $data[] = $data[2];
+ $data[2] = '';
+ }
+
+ $data[] = $this->createByte('00');
+
+ return $data;
+ }
+
+ /**
+ * Send our final message with all our data.
+ *
+ * @param string $response Message 1 response (message 2)
+ * @param string $username
+ * @param string $password
+ * @param string $timestamp
+ * @param string $client
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param bool $v2 Use version2 of the protocol
+ *
+ * @return string
+ */
+ protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true)
+ {
+ list($domain, $username) = $this->getDomainAndUsername($username);
+ //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter
+ list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response);
+
+ if (!$v2) {
+ // LMv1
+ $lmResponse = $this->createLMPassword($password, $challenge);
+ // NTLMv1
+ $ntlmResponse = $this->createNTLMPassword($password, $challenge);
+ } else {
+ // LMv2
+ $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client);
+ // NTLMv2
+ $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client);
+ }
+
+ $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse);
+
+ return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), array(235));
+ }
+
+ /**
+ * Create our message 1.
+ *
+ * @return string
+ */
+ protected function createMessage1()
+ {
+ return self::NTLMSIG
+ .$this->createByte('01') // Message 1
+.$this->createByte('0702'); // Flags
+ }
+
+ /**
+ * Create our message 3.
+ *
+ * @param string $domain
+ * @param string $username
+ * @param string $workstation
+ * @param string $lmResponse
+ * @param string $ntlmResponse
+ *
+ * @return string
+ */
+ protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse)
+ {
+ // Create security buffers
+ $domainSec = $this->createSecurityBuffer($domain, 64);
+ $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec));
+ $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2);
+ $userInfo = $this->readSecurityBuffer(bin2hex($userSec));
+ $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2);
+ $workInfo = $this->readSecurityBuffer(bin2hex($workSec));
+ $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true);
+ $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec));
+ $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true);
+
+ return self::NTLMSIG
+ .$this->createByte('03') // TYPE 3 message
+.$lmSec // LM response header
+.$ntlmSec // NTLM response header
+.$domainSec // Domain header
+.$userSec // User header
+.$workSec // Workstation header
+.$this->createByte('000000009a', 8) // session key header (empty)
+.$this->createByte('01020000') // FLAGS
+.$this->convertTo16bit($domain) // domain name
+.$this->convertTo16bit($username) // username
+.$this->convertTo16bit($workstation) // workstation
+.$lmResponse
+ .$ntlmResponse;
+ }
+
+ /**
+ * @param string $timestamp Epoch timestamp in microseconds
+ * @param string $client Random bytes
+ * @param string $targetInfo
+ *
+ * @return string
+ */
+ protected function createBlob($timestamp, $client, $targetInfo)
+ {
+ return $this->createByte('0101')
+ .$this->createByte('00')
+ .$timestamp
+ .$client
+ .$this->createByte('00')
+ .$targetInfo
+ .$this->createByte('00');
+ }
+
+ /**
+ * Get domain and username from our username.
+ *
+ * @example DOMAIN\username
+ *
+ * @param string $name
+ *
+ * @return array
+ */
+ protected function getDomainAndUsername($name)
+ {
+ if (strpos($name, '\\') !== false) {
+ return explode('\\', $name);
+ }
+
+ list($user, $domain) = explode('@', $name);
+
+ return array($domain, $user);
+ }
+
+ /**
+ * Create LMv1 response.
+ *
+ * @param string $password
+ * @param string $challenge
+ *
+ * @return string
+ */
+ protected function createLMPassword($password, $challenge)
+ {
+ // FIRST PART
+ $password = $this->createByte(strtoupper($password), 14, false);
+ list($key1, $key2) = str_split($password, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+
+ $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false);
+
+ // SECOND PART
+ list($key1, $key2, $key3) = str_split($constantDecrypt, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+ $desKey3 = $this->createDesKey($key3);
+
+ return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
+ }
+
+ /**
+ * Create NTLMv1 response.
+ *
+ * @param string $password
+ * @param string $challenge
+ *
+ * @return string
+ */
+ protected function createNTLMPassword($password, $challenge)
+ {
+ // FIRST PART
+ $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false);
+ list($key1, $key2, $key3) = str_split($ntlmHash, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+ $desKey3 = $this->createDesKey($key3);
+
+ return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
+ }
+
+ /**
+ * Convert a normal timestamp to a tenth of a microtime epoch time.
+ *
+ * @param string $time
+ *
+ * @return string
+ */
+ protected function getCorrectTimestamp($time)
+ {
+ // Get our timestamp (tricky!)
+ bcscale(0);
+
+ $time = number_format($time, 0, '.', ''); // save microtime to string
+ $time = bcadd($time, '11644473600000'); // add epoch time
+ $time = bcmul($time, 10000); // tenths of a microsecond.
+
+ $binary = $this->si2bin($time, 64); // create 64 bit binary string
+ $timestamp = '';
+ for ($i = 0; $i < 8; ++$i) {
+ $timestamp .= chr(bindec(substr($binary, -(($i + 1) * 8), 8)));
+ }
+
+ return $timestamp;
+ }
+
+ /**
+ * Create LMv2 response.
+ *
+ * @param string $password
+ * @param string $username
+ * @param string $domain
+ * @param string $challenge NTLM Challenge
+ * @param string $client Random string
+ *
+ * @return string
+ */
+ protected function createLMv2Password($password, $username, $domain, $challenge, $client)
+ {
+ $lmPass = '00'; // by default 00
+ // if $password > 15 than we can't use this method
+ if (strlen($password) <= 15) {
+ $ntlmHash = $this->md4Encrypt($password);
+ $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
+
+ $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client);
+ }
+
+ return $this->createByte($lmPass, 24);
+ }
+
+ /**
+ * Create NTLMv2 response.
+ *
+ * @param string $password
+ * @param string $username
+ * @param string $domain
+ * @param string $challenge Hex values
+ * @param string $targetInfo Hex values
+ * @param string $timestamp
+ * @param string $client Random bytes
+ *
+ * @return string
+ *
+ * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse
+ */
+ protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client)
+ {
+ $ntlmHash = $this->md4Encrypt($password);
+ $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
+
+ // create blob
+ $blob = $this->createBlob($timestamp, $client, $targetInfo);
+
+ $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob);
+
+ return $ntlmv2Response.$blob;
+ }
+
+ protected function createDesKey($key)
+ {
+ $material = array(bin2hex($key[0]));
+ $len = strlen($key);
+ for ($i = 1; $i < $len; ++$i) {
+ list($high, $low) = str_split(bin2hex($key[$i]));
+ $v = $this->castToByte(ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i));
+ $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte
+ }
+ $material[] = str_pad(substr(dechex($this->castToByte(ord($key[6]) << 1)), -2), 2, '0');
+
+ // odd parity
+ foreach ($material as $k => $v) {
+ $b = $this->castToByte(hexdec($v));
+ $needsParity = (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5)
+ ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2)
+ ^ $this->uRShift($b, 1)) & 0x01) == 0;
+
+ list($high, $low) = str_split($v);
+ if ($needsParity) {
+ $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1);
+ } else {
+ $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe);
+ }
+ }
+
+ return $this->hex2bin(implode('', $material));
+ }
+
+ /** HELPER FUNCTIONS */
+ /**
+ * Create our security buffer depending on length and offset.
+ *
+ * @param string $value Value we want to put in
+ * @param int $offset start of value
+ * @param bool $is16 Do we 16bit string or not?
+ *
+ * @return string
+ */
+ protected function createSecurityBuffer($value, $offset, $is16 = false)
+ {
+ $length = strlen(bin2hex($value));
+ $length = $is16 ? $length / 2 : $length;
+ $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2);
+
+ return $length.$length.$this->createByte(dechex($offset), 4);
+ }
+
+ /**
+ * Read our security buffer to fetch length and offset of our value.
+ *
+ * @param string $value Securitybuffer in hex
+ *
+ * @return array array with length and offset
+ */
+ protected function readSecurityBuffer($value)
+ {
+ $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2;
+ $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2;
+
+ return array($length, $offset);
+ }
+
+ /**
+ * Cast to byte java equivalent to (byte).
+ *
+ * @param int $v
+ *
+ * @return int
+ */
+ protected function castToByte($v)
+ {
+ return (($v + 128) % 256) - 128;
+ }
+
+ /**
+ * Java unsigned right bitwise
+ * $a >>> $b.
+ *
+ * @param int $a
+ * @param int $b
+ *
+ * @return int
+ */
+ protected function uRShift($a, $b)
+ {
+ if ($b == 0) {
+ return $a;
+ }
+
+ return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1));
+ }
+
+ /**
+ * Right padding with 0 to certain length.
+ *
+ * @param string $input
+ * @param int $bytes Length of bytes
+ * @param bool $isHex Did we provided hex value
+ *
+ * @return string
+ */
+ protected function createByte($input, $bytes = 4, $isHex = true)
+ {
+ if ($isHex) {
+ $byte = $this->hex2bin(str_pad($input, $bytes * 2, '00'));
+ } else {
+ $byte = str_pad($input, $bytes, "\x00");
+ }
+
+ return $byte;
+ }
+
+ /**
+ * Create random bytes.
+ *
+ * @param $length
+ *
+ * @return string
+ */
+ protected function getRandomBytes($length)
+ {
+ $bytes = openssl_random_pseudo_bytes($length, $strong);
+
+ if (false !== $bytes && true === $strong) {
+ return $bytes;
+ }
+
+ throw new RuntimeException('OpenSSL did not produce a secure random number.');
+ }
+
+ /** ENCRYPTION ALGORITHMS */
+ /**
+ * DES Encryption.
+ *
+ * @param string $value An 8-byte string
+ * @param string $key
+ *
+ * @return string
+ */
+ protected function desEncrypt($value, $key)
+ {
+ // 1 == OPENSSL_RAW_DATA - but constant is only available as of PHP 5.4.
+ return substr(openssl_encrypt($value, 'DES-ECB', $key, 1), 0, 8);
+ }
+
+ /**
+ * MD5 Encryption.
+ *
+ * @param string $key Encryption key
+ * @param string $msg Message to encrypt
+ *
+ * @return string
+ */
+ protected function md5Encrypt($key, $msg)
+ {
+ $blocksize = 64;
+ if (strlen($key) > $blocksize) {
+ $key = pack('H*', md5($key));
+ }
+
+ $key = str_pad($key, $blocksize, "\0");
+ $ipadk = $key ^ str_repeat("\x36", $blocksize);
+ $opadk = $key ^ str_repeat("\x5c", $blocksize);
+
+ return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg))));
+ }
+
+ /**
+ * MD4 Encryption.
+ *
+ * @param string $input
+ *
+ * @return string
+ *
+ * @see http://php.net/manual/en/ref.hash.php
+ */
+ protected function md4Encrypt($input)
+ {
+ $input = $this->convertTo16bit($input);
+
+ return function_exists('hash') ? $this->hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input);
+ }
+
+ /**
+ * Convert UTF-8 to UTF-16.
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ protected function convertTo16bit($input)
+ {
+ return iconv('UTF-8', 'UTF-16LE', $input);
+ }
+
+ /**
+ * Hex2bin replacement for < PHP 5.4.
+ *
+ * @param string $hex
+ *
+ * @return string Binary
+ */
+ protected function hex2bin($hex)
+ {
+ if (function_exists('hex2bin')) {
+ return hex2bin($hex);
+ } else {
+ return pack('H*', $hex);
+ }
+ }
+
+ /**
+ * @param string $message
+ */
+ protected function debug($message)
+ {
+ $message = bin2hex($message);
+ $messageId = substr($message, 16, 8);
+ echo substr($message, 0, 16)." NTLMSSP Signature
\n";
+ echo $messageId." Type Indicator
\n";
+
+ if ($messageId == '02000000') {
+ $map = array(
+ 'Challenge',
+ 'Context',
+ 'Target Information Security Buffer',
+ 'Target Name Data',
+ 'NetBIOS Domain Name',
+ 'NetBIOS Server Name',
+ 'DNS Domain Name',
+ 'DNS Server Name',
+ 'BLOB',
+ 'Target Information Terminator',
+ );
+
+ $data = $this->parseMessage2($this->hex2bin($message));
+
+ foreach ($map as $key => $value) {
+ echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n";
+ }
+ } elseif ($messageId == '03000000') {
+ $i = 0;
+ $data[$i++] = substr($message, 24, 16);
+ list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 40, 16);
+ list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 56, 16);
+ list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 72, 16);
+ list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 88, 16);
+ list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 104, 16);
+ $data[$i++] = substr($message, 120, 8);
+ $data[$i++] = substr($message, $targetOffset, $targetLength);
+ $data[$i++] = substr($message, $userOffset, $userLength);
+ $data[$i++] = substr($message, $workOffset, $workLength);
+ $data[$i++] = substr($message, $lmOffset, $lmLength);
+ $data[$i] = substr($message, $ntmlOffset, $ntmlLength);
+
+ $map = array(
+ 'LM Response Security Buffer',
+ 'NTLM Response Security Buffer',
+ 'Target Name Security Buffer',
+ 'User Name Security Buffer',
+ 'Workstation Name Security Buffer',
+ 'Session Key Security Buffer',
+ 'Flags',
+ 'Target Name Data',
+ 'User Name Data',
+ 'Workstation Name Data',
+ 'LM Response Data',
+ 'NTLM Response Data',
+ );
+
+ foreach ($map as $key => $value) {
+ echo $data[$key].' - '.$this->hex2bin($data[$key]).' ||| '.$value."
\n";
+ }
+ }
+
+ echo '
';
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
new file mode 100644
index 00000000..43219f93
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
@@ -0,0 +1,50 @@
+executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php
new file mode 100644
index 00000000..ca35e7b8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php
@@ -0,0 +1,70 @@
+
+ * $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 587, 'tls')
+ * ->setAuthMode('XOAUTH2')
+ * ->setUsername('YOUR_EMAIL_ADDRESS')
+ * ->setPassword('YOUR_ACCESS_TOKEN');
+ *
+ *
+ * @author xu.li
+ *
+ * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol
+ */
+class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'XOAUTH2';
+ }
+
+ /**
+ * Try to authenticate the user with $email and $token.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $email
+ * @param string $token
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token)
+ {
+ try {
+ $param = $this->constructXOAuth2Params($email, $token);
+ $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ /**
+ * Construct the auth parameter.
+ *
+ * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism
+ */
+ protected function constructXOAuth2Params($email, $token)
+ {
+ return base64_encode("user=$email\1auth=Bearer $token\1\1");
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php
new file mode 100644
index 00000000..cb36133c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php
@@ -0,0 +1,263 @@
+setAuthenticators($authenticators);
+ }
+
+ /**
+ * Set the Authenticators which can process a login request.
+ *
+ * @param Swift_Transport_Esmtp_Authenticator[] $authenticators
+ */
+ public function setAuthenticators(array $authenticators)
+ {
+ $this->_authenticators = $authenticators;
+ }
+
+ /**
+ * Get the Authenticators which can process a login request.
+ *
+ * @return Swift_Transport_Esmtp_Authenticator[]
+ */
+ public function getAuthenticators()
+ {
+ return $this->_authenticators;
+ }
+
+ /**
+ * Set the username to authenticate with.
+ *
+ * @param string $username
+ */
+ public function setUsername($username)
+ {
+ $this->_username = $username;
+ }
+
+ /**
+ * Get the username to authenticate with.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->_username;
+ }
+
+ /**
+ * Set the password to authenticate with.
+ *
+ * @param string $password
+ */
+ public function setPassword($password)
+ {
+ $this->_password = $password;
+ }
+
+ /**
+ * Get the password to authenticate with.
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->_password;
+ }
+
+ /**
+ * Set the auth mode to use to authenticate.
+ *
+ * @param string $mode
+ */
+ public function setAuthMode($mode)
+ {
+ $this->_auth_mode = $mode;
+ }
+
+ /**
+ * Get the auth mode to use to authenticate.
+ *
+ * @return string
+ */
+ public function getAuthMode()
+ {
+ return $this->_auth_mode;
+ }
+
+ /**
+ * Get the name of the ESMTP extension this handles.
+ *
+ * @return bool
+ */
+ public function getHandledKeyword()
+ {
+ return 'AUTH';
+ }
+
+ /**
+ * Set the parameters which the EHLO greeting indicated.
+ *
+ * @param string[] $parameters
+ */
+ public function setKeywordParams(array $parameters)
+ {
+ $this->_esmtpParams = $parameters;
+ }
+
+ /**
+ * Runs immediately after a EHLO has been issued.
+ *
+ * @param Swift_Transport_SmtpAgent $agent to read/write
+ */
+ public function afterEhlo(Swift_Transport_SmtpAgent $agent)
+ {
+ if ($this->_username) {
+ $count = 0;
+ foreach ($this->_getAuthenticatorsForAgent() as $authenticator) {
+ if (in_array(strtolower($authenticator->getAuthKeyword()),
+ array_map('strtolower', $this->_esmtpParams))) {
+ ++$count;
+ if ($authenticator->authenticate($agent, $this->_username, $this->_password)) {
+ return;
+ }
+ }
+ }
+ throw new Swift_TransportException(
+ 'Failed to authenticate on SMTP server with username "'.
+ $this->_username.'" using '.$count.' possible authenticators'
+ );
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function getMailParams()
+ {
+ return array();
+ }
+
+ /**
+ * Not used.
+ */
+ public function getRcptParams()
+ {
+ return array();
+ }
+
+ /**
+ * Not used.
+ */
+ public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false)
+ {
+ }
+
+ /**
+ * Returns +1, -1 or 0 according to the rules for usort().
+ *
+ * This method is called to ensure extensions can be execute in an appropriate order.
+ *
+ * @param string $esmtpKeyword to compare with
+ *
+ * @return int
+ */
+ public function getPriorityOver($esmtpKeyword)
+ {
+ return 0;
+ }
+
+ /**
+ * Returns an array of method names which are exposed to the Esmtp class.
+ *
+ * @return string[]
+ */
+ public function exposeMixinMethods()
+ {
+ return array('setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode');
+ }
+
+ /**
+ * Not used.
+ */
+ public function resetState()
+ {
+ }
+
+ /**
+ * Returns the authenticator list for the given agent.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ *
+ * @return array
+ */
+ protected function _getAuthenticatorsForAgent()
+ {
+ if (!$mode = strtolower($this->_auth_mode)) {
+ return $this->_authenticators;
+ }
+
+ foreach ($this->_authenticators as $authenticator) {
+ if (strtolower($authenticator->getAuthKeyword()) == $mode) {
+ return array($authenticator);
+ }
+ }
+
+ throw new Swift_TransportException('Auth mode '.$mode.' is invalid');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php
new file mode 100644
index 00000000..12a9abf8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php
@@ -0,0 +1,35 @@
+.
+ *
+ * @return string[]
+ */
+ public function getMailParams();
+
+ /**
+ * Get params which are appended to RCPT TO:<>.
+ *
+ * @return string[]
+ */
+ public function getRcptParams();
+
+ /**
+ * Runs when a command is due to be sent.
+ *
+ * @param Swift_Transport_SmtpAgent $agent to read/write
+ * @param string $command to send
+ * @param int[] $codes expected in response
+ * @param string[] $failedRecipients to collect failures
+ * @param bool $stop to be set true by-reference if the command is now sent
+ */
+ public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false);
+
+ /**
+ * Returns +1, -1 or 0 according to the rules for usort().
+ *
+ * This method is called to ensure extensions can be execute in an appropriate order.
+ *
+ * @param string $esmtpKeyword to compare with
+ *
+ * @return int
+ */
+ public function getPriorityOver($esmtpKeyword);
+
+ /**
+ * Returns an array of method names which are exposed to the Esmtp class.
+ *
+ * @return string[]
+ */
+ public function exposeMixinMethods();
+
+ /**
+ * Tells this handler to clear any buffers and reset its state.
+ */
+ public function resetState();
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php
new file mode 100644
index 00000000..4106df41
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php
@@ -0,0 +1,413 @@
+ 'tcp',
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'timeout' => 30,
+ 'blocking' => 1,
+ 'tls' => false,
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
+ 'stream_context_options' => array(),
+ );
+
+ /**
+ * Creates a new EsmtpTransport using the given I/O buffer.
+ *
+ * @param Swift_Transport_IoBuffer $buf
+ * @param Swift_Transport_EsmtpHandler[] $extensionHandlers
+ * @param Swift_Events_EventDispatcher $dispatcher
+ */
+ public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher)
+ {
+ parent::__construct($buf, $dispatcher);
+ $this->setExtensionHandlers($extensionHandlers);
+ }
+
+ /**
+ * Set the host to connect to.
+ *
+ * @param string $host
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setHost($host)
+ {
+ $this->_params['host'] = $host;
+
+ return $this;
+ }
+
+ /**
+ * Get the host to connect to.
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->_params['host'];
+ }
+
+ /**
+ * Set the port to connect to.
+ *
+ * @param int $port
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setPort($port)
+ {
+ $this->_params['port'] = (int) $port;
+
+ return $this;
+ }
+
+ /**
+ * Get the port to connect to.
+ *
+ * @return int
+ */
+ public function getPort()
+ {
+ return $this->_params['port'];
+ }
+
+ /**
+ * Set the connection timeout.
+ *
+ * @param int $timeout seconds
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setTimeout($timeout)
+ {
+ $this->_params['timeout'] = (int) $timeout;
+ $this->_buffer->setParam('timeout', (int) $timeout);
+
+ return $this;
+ }
+
+ /**
+ * Get the connection timeout.
+ *
+ * @return int
+ */
+ public function getTimeout()
+ {
+ return $this->_params['timeout'];
+ }
+
+ /**
+ * Set the encryption type (tls or ssl).
+ *
+ * @param string $encryption
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setEncryption($encryption)
+ {
+ $encryption = strtolower($encryption);
+ if ('tls' == $encryption) {
+ $this->_params['protocol'] = 'tcp';
+ $this->_params['tls'] = true;
+ } else {
+ $this->_params['protocol'] = $encryption;
+ $this->_params['tls'] = false;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the encryption type.
+ *
+ * @return string
+ */
+ public function getEncryption()
+ {
+ return $this->_params['tls'] ? 'tls' : $this->_params['protocol'];
+ }
+
+ /**
+ * Sets the stream context options.
+ *
+ * @param array $options
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setStreamOptions($options)
+ {
+ $this->_params['stream_context_options'] = $options;
+
+ return $this;
+ }
+
+ /**
+ * Returns the stream context options.
+ *
+ * @return array
+ */
+ public function getStreamOptions()
+ {
+ return $this->_params['stream_context_options'];
+ }
+
+ /**
+ * Sets the source IP.
+ *
+ * @param string $source
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setSourceIp($source)
+ {
+ $this->_params['sourceIp'] = $source;
+
+ return $this;
+ }
+
+ /**
+ * Returns the IP used to connect to the destination.
+ *
+ * @return string
+ */
+ public function getSourceIp()
+ {
+ return isset($this->_params['sourceIp']) ? $this->_params['sourceIp'] : null;
+ }
+
+ /**
+ * Set ESMTP extension handlers.
+ *
+ * @param Swift_Transport_EsmtpHandler[] $handlers
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setExtensionHandlers(array $handlers)
+ {
+ $assoc = array();
+ foreach ($handlers as $handler) {
+ $assoc[$handler->getHandledKeyword()] = $handler;
+ }
+
+ @uasort($assoc, array($this, '_sortHandlers'));
+ $this->_handlers = $assoc;
+ $this->_setHandlerParams();
+
+ return $this;
+ }
+
+ /**
+ * Get ESMTP extension handlers.
+ *
+ * @return Swift_Transport_EsmtpHandler[]
+ */
+ public function getExtensionHandlers()
+ {
+ return array_values($this->_handlers);
+ }
+
+ /**
+ * Run a command against the buffer, expecting the given response codes.
+ *
+ * If no response codes are given, the response will not be validated.
+ * If codes are given, an exception will be thrown on an invalid response.
+ *
+ * @param string $command
+ * @param int[] $codes
+ * @param string[] $failures An array of failures by-reference
+ *
+ * @return string
+ */
+ public function executeCommand($command, $codes = array(), &$failures = null)
+ {
+ $failures = (array) $failures;
+ $stopSignal = false;
+ $response = null;
+ foreach ($this->_getActiveHandlers() as $handler) {
+ $response = $handler->onCommand(
+ $this, $command, $codes, $failures, $stopSignal
+ );
+ if ($stopSignal) {
+ return $response;
+ }
+ }
+
+ return parent::executeCommand($command, $codes, $failures);
+ }
+
+ // -- Mixin invocation code
+
+ /** Mixin handling method for ESMTP handlers */
+ public function __call($method, $args)
+ {
+ foreach ($this->_handlers as $handler) {
+ if (in_array(strtolower($method),
+ array_map('strtolower', (array) $handler->exposeMixinMethods())
+ )) {
+ $return = call_user_func_array(array($handler, $method), $args);
+ // Allow fluid method calls
+ if (is_null($return) && substr($method, 0, 3) == 'set') {
+ return $this;
+ } else {
+ return $return;
+ }
+ }
+ }
+ trigger_error('Call to undefined method '.$method, E_USER_ERROR);
+ }
+
+ /** Get the params to initialize the buffer */
+ protected function _getBufferParams()
+ {
+ return $this->_params;
+ }
+
+ /** Overridden to perform EHLO instead */
+ protected function _doHeloCommand()
+ {
+ try {
+ $response = $this->executeCommand(
+ sprintf("EHLO %s\r\n", $this->_domain), array(250)
+ );
+ } catch (Swift_TransportException $e) {
+ return parent::_doHeloCommand();
+ }
+
+ if ($this->_params['tls']) {
+ try {
+ $this->executeCommand("STARTTLS\r\n", array(220));
+
+ if (!$this->_buffer->startTLS()) {
+ throw new Swift_TransportException('Unable to connect with TLS encryption');
+ }
+
+ try {
+ $response = $this->executeCommand(
+ sprintf("EHLO %s\r\n", $this->_domain), array(250)
+ );
+ } catch (Swift_TransportException $e) {
+ return parent::_doHeloCommand();
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ }
+
+ $this->_capabilities = $this->_getCapabilities($response);
+ $this->_setHandlerParams();
+ foreach ($this->_getActiveHandlers() as $handler) {
+ $handler->afterEhlo($this);
+ }
+ }
+
+ /** Overridden to add Extension support */
+ protected function _doMailFromCommand($address)
+ {
+ $handlers = $this->_getActiveHandlers();
+ $params = array();
+ foreach ($handlers as $handler) {
+ $params = array_merge($params, (array) $handler->getMailParams());
+ }
+ $paramStr = !empty($params) ? ' '.implode(' ', $params) : '';
+ $this->executeCommand(
+ sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), array(250)
+ );
+ }
+
+ /** Overridden to add Extension support */
+ protected function _doRcptToCommand($address)
+ {
+ $handlers = $this->_getActiveHandlers();
+ $params = array();
+ foreach ($handlers as $handler) {
+ $params = array_merge($params, (array) $handler->getRcptParams());
+ }
+ $paramStr = !empty($params) ? ' '.implode(' ', $params) : '';
+ $this->executeCommand(
+ sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), array(250, 251, 252)
+ );
+ }
+
+ /** Determine ESMTP capabilities by function group */
+ private function _getCapabilities($ehloResponse)
+ {
+ $capabilities = array();
+ $ehloResponse = trim($ehloResponse);
+ $lines = explode("\r\n", $ehloResponse);
+ array_shift($lines);
+ foreach ($lines as $line) {
+ if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) {
+ $keyword = strtoupper($matches[1]);
+ $paramStr = strtoupper(ltrim($matches[2], ' ='));
+ $params = !empty($paramStr) ? explode(' ', $paramStr) : array();
+ $capabilities[$keyword] = $params;
+ }
+ }
+
+ return $capabilities;
+ }
+
+ /** Set parameters which are used by each extension handler */
+ private function _setHandlerParams()
+ {
+ foreach ($this->_handlers as $keyword => $handler) {
+ if (array_key_exists($keyword, $this->_capabilities)) {
+ $handler->setKeywordParams($this->_capabilities[$keyword]);
+ }
+ }
+ }
+
+ /** Get ESMTP handlers which are currently ok to use */
+ private function _getActiveHandlers()
+ {
+ $handlers = array();
+ foreach ($this->_handlers as $keyword => $handler) {
+ if (array_key_exists($keyword, $this->_capabilities)) {
+ $handlers[] = $handler;
+ }
+ }
+
+ return $handlers;
+ }
+
+ /** Custom sort for extension handler ordering */
+ private function _sortHandlers($a, $b)
+ {
+ return $a->getPriorityOver($b->getHandledKeyword());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php
new file mode 100644
index 00000000..311a0f2a
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php
@@ -0,0 +1,88 @@
+_transports);
+ $sent = 0;
+ $this->_lastUsedTransport = null;
+
+ for ($i = 0; $i < $maxTransports
+ && $transport = $this->_getNextTransport(); ++$i) {
+ try {
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+
+ if ($sent = $transport->send($message, $failedRecipients)) {
+ $this->_lastUsedTransport = $transport;
+
+ return $sent;
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_killCurrentTransport();
+ }
+ }
+
+ if (count($this->_transports) == 0) {
+ throw new Swift_TransportException(
+ 'All Transports in FailoverTransport failed, or no Transports available'
+ );
+ }
+
+ return $sent;
+ }
+
+ protected function _getNextTransport()
+ {
+ if (!isset($this->_currentTransport)) {
+ $this->_currentTransport = parent::_getNextTransport();
+ }
+
+ return $this->_currentTransport;
+ }
+
+ protected function _killCurrentTransport()
+ {
+ $this->_currentTransport = null;
+ parent::_killCurrentTransport();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php
new file mode 100644
index 00000000..af97adf1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php
@@ -0,0 +1,67 @@
+_transports = $transports;
+ $this->_deadTransports = array();
+ }
+
+ /**
+ * Get $transports to delegate to.
+ *
+ * @return Swift_Transport[]
+ */
+ public function getTransports()
+ {
+ return array_merge($this->_transports, $this->_deadTransports);
+ }
+
+ /**
+ * Get the Transport used in the last successful send operation.
+ *
+ * @return Swift_Transport
+ */
+ public function getLastUsedTransport()
+ {
+ return $this->_lastUsedTransport;
+ }
+
+ /**
+ * Test if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return count($this->_transports) > 0;
+ }
+
+ /**
+ * Start this Transport mechanism.
+ */
+ public function start()
+ {
+ $this->_transports = array_merge($this->_transports, $this->_deadTransports);
+ }
+
+ /**
+ * Stop this Transport mechanism.
+ */
+ public function stop()
+ {
+ foreach ($this->_transports as $transport) {
+ $transport->stop();
+ }
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $maxTransports = count($this->_transports);
+ $sent = 0;
+ $this->_lastUsedTransport = null;
+
+ for ($i = 0; $i < $maxTransports
+ && $transport = $this->_getNextTransport(); ++$i) {
+ try {
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+ if ($sent = $transport->send($message, $failedRecipients)) {
+ $this->_lastUsedTransport = $transport;
+ break;
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_killCurrentTransport();
+ }
+ }
+
+ if (count($this->_transports) == 0) {
+ throw new Swift_TransportException(
+ 'All Transports in LoadBalancedTransport failed, or no Transports available'
+ );
+ }
+
+ return $sent;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ foreach ($this->_transports as $transport) {
+ $transport->registerPlugin($plugin);
+ }
+ }
+
+ /**
+ * Rotates the transport list around and returns the first instance.
+ *
+ * @return Swift_Transport
+ */
+ protected function _getNextTransport()
+ {
+ if ($next = array_shift($this->_transports)) {
+ $this->_transports[] = $next;
+ }
+
+ return $next;
+ }
+
+ /**
+ * Tag the currently used (top of stack) transport as dead/useless.
+ */
+ protected function _killCurrentTransport()
+ {
+ if ($transport = array_pop($this->_transports)) {
+ try {
+ $transport->stop();
+ } catch (Exception $e) {
+ }
+ $this->_deadTransports[] = $transport;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php
new file mode 100644
index 00000000..77489ced
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php
@@ -0,0 +1,32 @@
+_invoker = $invoker;
+ $this->_eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Not used.
+ */
+ public function isStarted()
+ {
+ return false;
+ }
+
+ /**
+ * Not used.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Set the additional parameters used on the mail() function.
+ *
+ * This string is formatted for sprintf() where %s is the sender address.
+ *
+ * @param string $params
+ *
+ * @return Swift_Transport_MailTransport
+ */
+ public function setExtraParams($params)
+ {
+ $this->_extraParams = $params;
+
+ return $this;
+ }
+
+ /**
+ * Get the additional parameters used on the mail() function.
+ *
+ * This string is formatted for sprintf() where %s is the sender address.
+ *
+ * @return string
+ */
+ public function getExtraParams()
+ {
+ return $this->_extraParams;
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ $count = (
+ count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ );
+
+ $toHeader = $message->getHeaders()->get('To');
+ $subjectHeader = $message->getHeaders()->get('Subject');
+
+ if (0 === $count) {
+ $this->_throwException(new Swift_TransportException('Cannot send message without a recipient'));
+ }
+ $to = $toHeader ? $toHeader->getFieldBody() : '';
+ $subject = $subjectHeader ? $subjectHeader->getFieldBody() : '';
+
+ $reversePath = $this->_getReversePath($message);
+
+ // Remove headers that would otherwise be duplicated
+ $message->getHeaders()->remove('To');
+ $message->getHeaders()->remove('Subject');
+
+ $messageStr = $message->toString();
+
+ if ($toHeader) {
+ $message->getHeaders()->set($toHeader);
+ }
+ $message->getHeaders()->set($subjectHeader);
+
+ // Separate headers from body
+ if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) {
+ $headers = substr($messageStr, 0, $endHeaders)."\r\n"; //Keep last EOL
+ $body = substr($messageStr, $endHeaders + 4);
+ } else {
+ $headers = $messageStr."\r\n";
+ $body = '';
+ }
+
+ unset($messageStr);
+
+ if ("\r\n" != PHP_EOL) {
+ // Non-windows (not using SMTP)
+ $headers = str_replace("\r\n", PHP_EOL, $headers);
+ $subject = str_replace("\r\n", PHP_EOL, $subject);
+ $body = str_replace("\r\n", PHP_EOL, $body);
+ } else {
+ // Windows, using SMTP
+ $headers = str_replace("\r\n.", "\r\n..", $headers);
+ $subject = str_replace("\r\n.", "\r\n..", $subject);
+ $body = str_replace("\r\n.", "\r\n..", $body);
+ }
+
+ if ($this->_invoker->mail($to, $subject, $body, $headers, $this->_formatExtraParams($this->_extraParams, $reversePath))) {
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+ } else {
+ $failedRecipients = array_merge(
+ $failedRecipients,
+ array_keys((array) $message->getTo()),
+ array_keys((array) $message->getCc()),
+ array_keys((array) $message->getBcc())
+ );
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId();
+
+ $count = 0;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+
+ /** Throw a TransportException, first sending it to any listeners */
+ protected function _throwException(Swift_TransportException $e)
+ {
+ if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
+ if (!$evt->bubbleCancelled()) {
+ throw $e;
+ }
+ } else {
+ throw $e;
+ }
+ }
+
+ /** Determine the best-use reverse path for this message */
+ private function _getReversePath(Swift_Mime_Message $message)
+ {
+ $return = $message->getReturnPath();
+ $sender = $message->getSender();
+ $from = $message->getFrom();
+ $path = null;
+ if (!empty($return)) {
+ $path = $return;
+ } elseif (!empty($sender)) {
+ $keys = array_keys($sender);
+ $path = array_shift($keys);
+ } elseif (!empty($from)) {
+ $keys = array_keys($from);
+ $path = array_shift($keys);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Fix CVE-2016-10074 by disallowing potentially unsafe shell characters.
+ *
+ * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
+ *
+ * @param string $string The string to be validated
+ *
+ * @return bool
+ */
+ private function _isShellSafe($string)
+ {
+ // Future-proof
+ if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))) {
+ return false;
+ }
+
+ $length = strlen($string);
+ for ($i = 0; $i < $length; ++$i) {
+ $c = $string[$i];
+ // All other characters have a special meaning in at least one common shell, including = and +.
+ // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
+ // Note that this does permit non-Latin alphanumeric characters based on the current locale.
+ if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Return php mail extra params to use for invoker->mail.
+ *
+ * @param $extraParams
+ * @param $reversePath
+ *
+ * @return string|null
+ */
+ private function _formatExtraParams($extraParams, $reversePath)
+ {
+ if (false !== strpos($extraParams, '-f%s')) {
+ if (empty($reversePath) || false === $this->_isShellSafe($reversePath)) {
+ $extraParams = str_replace('-f%s', '', $extraParams);
+ } else {
+ $extraParams = sprintf($extraParams, $reversePath);
+ }
+ }
+
+ return !empty($extraParams) ? $extraParams : null;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php
new file mode 100644
index 00000000..ad20e0e5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php
@@ -0,0 +1,93 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pretends messages have been sent, but just ignores them.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Transport_NullTransport implements Swift_Transport
+{
+ /** The event dispatcher from the plugin API */
+ private $_eventDispatcher;
+
+ /**
+ * Constructor.
+ */
+ public function __construct(Swift_Events_EventDispatcher $eventDispatcher)
+ {
+ $this->_eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Sends the given message.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $count = (
+ count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ );
+
+ return $count;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php
new file mode 100644
index 00000000..34ac4ce3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php
@@ -0,0 +1,160 @@
+ 30,
+ 'blocking' => 1,
+ 'command' => '/usr/sbin/sendmail -bs',
+ 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS,
+ );
+
+ /**
+ * Create a new SendmailTransport with $buf for I/O.
+ *
+ * @param Swift_Transport_IoBuffer $buf
+ * @param Swift_Events_EventDispatcher $dispatcher
+ */
+ public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher)
+ {
+ parent::__construct($buf, $dispatcher);
+ }
+
+ /**
+ * Start the standalone SMTP session if running in -bs mode.
+ */
+ public function start()
+ {
+ if (false !== strpos($this->getCommand(), ' -bs')) {
+ parent::start();
+ }
+ }
+
+ /**
+ * Set the command to invoke.
+ *
+ * If using -t mode you are strongly advised to include -oi or -i in the flags.
+ * For example: /usr/sbin/sendmail -oi -t
+ * Swift will append a -f flag if one is not present.
+ *
+ * The recommended mode is "-bs" since it is interactive and failure notifications
+ * are hence possible.
+ *
+ * @param string $command
+ *
+ * @return Swift_Transport_SendmailTransport
+ */
+ public function setCommand($command)
+ {
+ $this->_params['command'] = $command;
+
+ return $this;
+ }
+
+ /**
+ * Get the sendmail command which will be invoked.
+ *
+ * @return string
+ */
+ public function getCommand()
+ {
+ return $this->_params['command'];
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ *
+ * The return value is the number of recipients who were accepted for delivery.
+ * NOTE: If using 'sendmail -t' you will not be aware of any failures until
+ * they bounce (i.e. send() will always return 100% success).
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+ $command = $this->getCommand();
+ $buffer = $this->getBuffer();
+ $count = 0;
+
+ if (false !== strpos($command, ' -t')) {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if (false === strpos($command, ' -f')) {
+ $command .= ' -f'.escapeshellarg($this->_getReversePath($message));
+ }
+
+ $buffer->initialize(array_merge($this->_params, array('command' => $command)));
+
+ if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) {
+ $buffer->setWriteTranslations(array("\r\n" => "\n", "\n." => "\n.."));
+ } else {
+ $buffer->setWriteTranslations(array("\r\n" => "\n"));
+ }
+
+ $count = count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ ;
+ $message->toByteStream($buffer);
+ $buffer->flushBuffers();
+ $buffer->setWriteTranslations(array());
+ $buffer->terminate();
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId();
+ } elseif (false !== strpos($command, ' -bs')) {
+ $count = parent::send($message, $failedRecipients);
+ } else {
+ $this->_throwException(new Swift_TransportException(
+ 'Unsupported sendmail command flags ['.$command.']. '.
+ 'Must be one of "-bs" or "-t" but can include additional flags.'
+ ));
+ }
+
+ return $count;
+ }
+
+ /** Get the params to initialize the buffer */
+ protected function _getBufferParams()
+ {
+ return $this->_params;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php
new file mode 100644
index 00000000..4cab66bd
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php
@@ -0,0 +1,39 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Transport_SpoolTransport implements Swift_Transport
+{
+ /** The spool instance */
+ private $_spool;
+
+ /** The event dispatcher from the plugin API */
+ private $_eventDispatcher;
+
+ /**
+ * Constructor.
+ */
+ public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null)
+ {
+ $this->_eventDispatcher = $eventDispatcher;
+ $this->_spool = $spool;
+ }
+
+ /**
+ * Sets the spool object.
+ *
+ * @param Swift_Spool $spool
+ *
+ * @return Swift_Transport_SpoolTransport
+ */
+ public function setSpool(Swift_Spool $spool)
+ {
+ $this->_spool = $spool;
+
+ return $this;
+ }
+
+ /**
+ * Get the spool object.
+ *
+ * @return Swift_Spool
+ */
+ public function getSpool()
+ {
+ return $this->_spool;
+ }
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Sends the given message.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent e-mail's
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ $success = $this->_spool->queueMessage($message);
+
+ if ($evt) {
+ $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ return 1;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php
new file mode 100644
index 00000000..5134ea48
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php
@@ -0,0 +1,325 @@
+_replacementFactory = $replacementFactory;
+ }
+
+ /**
+ * Perform any initialization needed, using the given $params.
+ *
+ * Parameters will vary depending upon the type of IoBuffer used.
+ *
+ * @param array $params
+ */
+ public function initialize(array $params)
+ {
+ $this->_params = $params;
+ switch ($params['type']) {
+ case self::TYPE_PROCESS:
+ $this->_establishProcessConnection();
+ break;
+ case self::TYPE_SOCKET:
+ default:
+ $this->_establishSocketConnection();
+ break;
+ }
+ }
+
+ /**
+ * Set an individual param on the buffer (e.g. switching to SSL).
+ *
+ * @param string $param
+ * @param mixed $value
+ */
+ public function setParam($param, $value)
+ {
+ if (isset($this->_stream)) {
+ switch ($param) {
+ case 'timeout':
+ if ($this->_stream) {
+ stream_set_timeout($this->_stream, $value);
+ }
+ break;
+
+ case 'blocking':
+ if ($this->_stream) {
+ stream_set_blocking($this->_stream, 1);
+ }
+
+ }
+ }
+ $this->_params[$param] = $value;
+ }
+
+ public function startTLS()
+ {
+ return stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+ }
+
+ /**
+ * Perform any shutdown logic needed.
+ */
+ public function terminate()
+ {
+ if (isset($this->_stream)) {
+ switch ($this->_params['type']) {
+ case self::TYPE_PROCESS:
+ fclose($this->_in);
+ fclose($this->_out);
+ proc_close($this->_stream);
+ break;
+ case self::TYPE_SOCKET:
+ default:
+ fclose($this->_stream);
+ break;
+ }
+ }
+ $this->_stream = null;
+ $this->_out = null;
+ $this->_in = null;
+ }
+
+ /**
+ * Set an array of string replacements which should be made on data written
+ * to the buffer.
+ *
+ * This could replace LF with CRLF for example.
+ *
+ * @param string[] $replacements
+ */
+ public function setWriteTranslations(array $replacements)
+ {
+ foreach ($this->_translations as $search => $replace) {
+ if (!isset($replacements[$search])) {
+ $this->removeFilter($search);
+ unset($this->_translations[$search]);
+ }
+ }
+
+ foreach ($replacements as $search => $replace) {
+ if (!isset($this->_translations[$search])) {
+ $this->addFilter(
+ $this->_replacementFactory->createFilter($search, $replace), $search
+ );
+ $this->_translations[$search] = true;
+ }
+ }
+ }
+
+ /**
+ * Get a line of output (including any CRLF).
+ *
+ * The $sequence number comes from any writes and may or may not be used
+ * depending upon the implementation.
+ *
+ * @param int $sequence of last write to scan from
+ *
+ * @throws Swift_IoException
+ *
+ * @return string
+ */
+ public function readLine($sequence)
+ {
+ if (isset($this->_out) && !feof($this->_out)) {
+ $line = fgets($this->_out);
+ if (strlen($line) == 0) {
+ $metas = stream_get_meta_data($this->_out);
+ if ($metas['timed_out']) {
+ throw new Swift_IoException(
+ 'Connection to '.
+ $this->_getReadConnectionDescription().
+ ' Timed Out'
+ );
+ }
+ }
+
+ return $line;
+ }
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the remaining bytes are given instead.
+ * If no bytes are remaining at all, boolean false is returned.
+ *
+ * @param int $length
+ *
+ * @throws Swift_IoException
+ *
+ * @return string|bool
+ */
+ public function read($length)
+ {
+ if (isset($this->_out) && !feof($this->_out)) {
+ $ret = fread($this->_out, $length);
+ if (strlen($ret) == 0) {
+ $metas = stream_get_meta_data($this->_out);
+ if ($metas['timed_out']) {
+ throw new Swift_IoException(
+ 'Connection to '.
+ $this->_getReadConnectionDescription().
+ ' Timed Out'
+ );
+ }
+ }
+
+ return $ret;
+ }
+ }
+
+ /** Not implemented */
+ public function setReadPointer($byteOffset)
+ {
+ }
+
+ /** Flush the stream contents */
+ protected function _flush()
+ {
+ if (isset($this->_in)) {
+ fflush($this->_in);
+ }
+ }
+
+ /** Write this bytes to the stream */
+ protected function _commit($bytes)
+ {
+ if (isset($this->_in)) {
+ $bytesToWrite = strlen($bytes);
+ $totalBytesWritten = 0;
+
+ while ($totalBytesWritten < $bytesToWrite) {
+ $bytesWritten = fwrite($this->_in, substr($bytes, $totalBytesWritten));
+ if (false === $bytesWritten || 0 === $bytesWritten) {
+ break;
+ }
+
+ $totalBytesWritten += $bytesWritten;
+ }
+
+ if ($totalBytesWritten > 0) {
+ return ++$this->_sequence;
+ }
+ }
+ }
+
+ /**
+ * Establishes a connection to a remote server.
+ */
+ private function _establishSocketConnection()
+ {
+ $host = $this->_params['host'];
+ if (!empty($this->_params['protocol'])) {
+ $host = $this->_params['protocol'].'://'.$host;
+ }
+ $timeout = 15;
+ if (!empty($this->_params['timeout'])) {
+ $timeout = $this->_params['timeout'];
+ }
+ $options = array();
+ if (!empty($this->_params['sourceIp'])) {
+ $options['socket']['bindto'] = $this->_params['sourceIp'].':0';
+ }
+ if (isset($this->_params['stream_context_options'])) {
+ $options = array_merge($options, $this->_params['stream_context_options']);
+ }
+ $streamContext = stream_context_create($options);
+ $this->_stream = @stream_socket_client($host.':'.$this->_params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
+ if (false === $this->_stream) {
+ throw new Swift_TransportException(
+ 'Connection could not be established with host '.$this->_params['host'].
+ ' ['.$errstr.' #'.$errno.']'
+ );
+ }
+ if (!empty($this->_params['blocking'])) {
+ stream_set_blocking($this->_stream, 1);
+ } else {
+ stream_set_blocking($this->_stream, 0);
+ }
+ stream_set_timeout($this->_stream, $timeout);
+ $this->_in = &$this->_stream;
+ $this->_out = &$this->_stream;
+ }
+
+ /**
+ * Opens a process for input/output.
+ */
+ private function _establishProcessConnection()
+ {
+ $command = $this->_params['command'];
+ $descriptorSpec = array(
+ 0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w'),
+ );
+ $this->_stream = proc_open($command, $descriptorSpec, $pipes);
+ stream_set_blocking($pipes[2], 0);
+ if ($err = stream_get_contents($pipes[2])) {
+ throw new Swift_TransportException(
+ 'Process could not be started ['.$err.']'
+ );
+ }
+ $this->_in = &$pipes[0];
+ $this->_out = &$pipes[1];
+ }
+
+ private function _getReadConnectionDescription()
+ {
+ switch ($this->_params['type']) {
+ case self::TYPE_PROCESS:
+ return 'Process '.$this->_params['command'];
+ break;
+
+ case self::TYPE_SOCKET:
+ default:
+ $host = $this->_params['host'];
+ if (!empty($this->_params['protocol'])) {
+ $host = $this->_params['protocol'].'://'.$host;
+ }
+ $host .= ':'.$this->_params['port'];
+
+ return $host;
+ break;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php
new file mode 100644
index 00000000..4ae2412e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php
@@ -0,0 +1,29 @@
+
+ */
+class Swift_Validate
+{
+ /**
+ * Grammar Object.
+ *
+ * @var Swift_Mime_Grammar
+ */
+ private static $grammar = null;
+
+ /**
+ * Checks if an e-mail address matches the current grammars.
+ *
+ * @param string $email
+ *
+ * @return bool
+ */
+ public static function email($email)
+ {
+ if (self::$grammar === null) {
+ self::$grammar = Swift_DependencyContainer::getInstance()
+ ->lookup('mime.grammar');
+ }
+
+ return (bool) preg_match(
+ '/^'.self::$grammar->getDefinition('addr-spec').'$/D',
+ $email
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php
new file mode 100644
index 00000000..6023448e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php
@@ -0,0 +1,23 @@
+register('cache')
+ ->asAliasOf('cache.array')
+
+ ->register('tempdir')
+ ->asValue('/tmp')
+
+ ->register('cache.null')
+ ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache')
+
+ ->register('cache.array')
+ ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache')
+ ->withDependencies(array('cache.inputstream'))
+
+ ->register('cache.disk')
+ ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache')
+ ->withDependencies(array('cache.inputstream', 'tempdir'))
+
+ ->register('cache.inputstream')
+ ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream')
+;
diff --git a/vendor/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php
new file mode 100644
index 00000000..64d69d21
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php
@@ -0,0 +1,9 @@
+register('message.message')
+ ->asNewInstanceOf('Swift_Message')
+
+ ->register('message.mimepart')
+ ->asNewInstanceOf('Swift_MimePart')
+;
diff --git a/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php
new file mode 100644
index 00000000..56169c92
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php
@@ -0,0 +1,123 @@
+register('properties.charset')
+ ->asValue('utf-8')
+
+ ->register('mime.grammar')
+ ->asSharedInstanceOf('Swift_Mime_Grammar')
+
+ ->register('mime.message')
+ ->asNewInstanceOf('Swift_Mime_SimpleMessage')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.qpcontentencoder',
+ 'cache',
+ 'mime.grammar',
+ 'properties.charset',
+ ))
+
+ ->register('mime.part')
+ ->asNewInstanceOf('Swift_Mime_MimePart')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.qpcontentencoder',
+ 'cache',
+ 'mime.grammar',
+ 'properties.charset',
+ ))
+
+ ->register('mime.attachment')
+ ->asNewInstanceOf('Swift_Mime_Attachment')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.base64contentencoder',
+ 'cache',
+ 'mime.grammar',
+ ))
+ ->addConstructorValue($swift_mime_types)
+
+ ->register('mime.embeddedfile')
+ ->asNewInstanceOf('Swift_Mime_EmbeddedFile')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.base64contentencoder',
+ 'cache',
+ 'mime.grammar',
+ ))
+ ->addConstructorValue($swift_mime_types)
+
+ ->register('mime.headerfactory')
+ ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory')
+ ->withDependencies(array(
+ 'mime.qpheaderencoder',
+ 'mime.rfc2231encoder',
+ 'mime.grammar',
+ 'properties.charset',
+ ))
+
+ ->register('mime.headerset')
+ ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet')
+ ->withDependencies(array('mime.headerfactory', 'properties.charset'))
+
+ ->register('mime.qpheaderencoder')
+ ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder')
+ ->withDependencies(array('mime.charstream'))
+
+ ->register('mime.base64headerencoder')
+ ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder')
+ ->withDependencies(array('mime.charstream'))
+
+ ->register('mime.charstream')
+ ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream')
+ ->withDependencies(array('mime.characterreaderfactory', 'properties.charset'))
+
+ ->register('mime.bytecanonicalizer')
+ ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter')
+ ->addConstructorValue(array(array(0x0D, 0x0A), array(0x0D), array(0x0A)))
+ ->addConstructorValue(array(array(0x0A), array(0x0A), array(0x0D, 0x0A)))
+
+ ->register('mime.characterreaderfactory')
+ ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory')
+
+ ->register('mime.safeqpcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder')
+ ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer'))
+
+ ->register('mime.rawcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder')
+
+ ->register('mime.nativeqpcontentencoder')
+ ->withDependencies(array('properties.charset'))
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder')
+
+ ->register('mime.qpcontentencoderproxy')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy')
+ ->withDependencies(array('mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset'))
+
+ ->register('mime.7bitcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder')
+ ->addConstructorValue('7bit')
+ ->addConstructorValue(true)
+
+ ->register('mime.8bitcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder')
+ ->addConstructorValue('8bit')
+ ->addConstructorValue(true)
+
+ ->register('mime.base64contentencoder')
+ ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder')
+
+ ->register('mime.rfc2231encoder')
+ ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder')
+ ->withDependencies(array('mime.charstream'))
+
+ // As of PHP 5.4.7, the quoted_printable_encode() function behaves correctly.
+ // see https://github.com/php/php-src/commit/18bb426587d62f93c54c40bf8535eb8416603629
+ ->register('mime.qpcontentencoder')
+ ->asAliasOf(version_compare(phpversion(), '5.4.7', '>=') ? 'mime.qpcontentencoderproxy' : 'mime.safeqpcontentencoder')
+;
+
+unset($swift_mime_types);
diff --git a/vendor/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php
new file mode 100644
index 00000000..77e432cf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php
@@ -0,0 +1,76 @@
+register('transport.smtp')
+ ->asNewInstanceOf('Swift_Transport_EsmtpTransport')
+ ->withDependencies(array(
+ 'transport.buffer',
+ array('transport.authhandler'),
+ 'transport.eventdispatcher',
+ ))
+
+ ->register('transport.sendmail')
+ ->asNewInstanceOf('Swift_Transport_SendmailTransport')
+ ->withDependencies(array(
+ 'transport.buffer',
+ 'transport.eventdispatcher',
+ ))
+
+ ->register('transport.mail')
+ ->asNewInstanceOf('Swift_Transport_MailTransport')
+ ->withDependencies(array('transport.mailinvoker', 'transport.eventdispatcher'))
+
+ ->register('transport.loadbalanced')
+ ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport')
+
+ ->register('transport.failover')
+ ->asNewInstanceOf('Swift_Transport_FailoverTransport')
+
+ ->register('transport.spool')
+ ->asNewInstanceOf('Swift_Transport_SpoolTransport')
+ ->withDependencies(array('transport.eventdispatcher'))
+
+ ->register('transport.null')
+ ->asNewInstanceOf('Swift_Transport_NullTransport')
+ ->withDependencies(array('transport.eventdispatcher'))
+
+ ->register('transport.mailinvoker')
+ ->asSharedInstanceOf('Swift_Transport_SimpleMailInvoker')
+
+ ->register('transport.buffer')
+ ->asNewInstanceOf('Swift_Transport_StreamBuffer')
+ ->withDependencies(array('transport.replacementfactory'))
+
+ ->register('transport.authhandler')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler')
+ ->withDependencies(array(
+ array(
+ 'transport.crammd5auth',
+ 'transport.loginauth',
+ 'transport.plainauth',
+ 'transport.ntlmauth',
+ 'transport.xoauth2auth',
+ ),
+ ))
+
+ ->register('transport.crammd5auth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator')
+
+ ->register('transport.loginauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator')
+
+ ->register('transport.plainauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator')
+
+ ->register('transport.xoauth2auth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator')
+
+ ->register('transport.ntlmauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator')
+
+ ->register('transport.eventdispatcher')
+ ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher')
+
+ ->register('transport.replacementfactory')
+ ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory')
+;
diff --git a/vendor/swiftmailer/swiftmailer/lib/mime_types.php b/vendor/swiftmailer/swiftmailer/lib/mime_types.php
new file mode 100644
index 00000000..2d7b98dc
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/mime_types.php
@@ -0,0 +1,1007 @@
+ 'text/vnd.in3d.3dml',
+ '3ds' => 'image/x-3ds',
+ '3g2' => 'video/3gpp2',
+ '3gp' => 'video/3gpp',
+ '7z' => 'application/x-7z-compressed',
+ 'aab' => 'application/x-authorware-bin',
+ 'aac' => 'audio/x-aac',
+ 'aam' => 'application/x-authorware-map',
+ 'aas' => 'application/x-authorware-seg',
+ 'abw' => 'application/x-abiword',
+ 'ac' => 'application/pkix-attr-cert',
+ 'acc' => 'application/vnd.americandynamics.acc',
+ 'ace' => 'application/x-ace-compressed',
+ 'acu' => 'application/vnd.acucobol',
+ 'acutc' => 'application/vnd.acucorp',
+ 'adp' => 'audio/adpcm',
+ 'aep' => 'application/vnd.audiograph',
+ 'afm' => 'application/x-font-type1',
+ 'afp' => 'application/vnd.ibm.modcap',
+ 'ahead' => 'application/vnd.ahead.space',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+ 'ait' => 'application/vnd.dvb.ait',
+ 'ami' => 'application/vnd.amiga.ami',
+ 'apk' => 'application/vnd.android.package-archive',
+ 'appcache' => 'text/cache-manifest',
+ 'apr' => 'application/vnd.lotus-approach',
+ 'aps' => 'application/postscript',
+ 'arc' => 'application/x-freearc',
+ 'asc' => 'application/pgp-signature',
+ 'asf' => 'video/x-ms-asf',
+ 'asm' => 'text/x-asm',
+ 'aso' => 'application/vnd.accpac.simply.aso',
+ 'asx' => 'video/x-ms-asf',
+ 'atc' => 'application/vnd.acucorp',
+ 'atom' => 'application/atom+xml',
+ 'atomcat' => 'application/atomcat+xml',
+ 'atomsvc' => 'application/atomsvc+xml',
+ 'atx' => 'application/vnd.antix.game-component',
+ 'au' => 'audio/basic',
+ 'avi' => 'video/x-msvideo',
+ 'aw' => 'application/applixware',
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
+ 'azw' => 'application/vnd.amazon.ebook',
+ 'bat' => 'application/x-msdownload',
+ 'bcpio' => 'application/x-bcpio',
+ 'bdf' => 'application/x-font-bdf',
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
+ 'bed' => 'application/vnd.realvnc.bed',
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
+ 'bin' => 'application/octet-stream',
+ 'blb' => 'application/x-blorb',
+ 'blorb' => 'application/x-blorb',
+ 'bmi' => 'application/vnd.bmi',
+ 'bmp' => 'image/bmp',
+ 'book' => 'application/vnd.framemaker',
+ 'box' => 'application/vnd.previewsystems.box',
+ 'boz' => 'application/x-bzip2',
+ 'bpk' => 'application/octet-stream',
+ 'btif' => 'image/prs.btif',
+ 'bz' => 'application/x-bzip',
+ 'bz2' => 'application/x-bzip2',
+ 'c' => 'text/x-c',
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+ 'c4d' => 'application/vnd.clonk.c4group',
+ 'c4f' => 'application/vnd.clonk.c4group',
+ 'c4g' => 'application/vnd.clonk.c4group',
+ 'c4p' => 'application/vnd.clonk.c4group',
+ 'c4u' => 'application/vnd.clonk.c4group',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+ 'caf' => 'audio/x-caf',
+ 'cap' => 'application/vnd.tcpdump.pcap',
+ 'car' => 'application/vnd.curl.car',
+ 'cat' => 'application/vnd.ms-pki.seccat',
+ 'cb7' => 'application/x-cbr',
+ 'cba' => 'application/x-cbr',
+ 'cbr' => 'application/x-cbr',
+ 'cbt' => 'application/x-cbr',
+ 'cbz' => 'application/x-cbr',
+ 'cc' => 'text/x-c',
+ 'cct' => 'application/x-director',
+ 'ccxml' => 'application/ccxml+xml',
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
+ 'cdf' => 'application/x-netcdf',
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
+ 'cdmia' => 'application/cdmi-capability',
+ 'cdmic' => 'application/cdmi-container',
+ 'cdmid' => 'application/cdmi-domain',
+ 'cdmio' => 'application/cdmi-object',
+ 'cdmiq' => 'application/cdmi-queue',
+ 'cdx' => 'chemical/x-cdx',
+ 'cdxml' => 'application/vnd.chemdraw+xml',
+ 'cdy' => 'application/vnd.cinderella',
+ 'cer' => 'application/pkix-cert',
+ 'cfs' => 'application/x-cfs-compressed',
+ 'cgm' => 'image/cgm',
+ 'chat' => 'application/x-chat',
+ 'chm' => 'application/vnd.ms-htmlhelp',
+ 'chrt' => 'application/vnd.kde.kchart',
+ 'cif' => 'chemical/x-cif',
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+ 'cil' => 'application/vnd.ms-artgalry',
+ 'cla' => 'application/vnd.claymore',
+ 'class' => 'application/java-vm',
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
+ 'clkp' => 'application/vnd.crick.clicker.palette',
+ 'clkt' => 'application/vnd.crick.clicker.template',
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
+ 'clkx' => 'application/vnd.crick.clicker',
+ 'clp' => 'application/x-msclip',
+ 'cmc' => 'application/vnd.cosmocaller',
+ 'cmdf' => 'chemical/x-cmdf',
+ 'cml' => 'chemical/x-cml',
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
+ 'cmx' => 'image/x-cmx',
+ 'cod' => 'application/vnd.rim.cod',
+ 'com' => 'application/x-msdownload',
+ 'conf' => 'text/plain',
+ 'cpio' => 'application/x-cpio',
+ 'cpp' => 'text/x-c',
+ 'cpt' => 'application/mac-compactpro',
+ 'crd' => 'application/x-mscardfile',
+ 'crl' => 'application/pkix-crl',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'csh' => 'application/x-csh',
+ 'csml' => 'chemical/x-csml',
+ 'csp' => 'application/vnd.commonspace',
+ 'css' => 'text/css',
+ 'cst' => 'application/x-director',
+ 'csv' => 'text/csv',
+ 'cu' => 'application/cu-seeme',
+ 'curl' => 'text/vnd.curl',
+ 'cww' => 'application/prs.cww',
+ 'cxt' => 'application/x-director',
+ 'cxx' => 'text/x-c',
+ 'dae' => 'model/vnd.collada+xml',
+ 'daf' => 'application/vnd.mobius.daf',
+ 'dart' => 'application/vnd.dart',
+ 'dataless' => 'application/vnd.fdsn.seed',
+ 'davmount' => 'application/davmount+xml',
+ 'dbk' => 'application/docbook+xml',
+ 'dcr' => 'application/x-director',
+ 'dcurl' => 'text/vnd.curl.dcurl',
+ 'dd2' => 'application/vnd.oma.dd2+xml',
+ 'ddd' => 'application/vnd.fujixerox.ddd',
+ 'deb' => 'application/x-debian-package',
+ 'def' => 'text/plain',
+ 'deploy' => 'application/octet-stream',
+ 'der' => 'application/x-x509-ca-cert',
+ 'dfac' => 'application/vnd.dreamfactory',
+ 'dgc' => 'application/x-dgc-compressed',
+ 'dic' => 'text/x-c',
+ 'dir' => 'application/x-director',
+ 'dis' => 'application/vnd.mobius.dis',
+ 'dist' => 'application/octet-stream',
+ 'distz' => 'application/octet-stream',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/x-msdownload',
+ 'dmg' => 'application/x-apple-diskimage',
+ 'dmp' => 'application/vnd.tcpdump.pcap',
+ 'dms' => 'application/octet-stream',
+ 'dna' => 'application/vnd.dna',
+ 'doc' => 'application/msword',
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dot' => 'application/msword',
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'dp' => 'application/vnd.osgi.dp',
+ 'dpg' => 'application/vnd.dpgraph',
+ 'dra' => 'audio/vnd.dra',
+ 'dsc' => 'text/prs.lines.tag',
+ 'dssc' => 'application/dssc+der',
+ 'dtb' => 'application/x-dtbook+xml',
+ 'dtd' => 'application/xml-dtd',
+ 'dts' => 'audio/vnd.dts',
+ 'dtshd' => 'audio/vnd.dts.hd',
+ 'dump' => 'application/octet-stream',
+ 'dvb' => 'video/vnd.dvb.file',
+ 'dvi' => 'application/x-dvi',
+ 'dwf' => 'model/vnd.dwf',
+ 'dwg' => 'image/vnd.dwg',
+ 'dxf' => 'image/vnd.dxf',
+ 'dxp' => 'application/vnd.spotfire.dxp',
+ 'dxr' => 'application/x-director',
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+ 'ecma' => 'application/ecmascript',
+ 'edm' => 'application/vnd.novadigm.edm',
+ 'edx' => 'application/vnd.novadigm.edx',
+ 'efif' => 'application/vnd.picsel',
+ 'ei6' => 'application/vnd.pg.osasli',
+ 'elc' => 'application/octet-stream',
+ 'emf' => 'application/x-msmetafile',
+ 'eml' => 'message/rfc822',
+ 'emma' => 'application/emma+xml',
+ 'emz' => 'application/x-msmetafile',
+ 'eol' => 'audio/vnd.digital-winds',
+ 'eot' => 'application/vnd.ms-fontobject',
+ 'eps' => 'application/postscript',
+ 'epub' => 'application/epub+zip',
+ 'es3' => 'application/vnd.eszigno3+xml',
+ 'esa' => 'application/vnd.osgi.subsystem',
+ 'esf' => 'application/vnd.epson.esf',
+ 'et3' => 'application/vnd.eszigno3+xml',
+ 'etx' => 'text/x-setext',
+ 'eva' => 'application/x-eva',
+ 'evy' => 'application/x-envoy',
+ 'exe' => 'application/x-msdownload',
+ 'exi' => 'application/exi',
+ 'ext' => 'application/vnd.novadigm.ext',
+ 'ez' => 'application/andrew-inset',
+ 'ez2' => 'application/vnd.ezpix-album',
+ 'ez3' => 'application/vnd.ezpix-package',
+ 'f' => 'text/x-fortran',
+ 'f4v' => 'video/x-f4v',
+ 'f77' => 'text/x-fortran',
+ 'f90' => 'text/x-fortran',
+ 'fbs' => 'image/vnd.fastbidsheet',
+ 'fcdt' => 'application/vnd.adobe.formscentral.fcdt',
+ 'fcs' => 'application/vnd.isac.fcs',
+ 'fdf' => 'application/vnd.fdf',
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
+ 'fgd' => 'application/x-director',
+ 'fh' => 'image/x-freehand',
+ 'fh4' => 'image/x-freehand',
+ 'fh5' => 'image/x-freehand',
+ 'fh7' => 'image/x-freehand',
+ 'fhc' => 'image/x-freehand',
+ 'fig' => 'application/x-xfig',
+ 'flac' => 'audio/x-flac',
+ 'fli' => 'video/x-fli',
+ 'flo' => 'application/vnd.micrografx.flo',
+ 'flv' => 'video/x-flv',
+ 'flw' => 'application/vnd.kde.kivio',
+ 'flx' => 'text/vnd.fmi.flexstor',
+ 'fly' => 'text/vnd.fly',
+ 'fm' => 'application/vnd.framemaker',
+ 'fnc' => 'application/vnd.frogans.fnc',
+ 'for' => 'text/x-fortran',
+ 'fpx' => 'image/vnd.fpx',
+ 'frame' => 'application/vnd.framemaker',
+ 'fsc' => 'application/vnd.fsc.weblaunch',
+ 'fst' => 'image/vnd.fst',
+ 'ftc' => 'application/vnd.fluxtime.clip',
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+ 'fvt' => 'video/vnd.fvt',
+ 'fxp' => 'application/vnd.adobe.fxp',
+ 'fxpl' => 'application/vnd.adobe.fxp',
+ 'fzs' => 'application/vnd.fuzzysheet',
+ 'g2w' => 'application/vnd.geoplan',
+ 'g3' => 'image/g3fax',
+ 'g3w' => 'application/vnd.geospace',
+ 'gac' => 'application/vnd.groove-account',
+ 'gam' => 'application/x-tads',
+ 'gbr' => 'application/rpki-ghostbusters',
+ 'gca' => 'application/x-gca-compressed',
+ 'gdl' => 'model/vnd.gdl',
+ 'geo' => 'application/vnd.dynageo',
+ 'gex' => 'application/vnd.geometry-explorer',
+ 'ggb' => 'application/vnd.geogebra.file',
+ 'ggt' => 'application/vnd.geogebra.tool',
+ 'ghf' => 'application/vnd.groove-help',
+ 'gif' => 'image/gif',
+ 'gim' => 'application/vnd.groove-identity-message',
+ 'gml' => 'application/gml+xml',
+ 'gmx' => 'application/vnd.gmx',
+ 'gnumeric' => 'application/x-gnumeric',
+ 'gph' => 'application/vnd.flographit',
+ 'gpx' => 'application/gpx+xml',
+ 'gqf' => 'application/vnd.grafeq',
+ 'gqs' => 'application/vnd.grafeq',
+ 'gram' => 'application/srgs',
+ 'gramps' => 'application/x-gramps-xml',
+ 'gre' => 'application/vnd.geometry-explorer',
+ 'grv' => 'application/vnd.groove-injector',
+ 'grxml' => 'application/srgs+xml',
+ 'gsf' => 'application/x-font-ghostscript',
+ 'gtar' => 'application/x-gtar',
+ 'gtm' => 'application/vnd.groove-tool-message',
+ 'gtw' => 'model/vnd.gtw',
+ 'gv' => 'text/vnd.graphviz',
+ 'gxf' => 'application/gxf',
+ 'gxt' => 'application/vnd.geonext',
+ 'gz' => 'application/x-gzip',
+ 'h' => 'text/x-c',
+ 'h261' => 'video/h261',
+ 'h263' => 'video/h263',
+ 'h264' => 'video/h264',
+ 'hal' => 'application/vnd.hal+xml',
+ 'hbci' => 'application/vnd.hbci',
+ 'hdf' => 'application/x-hdf',
+ 'hh' => 'text/x-c',
+ 'hlp' => 'application/winhlp',
+ 'hpgl' => 'application/vnd.hp-hpgl',
+ 'hpid' => 'application/vnd.hp-hpid',
+ 'hps' => 'application/vnd.hp-hps',
+ 'hqx' => 'application/mac-binhex40',
+ 'htke' => 'application/vnd.kenameaapp',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
+ 'hvs' => 'application/vnd.yamaha.hv-script',
+ 'i2g' => 'application/vnd.intergeo',
+ 'icc' => 'application/vnd.iccprofile',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'icm' => 'application/vnd.iccprofile',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ief' => 'image/ief',
+ 'ifb' => 'text/calendar',
+ 'ifm' => 'application/vnd.shana.informed.formdata',
+ 'iges' => 'model/iges',
+ 'igl' => 'application/vnd.igloader',
+ 'igm' => 'application/vnd.insors.igm',
+ 'igs' => 'model/iges',
+ 'igx' => 'application/vnd.micrografx.igx',
+ 'iif' => 'application/vnd.shana.informed.interchange',
+ 'imp' => 'application/vnd.accpac.simply.imp',
+ 'ims' => 'application/vnd.ms-ims',
+ 'in' => 'text/plain',
+ 'ink' => 'application/inkml+xml',
+ 'inkml' => 'application/inkml+xml',
+ 'install' => 'application/x-install-instructions',
+ 'iota' => 'application/vnd.astraea-software.iota',
+ 'ipfix' => 'application/ipfix',
+ 'ipk' => 'application/vnd.shana.informed.package',
+ 'irm' => 'application/vnd.ibm.rights-management',
+ 'irp' => 'application/vnd.irepository.package+xml',
+ 'iso' => 'application/x-iso9660-image',
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
+ 'ivp' => 'application/vnd.immervision-ivp',
+ 'ivu' => 'application/vnd.immervision-ivu',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'jam' => 'application/vnd.jam',
+ 'jar' => 'application/java-archive',
+ 'java' => 'text/x-java-source',
+ 'jisp' => 'application/vnd.jisp',
+ 'jlt' => 'application/vnd.hp-jlyt',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'joda' => 'application/vnd.joost.joda-archive',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpgm' => 'video/jpm',
+ 'jpgv' => 'video/jpeg',
+ 'jpm' => 'video/jpm',
+ 'js' => 'application/javascript',
+ 'json' => 'application/json',
+ 'jsonml' => 'application/jsonml+json',
+ 'kar' => 'audio/midi',
+ 'karbon' => 'application/vnd.kde.karbon',
+ 'kfo' => 'application/vnd.kde.kformula',
+ 'kia' => 'application/vnd.kidspiration',
+ 'kml' => 'application/vnd.google-earth.kml+xml',
+ 'kmz' => 'application/vnd.google-earth.kmz',
+ 'kne' => 'application/vnd.kinar',
+ 'knp' => 'application/vnd.kinar',
+ 'kon' => 'application/vnd.kde.kontour',
+ 'kpr' => 'application/vnd.kde.kpresenter',
+ 'kpt' => 'application/vnd.kde.kpresenter',
+ 'kpxx' => 'application/vnd.ds-keypoint',
+ 'ksp' => 'application/vnd.kde.kspread',
+ 'ktr' => 'application/vnd.kahootz',
+ 'ktx' => 'image/ktx',
+ 'ktz' => 'application/vnd.kahootz',
+ 'kwd' => 'application/vnd.kde.kword',
+ 'kwt' => 'application/vnd.kde.kword',
+ 'lasxml' => 'application/vnd.las.las+xml',
+ 'latex' => 'application/x-latex',
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+ 'les' => 'application/vnd.hhe.lesson-player',
+ 'lha' => 'application/x-lzh-compressed',
+ 'link66' => 'application/vnd.route66.link66+xml',
+ 'list' => 'text/plain',
+ 'list3820' => 'application/vnd.ibm.modcap',
+ 'listafp' => 'application/vnd.ibm.modcap',
+ 'lnk' => 'application/x-ms-shortcut',
+ 'log' => 'text/plain',
+ 'lostxml' => 'application/lost+xml',
+ 'lrf' => 'application/octet-stream',
+ 'lrm' => 'application/vnd.ms-lrm',
+ 'ltf' => 'application/vnd.frogans.ltf',
+ 'lvp' => 'audio/vnd.lucent.voice',
+ 'lwp' => 'application/vnd.lotus-wordpro',
+ 'lzh' => 'application/x-lzh-compressed',
+ 'm13' => 'application/x-msmediaview',
+ 'm14' => 'application/x-msmediaview',
+ 'm1v' => 'video/mpeg',
+ 'm21' => 'application/mp21',
+ 'm2a' => 'audio/mpeg',
+ 'm2v' => 'video/mpeg',
+ 'm3a' => 'audio/mpeg',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm3u8' => 'application/vnd.apple.mpegurl',
+ 'm4a' => 'audio/mp4',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/x-m4v',
+ 'ma' => 'application/mathematica',
+ 'mads' => 'application/mads+xml',
+ 'mag' => 'application/vnd.ecowin.chart',
+ 'maker' => 'application/vnd.framemaker',
+ 'man' => 'text/troff',
+ 'mar' => 'application/octet-stream',
+ 'mathml' => 'application/mathml+xml',
+ 'mb' => 'application/mathematica',
+ 'mbk' => 'application/vnd.mobius.mbk',
+ 'mbox' => 'application/mbox',
+ 'mc1' => 'application/vnd.medcalcdata',
+ 'mcd' => 'application/vnd.mcd',
+ 'mcurl' => 'text/vnd.curl.mcurl',
+ 'mdb' => 'application/x-msaccess',
+ 'mdi' => 'image/vnd.ms-modi',
+ 'me' => 'text/troff',
+ 'mesh' => 'model/mesh',
+ 'meta4' => 'application/metalink4+xml',
+ 'metalink' => 'application/metalink+xml',
+ 'mets' => 'application/mets+xml',
+ 'mfm' => 'application/vnd.mfmp',
+ 'mft' => 'application/rpki-manifest',
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
+ 'mgz' => 'application/vnd.proteus.magazine',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mie' => 'application/x-mie',
+ 'mif' => 'application/vnd.mif',
+ 'mime' => 'message/rfc822',
+ 'mj2' => 'video/mj2',
+ 'mjp2' => 'video/mj2',
+ 'mk3d' => 'video/x-matroska',
+ 'mka' => 'audio/x-matroska',
+ 'mks' => 'video/x-matroska',
+ 'mkv' => 'video/x-matroska',
+ 'mlp' => 'application/vnd.dolby.mlp',
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+ 'mmf' => 'application/vnd.smaf',
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+ 'mng' => 'video/x-mng',
+ 'mny' => 'application/x-msmoney',
+ 'mobi' => 'application/x-mobipocket-ebook',
+ 'mods' => 'application/mods+xml',
+ 'mov' => 'video/quicktime',
+ 'movie' => 'video/x-sgi-movie',
+ 'mp2' => 'audio/mpeg',
+ 'mp21' => 'application/mp21',
+ 'mp2a' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mp4a' => 'audio/mp4',
+ 'mp4s' => 'application/mp4',
+ 'mp4v' => 'video/mp4',
+ 'mpc' => 'application/vnd.mophun.certificate',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpg4' => 'video/mp4',
+ 'mpga' => 'audio/mpeg',
+ 'mpkg' => 'application/vnd.apple.installer+xml',
+ 'mpm' => 'application/vnd.blueice.multipass',
+ 'mpn' => 'application/vnd.mophun.application',
+ 'mpp' => 'application/vnd.ms-project',
+ 'mpt' => 'application/vnd.ms-project',
+ 'mpy' => 'application/vnd.ibm.minipay',
+ 'mqy' => 'application/vnd.mobius.mqy',
+ 'mrc' => 'application/marc',
+ 'mrcx' => 'application/marcxml+xml',
+ 'ms' => 'text/troff',
+ 'mscml' => 'application/mediaservercontrol+xml',
+ 'mseed' => 'application/vnd.fdsn.mseed',
+ 'mseq' => 'application/vnd.mseq',
+ 'msf' => 'application/vnd.epson.msf',
+ 'msh' => 'model/mesh',
+ 'msi' => 'application/x-msdownload',
+ 'msl' => 'application/vnd.mobius.msl',
+ 'msty' => 'application/vnd.muvee.style',
+ 'mts' => 'model/vnd.mts',
+ 'mus' => 'application/vnd.musician',
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
+ 'mvb' => 'application/x-msmediaview',
+ 'mwf' => 'application/vnd.mfer',
+ 'mxf' => 'application/mxf',
+ 'mxl' => 'application/vnd.recordare.musicxml',
+ 'mxml' => 'application/xv+xml',
+ 'mxs' => 'application/vnd.triscape.mxs',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+ 'n3' => 'text/n3',
+ 'nb' => 'application/mathematica',
+ 'nbp' => 'application/vnd.wolfram.player',
+ 'nc' => 'application/x-netcdf',
+ 'ncx' => 'application/x-dtbncx+xml',
+ 'nfo' => 'text/x-nfo',
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
+ 'nitf' => 'application/vnd.nitf',
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
+ 'nml' => 'application/vnd.enliven',
+ 'nnd' => 'application/vnd.noblenet-directory',
+ 'nns' => 'application/vnd.noblenet-sealer',
+ 'nnw' => 'application/vnd.noblenet-web',
+ 'npx' => 'image/vnd.net-fpx',
+ 'nsc' => 'application/x-conference',
+ 'nsf' => 'application/vnd.lotus-notes',
+ 'ntf' => 'application/vnd.nitf',
+ 'nzb' => 'application/x-nzb',
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
+ 'oas' => 'application/vnd.fujitsu.oasys',
+ 'obd' => 'application/x-msbinder',
+ 'obj' => 'application/x-tgif',
+ 'oda' => 'application/oda',
+ 'odb' => 'application/vnd.oasis.opendocument.database',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'oga' => 'audio/ogg',
+ 'ogg' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'ogx' => 'application/ogg',
+ 'omdoc' => 'application/omdoc+xml',
+ 'onepkg' => 'application/onenote',
+ 'onetmp' => 'application/onenote',
+ 'onetoc' => 'application/onenote',
+ 'onetoc2' => 'application/onenote',
+ 'opf' => 'application/oebps-package+xml',
+ 'opml' => 'text/x-opml',
+ 'oprc' => 'application/vnd.palm',
+ 'org' => 'application/vnd.lotus-organizer',
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
+ 'otf' => 'application/x-font-otf',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oxps' => 'application/oxps',
+ 'oxt' => 'application/vnd.openofficeorg.extension',
+ 'p' => 'text/x-pascal',
+ 'p10' => 'application/pkcs10',
+ 'p12' => 'application/x-pkcs12',
+ 'p7b' => 'application/x-pkcs7-certificates',
+ 'p7c' => 'application/pkcs7-mime',
+ 'p7m' => 'application/pkcs7-mime',
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'p7s' => 'application/pkcs7-signature',
+ 'p8' => 'application/pkcs8',
+ 'pas' => 'text/x-pascal',
+ 'paw' => 'application/vnd.pawaafile',
+ 'pbd' => 'application/vnd.powerbuilder6',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pcap' => 'application/vnd.tcpdump.pcap',
+ 'pcf' => 'application/x-font-pcf',
+ 'pcl' => 'application/vnd.hp-pcl',
+ 'pclxl' => 'application/vnd.hp-pclxl',
+ 'pct' => 'image/x-pict',
+ 'pcurl' => 'application/vnd.curl.pcurl',
+ 'pcx' => 'image/x-pcx',
+ 'pdb' => 'application/vnd.palm',
+ 'pdf' => 'application/pdf',
+ 'pfa' => 'application/x-font-type1',
+ 'pfb' => 'application/x-font-type1',
+ 'pfm' => 'application/x-font-type1',
+ 'pfr' => 'application/font-tdpfr',
+ 'pfx' => 'application/x-pkcs12',
+ 'pgm' => 'image/x-portable-graymap',
+ 'pgn' => 'application/x-chess-pgn',
+ 'pgp' => 'application/pgp-encrypted',
+ 'php' => 'application/x-php',
+ 'php3' => 'application/x-php',
+ 'php4' => 'application/x-php',
+ 'php5' => 'application/x-php',
+ 'pic' => 'image/x-pict',
+ 'pkg' => 'application/octet-stream',
+ 'pki' => 'application/pkixcmp',
+ 'pkipath' => 'application/pkix-pkipath',
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
+ 'plc' => 'application/vnd.mobius.plc',
+ 'plf' => 'application/vnd.pocketlearn',
+ 'pls' => 'application/pls+xml',
+ 'pml' => 'application/vnd.ctc-posml',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'portpkg' => 'application/vnd.macports.portpkg',
+ 'pot' => 'application/vnd.ms-powerpoint',
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
+ 'ppd' => 'application/vnd.cups-ppd',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'pqa' => 'application/vnd.palm',
+ 'prc' => 'application/x-mobipocket-ebook',
+ 'pre' => 'application/vnd.lotus-freelance',
+ 'prf' => 'application/pics-rules',
+ 'ps' => 'application/postscript',
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'psf' => 'application/x-font-linux-psf',
+ 'pskcxml' => 'application/pskc+xml',
+ 'ptid' => 'application/vnd.pvi.ptid1',
+ 'pub' => 'application/x-mspublisher',
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
+ 'pwn' => 'application/vnd.3m.post-it-notes',
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
+ 'qam' => 'application/vnd.epson.quickanime',
+ 'qbo' => 'application/vnd.intu.qbo',
+ 'qfx' => 'application/vnd.intu.qfx',
+ 'qps' => 'application/vnd.publishare-delta-tree',
+ 'qt' => 'video/quicktime',
+ 'qwd' => 'application/vnd.quark.quarkxpress',
+ 'qwt' => 'application/vnd.quark.quarkxpress',
+ 'qxb' => 'application/vnd.quark.quarkxpress',
+ 'qxd' => 'application/vnd.quark.quarkxpress',
+ 'qxl' => 'application/vnd.quark.quarkxpress',
+ 'qxt' => 'application/vnd.quark.quarkxpress',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rar' => 'application/x-rar-compressed',
+ 'ras' => 'image/x-cmu-raster',
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+ 'rdf' => 'application/rdf+xml',
+ 'rdz' => 'application/vnd.data-vision.rdz',
+ 'rep' => 'application/vnd.businessobjects',
+ 'res' => 'application/x-dtbresource+xml',
+ 'rgb' => 'image/x-rgb',
+ 'rif' => 'application/reginfo+xml',
+ 'rip' => 'audio/vnd.rip',
+ 'ris' => 'application/x-research-info-systems',
+ 'rl' => 'application/resource-lists+xml',
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+ 'rld' => 'application/resource-lists-diff+xml',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'rmi' => 'audio/midi',
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
+ 'rmvb' => 'application/vnd.rn-realmedia-vbr',
+ 'rnc' => 'application/relax-ng-compact-syntax',
+ 'roa' => 'application/rpki-roa',
+ 'roff' => 'text/troff',
+ 'rp9' => 'application/vnd.cloanto.rp9',
+ 'rpss' => 'application/vnd.nokia.radio-presets',
+ 'rpst' => 'application/vnd.nokia.radio-preset',
+ 'rq' => 'application/sparql-query',
+ 'rs' => 'application/rls-services+xml',
+ 'rsd' => 'application/rsd+xml',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'application/rtf',
+ 'rtx' => 'text/richtext',
+ 's' => 'text/x-asm',
+ 's3m' => 'audio/s3m',
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
+ 'sbml' => 'application/sbml+xml',
+ 'sc' => 'application/vnd.ibm.secure-container',
+ 'scd' => 'application/x-msschedule',
+ 'scm' => 'application/vnd.lotus-screencam',
+ 'scq' => 'application/scvp-cv-request',
+ 'scs' => 'application/scvp-cv-response',
+ 'scurl' => 'text/vnd.curl.scurl',
+ 'sda' => 'application/vnd.stardivision.draw',
+ 'sdc' => 'application/vnd.stardivision.calc',
+ 'sdd' => 'application/vnd.stardivision.impress',
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
+ 'sdp' => 'application/sdp',
+ 'sdw' => 'application/vnd.stardivision.writer',
+ 'see' => 'application/vnd.seemail',
+ 'seed' => 'application/vnd.fdsn.seed',
+ 'sema' => 'application/vnd.sema',
+ 'semd' => 'application/vnd.semd',
+ 'semf' => 'application/vnd.semf',
+ 'ser' => 'application/java-serialized-object',
+ 'setpay' => 'application/set-payment-initiation',
+ 'setreg' => 'application/set-registration-initiation',
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+ 'sfs' => 'application/vnd.spotfire.sfs',
+ 'sfv' => 'text/x-sfv',
+ 'sgi' => 'image/sgi',
+ 'sgl' => 'application/vnd.stardivision.writer-global',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'shf' => 'application/shf+xml',
+ 'sid' => 'image/x-mrsid-image',
+ 'sig' => 'application/pgp-signature',
+ 'sil' => 'audio/silk',
+ 'silo' => 'model/mesh',
+ 'sis' => 'application/vnd.symbian.install',
+ 'sisx' => 'application/vnd.symbian.install',
+ 'sit' => 'application/x-stuffit',
+ 'sitx' => 'application/x-stuffitx',
+ 'skd' => 'application/vnd.koan',
+ 'skm' => 'application/vnd.koan',
+ 'skp' => 'application/vnd.koan',
+ 'skt' => 'application/vnd.koan',
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'slt' => 'application/vnd.epson.salt',
+ 'sm' => 'application/vnd.stepmania.stepchart',
+ 'smf' => 'application/vnd.stardivision.math',
+ 'smi' => 'application/smil+xml',
+ 'smil' => 'application/smil+xml',
+ 'smv' => 'video/x-smv',
+ 'smzip' => 'application/vnd.stepmania.package',
+ 'snd' => 'audio/basic',
+ 'snf' => 'application/x-font-snf',
+ 'so' => 'application/octet-stream',
+ 'spc' => 'application/x-pkcs7-certificates',
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
+ 'spl' => 'application/x-futuresplash',
+ 'spot' => 'text/vnd.in3d.spot',
+ 'spp' => 'application/scvp-vp-response',
+ 'spq' => 'application/scvp-vp-request',
+ 'spx' => 'audio/ogg',
+ 'sql' => 'application/x-sql',
+ 'src' => 'application/x-wais-source',
+ 'srt' => 'application/x-subrip',
+ 'sru' => 'application/sru+xml',
+ 'srx' => 'application/sparql-results+xml',
+ 'ssdl' => 'application/ssdl+xml',
+ 'sse' => 'application/vnd.kodak-descriptor',
+ 'ssf' => 'application/vnd.epson.ssf',
+ 'ssml' => 'application/ssml+xml',
+ 'st' => 'application/vnd.sailingtracker.track',
+ 'stc' => 'application/vnd.sun.xml.calc.template',
+ 'std' => 'application/vnd.sun.xml.draw.template',
+ 'stf' => 'application/vnd.wt.stf',
+ 'sti' => 'application/vnd.sun.xml.impress.template',
+ 'stk' => 'application/hyperstudio',
+ 'stl' => 'application/vnd.ms-pki.stl',
+ 'str' => 'application/vnd.pg.format',
+ 'stw' => 'application/vnd.sun.xml.writer.template',
+ 'sub' => 'text/vnd.dvb.subtitle',
+ 'sus' => 'application/vnd.sus-calendar',
+ 'susp' => 'application/vnd.sus-calendar',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'svc' => 'application/vnd.dvb.service',
+ 'svd' => 'application/vnd.svd',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'swa' => 'application/x-director',
+ 'swf' => 'application/x-shockwave-flash',
+ 'swi' => 'application/vnd.aristanetworks.swi',
+ 'sxc' => 'application/vnd.sun.xml.calc',
+ 'sxd' => 'application/vnd.sun.xml.draw',
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
+ 'sxi' => 'application/vnd.sun.xml.impress',
+ 'sxm' => 'application/vnd.sun.xml.math',
+ 'sxw' => 'application/vnd.sun.xml.writer',
+ 't' => 'text/troff',
+ 't3' => 'application/x-t3vm-image',
+ 'taglet' => 'application/vnd.mynfc',
+ 'tao' => 'application/vnd.tao.intent-module-archive',
+ 'tar' => 'application/x-tar',
+ 'tcap' => 'application/vnd.3gpp2.tcap',
+ 'tcl' => 'application/x-tcl',
+ 'teacher' => 'application/vnd.smart.teacher',
+ 'tei' => 'application/tei+xml',
+ 'teicorpus' => 'application/tei+xml',
+ 'tex' => 'application/x-tex',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'text' => 'text/plain',
+ 'tfi' => 'application/thraud+xml',
+ 'tfm' => 'application/x-tex-tfm',
+ 'tga' => 'image/x-tga',
+ 'thmx' => 'application/vnd.ms-officetheme',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tmo' => 'application/vnd.tmobile-livetv',
+ 'torrent' => 'application/x-bittorrent',
+ 'tpl' => 'application/vnd.groove-tool-template',
+ 'tpt' => 'application/vnd.trid.tpt',
+ 'tr' => 'text/troff',
+ 'tra' => 'application/vnd.trueapp',
+ 'trm' => 'application/x-msterminal',
+ 'tsd' => 'application/timestamped-data',
+ 'tsv' => 'text/tab-separated-values',
+ 'ttc' => 'application/x-font-ttf',
+ 'ttf' => 'application/x-font-ttf',
+ 'ttl' => 'text/turtle',
+ 'twd' => 'application/vnd.simtech-mindmapper',
+ 'twds' => 'application/vnd.simtech-mindmapper',
+ 'txd' => 'application/vnd.genomatix.tuxedo',
+ 'txf' => 'application/vnd.mobius.txf',
+ 'txt' => 'text/plain',
+ 'u32' => 'application/x-authorware-bin',
+ 'udeb' => 'application/x-debian-package',
+ 'ufd' => 'application/vnd.ufdl',
+ 'ufdl' => 'application/vnd.ufdl',
+ 'ulx' => 'application/x-glulx',
+ 'umj' => 'application/vnd.umajin',
+ 'unityweb' => 'application/vnd.unity',
+ 'uoml' => 'application/vnd.uoml+xml',
+ 'uri' => 'text/uri-list',
+ 'uris' => 'text/uri-list',
+ 'urls' => 'text/uri-list',
+ 'ustar' => 'application/x-ustar',
+ 'utz' => 'application/vnd.uiq.theme',
+ 'uu' => 'text/x-uuencode',
+ 'uva' => 'audio/vnd.dece.audio',
+ 'uvd' => 'application/vnd.dece.data',
+ 'uvf' => 'application/vnd.dece.data',
+ 'uvg' => 'image/vnd.dece.graphic',
+ 'uvh' => 'video/vnd.dece.hd',
+ 'uvi' => 'image/vnd.dece.graphic',
+ 'uvm' => 'video/vnd.dece.mobile',
+ 'uvp' => 'video/vnd.dece.pd',
+ 'uvs' => 'video/vnd.dece.sd',
+ 'uvt' => 'application/vnd.dece.ttml+xml',
+ 'uvu' => 'video/vnd.uvvu.mp4',
+ 'uvv' => 'video/vnd.dece.video',
+ 'uvva' => 'audio/vnd.dece.audio',
+ 'uvvd' => 'application/vnd.dece.data',
+ 'uvvf' => 'application/vnd.dece.data',
+ 'uvvg' => 'image/vnd.dece.graphic',
+ 'uvvh' => 'video/vnd.dece.hd',
+ 'uvvi' => 'image/vnd.dece.graphic',
+ 'uvvm' => 'video/vnd.dece.mobile',
+ 'uvvp' => 'video/vnd.dece.pd',
+ 'uvvs' => 'video/vnd.dece.sd',
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
+ 'uvvu' => 'video/vnd.uvvu.mp4',
+ 'uvvv' => 'video/vnd.dece.video',
+ 'uvvx' => 'application/vnd.dece.unspecified',
+ 'uvvz' => 'application/vnd.dece.zip',
+ 'uvx' => 'application/vnd.dece.unspecified',
+ 'uvz' => 'application/vnd.dece.zip',
+ 'vcard' => 'text/vcard',
+ 'vcd' => 'application/x-cdlink',
+ 'vcf' => 'text/x-vcard',
+ 'vcg' => 'application/vnd.groove-vcard',
+ 'vcs' => 'text/x-vcalendar',
+ 'vcx' => 'application/vnd.vcx',
+ 'vis' => 'application/vnd.visionary',
+ 'viv' => 'video/vnd.vivo',
+ 'vob' => 'video/x-ms-vob',
+ 'vor' => 'application/vnd.stardivision.writer',
+ 'vox' => 'application/x-authorware-bin',
+ 'vrml' => 'model/vrml',
+ 'vsd' => 'application/vnd.visio',
+ 'vsf' => 'application/vnd.vsf',
+ 'vss' => 'application/vnd.visio',
+ 'vst' => 'application/vnd.visio',
+ 'vsw' => 'application/vnd.visio',
+ 'vtu' => 'model/vnd.vtu',
+ 'vxml' => 'application/voicexml+xml',
+ 'w3d' => 'application/x-director',
+ 'wad' => 'application/x-doom',
+ 'wav' => 'audio/x-wav',
+ 'wax' => 'audio/x-ms-wax',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wcm' => 'application/vnd.ms-works',
+ 'wdb' => 'application/vnd.ms-works',
+ 'wdp' => 'image/vnd.ms-photo',
+ 'weba' => 'audio/webm',
+ 'webm' => 'video/webm',
+ 'webp' => 'image/webp',
+ 'wg' => 'application/vnd.pmi.widget',
+ 'wgt' => 'application/widget',
+ 'wks' => 'application/vnd.ms-works',
+ 'wm' => 'video/x-ms-wm',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmd' => 'application/x-ms-wmd',
+ 'wmf' => 'application/x-msmetafile',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wmz' => 'application/x-msmetafile',
+ 'woff' => 'application/font-woff',
+ 'wpd' => 'application/vnd.wordperfect',
+ 'wpl' => 'application/vnd.ms-wpl',
+ 'wps' => 'application/vnd.ms-works',
+ 'wqd' => 'application/vnd.wqd',
+ 'wri' => 'application/x-mswrite',
+ 'wrl' => 'model/vrml',
+ 'wsdl' => 'application/wsdl+xml',
+ 'wspolicy' => 'application/wspolicy+xml',
+ 'wtb' => 'application/vnd.webturbo',
+ 'wvx' => 'video/x-ms-wvx',
+ 'x32' => 'application/x-authorware-bin',
+ 'x3d' => 'model/x3d+xml',
+ 'x3db' => 'model/x3d+binary',
+ 'x3dbz' => 'model/x3d+binary',
+ 'x3dv' => 'model/x3d+vrml',
+ 'x3dvz' => 'model/x3d+vrml',
+ 'x3dz' => 'model/x3d+xml',
+ 'xaml' => 'application/xaml+xml',
+ 'xap' => 'application/x-silverlight-app',
+ 'xar' => 'application/vnd.xara',
+ 'xbap' => 'application/x-ms-xbap',
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+ 'xbm' => 'image/x-xbitmap',
+ 'xdf' => 'application/xcap-diff+xml',
+ 'xdm' => 'application/vnd.syncml.dm+xml',
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
+ 'xdssc' => 'application/dssc+xml',
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
+ 'xenc' => 'application/xenc+xml',
+ 'xer' => 'application/patch-ops-error+xml',
+ 'xfdf' => 'application/vnd.adobe.xfdf',
+ 'xfdl' => 'application/vnd.xfdl',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xhvml' => 'application/xv+xml',
+ 'xif' => 'image/vnd.xiff',
+ 'xla' => 'application/vnd.ms-excel',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
+ 'xlc' => 'application/vnd.ms-excel',
+ 'xlf' => 'application/x-xliff+xml',
+ 'xlm' => 'application/vnd.ms-excel',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xlt' => 'application/vnd.ms-excel',
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'xlw' => 'application/vnd.ms-excel',
+ 'xm' => 'audio/xm',
+ 'xml' => 'application/xml',
+ 'xo' => 'application/vnd.olpc-sugar',
+ 'xop' => 'application/xop+xml',
+ 'xpi' => 'application/x-xpinstall',
+ 'xpl' => 'application/xproc+xml',
+ 'xpm' => 'image/x-xpixmap',
+ 'xpr' => 'application/vnd.is-xpr',
+ 'xps' => 'application/vnd.ms-xpsdocument',
+ 'xpw' => 'application/vnd.intercon.formnet',
+ 'xpx' => 'application/vnd.intercon.formnet',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xsm' => 'application/vnd.syncml+xml',
+ 'xspf' => 'application/xspf+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'xvm' => 'application/xv+xml',
+ 'xvml' => 'application/xv+xml',
+ 'xwd' => 'image/x-xwindowdump',
+ 'xyz' => 'chemical/x-xyz',
+ 'xz' => 'application/x-xz',
+ 'yang' => 'application/yang',
+ 'yin' => 'application/yin+xml',
+ 'z1' => 'application/x-zmachine',
+ 'z2' => 'application/x-zmachine',
+ 'z3' => 'application/x-zmachine',
+ 'z4' => 'application/x-zmachine',
+ 'z5' => 'application/x-zmachine',
+ 'z6' => 'application/x-zmachine',
+ 'z7' => 'application/x-zmachine',
+ 'z8' => 'application/x-zmachine',
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
+ 'zip' => 'application/zip',
+ 'zir' => 'application/vnd.zul',
+ 'zirz' => 'application/vnd.zul',
+ 'zmm' => 'application/vnd.handheld-entertainment+xml',
+ '123' => 'application/vnd.lotus-1-2-3',
+);
diff --git a/vendor/swiftmailer/swiftmailer/lib/preferences.php b/vendor/swiftmailer/swiftmailer/lib/preferences.php
new file mode 100644
index 00000000..e5195014
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/preferences.php
@@ -0,0 +1,25 @@
+setCharset('utf-8');
+
+// Without these lines the default caching mechanism is "array" but this uses a lot of memory.
+// If possible, use a disk cache to enable attaching large attachments etc.
+// You can override the default temporary directory by setting the TMPDIR environment variable.
+if (@is_writable($tmpDir = sys_get_temp_dir())) {
+ $preferences->setTempDir($tmpDir)->setCacheType('disk');
+}
+
+// this should only be done when Swiftmailer won't use the native QP content encoder
+// see mime_deps.php
+if (version_compare(phpversion(), '5.4.7', '<')) {
+ $preferences->setQPDotEscape(false);
+}
diff --git a/vendor/swiftmailer/swiftmailer/lib/swift_init.php b/vendor/swiftmailer/swiftmailer/lib/swift_init.php
new file mode 100644
index 00000000..ff719634
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/lib/swift_init.php
@@ -0,0 +1,28 @@
+ 'application/x-php',
+ 'php3' => 'application/x-php',
+ 'php4' => 'application/x-php',
+ 'php5' => 'application/x-php',
+ 'zip' => 'application/zip',
+ 'gif' => 'image/gif',
+ 'png' => 'image/png',
+ 'css' => 'text/css',
+ 'js' => 'text/javascript',
+ 'txt' => 'text/plain',
+ 'aif' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'avi' => 'video/avi',
+ 'bmp' => 'image/bmp',
+ 'bz2' => 'application/x-bz2',
+ 'csv' => 'text/csv',
+ 'dmg' => 'application/x-apple-diskimage',
+ 'doc' => 'application/msword',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'eml' => 'message/rfc822',
+ 'aps' => 'application/postscript',
+ 'exe' => 'application/x-ms-dos-executable',
+ 'flv' => 'video/x-flv',
+ 'gz' => 'application/x-gzip',
+ 'hqx' => 'application/stuffit',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'jar' => 'application/x-java-archive',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm4a' => 'audio/mp4',
+ 'mdb' => 'application/x-msaccess',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mov' => 'video/quicktime',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'odg' => 'vnd.oasis.opendocument.graphics',
+ 'odp' => 'vnd.oasis.opendocument.presentation',
+ 'odt' => 'vnd.oasis.opendocument.text',
+ 'ods' => 'vnd.oasis.opendocument.spreadsheet',
+ 'ogg' => 'audio/ogg',
+ 'pdf' => 'application/pdf',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'ps' => 'application/postscript',
+ 'rar' => 'application/x-rar-compressed',
+ 'rtf' => 'application/rtf',
+ 'tar' => 'application/x-tar',
+ 'sit' => 'application/x-stuffit',
+ 'svg' => 'image/svg+xml',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'ttf' => 'application/x-font-truetype',
+ 'vcf' => 'text/x-vcard',
+ 'wav' => 'audio/wav',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmv' => 'audio/x-ms-wmv',
+ 'xls' => 'application/excel',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xml' => 'application/xml',
+ );
+
+ // wrap array for generating file
+ foreach ($valid_mime_types_preset as $extension => $mime_type) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+
+ // collect extensions
+ $valid_extensions = array();
+
+ // all extensions from second match
+ foreach ($matches[2] as $i => $extensions) {
+ // explode multiple extensions from string
+ $extensions = explode(' ', strtolower($extensions));
+
+ // force array for foreach
+ if (!is_array($extensions)) {
+ $extensions = array($extensions);
+ }
+
+ foreach ($extensions as $extension) {
+ // get mime type
+ $mime_type = $matches[1][$i];
+
+ // check if string length lower than 10
+ if (strlen($extension) < 10) {
+ // add extension
+ $valid_extensions[] = $extension;
+
+ if (!isset($valid_mime_types[$mime_type])) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+ }
+ }
+ }
+ }
+
+ $xml = simplexml_load_string($mime_xml);
+
+ foreach ($xml as $node) {
+ // check if there is no pattern
+ if (!isset($node->glob['pattern'])) {
+ continue;
+ }
+
+ // get all matching extensions from match
+ foreach ((array) $node->glob['pattern'] as $extension) {
+ // skip none glob extensions
+ if (strpos($extension, '.') === false) {
+ continue;
+ }
+
+ // remove get only last part
+ $extension = explode('.', strtolower($extension));
+ $extension = end($extension);
+
+ // maximum length in database column
+ if (strlen($extension) <= 9) {
+ $valid_extensions[] = $extension;
+ }
+ }
+
+ if (isset($node->glob['pattern'][0])) {
+ // mime type
+ $mime_type = strtolower((string) $node['type']);
+
+ // get first extension
+ $extension = strtolower(trim($node->glob['ddpattern'][0], '*.'));
+
+ // skip none glob extensions and check if string length between 1 and 10
+ if (strpos($extension, '.') !== false || strlen($extension) < 1 || strlen($extension) > 9) {
+ continue;
+ }
+
+ // check if string length lower than 10
+ if (!isset($valid_mime_types[$mime_type])) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+ }
+ }
+
+ // full list of valid extensions only
+ $valid_mime_types = array_unique($valid_mime_types);
+ ksort($valid_mime_types);
+
+ // combine mime types and extensions array
+ $output = "$preamble\$swift_mime_types = array(\n ".implode($valid_mime_types, ",\n ")."\n);";
+
+ // write mime_types.php config file
+ @file_put_contents('./mime_types.php', $output);
+}
+
+generateUpToDateMimeArray();
diff --git a/vendor/swiftmailer/swiftmailer/phpunit.xml.dist b/vendor/swiftmailer/swiftmailer/phpunit.xml.dist
new file mode 100644
index 00000000..606c5b44
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/phpunit.xml.dist
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+ tests/unit
+
+
+ tests/acceptance
+
+
+ tests/bug
+
+
+ tests/smoke
+
+
+
+
+
+
+
+
diff --git a/vendor/swiftmailer/swiftmailer/tests/IdenticalBinaryConstraint.php b/vendor/swiftmailer/swiftmailer/tests/IdenticalBinaryConstraint.php
new file mode 100644
index 00000000..069d11ab
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/IdenticalBinaryConstraint.php
@@ -0,0 +1,62 @@
+value = $value;
+ }
+
+ /**
+ * Evaluates the constraint for parameter $other. Returns TRUE if the
+ * constraint is met, FALSE otherwise.
+ *
+ * @param mixed $other Value or object to evaluate.
+ *
+ * @return bool
+ */
+ public function matches($other)
+ {
+ $aHex = $this->asHexString($this->value);
+ $bHex = $this->asHexString($other);
+
+ return $aHex === $bHex;
+ }
+
+ /**
+ * Returns a string representation of the constraint.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'indentical binary';
+ }
+
+ /**
+ * Get the given string of bytes as a stirng of Hexadecimal sequences.
+ *
+ * @param string $binary
+ *
+ * @return string
+ */
+ private function asHexString($binary)
+ {
+ $hex = '';
+
+ $bytes = unpack('H*', $binary);
+
+ foreach ($bytes as &$byte) {
+ $byte = strtoupper($byte);
+ }
+
+ return implode('', $bytes);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/StreamCollector.php b/vendor/swiftmailer/swiftmailer/tests/StreamCollector.php
new file mode 100644
index 00000000..7f079d98
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/StreamCollector.php
@@ -0,0 +1,11 @@
+content .= $arg;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/SwiftMailerSmokeTestCase.php b/vendor/swiftmailer/swiftmailer/tests/SwiftMailerSmokeTestCase.php
new file mode 100644
index 00000000..21d89e83
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/SwiftMailerSmokeTestCase.php
@@ -0,0 +1,46 @@
+markTestSkipped(
+ 'Smoke tests are skipped if tests/smoke.conf.php is not edited'
+ );
+ }
+ }
+
+ protected function _getMailer()
+ {
+ switch (SWIFT_SMOKE_TRANSPORT_TYPE) {
+ case 'smtp':
+ $transport = Swift_DependencyContainer::getInstance()->lookup('transport.smtp')
+ ->setHost(SWIFT_SMOKE_SMTP_HOST)
+ ->setPort(SWIFT_SMOKE_SMTP_PORT)
+ ->setUsername(SWIFT_SMOKE_SMTP_USER)
+ ->setPassword(SWIFT_SMOKE_SMTP_PASS)
+ ->setEncryption(SWIFT_SMOKE_SMTP_ENCRYPTION)
+ ;
+ break;
+ case 'sendmail':
+ $transport = Swift_DependencyContainer::getInstance()->lookup('transport.sendmail')
+ ->setCommand(SWIFT_SMOKE_SENDMAIL_COMMAND)
+ ;
+ break;
+ case 'mail':
+ case 'nativemail':
+ $transport = Swift_DependencyContainer::getInstance()->lookup('transport.mail');
+ break;
+ default:
+ throw new Exception('Undefined transport ['.SWIFT_SMOKE_TRANSPORT_TYPE.']');
+ }
+
+ return new Swift_Mailer($transport);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/SwiftMailerTestCase.php b/vendor/swiftmailer/swiftmailer/tests/SwiftMailerTestCase.php
new file mode 100644
index 00000000..f0e27361
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/SwiftMailerTestCase.php
@@ -0,0 +1,34 @@
+
\ No newline at end of file
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/files/swiftmailer.png b/vendor/swiftmailer/swiftmailer/tests/_samples/files/swiftmailer.png
new file mode 100644
index 00000000..1b95f619
Binary files /dev/null and b/vendor/swiftmailer/swiftmailer/tests/_samples/files/swiftmailer.png differ
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/files/textfile.zip b/vendor/swiftmailer/swiftmailer/tests/_samples/files/textfile.zip
new file mode 100644
index 00000000..5a580ecb
Binary files /dev/null and b/vendor/swiftmailer/swiftmailer/tests/_samples/files/textfile.zip differ
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/CA.srl b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/CA.srl
new file mode 100644
index 00000000..dd9818ab
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/CA.srl
@@ -0,0 +1 @@
+D42DA34CF90FA0DE
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.crt
new file mode 100644
index 00000000..695f8142
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDazCCAlOgAwIBAgIJAKJCGQYLxWT1MA0GCSqGSIb3DQEBBQUAMEwxFzAVBgNV
+BAMMDlN3aWZ0bWFpbGVyIENBMRQwEgYDVQQKDAtTd2lmdG1haWxlcjEOMAwGA1UE
+BwwFUGFyaXMxCzAJBgNVBAYTAkZSMB4XDTEzMTEyNzA4MzkxMFoXDTE3MTEyNjA4
+MzkxMFowTDEXMBUGA1UEAwwOU3dpZnRtYWlsZXIgQ0ExFDASBgNVBAoMC1N3aWZ0
+bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC7RLdHE3OWo9aZwv1xA/cYyPui/gegxpTqClRp
+gGcVQ+jxIfnJQDQndyoAvFDiqOiZ+gAjZGJeUHDp9C/2IZp05MLh+omt9N8pBykm
+3nj/3ZwPXOAO0uyDPAOHhISITAxEuZCqDnq7iYujywtwfQ7bpW1hCK9PfNZYMStM
+kw7LsGr5BqcKkPuOWTvxE3+NqK8HxydYolsoApEGhgonyImVh1Pg1Kjkt5ojvwAX
+zOdjfw5poY5NArwuLORUH+XocetRo8DC6S42HkU/MoqcYxa9EuRuwuQh7GtE6baR
+PgrDsEYaY4Asy43sK81V51F/8Q1bHZKN/goQdxQwzv+/nOLTAgMBAAGjUDBOMB0G
+A1UdDgQWBBRHgqkl543tKhsVAvcx1I0JFU7JuDAfBgNVHSMEGDAWgBRHgqkl543t
+KhsVAvcx1I0JFU7JuDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAz
+OJiEQcygKGkkXXDiXGBvP/cSznj3nG9FolON0yHUBgdvLfNnctRMStGzPke0siLt
+RJvjqiL0Uw+blmLJU8lgMyLJ9ctXkiLJ/WflabN7VzmwYRWe5HzafGQJAg5uFjae
+VtAAHQgvbmdXB6brWvcMQmB8di7wjVedeigZvkt1z2V0FtBy8ybJaT5H6bX9Bf5C
+dS9r4mLhk/0ThthpRhRxsmupSL6e49nJaIk9q0UTEQVnorJXPcs4SPTIY51bCp6u
+cOebhNgndSxCiy0zSD7vRjNiyB/YNGZ9Uv/3DNTLleMZ9kZgfoKVpwYKrRL0IFT/
+cfS2OV1wxRxq668qaOfK
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.key
new file mode 100644
index 00000000..df674708
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAu0S3RxNzlqPWmcL9cQP3GMj7ov4HoMaU6gpUaYBnFUPo8SH5
+yUA0J3cqALxQ4qjomfoAI2RiXlBw6fQv9iGadOTC4fqJrfTfKQcpJt54/92cD1zg
+DtLsgzwDh4SEiEwMRLmQqg56u4mLo8sLcH0O26VtYQivT3zWWDErTJMOy7Bq+Qan
+CpD7jlk78RN/jaivB8cnWKJbKAKRBoYKJ8iJlYdT4NSo5LeaI78AF8znY38OaaGO
+TQK8LizkVB/l6HHrUaPAwukuNh5FPzKKnGMWvRLkbsLkIexrROm2kT4Kw7BGGmOA
+LMuN7CvNVedRf/ENWx2Sjf4KEHcUMM7/v5zi0wIDAQABAoIBAGyaWkvu/O7Uz2TW
+z1JWgVuvWzfYaKYV5FCicvfITn/npVUKZikPge+NTR+mFqaMXHDHqoLb+axGrGUR
+hysPq9q0vEx/lo763tyVWYlAJh4E8Dd8njganK0zBbz23kGJEOheUYY95XGTQBda
+bqTq8c3x7zAB8GGBvXDh+wFqm38GLyMF6T+YEzWJZqXfg31f1ldRvf6+VFwlLfz6
+cvTR7oUpYIsUeGE47kBs13SN7Oju6a355o/7wy9tOCRiu+r/ikXFh8rFGLfeTiwv
+R1dhYjcEYGxZUD8u64U+Cj4qR1P0gHJL0kbh22VMMqgALOc8FpndkjNdg1Nun2X8
+BWpsPwECgYEA7C9PfTOIZfxGBlCl05rmWex++/h5E5PbH1Cw/NGjIH1HjmAkO3+5
+WyMXhySOJ8yWyCBQ/nxqc0w7+TO4C7wQcEdZdUak25KJ74v0sfmWWrVw6kcnLU6k
+oawW/L2F2w7ET3zDoxKh4fOF34pfHpSbZk7XJ68YOfHpYVnP4efkQVMCgYEAyvrM
+KA7xjnsKumWh206ag3QEI0M/9uPHWmrh2164p7w1MtawccZTxYYJ5o5SsjTwbxkf
+0cAamp4qLInmRUxU1gk76tPYC3Ndp6Yf1C+dt0q/vtzyJetCDrdz8HHT1SpKbW0l
+g6z1I5FMwa6oWvWsfS++W51vsxUheNsOJ4uxKIECgYBwM7GRiw+7U3N4wItm0Wmp
+Qp642Tu7vzwTzmOmV3klkB6UVrwfv/ewgiVFQGqAIcNn42JW44g2qfq70oQWnws4
+K80l15+t6Bm7QUPH4Qg6o4O26IKGFZxEadqpyudyP7um/2B5cfqRuvzYS4YQowyI
+N+AirB3YOUJjyyTk7yMSnQKBgGNLpSvDg6+ryWe96Bwcq8G6s3t8noHsk81LlAl4
+oOSNUYj5NX+zAbATDizXWuUKuMPgioxVaa5RyVfYbelgme/KvKD32Sxg12P4BIIM
+eR79VifMdjjOiZYhcHojdPlGovo89qkfpxwrLF1jT8CPhj4HaRvwPIBiyekRYC9A
+Sv4BAoGAXCIC1xxAJP15osUuQjcM8KdsL1qw+LiPB2+cJJ2VMAZGV7CR2K0aCsis
+OwRaYM0jZKUpxzp1uwtfrfqbhdYsv+jIBkfwoShYZuo6MhbUrj0sffkhJC3WrT2z
+xafCFLFv1idzGvvNxatlp1DNKrndG2NS3syVAox9MnL5OMsvGM8=
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/create-cert.sh b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/create-cert.sh
new file mode 100644
index 00000000..0454f205
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/create-cert.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+openssl genrsa -out CA.key 2048
+openssl req -x509 -new -nodes -key CA.key -days 1460 -subj '/CN=Swiftmailer CA/O=Swiftmailer/L=Paris/C=FR' -out CA.crt
+openssl x509 -in CA.crt -clrtrust -out CA.crt
+
+openssl genrsa -out sign.key 2048
+openssl req -new -key sign.key -subj '/CN=Swiftmailer-User/O=Swiftmailer/L=Paris/C=FR' -out sign.csr
+openssl x509 -req -in sign.csr -CA CA.crt -CAkey CA.key -out sign.crt -days 1460 -addtrust emailProtection
+openssl x509 -in sign.crt -clrtrust -out sign.crt
+
+rm sign.csr
+
+openssl genrsa -out intermediate.key 2048
+openssl req -new -key intermediate.key -subj '/CN=Swiftmailer Intermediate/O=Swiftmailer/L=Paris/C=FR' -out intermediate.csr
+openssl x509 -req -in intermediate.csr -CA CA.crt -CAkey CA.key -set_serial 01 -out intermediate.crt -days 1460
+openssl x509 -in intermediate.crt -clrtrust -out intermediate.crt
+
+rm intermediate.csr
+
+openssl genrsa -out sign2.key 2048
+openssl req -new -key sign2.key -subj '/CN=Swiftmailer-User2/O=Swiftmailer/L=Paris/C=FR' -out sign2.csr
+openssl x509 -req -in sign2.csr -CA intermediate.crt -CAkey intermediate.key -set_serial 01 -out sign2.crt -days 1460 -addtrust emailProtection
+openssl x509 -in sign2.crt -clrtrust -out sign2.crt
+
+rm sign2.csr
+
+openssl genrsa -out encrypt.key 2048
+openssl req -new -key encrypt.key -subj '/CN=Swiftmailer-User/O=Swiftmailer/L=Paris/C=FR' -out encrypt.csr
+openssl x509 -req -in encrypt.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out encrypt.crt -days 1460 -addtrust emailProtection
+openssl x509 -in encrypt.crt -clrtrust -out encrypt.crt
+
+rm encrypt.csr
+
+openssl genrsa -out encrypt2.key 2048
+openssl req -new -key encrypt2.key -subj '/CN=Swiftmailer-User2/O=Swiftmailer/L=Paris/C=FR' -out encrypt2.csr
+openssl x509 -req -in encrypt2.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out encrypt2.crt -days 1460 -addtrust emailProtection
+openssl x509 -in encrypt2.crt -clrtrust -out encrypt2.crt
+
+rm encrypt2.csr
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt
new file mode 100644
index 00000000..7435855c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFjCCAf4CCQDULaNM+Q+g3TANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
+d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
+cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTFaFw0xNzExMjYwODM5MTFa
+ME4xGTAXBgNVBAMMEFN3aWZ0bWFpbGVyLVVzZXIxFDASBgNVBAoMC1N3aWZ0bWFp
+bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCcNO+fVZBT2znmVwXXZ08n3G5WA1kyvqh9z4RBBZOD
+V46Gc1X9MMXr9+wzZBFkAckKaa6KsTkeUr4pC8XUBpQnakxH/kW9CaDPdOE+7wNo
+FkPfc6pjWWgpAVxdkrtk7pb4/aGQ++HUkqVu0cMpIcj/7ht7H+3QLZHybn+oMr2+
+FDnn8vPmHxVioinSrxKTlUITuLWS9ZZUTrDa0dG8UAv55A/Tba4T4McCPDpJSA4m
+9jrW321NGQUntQoItOJxagaueSvh6PveGV826gTXoU5X+YJ3I2OZUEQ2l6yByAzf
+nT+QlxPj5ikotFwL72HsenYtetynOO/k43FblAF/V/l7AgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBAJ048Sdb9Sw5OJM5L00OtGHgcT1B/phqdzSjkM/s64cg3Q20VN+F
+fZIIkOnxgyYWcpOWXcdNw2tm5OWhWPGsBcYgMac7uK/ukgoOJSjICg+TTS5kRo96
+iHtmImqkWc6WjNODh7uMnQ6DsZsscdl7Bkx5pKhgGnEdHr5GW8sztgXgyPQO5LUs
+YzCmR1RK1WoNMxwbPrGLgYdcpJw69ns5hJbZbMWwrdufiMjYWvTfBPABkk1JRCcY
+K6rRTAx4fApsw1kEIY8grGxyAzfRXLArpro7thJr0SIquZ8GpXkQT/mgRR8JD9Hp
+z9yhr98EnKzITE/yclGN4pUsuk9S3jiyzUU=
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key
new file mode 100644
index 00000000..aa620ca6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAnDTvn1WQU9s55lcF12dPJ9xuVgNZMr6ofc+EQQWTg1eOhnNV
+/TDF6/fsM2QRZAHJCmmuirE5HlK+KQvF1AaUJ2pMR/5FvQmgz3ThPu8DaBZD33Oq
+Y1loKQFcXZK7ZO6W+P2hkPvh1JKlbtHDKSHI/+4bex/t0C2R8m5/qDK9vhQ55/Lz
+5h8VYqIp0q8Sk5VCE7i1kvWWVE6w2tHRvFAL+eQP022uE+DHAjw6SUgOJvY61t9t
+TRkFJ7UKCLTicWoGrnkr4ej73hlfNuoE16FOV/mCdyNjmVBENpesgcgM350/kJcT
+4+YpKLRcC+9h7Hp2LXrcpzjv5ONxW5QBf1f5ewIDAQABAoIBADmuMm2botfUM+Ui
+bT3FIC2P8A5C3kUmsgEDB8sazAXL5w0uuanswKkJu2aepO1Q23PE4nbESlswIpf1
+iO9qHnsPfWt4MThEveTdO++JQrDEx/tTMq/M6/F4VysWa6wxjf4Taf2nhRSBsiTh
+wDcICri2q98jQyWELkhfFTR+yCHPsn6iNtzE2OpNv9ojKiSqck/sVjC39Z+uU/HD
+N4v0CPf9pDGkO+modaVGKf2TpvZT7Hpq/jsPzkk1h7BY7aWdZiIY4YkBkWYqZk8f
+0dsxKkOR2glfuEYNtcywG+4UGx3i1AY0mMu96hH5M1ACFmFrTCoodmWDnWy9wUpm
+leLmG8ECgYEAywWdryqcvLyhcmqHbnmUhCL9Vl4/5w5fr/5/FNvqArxSGwd2CxcN
+Jtkvu22cxWAUoe155eMc6GlPIdNRG8KdWg4sg0TN3Jb2jiHQ3QkHXUJlWU6onjP1
+g2n5h052JxVNGBEb7hr3U7ZMW6wnuYnGdYwCB9P3r5oGxxtfVRB8ygUCgYEAxPfy
+tAd3SNT8Sv/cciw76GYKbztUjJRXkLo6GOBGq/AQxP1NDWMuL2AES11YIahidMsF
+TMmM+zhkNHsd5P69p87FTMWx0cLoH0M9iQNK7Q6C1luTjLf5DTFuk+nHGErM4Drs
++6Ly1Z4KLXfXgBDD8Ce6U9+W3RrCc36poGZvjX8CgYEAna0P6WJr9r19mhIYevmc
+Gf/ex7xNXxMvx80dP8MIfPVrwyhJSpWtljVpt+SKtFRJ0fVRDfUUl4Bqf/fR74B3
+muCVO6ItTBxHAt5Ki9CeUpTlh7XqiWwLSvP8Y1TRuMr3ZDCtg4CYBAD6Ttxmwde6
+NcL2NMQwgsZaazrcEIHMmU0CgYEAl/Mn2tZ/oUIdt8YWzEVvmeNOXW0J1sGBo/bm
+ZtZt7qpuZWl7jb5bnNSXu4QxPxXljnAokIpUJmHke9AWydfze4c6EfXZLhcMd0Gq
+MQ7HOIWfTbqr4zzx9smRoq4Ql57s2nba521XpJAdDeKL7xH/9j7PsXCls8C3Dd5D
+AajEmgUCgYAGEdn6tYxIdX7jF39E3x7zHQf8jHIoQ7+cLTLtd944mSGgeqMfbiww
+CoUa+AAUqjdAD5ViAyJrA+gmDtWpkFnJZtToXYwfUF2o3zRo4k1DeBrVbFqwSQkE
+omrfiBGtviYIPdqQLE34LYpWEooNPraqO9qTyc+9w5038u2OFS+WmQ==
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt
new file mode 100644
index 00000000..69081656
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFzCCAf8CCQDULaNM+Q+g3jANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
+d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
+cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTJaFw0xNzExMjYwODM5MTJa
+ME8xGjAYBgNVBAMMEVN3aWZ0bWFpbGVyLVVzZXIyMRQwEgYDVQQKDAtTd2lmdG1h
+aWxlcjEOMAwGA1UEBwwFUGFyaXMxCzAJBgNVBAYTAkZSMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAw4AoYVYss2sa1BWJAJpK6gVemjXrp1mVXVpb1/z6
+SH15AGsp3kiNXsMpgvsdofbqC/5HXrw2G8gWqo+uh6GuK67+Tvp7tO2aD4+8CZzU
+K1cffj7Pbx95DUPwXckv79PT5ZcuyeFaVo92aug11+gS/P8n0WXSlzZxNuZ1f3G2
+r/IgwfNKZlarEf1Ih781L2SwmyveW/dtsV2pdrd4IZwsV5SOF2zBFIXSuhPN0c+m
+mtwSJe+Ow1udLX4KJkAX8sGVFJ5P5q4s2nS9vLkkj7X6YRQscbyJO9L7e1TksRqL
+DLxZwiko6gUhp4/bIs1wDj5tzkQBi4qXviRq3i7A9b2d0QIDAQABMA0GCSqGSIb3
+DQEBBQUAA4IBAQAj8iARhPB2DA3YfT5mJJrgU156Sm0Z3mekAECsr+VqFZtU/9Dz
+pPFYEf0hg61cjvwhLtOmaTB+50hu1KNNlu8QlxAfPJqNxtH85W0CYiZHJwW9eSTr
+z1swaHpRHLDUgo3oAXdh5syMbdl0MWos0Z14WP5yYu4IwJXs+j2JRW70BICyrNjm
+d+AjCzoYjKMdJkSj4uxQEOuW2/5veAoDyU+kHDdfT7SmbyoKu+Pw4Xg/XDuKoWYg
+w5/sRiw5vxsmOr9+anspDHdP9rUe1JEfwAJqZB3fwdqEyxu54Xw/GedG4wZBEJf0
+ZcS1eh31emcjYUHQa1IA93jcFSmXzJ+ftJrY
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key
new file mode 100644
index 00000000..e322a8f4
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAw4AoYVYss2sa1BWJAJpK6gVemjXrp1mVXVpb1/z6SH15AGsp
+3kiNXsMpgvsdofbqC/5HXrw2G8gWqo+uh6GuK67+Tvp7tO2aD4+8CZzUK1cffj7P
+bx95DUPwXckv79PT5ZcuyeFaVo92aug11+gS/P8n0WXSlzZxNuZ1f3G2r/IgwfNK
+ZlarEf1Ih781L2SwmyveW/dtsV2pdrd4IZwsV5SOF2zBFIXSuhPN0c+mmtwSJe+O
+w1udLX4KJkAX8sGVFJ5P5q4s2nS9vLkkj7X6YRQscbyJO9L7e1TksRqLDLxZwiko
+6gUhp4/bIs1wDj5tzkQBi4qXviRq3i7A9b2d0QIDAQABAoIBAH8RvK1PmqxfkEeL
+W8oVf13OcafgJjRW6NuNkKa5mmAlldFs1gDRvXl7dm7ZE3CjkYqMEw2DXdP+4KSp
+0TH9J7zi+A6ThnaZ/QniTcEdu1YUQbcH0kIS/dZec0wyKUNDtrXC5zl2jQY4Jyrj
+laOpBzaEDfhvq0p3q2yYrIRSgACpSEVEsfPoHrxtlLhfMkVNe8P0nkQkzdwou5MQ
+MZKV4JUopLHLgPH6IXQCqA1wzlU32yZ86w88GFcBVLkwlLJCKbuAo7yxMCD+nzvA
+xm5NuF1kzpP0gk+kZRXF+rFEV4av/2kSS+n8IeUBQZrxovLBuQHVDvJXoqcEjmlh
+ZUltznUCgYEA4inwieePfb7kh7L/ma5OLLn+uCNwzVw9LayzXT1dyPravOnkHl6h
+MgaoTspqDyU8k8pStedRrr5dVYbseni/A4WSMGvi4innqSXBQGp64TyeJy/e+LrS
+ypSWQ6RSJkCxI5t8s4mOpR7FMcdE34I5qeA4G5RS1HIacn7Hxc7uXtcCgYEA3Uqn
+E7EDfNfYdZm6AikvE6x64oihWI0x47rlkLu6lf6ihiF1dbfaEN+IAaIxQ/unGYwU
+130F0TUwarXnVkeBIRlij4fXhExyd7USSQH1VpqmIqDwsS2ojrzQVMo5UcH+A22G
+bbHPtwJNmw8a7yzTPWo2/vnjgV2OaXEQ9vCVG5cCgYEAu1kEoihJDGBijSqxY4wp
+xBE7OSxamDNtlnV2i6l3FDMBmfaieqnnHDq5l7NDklJFUSQLyhXZ60hUprHDGV0G
+1pMCW8wzQSh3d/4HjSXnrsd5N3sHWMHiNeBKbbQkPP3f/2AhN9SebpgDwE2S9xe4
+TsmnkOkYiFYRJIFzWaAmhDcCgYEAwxRCgZt0xaPKULG6RpljxOYyVm24PsYKCwYB
+xjuYWw5k2/W3BJWVCXblAPuojpPUVTMmVGkErc9D5W6Ch471iOZF+t334cs6xci8
+W9v8GeKvPqu+Q5NKmrpctcKoESkA8qik7yLnSCAhpeYFCn/roKJ35QMJyktddhqU
+p/yilfUCgYBxZ6YmFjYH6l5SxQdcfa5JQ2To8lZCfRJwB65EyWj4pKH4TaWFS7vb
+50WOGTBwJgyhTKLCO3lOmXIUyIwC+OO9xzaeRCBjqEhpup/Ih3MsfMEd6BZRVK5E
+IxtmIWba5HQ52k8FKHeRrRB7PSVSADUN2pUFkLudH+j/01kSZyJoLA==
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.crt
new file mode 100644
index 00000000..012f734e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFjCCAf4CAQEwDQYJKoZIhvcNAQEFBQAwTDEXMBUGA1UEAwwOU3dpZnRtYWls
+ZXIgQ0ExFDASBgNVBAoMC1N3aWZ0bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkG
+A1UEBhMCRlIwHhcNMTQxMTIwMTMyNTQxWhcNMTgxMTE5MTMyNTQxWjBWMSEwHwYD
+VQQDDBhTd2lmdG1haWxlciBJbnRlcm1lZGlhdGUxFDASBgNVBAoMC1N3aWZ0bWFp
+bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDSgEhftX6f1wV+uqWl4J+zwCn8fHaLZT6GZ0Gs9ThE
+4e+4mkLG1rvSEIJon8U0ic8Zph1UGa1Grveh5bgbldHlFxYSsCCyDGgixRvRWNhI
+KuO+SxaIZChqqKwVn3aNQ4BZOSo/MjJ/jQyr9BMgMmdxlHR3e1wkkeAkW//sOsfu
+xQGF1h9yeQvuu/GbG6K7vHSGOGd5O3G7bftfQ7l78TMqeJ7jV32AdJeuO5MD4dRn
+W4CQLTaeribLN0MKn35UdSiFoZxKHqqWcgtl5xcJWPOmq6CsAJ2Eo90kW/BHOrLv
+10h6Oan9R1PdXSvSCvVnXY3Kz30zofw305oA/KJk/hVzAgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBABijZ2NNd05Js5VFNr4uyaydam9Yqu/nnrxbPRbAXPlCduydu2Gd
+d1ekn3nblMJ87Bc7zVyHdAQD8/AfS1LOKuoWHpTzmlpIL+8T5sbCYG5J1jKdeLkh
+7L/UD5v1ACgA33oKtN8GzcrIq8Zp73r0n+c3hFCfDYRSZRCxGyIf3qgU2LBOD0A3
+wTff/N8E/p3WaJX9VnuQ7xyRMOubDuqJnlo5YsFv7wjyGOIAz9afZzcEbH6czt/t
+g0Xc/kGr/fkAjUu+z3ZfE4247Gut5m3hEVwWkpEEzQo4osX/BEX20Q2nPz9WBq4a
+pK3qNNGwAqS4gdE3ihOExMWxAKgr9d2CcU4=
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.key
new file mode 100644
index 00000000..569eb0c5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA0oBIX7V+n9cFfrqlpeCfs8Ap/Hx2i2U+hmdBrPU4ROHvuJpC
+xta70hCCaJ/FNInPGaYdVBmtRq73oeW4G5XR5RcWErAgsgxoIsUb0VjYSCrjvksW
+iGQoaqisFZ92jUOAWTkqPzIyf40Mq/QTIDJncZR0d3tcJJHgJFv/7DrH7sUBhdYf
+cnkL7rvxmxuiu7x0hjhneTtxu237X0O5e/EzKnie41d9gHSXrjuTA+HUZ1uAkC02
+nq4myzdDCp9+VHUohaGcSh6qlnILZecXCVjzpqugrACdhKPdJFvwRzqy79dIejmp
+/UdT3V0r0gr1Z12Nys99M6H8N9OaAPyiZP4VcwIDAQABAoIBAQDLJiKyu2XIvKsA
+8wCKZY262+mpUjTVso/1BhHL6Zy0XZgMgFORsgrxYB16+zZGzfiguD/1uhIP9Svn
+gtt7Q8udW/phbrkfG/okFDYUg7m3bCz+qVjFqGOZC8+Hzq2LB2oGsbSj6L3zexyP
+lq4elIZghvUfml4CrQW0EVWbld79/kF7XHABcIOk2+3f63XAQWkjdFNxj5+z6TR0
+52Rv7SmRioAsukW9wr77G3Luv/0cEzDFXgGW5s0wO+rJg28smlsIaj+Y0KsptTig
+reQvReAT/S5ZxEp4H6WtXQ1WmaliMB0Gcu4TKB0yE8DoTeCePuslo9DqGokXYT66
+oqtcVMqBAoGBAPoOL9byNNU/bBNDWSCiq8PqhSjl0M4vYBGqtgMXM4GFOJU+W2nX
+YRJbbxoSd/DKjnxEsR6V0vDTDHj4ZSkgmpEmVhEdAiwUwaZ0T8YUaCPhdiAENo5+
+zRBWVJcvAC2XKTK1hy5D7Z5vlC32HHygYqitU+JsK4ylvhrdeOcGx5cfAoGBANeB
+X0JbeuqBEwwEHZqYSpzmtB+IEiuYc9ARTttHEvIWgCThK4ldAzbXhDUIQy3Hm0sL
+PzDA33furNl2WwB+vmOuioYMNjArKrfg689Aim1byg4AHM5XVQcqoDSOABtI55iP
+E0hYDe/d4ema2gk1uR/mT4pnLnk2VzRKsHUbP9stAoGBAKjyIuJwPMADnMqbC0Hg
+hnrVHejW9TAJlDf7hgQqjdMppmQ3gF3PdjeH7VXJOp5GzOQrKRxIEABEJ74n3Xlf
+HO+K3kWrusb7syb6mNd0/DOZ5kyVbCL0iypJmdeXmuAyrFQlj9LzdD1Cl/RBv1d4
+qY/bo7xsZzQc24edMU2uJ/XzAoGBAMHChA95iK5HlwR6vtM8kfk4REMFaLDhxV8R
+8MCeyp33NQfzm91JT5aDd07nOt9yVGHInuwKveFrKuXq0C9FxZCCYfHcEOyGI0Zo
+aBxTfyKMIMMtvriXNM/Yt2oJMndVuUUlfsTQxtcfu/r5S4h0URopTOK3msVI4mcV
+sEnaUjORAoGAGDnslKYtROQMXTe4sh6CoJ32J8UZVV9M+8NLus9rO0v/eZ/pIFxo
+MXGrrrl51ScqahCQ+DXHzpLvInsdlAJvDP3ymhb7H2xGsyvb3x2YgsLmr1YVOnli
+ISbCssno3vZyFU1TDjeEIKqZHc92byHNMjMuhmlaA25g8kb0cCO76EA=
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.crt
new file mode 100644
index 00000000..15fd65d2
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFjCCAf4CCQDULaNM+Q+g3DANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T
+d2lmdG1haWxlciBDQTEUMBIGA1UECgwLU3dpZnRtYWlsZXIxDjAMBgNVBAcMBVBh
+cmlzMQswCQYDVQQGEwJGUjAeFw0xMzExMjcwODM5MTBaFw0xNzExMjYwODM5MTBa
+ME4xGTAXBgNVBAMMEFN3aWZ0bWFpbGVyLVVzZXIxFDASBgNVBAoMC1N3aWZ0bWFp
+bGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCTe8ZouyjVGgqlljhaswYqLj7icMoHq+Qg13CE+zJg
+tl2/UzyPhAd3WWOIvlQ0lu+E/n0bXrS6+q28DrQ3UgJ9BskzzLz15qUO12b92AvG
+vLJ+9kKuiM5KXDljOAsXc7/A9UUGwEFA1D0mkeMmkHuiQavAMkzBLha22hGpg/hz
+VbE6W9MGna0szd8yh38IY1M5uR+OZ0dG3KbVZb7H3N0OLOP8j8n+4YtAGAW+Onz/
+2CGPfZ1kaDMvY/WTZwyGeA4FwCPy1D8tfeswqKnWDB9Sfl8hns5VxnoJ3dqKQHeX
+iC4OMfQ0U4CcuM5sVYJZRNNwP7/TeUh3HegnOnuZ1hy9AgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBAAEPjGt98GIK6ecAEat52aG+8UP7TuZaxoH3cbZdhFTafrP8187F
+Rk5G3LCPTeA/QIzbHppA4fPAiS07OVSwVCknpTJbtKKn0gmtTZxThacFHF2NlzTH
+XxM5bIbkK3jzIF+WattyTSj34UHHfaNAmvmS7Jyq6MhjSDbcQ+/dZ9eo2tF/AmrC
++MBhyH8aUYwKhTOQQh8yC11niziHhGO99FQ4tpuD9AKlun5snHq4uK9AOFe8VhoR
+q2CqX5g5v8OAtdlvzhp50IqD4BNOP+JrUxjGLHDG76BZZIK2Ai1eBz+GhRlIQru/
+8EhQzd94mdFEPblGbmuD2QXWLFFKLiYOwOc=
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.key
new file mode 100644
index 00000000..b3d3c535
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAk3vGaLso1RoKpZY4WrMGKi4+4nDKB6vkINdwhPsyYLZdv1M8
+j4QHd1ljiL5UNJbvhP59G160uvqtvA60N1ICfQbJM8y89ealDtdm/dgLxryyfvZC
+rojOSlw5YzgLF3O/wPVFBsBBQNQ9JpHjJpB7okGrwDJMwS4WttoRqYP4c1WxOlvT
+Bp2tLM3fMod/CGNTObkfjmdHRtym1WW+x9zdDizj/I/J/uGLQBgFvjp8/9ghj32d
+ZGgzL2P1k2cMhngOBcAj8tQ/LX3rMKip1gwfUn5fIZ7OVcZ6Cd3aikB3l4guDjH0
+NFOAnLjObFWCWUTTcD+/03lIdx3oJzp7mdYcvQIDAQABAoIBAH2vrw/T6GFrlwU0
+twP8q1VJIghCDLpq77hZQafilzU6VTxWyDaaUu6QPDXt1b8Xnjnd02p+1FDAj0zD
+zyuR9VLtdIxzf9mj3KiAQ2IzOx3787YlUgCB0CQo4jM/MJyk5RahL1kogLOp7A8x
+pr5XxTUq+B6L/0Nmbq8XupOXRyWp53amZ5N8sgWDv4oKh9fqgAhxbSG6KUkTmhYs
+DLinWg86Q28pSn+eivf4dehR56YwtTBVguXW3WKO70+GW1RotSrS6e6SSxfKYksZ
+a7/J1hCmJkEE3+4C8BpcI0MelgaK66ocN0pOqDF9ByxphARqyD7tYCfoS2P8gi81
+XoiZJaECgYEAwqx4AnDX63AANsfKuKVsEQfMSAG47SnKOVwHB7prTAgchTRcDph1
+EVOPtJ+4ssanosXzLcN/dCRlvqLEqnKYAOizy3C56CyRguCpO1AGbRpJjRmHTRgA
+w8iArhM07HgJ3XLFn99V/0bsPCMxW8dje1ZMjKjoQtDrXRQMtWaVY+UCgYEAwfGi
+f0If6z7wJj9gQUkGimWDAg/bxDkvEeh3nSD/PQyNiW0XDclcb3roNPQsal2ZoMwt
+f1bwkclw7yUCIZBvXWEkZapjKCdseTp6nglScxr8GAzfN9p5KQl+OS3GzC6xZf6C
+BsZQ5ucsHTHsCAi3WbwGK829z9c7x0qRwgwu9/kCgYEAsqwEwYi8Q/RZ3e1lXC9H
+jiHwFi6ugc2XMyoJscghbnkLZB54V1UKLUraXFcz97FobnbsCJajxf8Z+uv9QMtI
+Q51QV2ow1q0BKHP2HuAF5eD4nK5Phix/lzHRGPO74UUTGNKcG22pylBXxaIvTSMl
+ZTABth/YfGqvepBKUbvDZRkCgYB5ykbUCW9H6D8glZ3ZgYU09ag+bD0CzTIs2cH7
+j1QZPz/GdBYNF00PyKv3TPpzVRH7cxyDIdJyioB7/M6Iy03T4wPbQBOCjLdGrZ2A
+jrQTCngSlkq6pVx+k7KLL57ua8gFF70JihIV3kfKkaX6KZcSJ8vsSAgRc8TbUo2T
+wNjh6QKBgDyxw4bG2ULs+LVaHcnp7nizLgRGXJsCkDICjla6y0eCgAnG8fSt8CcG
+s5DIfJeVs/NXe/NVNuVrfwsUx0gBOirtFwQStvi5wJnY/maGAyjmgafisNFgAroT
+aM5f+wyGPQeGCs7bj7JWY7Nx9lkyuUV7DdKBTZNMOe51K3+PTEL3
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.crt b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.crt
new file mode 100644
index 00000000..44f4d9bc
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDGTCCAgECAQEwDQYJKoZIhvcNAQEFBQAwVjEhMB8GA1UEAwwYU3dpZnRtYWls
+ZXIgSW50ZXJtZWRpYXRlMRQwEgYDVQQKDAtTd2lmdG1haWxlcjEOMAwGA1UEBwwF
+UGFyaXMxCzAJBgNVBAYTAkZSMB4XDTE0MTEyMDEzMjYyNloXDTE4MTExOTEzMjYy
+NlowTzEaMBgGA1UEAwwRU3dpZnRtYWlsZXItVXNlcjIxFDASBgNVBAoMC1N3aWZ0
+bWFpbGVyMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDbr1m4z/rzFS/DxUUQIhKNx19oAeGYLt3niaEP
+twfvBMNB80gMgM9d+XtqrPAMPeY/2C8t5NlChNPKMcR70JBKdmlSH4/aTjaIfWmD
+PoZJjvRRXINZgSHNKIt4ZGAN/EPFr19CBisV4iPxzu+lyIbbkaZJ/qtyatlP7m/q
+8TnykFRlyxNEveCakpcXeRd3YTFGKWoED+/URhVc0cCPZVjoeSTtPHAYBnC29lG5
+VFbq6NBQiyF4tpjOHRarq6G8PtQFH9CpAZg5bPk3bqka9C8mEr5jWfrM4EHtUkTl
+CwVLOQRBsz/nMBT27pXZh18GU0hc3geNDN4kqaeqgNBo0mblAgMBAAEwDQYJKoZI
+hvcNAQEFBQADggEBAAHDMuv6oxWPsTQWWGWWFIk7QZu3iogMqFuxhhQxg8BE37CT
+Vt1mBVEjYGMkWhMSwWBMWuP6yuOZecWtpp6eOie/UKGg1XoW7Y7zq2aQaP7YPug0
+8Lgq1jIo7iO2b6gZeMtLiTZrxyte0z1XzS3wy7ZC9mZjYd7QE7mZ+/rzQ0x5zjOp
+G8b3msS/yYYJCMN+HtHln++HOGmm6uhvbsHTfvvZvtl7F5vJ5WhGGlUfjhanSEtZ
+1RKx+cbgIv1eFOGO1OTuZfEuKdLb0T38d/rjLeI99nVVKEIGtLmX4dj327GHe/D3
+aPr2blF2gOvlzkfN9Vz6ZUE2s3rVBeCg2AVseYQ=
+-----END CERTIFICATE-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.key b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.key
new file mode 100644
index 00000000..ffb189b0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA269ZuM/68xUvw8VFECISjcdfaAHhmC7d54mhD7cH7wTDQfNI
+DIDPXfl7aqzwDD3mP9gvLeTZQoTTyjHEe9CQSnZpUh+P2k42iH1pgz6GSY70UVyD
+WYEhzSiLeGRgDfxDxa9fQgYrFeIj8c7vpciG25GmSf6rcmrZT+5v6vE58pBUZcsT
+RL3gmpKXF3kXd2ExRilqBA/v1EYVXNHAj2VY6Hkk7TxwGAZwtvZRuVRW6ujQUIsh
+eLaYzh0Wq6uhvD7UBR/QqQGYOWz5N26pGvQvJhK+Y1n6zOBB7VJE5QsFSzkEQbM/
+5zAU9u6V2YdfBlNIXN4HjQzeJKmnqoDQaNJm5QIDAQABAoIBAAM2FvuqnqJ7Bs23
+zoCj3t2PsodUr7WHydqemmoeZNFLoocORVlZcK6Q/QrcKE4lgX4hbN8g30QnqOjl
+vVeJ/vH3tSZsK7AnQIjSPH6cpV3h5xRhY9IlHxdepltGLFlH/L2hCKVwbaTOP3RD
+cCFeQwpmoKWoQV1UzoRqmdw3Vn+DMaUULomLVR9aSW9PnKeFL+tPWShf7GmVISfM
+2H6xKw/qT0XAX59ZHA1laxSFVvbV5ZcKrBOFMV407Vzw2d3ojmfEzNsHjUVBXX8j
+B5nK1VeJiTVmcoVhnRX7tXESDaZy+Kv38pqOmc8Svn70lDJ35SM2EpWnX39w5LsQ
+29NsIUECgYEA/vNKiMfVmmZNQrpcuHQe5adlmz9+I4xJ4wbRzrS7czpbKF0/iaPf
+dKoVz67yYHOJCBHTVaXWkElQsq1mkyuFt/cc0ReJXO8709+t+6ULsE50cLQm/HN5
+npg3gw0Ls/9dy/cHM5SdVIHMBm9oQ65rXup/dqWC8Dz2cAAOQhIPwx0CgYEA3Jbk
+DPdUlrj4sXcE3V/CtmBuK9Xq1xolJt026fYCrle0YhdMKmchRBDCc6BzM+F/vDyC
+llPfQu8TDXK40Oan7GbxMdoLqKK9gSIq1dvfG1YMMz8OrBcX8xKe61KFRWd7QSBJ
+BcY575NzYHapOHVGnUJ68j8zCow0gfb7q6iK4GkCgYEAz2mUuKSCxYL21hORfUqT
+HFjMU7oa38axEa6pn9XvLjZKlRMPruWP1HTPG9ADRa6Yy+TcnrA1V9sdeM+TRKXC
+usCiRAU27lF+xccS30gNs1iQaGRX10gGqJzDhK1nWP+nClmlFTSRrn+OQan/FBjh
+Jy31lsveM54VC1cwQlY5Vo0CgYEArtjfnLNzFiE55xjq/znHUd4vlYlzItrzddHE
+lEBOsbiNH29ODRI/2P7b0uDsT8Q/BoqEC/ohLqHn3TIA8nzRv91880HdGecdBL17
+bJZiSv2yn/AshhWsAxzQYMDBKFk05lNb7jrIc3DR9DU6PqketsoaP+f+Yi7t89I8
+fD0VD3kCgYAaJCoQshng/ijiHF/RJXLrXXHJSUmaOfbweX/mzFup0YR1LxUjcv85
+cxvwc41Y2iI5MwUXyX97/GYKeoobzWZy3XflNWtg04rcInVaPsb/OOFDDqI+MkzT
+B4PcCurOmjzcxHMVE34CYvl3YVwWrPb5JO1rYG9T2gKUJnLU6qG4Bw==
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance.conf.php.default b/vendor/swiftmailer/swiftmailer/tests/acceptance.conf.php.default
new file mode 100644
index 00000000..68902d84
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance.conf.php.default
@@ -0,0 +1,44 @@
+markTestSkipped(
+ 'Cannot run test without a writable directory to use ('.
+ 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)'
+ );
+ }
+
+ $this->_tmpDir = SWIFT_TMP_DIR;
+ $this->_testFile = $this->_tmpDir.'/swift-test-file'.__CLASS__;
+ file_put_contents($this->_testFile, 'abcdefghijklm');
+ }
+
+ public function tearDown()
+ {
+ unlink($this->_testFile);
+ }
+
+ public function testFileDataCanBeRead()
+ {
+ $file = $this->_createFileStream($this->_testFile);
+ $str = '';
+ while (false !== $bytes = $file->read(8192)) {
+ $str .= $bytes;
+ }
+ $this->assertEquals('abcdefghijklm', $str);
+ }
+
+ public function testFileDataCanBeReadSequentially()
+ {
+ $file = $this->_createFileStream($this->_testFile);
+ $this->assertEquals('abcde', $file->read(5));
+ $this->assertEquals('fghijklm', $file->read(8));
+ $this->assertFalse($file->read(1));
+ }
+
+ public function testFilenameIsReturned()
+ {
+ $file = $this->_createFileStream($this->_testFile);
+ $this->assertEquals($this->_testFile, $file->getPath());
+ }
+
+ public function testFileCanBeWrittenTo()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $file->write('foobar');
+ $this->assertEquals('foobar', $file->read(8192));
+ }
+
+ public function testReadingFromThenWritingToFile()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $file->write('foobar');
+ $this->assertEquals('foobar', $file->read(8192));
+ $file->write('zipbutton');
+ $this->assertEquals('zipbutton', $file->read(8192));
+ }
+
+ public function testWritingToFileWithCanonicalization()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $file->addFilter($this->_createFilter(array("\r\n", "\r"), "\n"), 'allToLF');
+ $file->write("foo\r\nbar\r");
+ $file->write("\nzip\r\ntest\r");
+ $file->flushBuffers();
+ $this->assertEquals("foo\nbar\nzip\ntest\n", file_get_contents($this->_testFile));
+ }
+
+ public function testBindingOtherStreamsMirrorsWriteOperations()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is2->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+
+ $file->bind($is1);
+ $file->bind($is2);
+
+ $file->write('x');
+ $file->write('y');
+ }
+
+ public function testBindingOtherStreamsMirrorsFlushOperations()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->once())
+ ->method('flushBuffers');
+ $is2->expects($this->once())
+ ->method('flushBuffers');
+
+ $file->bind($is1);
+ $file->bind($is2);
+
+ $file->flushBuffers();
+ }
+
+ public function testUnbindingStreamPreventsFurtherWrites()
+ {
+ $file = $this->_createFileStream(
+ $this->_testFile, true
+ );
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->once())
+ ->method('write')
+ ->with('x');
+
+ $file->bind($is1);
+ $file->bind($is2);
+
+ $file->write('x');
+
+ $file->unbind($is2);
+
+ $file->write('y');
+ }
+
+ // -- Creation methods
+
+ private function _createFilter($search, $replace)
+ {
+ return new Swift_StreamFilters_StringReplacementFilter($search, $replace);
+ }
+
+ private function _createMockInputStream()
+ {
+ return $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ }
+
+ private function _createFileStream($file, $writable = false)
+ {
+ return new Swift_ByteStream_FileByteStream($file, $writable);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.php
new file mode 100644
index 00000000..8ce4a182
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.php
@@ -0,0 +1,179 @@
+_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ }
+
+ public function testCreatingUtf8Reader()
+ {
+ foreach (array('utf8', 'utf-8', 'UTF-8', 'UTF8') as $utf8) {
+ $reader = $this->_factory->getReaderFor($utf8);
+ $this->assertInstanceof($this->_prefix.'Utf8Reader', $reader);
+ }
+ }
+
+ public function testCreatingIso8859XReaders()
+ {
+ $charsets = array();
+ foreach (range(1, 16) as $number) {
+ foreach (array('iso', 'iec') as $body) {
+ $charsets[] = $body.'-8859-'.$number;
+ $charsets[] = $body.'8859-'.$number;
+ $charsets[] = strtoupper($body).'-8859-'.$number;
+ $charsets[] = strtoupper($body).'8859-'.$number;
+ }
+ }
+
+ foreach ($charsets as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingWindows125XReaders()
+ {
+ $charsets = array();
+ foreach (range(0, 8) as $number) {
+ $charsets[] = 'windows-125'.$number;
+ $charsets[] = 'windows125'.$number;
+ $charsets[] = 'WINDOWS-125'.$number;
+ $charsets[] = 'WINDOWS125'.$number;
+ }
+
+ foreach ($charsets as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingCodePageReaders()
+ {
+ $charsets = array();
+ foreach (range(0, 8) as $number) {
+ $charsets[] = 'cp-125'.$number;
+ $charsets[] = 'cp125'.$number;
+ $charsets[] = 'CP-125'.$number;
+ $charsets[] = 'CP125'.$number;
+ }
+
+ foreach (array(437, 737, 850, 855, 857, 858, 860,
+ 861, 863, 865, 866, 869, ) as $number) {
+ $charsets[] = 'cp-'.$number;
+ $charsets[] = 'cp'.$number;
+ $charsets[] = 'CP-'.$number;
+ $charsets[] = 'CP'.$number;
+ }
+
+ foreach ($charsets as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingAnsiReader()
+ {
+ foreach (array('ansi', 'ANSI') as $ansi) {
+ $reader = $this->_factory->getReaderFor($ansi);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingMacintoshReader()
+ {
+ foreach (array('macintosh', 'MACINTOSH') as $mac) {
+ $reader = $this->_factory->getReaderFor($mac);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingKOIReaders()
+ {
+ $charsets = array();
+ foreach (array('7', '8-r', '8-u', '8u', '8r') as $end) {
+ $charsets[] = 'koi-'.$end;
+ $charsets[] = 'koi'.$end;
+ $charsets[] = 'KOI-'.$end;
+ $charsets[] = 'KOI'.$end;
+ }
+
+ foreach ($charsets as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingIsciiReaders()
+ {
+ foreach (array('iscii', 'ISCII', 'viscii', 'VISCII') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingMIKReader()
+ {
+ foreach (array('mik', 'MIK') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingCorkReader()
+ {
+ foreach (array('cork', 'CORK', 't1', 'T1') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(1, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingUcs2Reader()
+ {
+ foreach (array('ucs-2', 'UCS-2', 'ucs2', 'UCS2') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(2, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingUtf16Reader()
+ {
+ foreach (array('utf-16', 'UTF-16', 'utf16', 'UTF16') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(2, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingUcs4Reader()
+ {
+ foreach (array('ucs-4', 'UCS-4', 'ucs4', 'UCS4') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(4, $reader->getInitialByteSize());
+ }
+ }
+
+ public function testCreatingUtf32Reader()
+ {
+ foreach (array('utf-32', 'UTF-32', 'utf32', 'UTF32') as $charset) {
+ $reader = $this->_factory->getReaderFor($charset);
+ $this->assertInstanceof($this->_prefix.'GenericFixedWidthReader', $reader);
+ $this->assertEquals(4, $reader->getInitialByteSize());
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php
new file mode 100644
index 00000000..e83c2bf5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php
@@ -0,0 +1,24 @@
+listItems() as $itemName) {
+ try {
+ // to be removed in 6.0
+ if ('transport.mail' === $itemName) {
+ continue;
+ }
+ $di->lookup($itemName);
+ } catch (Swift_DependencyException $e) {
+ $this->fail($e->getMessage());
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php
new file mode 100644
index 00000000..fc5a8147
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php
@@ -0,0 +1,12 @@
+_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
+ $this->_encoder = new Swift_Encoder_Base64Encoder();
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+ $encodedText = $this->_encoder->encodeString($text);
+
+ $this->assertEquals(
+ base64_decode($encodedText), $text,
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php
new file mode 100644
index 00000000..1da3b837
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php
@@ -0,0 +1,54 @@
+_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
+ $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $encoding = $encodingDir;
+ $charStream = new Swift_CharacterStream_ArrayCharacterStream(
+ $this->_factory, $encoding);
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+ $encodedText = $encoder->encodeString($text);
+
+ foreach (explode("\r\n", $encodedText) as $line) {
+ $this->assertLessThanOrEqual(76, strlen($line));
+ }
+
+ $this->assertEquals(
+ quoted_printable_decode($encodedText), $text,
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php
new file mode 100644
index 00000000..043ddf8c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php
@@ -0,0 +1,50 @@
+_samplesDir = realpath(__DIR__.'/../../../_samples/charsets');
+ $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $encoding = $encodingDir;
+ $charStream = new Swift_CharacterStream_ArrayCharacterStream(
+ $this->_factory, $encoding);
+ $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+ $encodedText = $encoder->encodeString($text);
+
+ $this->assertEquals(
+ urldecode(implode('', explode("\r\n", $encodedText))), $text,
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EncodingAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EncodingAcceptanceTest.php
new file mode 100644
index 00000000..6a4d05d3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EncodingAcceptanceTest.php
@@ -0,0 +1,30 @@
+assertEquals('7bit', $encoder->getName());
+ }
+
+ public function testGet8BitEncodingReturns8BitEncoder()
+ {
+ $encoder = Swift_Encoding::get8BitEncoding();
+ $this->assertEquals('8bit', $encoder->getName());
+ }
+
+ public function testGetQpEncodingReturnsQpEncoder()
+ {
+ $encoder = Swift_Encoding::getQpEncoding();
+ $this->assertEquals('quoted-printable', $encoder->getName());
+ }
+
+ public function testGetBase64EncodingReturnsBase64Encoder()
+ {
+ $encoder = Swift_Encoding::getBase64Encoding();
+ $this->assertEquals('base64', $encoder->getName());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php
new file mode 100644
index 00000000..6b06e2ee
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php
@@ -0,0 +1,173 @@
+_cache = new Swift_KeyCache_ArrayKeyCache(
+ new Swift_KeyCache_SimpleKeyCacheInputStream()
+ );
+ }
+
+ public function testStringDataCanBeSetAndFetched()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeOverwritten()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('whatever', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeAppended()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND
+ );
+ $this->assertEquals('testing', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testHasKeyReturnValue()
+ {
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyIsWellPartitioned()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $this->_cache->getString($this->_key2, 'foo'));
+ }
+
+ public function testItemKeyIsWellPartitioned()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $this->_cache->getString($this->_key1, 'bar'));
+ }
+
+ public function testByteStreamCanBeImported()
+ {
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write('abcdef');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('abcdef', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamCanBeAppended()
+ {
+ $os1 = new Swift_ByteStream_ArrayByteStream();
+ $os1->write('abcdef');
+
+ $os2 = new Swift_ByteStream_ArrayByteStream();
+ $os2->write('xyzuvw');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND
+ );
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND
+ );
+
+ $this->assertEquals('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamAndStringCanBeAppended()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND
+ );
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write('abcdef');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND
+ );
+ $this->assertEquals('testabcdef', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testDataCanBeExportedToByteStream()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+
+ $this->_cache->exportToByteStream($this->_key1, 'foo', $is);
+
+ $string = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $string .= $bytes;
+ }
+
+ $this->assertEquals('test', $string);
+ }
+
+ public function testKeyCanBeCleared()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->_cache->clearKey($this->_key1, 'foo');
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyCanBeCleared()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'bar'));
+ $this->_cache->clearAll($this->_key1);
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'bar'));
+ }
+
+ public function testKeyCacheInputStream()
+ {
+ $is = $this->_cache->getInputByteStream($this->_key1, 'foo');
+ $is->write('abc');
+ $is->write('xyz');
+ $this->assertEquals('abcxyz', $this->_cache->getString($this->_key1, 'foo'));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php
new file mode 100644
index 00000000..392edde8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php
@@ -0,0 +1,183 @@
+markTestSkipped(
+ 'Cannot run test without a writable directory to use ('.
+ 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)'
+ );
+ }
+
+ $this->_key1 = uniqid(microtime(true), true);
+ $this->_key2 = uniqid(microtime(true), true);
+ $this->_cache = new Swift_KeyCache_DiskKeyCache(
+ new Swift_KeyCache_SimpleKeyCacheInputStream(),
+ SWIFT_TMP_DIR
+ );
+ }
+
+ public function testStringDataCanBeSetAndFetched()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeOverwritten()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('whatever', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeAppended()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND
+ );
+ $this->assertEquals('testing', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testHasKeyReturnValue()
+ {
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyIsWellPartitioned()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $this->_cache->getString($this->_key2, 'foo'));
+ }
+
+ public function testItemKeyIsWellPartitioned()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $this->_cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $this->_cache->getString($this->_key1, 'bar'));
+ }
+
+ public function testByteStreamCanBeImported()
+ {
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write('abcdef');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('abcdef', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamCanBeAppended()
+ {
+ $os1 = new Swift_ByteStream_ArrayByteStream();
+ $os1->write('abcdef');
+
+ $os2 = new Swift_ByteStream_ArrayByteStream();
+ $os2->write('xyzuvw');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND
+ );
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND
+ );
+
+ $this->assertEquals('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamAndStringCanBeAppended()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND
+ );
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write('abcdef');
+
+ $this->_cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND
+ );
+ $this->assertEquals('testabcdef', $this->_cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testDataCanBeExportedToByteStream()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+
+ $this->_cache->exportToByteStream($this->_key1, 'foo', $is);
+
+ $string = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $string .= $bytes;
+ }
+
+ $this->assertEquals('test', $string);
+ }
+
+ public function testKeyCanBeCleared()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->_cache->clearKey($this->_key1, 'foo');
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyCanBeCleared()
+ {
+ $this->_cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->_cache->setString(
+ $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->assertTrue($this->_cache->hasKey($this->_key1, 'bar'));
+ $this->_cache->clearAll($this->_key1);
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo'));
+ $this->assertFalse($this->_cache->hasKey($this->_key1, 'bar'));
+ }
+
+ public function testKeyCacheInputStream()
+ {
+ $is = $this->_cache->getInputByteStream($this->_key1, 'foo');
+ $is->write('abc');
+ $is->write('xyz');
+ $this->assertEquals('abcxyz', $this->_cache->getString($this->_key1, 'foo'));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MessageAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MessageAcceptanceTest.php
new file mode 100644
index 00000000..9372fbfd
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MessageAcceptanceTest.php
@@ -0,0 +1,57 @@
+_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = $message->getDate();
+ $boundary = $message->getBoundary();
+
+ $message->addPart('foo', 'text/plain', 'iso-8859-1');
+ $message->addPart('test foo', 'text/html', 'iso-8859-1');
+
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'test foo'.
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createMessage()
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('properties.charset')->asValue(null);
+
+ return Swift_Message::newInstance();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php
new file mode 100644
index 00000000..e925367e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php
@@ -0,0 +1,125 @@
+_cache = new Swift_KeyCache_ArrayKeyCache(
+ new Swift_KeyCache_SimpleKeyCacheInputStream()
+ );
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+
+ $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $this->_grammar = new Swift_Mime_Grammar();
+ $this->_headers = new Swift_Mime_SimpleHeaderSet(
+ new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
+ );
+ }
+
+ public function testDispositionIsSetInHeader()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setDisposition('inline');
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: inline'."\r\n",
+ $attachment->toString()
+ );
+ }
+
+ public function testDispositionIsAttachmentByDefault()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment'."\r\n",
+ $attachment->toString()
+ );
+ }
+
+ public function testFilenameIsSetInHeader()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf'."\r\n",
+ $attachment->toString()
+ );
+ }
+
+ public function testSizeIsSetInHeader()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setSize(12340);
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; size=12340'."\r\n",
+ $attachment->toString()
+ );
+ }
+
+ public function testMultipleParametersInHeader()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setSize(12340);
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf; size=12340'."\r\n",
+ $attachment->toString()
+ );
+ }
+
+ public function testEndToEnd()
+ {
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setSize(12340);
+ $attachment->setBody('abcd');
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf; size=12340'."\r\n".
+ "\r\n".
+ base64_encode('abcd'),
+ $attachment->toString()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createAttachment()
+ {
+ $entity = new Swift_Mime_Attachment(
+ $this->_headers,
+ $this->_contentEncoder,
+ $this->_cache,
+ $this->_grammar
+ );
+
+ return $entity;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php
new file mode 100644
index 00000000..2a5c562b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php
@@ -0,0 +1,56 @@
+_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
+ $this->_encoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write($text);
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+
+ $this->_encoder->encodeByteStream($os, $is);
+
+ $encoded = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $encoded .= $bytes;
+ }
+
+ $this->assertEquals(
+ base64_decode($encoded), $text,
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php
new file mode 100644
index 00000000..ecd7fcd1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php
@@ -0,0 +1,88 @@
+_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
+ $this->_encoder = new Swift_Mime_ContentEncoder_NativeQpContentEncoder();
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write($text);
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+ $this->_encoder->encodeByteStream($os, $is);
+
+ $encoded = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $encoded .= $bytes;
+ }
+
+ $this->assertEquals(
+ quoted_printable_decode($encoded),
+ // CR and LF are converted to CRLF
+ preg_replace('~\r(?!\n)|(?_createEncoderFromContainer();
+ $this->assertSame('=C3=A4=C3=B6=C3=BC=C3=9F', $encoder->encodeString('äöüß'));
+ }
+
+ /**
+ * @expectedException RuntimeException
+ */
+ public function testCharsetChangeNotImplemented()
+ {
+ $this->_encoder->charsetChanged('utf-8');
+ $this->_encoder->charsetChanged('charset');
+ $this->_encoder->encodeString('foo');
+ }
+
+ public function testGetName()
+ {
+ $this->assertSame('quoted-printable', $this->_encoder->getName());
+ }
+
+ private function _createEncoderFromContainer()
+ {
+ return Swift_DependencyContainer::getInstance()
+ ->lookup('mime.nativeqpcontentencoder')
+ ;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php
new file mode 100644
index 00000000..1541b7ea
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php
@@ -0,0 +1,88 @@
+_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
+ $this->_encoder = new Swift_Mime_ContentEncoder_PlainContentEncoder('8bit');
+ }
+
+ public function testEncodingAndDecodingSamplesString()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+ $encodedText = $this->_encoder->encodeString($text);
+
+ $this->assertEquals(
+ $encodedText, $text,
+ '%s: Encoded string should be identical to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+
+ public function testEncodingAndDecodingSamplesByteStream()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write($text);
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+
+ $this->_encoder->encodeByteStream($os, $is);
+
+ $encoded = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $encoded .= $bytes;
+ }
+
+ $this->assertEquals(
+ $encoded, $text,
+ '%s: Encoded string should be identical to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php
new file mode 100644
index 00000000..84f7e03b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php
@@ -0,0 +1,160 @@
+_samplesDir = realpath(__DIR__.'/../../../../_samples/charsets');
+ $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ }
+
+ public function tearDown()
+ {
+ Swift_Preferences::getInstance()->setQPDotEscape(false);
+ }
+
+ public function testEncodingAndDecodingSamples()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $encoding = $encodingDir;
+ $charStream = new Swift_CharacterStream_NgCharacterStream(
+ $this->_factory, $encoding);
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write($text);
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+ $encoder->encodeByteStream($os, $is);
+
+ $encoded = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $encoded .= $bytes;
+ }
+
+ $this->assertEquals(
+ quoted_printable_decode($encoded), $text,
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+
+ public function testEncodingAndDecodingSamplesFromDiConfiguredInstance()
+ {
+ $sampleFp = opendir($this->_samplesDir);
+ while (false !== $encodingDir = readdir($sampleFp)) {
+ if (substr($encodingDir, 0, 1) == '.') {
+ continue;
+ }
+
+ $encoding = $encodingDir;
+ $encoder = $this->_createEncoderFromContainer();
+
+ $sampleDir = $this->_samplesDir.'/'.$encodingDir;
+
+ if (is_dir($sampleDir)) {
+ $fileFp = opendir($sampleDir);
+ while (false !== $sampleFile = readdir($fileFp)) {
+ if (substr($sampleFile, 0, 1) == '.') {
+ continue;
+ }
+
+ $text = file_get_contents($sampleDir.'/'.$sampleFile);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $os->write($text);
+
+ $is = new Swift_ByteStream_ArrayByteStream();
+ $encoder->encodeByteStream($os, $is);
+
+ $encoded = '';
+ while (false !== $bytes = $is->read(8192)) {
+ $encoded .= $bytes;
+ }
+
+ $this->assertEquals(
+ str_replace("\r\n", "\n", quoted_printable_decode($encoded)), str_replace("\r\n", "\n", $text),
+ '%s: Encoded string should decode back to original string for sample '.
+ $sampleDir.'/'.$sampleFile
+ );
+ }
+ closedir($fileFp);
+ }
+ }
+ closedir($sampleFp);
+ }
+
+ public function testEncodingLFTextWithDiConfiguredInstance()
+ {
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\nb\nc"));
+ }
+
+ public function testEncodingCRTextWithDiConfiguredInstance()
+ {
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\rb\rc"));
+ }
+
+ public function testEncodingLFCRTextWithDiConfiguredInstance()
+ {
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a\r\n\r\nb\r\n\r\nc", $encoder->encodeString("a\n\rb\n\rc"));
+ }
+
+ public function testEncodingCRLFTextWithDiConfiguredInstance()
+ {
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a\r\nb\r\nc", $encoder->encodeString("a\r\nb\r\nc"));
+ }
+
+ public function testEncodingDotStuffingWithDiConfiguredInstance()
+ {
+ // Enable DotEscaping
+ Swift_Preferences::getInstance()->setQPDotEscape(true);
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a=2E\r\n=2E\r\n=2Eb\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc"));
+ // Return to default
+ Swift_Preferences::getInstance()->setQPDotEscape(false);
+ $encoder = $this->_createEncoderFromContainer();
+ $this->assertEquals("a.\r\n.\r\n.b\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc"));
+ }
+
+ public function testDotStuffingEncodingAndDecodingSamplesFromDiConfiguredInstance()
+ {
+ // Enable DotEscaping
+ Swift_Preferences::getInstance()->setQPDotEscape(true);
+ $this->testEncodingAndDecodingSamplesFromDiConfiguredInstance();
+ }
+
+ private function _createEncoderFromContainer()
+ {
+ return Swift_DependencyContainer::getInstance()
+ ->lookup('mime.qpcontentencoder')
+ ;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php
new file mode 100644
index 00000000..8a04df6b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php
@@ -0,0 +1,138 @@
+_cache = new Swift_KeyCache_ArrayKeyCache(
+ new Swift_KeyCache_SimpleKeyCacheInputStream()
+ );
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+
+ $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $this->_grammar = new Swift_Mime_Grammar();
+ $this->_headers = new Swift_Mime_SimpleHeaderSet(
+ new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
+ );
+ }
+
+ public function testContentIdIsSetInHeader()
+ {
+ $file = $this->_createEmbeddedFile();
+ $file->setContentType('application/pdf');
+ $file->setId('foo@bar');
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: '."\r\n".
+ 'Content-Disposition: inline'."\r\n",
+ $file->toString()
+ );
+ }
+
+ public function testDispositionIsSetInHeader()
+ {
+ $file = $this->_createEmbeddedFile();
+ $id = $file->getId();
+ $file->setContentType('application/pdf');
+ $file->setDisposition('attachment');
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$id.'>'."\r\n".
+ 'Content-Disposition: attachment'."\r\n",
+ $file->toString()
+ );
+ }
+
+ public function testFilenameIsSetInHeader()
+ {
+ $file = $this->_createEmbeddedFile();
+ $id = $file->getId();
+ $file->setContentType('application/pdf');
+ $file->setFilename('foo.pdf');
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$id.'>'."\r\n".
+ 'Content-Disposition: inline; filename=foo.pdf'."\r\n",
+ $file->toString()
+ );
+ }
+
+ public function testSizeIsSetInHeader()
+ {
+ $file = $this->_createEmbeddedFile();
+ $id = $file->getId();
+ $file->setContentType('application/pdf');
+ $file->setSize(12340);
+ $this->assertEquals(
+ 'Content-Type: application/pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$id.'>'."\r\n".
+ 'Content-Disposition: inline; size=12340'."\r\n",
+ $file->toString()
+ );
+ }
+
+ public function testMultipleParametersInHeader()
+ {
+ $file = $this->_createEmbeddedFile();
+ $id = $file->getId();
+ $file->setContentType('application/pdf');
+ $file->setFilename('foo.pdf');
+ $file->setSize(12340);
+
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$id.'>'."\r\n".
+ 'Content-Disposition: inline; filename=foo.pdf; size=12340'."\r\n",
+ $file->toString()
+ );
+ }
+
+ public function testEndToEnd()
+ {
+ $file = $this->_createEmbeddedFile();
+ $id = $file->getId();
+ $file->setContentType('application/pdf');
+ $file->setFilename('foo.pdf');
+ $file->setSize(12340);
+ $file->setBody('abcd');
+ $this->assertEquals(
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$id.'>'."\r\n".
+ 'Content-Disposition: inline; filename=foo.pdf; size=12340'."\r\n".
+ "\r\n".
+ base64_encode('abcd'),
+ $file->toString()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createEmbeddedFile()
+ {
+ $entity = new Swift_Mime_EmbeddedFile(
+ $this->_headers,
+ $this->_contentEncoder,
+ $this->_cache,
+ $this->_grammar
+ );
+
+ return $entity;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php
new file mode 100644
index 00000000..304867a4
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php
@@ -0,0 +1,32 @@
+_encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
+ }
+
+ public function testEncodingJIS()
+ {
+ if (function_exists('mb_convert_encoding')) {
+ // base64_encode and split cannot handle long JIS text to fold
+ $subject = '長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い長い件名';
+
+ $encodedWrapperLength = strlen('=?iso-2022-jp?'.$this->_encoder->getName().'??=');
+
+ $old = mb_internal_encoding();
+ mb_internal_encoding('utf-8');
+ $newstring = mb_encode_mimeheader($subject, 'iso-2022-jp', 'B', "\r\n");
+ mb_internal_encoding($old);
+
+ $encoded = $this->_encoder->encodeString($subject, 0, 75 - $encodedWrapperLength, 'iso-2022-jp');
+ $this->assertEquals(
+ $encoded, $newstring,
+ 'Encoded string should decode back to original string for sample '
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php
new file mode 100644
index 00000000..8232fe63
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php
@@ -0,0 +1,129 @@
+_cache = new Swift_KeyCache_ArrayKeyCache(
+ new Swift_KeyCache_SimpleKeyCacheInputStream()
+ );
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $this->_contentEncoder = new Swift_Mime_ContentEncoder_QpContentEncoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'),
+ new Swift_StreamFilters_ByteArrayReplacementFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ )
+ );
+
+ $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
+ new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
+ );
+ $this->_grammar = new Swift_Mime_Grammar();
+ $this->_headers = new Swift_Mime_SimpleHeaderSet(
+ new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar)
+ );
+ }
+
+ public function testCharsetIsSetInHeader()
+ {
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('utf-8');
+ $part->setBody('foobar');
+ $this->assertEquals(
+ 'Content-Type: text/plain; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foobar',
+ $part->toString()
+ );
+ }
+
+ public function testFormatIsSetInHeaders()
+ {
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setFormat('flowed');
+ $part->setBody('> foobar');
+ $this->assertEquals(
+ 'Content-Type: text/plain; format=flowed'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ '> foobar',
+ $part->toString()
+ );
+ }
+
+ public function testDelSpIsSetInHeaders()
+ {
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setDelSp(true);
+ $part->setBody('foobar');
+ $this->assertEquals(
+ 'Content-Type: text/plain; delsp=yes'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foobar',
+ $part->toString()
+ );
+ }
+
+ public function testAll3ParamsInHeaders()
+ {
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('utf-8');
+ $part->setFormat('fixed');
+ $part->setDelSp(true);
+ $part->setBody('foobar');
+ $this->assertEquals(
+ 'Content-Type: text/plain; charset=utf-8; format=fixed; delsp=yes'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foobar',
+ $part->toString()
+ );
+ }
+
+ public function testBodyIsCanonicalized()
+ {
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('utf-8');
+ $part->setBody("foobar\r\rtest\ning\r");
+ $this->assertEquals(
+ 'Content-Type: text/plain; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ "foobar\r\n".
+ "\r\n".
+ "test\r\n".
+ "ing\r\n",
+ $part->toString()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createMimePart()
+ {
+ $entity = new Swift_Mime_MimePart(
+ $this->_headers,
+ $this->_contentEncoder,
+ $this->_cache,
+ $this->_grammar
+ );
+
+ return $entity;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php
new file mode 100644
index 00000000..cd6d910d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php
@@ -0,0 +1,1251 @@
+setCharset(null); //TODO: Test with the charset defined
+ }
+
+ public function testBasicHeaders()
+ {
+ /* -- RFC 2822, 3.6.
+ */
+
+ $message = $this->_createMessage();
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString(),
+ '%s: Only required headers, and non-empty headers should be displayed'
+ );
+ }
+
+ public function testSubjectIsDisplayedIfSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testDateCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $id = $message->getId();
+ $message->setDate(1234);
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', 1234)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMessageIdCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setId('foo@bar');
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: '."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testContentTypeCanBeChanged()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setContentType('text/html');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/html'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testCharsetCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setContentType('text/html');
+ $message->setCharset('iso-8859-1');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testFormatCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFormat('flowed');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain; format=flowed'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testEncoderCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setContentType('text/html');
+ $message->setEncoder(
+ new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit')
+ );
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/html'."\r\n".
+ 'Content-Transfer-Encoding: 7bit'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testFromAddressCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom('chris.corbyn@swiftmailer.org');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: chris.corbyn@swiftmailer.org'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testFromAddressCanBeSetWithName()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris Corbyn'));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMultipleFromAddressesCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org',
+ ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn , mark@swiftmailer.org'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testReturnPathAddressCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testEmptyReturnPathHeaderCanBeUsed()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Return-Path: <>'."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testSenderCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setSender('chris.corbyn@swiftmailer.org');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Sender: chris.corbyn@swiftmailer.org'."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testSenderCanBeSetWithName()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setSender(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Sender: Chris '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testReplyToCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array('chris@w3style.co.uk' => 'Myself'));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMultipleReplyAddressCanBeUsed()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testToAddressCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo('mark@swiftmailer.org');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMultipleToAddressesCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo(array(
+ 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org, Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testCcAddressCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo(array(
+ 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $message->setCc('john@some-site.com');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org, Chris Corbyn '."\r\n".
+ 'Cc: john@some-site.com'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMultipleCcAddressesCanBeSet()
+ {
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo(array(
+ 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $message->setCc(array(
+ 'john@some-site.com' => 'John West',
+ 'fred@another-site.co.uk' => 'Big Fred',
+ ));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org, Chris Corbyn '."\r\n".
+ 'Cc: John West , Big Fred '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testBccAddressCanBeSet()
+ {
+ //Obviously Transports need to setBcc(array()) and send to each Bcc recipient
+ // separately in accordance with RFC 2822/2821
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo(array(
+ 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $message->setCc(array(
+ 'john@some-site.com' => 'John West',
+ 'fred@another-site.co.uk' => 'Big Fred',
+ ));
+ $message->setBcc('x@alphabet.tld');
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org, Chris Corbyn '."\r\n".
+ 'Cc: John West , Big Fred '."\r\n".
+ 'Bcc: x@alphabet.tld'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testMultipleBccAddressesCanBeSet()
+ {
+ //Obviously Transports need to setBcc(array()) and send to each Bcc recipient
+ // separately in accordance with RFC 2822/2821
+ $message = $this->_createMessage();
+ $message->setSubject('just a test subject');
+ $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris'));
+ $message->setReplyTo(array(
+ 'chris@w3style.co.uk' => 'Myself',
+ 'my.other@address.com' => 'Me',
+ ));
+ $message->setTo(array(
+ 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $message->setCc(array(
+ 'john@some-site.com' => 'John West',
+ 'fred@another-site.co.uk' => 'Big Fred',
+ ));
+ $message->setBcc(array('x@alphabet.tld', 'a@alphabet.tld' => 'A'));
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris '."\r\n".
+ 'Reply-To: Myself , Me '."\r\n".
+ 'To: mark@swiftmailer.org, Chris Corbyn '."\r\n".
+ 'Cc: John West , Big Fred '."\r\n".
+ 'Bcc: x@alphabet.tld, A '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testStringBodyIsAppended()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setBody(
+ 'just a test body'."\r\n".
+ 'with a new line'
+ );
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'just a test body'."\r\n".
+ 'with a new line',
+ $message->toString()
+ );
+ }
+
+ public function testStringBodyIsEncoded()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setBody(
+ 'Just s'.pack('C*', 0xC2, 0x01, 0x01).'me multi-'."\r\n".
+ 'line message!'
+ );
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'Just s=C2=01=01me multi-'."\r\n".
+ 'line message!',
+ $message->toString()
+ );
+ }
+
+ public function testChildrenCanBeAttached()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = $message->getDate();
+ $boundary = $message->getBoundary();
+
+ $part1 = $this->_createMimePart();
+ $part1->setContentType('text/plain');
+ $part1->setCharset('iso-8859-1');
+ $part1->setBody('foo');
+
+ $message->attach($part1);
+
+ $part2 = $this->_createMimePart();
+ $part2->setContentType('text/html');
+ $part2->setCharset('iso-8859-1');
+ $part2->setBody('test foo');
+
+ $message->attach($part2);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'test foo'.
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testAttachmentsBeingAttached()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('iso-8859-1');
+ $part->setBody('foo');
+
+ $message->attach($part);
+
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setBody('');
+
+ $message->attach($attachment);
+
+ $this->assertRegExp(
+ '~^'.
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString()
+ );
+ }
+
+ public function testAttachmentsAndEmbeddedFilesBeingAttached()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('iso-8859-1');
+ $part->setBody('foo');
+
+ $message->attach($part);
+
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setBody('');
+
+ $message->attach($attachment);
+
+ $file = $this->_createEmbeddedFile();
+ $file->setContentType('image/jpeg');
+ $file->setFilename('myimage.jpg');
+ $file->setBody('');
+
+ $message->attach($file);
+
+ $cid = $file->getId();
+
+ $this->assertRegExp(
+ '~^'.
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\2'."\r\n".
+ 'Content-Type: image/jpeg; name=myimage.jpg'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$cid.'>'."\r\n".
+ 'Content-Disposition: inline; filename=myimage.jpg'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--\\2--'."\r\n".
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString()
+ );
+ }
+
+ public function testComplexEmbeddingOfContent()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setBody('');
+
+ $message->attach($attachment);
+
+ $file = $this->_createEmbeddedFile();
+ $file->setContentType('image/jpeg');
+ $file->setFilename('myimage.jpg');
+ $file->setBody('');
+
+ $part = $this->_createMimePart();
+ $part->setContentType('text/html');
+ $part->setCharset('iso-8859-1');
+ $part->setBody('foo ');
+
+ $message->attach($part);
+
+ $cid = $file->getId();
+
+ $this->assertRegExp(
+ '~^'.
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo './/=3D is just = in QP
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: image/jpeg; name=myimage.jpg'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$cid.'>'."\r\n".
+ 'Content-Disposition: inline; filename=myimage.jpg'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString()
+ );
+ }
+
+ public function testAttachingAndDetachingContent()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $part = $this->_createMimePart();
+ $part->setContentType('text/plain');
+ $part->setCharset('iso-8859-1');
+ $part->setBody('foo');
+
+ $message->attach($part);
+
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setBody('');
+
+ $message->attach($attachment);
+
+ $file = $this->_createEmbeddedFile();
+ $file->setContentType('image/jpeg');
+ $file->setFilename('myimage.jpg');
+ $file->setBody('');
+
+ $message->attach($file);
+
+ $cid = $file->getId();
+
+ $message->detach($attachment);
+
+ $this->assertRegExp(
+ '~^'.
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: image/jpeg; name=myimage.jpg'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$cid.'>'."\r\n".
+ 'Content-Disposition: inline; filename=myimage.jpg'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString(),
+ '%s: Attachment should have been detached'
+ );
+ }
+
+ public function testBoundaryDoesNotAppearAfterAllPartsAreDetached()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = $message->getDate();
+ $boundary = $message->getBoundary();
+
+ $part1 = $this->_createMimePart();
+ $part1->setContentType('text/plain');
+ $part1->setCharset('iso-8859-1');
+ $part1->setBody('foo');
+
+ $message->attach($part1);
+
+ $part2 = $this->_createMimePart();
+ $part2->setContentType('text/html');
+ $part2->setCharset('iso-8859-1');
+ $part2->setBody('test foo');
+
+ $message->attach($part2);
+
+ $message->detach($part1);
+ $message->detach($part2);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n",
+ $message->toString(),
+ '%s: Message should be restored to orignal state after parts are detached'
+ );
+ }
+
+ public function testCharsetFormatOrDelSpAreNotShownWhenBoundaryIsSet()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setCharset('utf-8');
+ $message->setFormat('flowed');
+ $message->setDelSp(true);
+
+ $id = $message->getId();
+ $date = $message->getDate();
+ $boundary = $message->getBoundary();
+
+ $part1 = $this->_createMimePart();
+ $part1->setContentType('text/plain');
+ $part1->setCharset('iso-8859-1');
+ $part1->setBody('foo');
+
+ $message->attach($part1);
+
+ $part2 = $this->_createMimePart();
+ $part2->setContentType('text/html');
+ $part2->setCharset('iso-8859-1');
+ $part2->setBody('test foo');
+
+ $message->attach($part2);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'test foo'.
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testBodyCanBeSetWithAttachments()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setContentType('text/html');
+ $message->setCharset('iso-8859-1');
+ $message->setBody('foo');
+
+ $id = $message->getId();
+ $date = date('r', $message->getDate());
+ $boundary = $message->getBoundary();
+
+ $attachment = $this->_createAttachment();
+ $attachment->setContentType('application/pdf');
+ $attachment->setFilename('foo.pdf');
+ $attachment->setBody('');
+
+ $message->attach($attachment);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=iso-8859-1'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: application/pdf; name=foo.pdf'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=foo.pdf'."\r\n".
+ "\r\n".
+ base64_encode('').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testHtmlPartAlwaysAppearsLast()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+
+ $id = $message->getId();
+ $date = date('r', $message->getDate());
+ $boundary = $message->getBoundary();
+
+ $part1 = $this->_createMimePart();
+ $part1->setContentType('text/html');
+ $part1->setBody('foo');
+
+ $part2 = $this->_createMimePart();
+ $part2->setContentType('text/plain');
+ $part2->setBody('bar');
+
+ $message->attach($part1);
+ $message->attach($part2);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'bar'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testBodyBecomesPartIfOtherPartsAttached()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setContentType('text/html');
+ $message->setBody('foo');
+
+ $id = $message->getId();
+ $date = date('r', $message->getDate());
+ $boundary = $message->getBoundary();
+
+ $part2 = $this->_createMimePart();
+ $part2->setContentType('text/plain');
+ $part2->setBody('bar');
+
+ $message->attach($part2);
+
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'bar'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'foo'.
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n",
+ $message->toString()
+ );
+ }
+
+ public function testBodyIsCanonicalized()
+ {
+ $message = $this->_createMessage();
+ $message->setReturnPath('chris@w3style.co.uk');
+ $message->setSubject('just a test subject');
+ $message->setFrom(array(
+ 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', ));
+ $message->setBody(
+ 'just a test body'."\n".
+ 'with a new line'
+ );
+ $id = $message->getId();
+ $date = $message->getDate();
+ $this->assertEquals(
+ 'Return-Path: '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.date('r', $date)."\r\n".
+ 'Subject: just a test subject'."\r\n".
+ 'From: Chris Corbyn '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: text/plain'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'just a test body'."\r\n".
+ 'with a new line',
+ $message->toString()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createMessage()
+ {
+ return new Swift_Message();
+ }
+
+ protected function _createMimePart()
+ {
+ return new Swift_MimePart();
+ }
+
+ protected function _createAttachment()
+ {
+ return new Swift_Attachment();
+ }
+
+ protected function _createEmbeddedFile()
+ {
+ return new Swift_EmbeddedFile();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MimePartAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MimePartAcceptanceTest.php
new file mode 100644
index 00000000..f42405df
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MimePartAcceptanceTest.php
@@ -0,0 +1,15 @@
+register('properties.charset')->asValue(null);
+
+ return Swift_MimePart::newInstance();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php
new file mode 100644
index 00000000..dc0d0a1d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php
@@ -0,0 +1,133 @@
+markTestSkipped(
+ 'Will fail on travis-ci if not skipped due to travis blocking '.
+ 'socket mailing tcp connections.'
+ );
+ }
+
+ $this->_buffer = new Swift_Transport_StreamBuffer(
+ $this->getMockBuilder('Swift_ReplacementFilterFactory')->getMock()
+ );
+ }
+
+ public function testReadLine()
+ {
+ $this->_initializeBuffer();
+
+ $line = $this->_buffer->readLine(0);
+ $this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
+ $seq = $this->_buffer->write("QUIT\r\n");
+ $this->assertTrue((bool) $seq);
+ $line = $this->_buffer->readLine($seq);
+ $this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
+ $this->_buffer->terminate();
+ }
+
+ public function testWrite()
+ {
+ $this->_initializeBuffer();
+
+ $line = $this->_buffer->readLine(0);
+ $this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
+
+ $seq = $this->_buffer->write("HELO foo\r\n");
+ $this->assertTrue((bool) $seq);
+ $line = $this->_buffer->readLine($seq);
+ $this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
+
+ $seq = $this->_buffer->write("QUIT\r\n");
+ $this->assertTrue((bool) $seq);
+ $line = $this->_buffer->readLine($seq);
+ $this->assertRegExp('/^[0-9]{3}.*?\r\n$/D', $line);
+ $this->_buffer->terminate();
+ }
+
+ public function testBindingOtherStreamsMirrorsWriteOperations()
+ {
+ $this->_initializeBuffer();
+
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is2->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+
+ $this->_buffer->bind($is1);
+ $this->_buffer->bind($is2);
+
+ $this->_buffer->write('x');
+ $this->_buffer->write('y');
+ }
+
+ public function testBindingOtherStreamsMirrorsFlushOperations()
+ {
+ $this->_initializeBuffer();
+
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->once())
+ ->method('flushBuffers');
+ $is2->expects($this->once())
+ ->method('flushBuffers');
+
+ $this->_buffer->bind($is1);
+ $this->_buffer->bind($is2);
+
+ $this->_buffer->flushBuffers();
+ }
+
+ public function testUnbindingStreamPreventsFurtherWrites()
+ {
+ $this->_initializeBuffer();
+
+ $is1 = $this->_createMockInputStream();
+ $is2 = $this->_createMockInputStream();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->once())
+ ->method('write')
+ ->with('x');
+
+ $this->_buffer->bind($is1);
+ $this->_buffer->bind($is2);
+
+ $this->_buffer->write('x');
+
+ $this->_buffer->unbind($is2);
+
+ $this->_buffer->write('y');
+ }
+
+ // -- Creation Methods
+
+ private function _createMockInputStream()
+ {
+ return $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php
new file mode 100644
index 00000000..51c998c6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php
@@ -0,0 +1,33 @@
+markTestSkipped(
+ 'Cannot run test without an SMTP host to connect to (define '.
+ 'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)'
+ );
+ }
+ parent::setUp();
+ }
+
+ protected function _initializeBuffer()
+ {
+ $parts = explode(':', SWIFT_SMTP_HOST);
+ $host = $parts[0];
+ $port = isset($parts[1]) ? $parts[1] : 25;
+
+ $this->_buffer->initialize(array(
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
+ 'host' => $host,
+ 'port' => $port,
+ 'protocol' => 'tcp',
+ 'blocking' => 1,
+ 'timeout' => 15,
+ ));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php
new file mode 100644
index 00000000..0e2924eb
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php
@@ -0,0 +1,26 @@
+markTestSkipped(
+ 'Cannot run test without a path to sendmail (define '.
+ 'SWIFT_SENDMAIL_PATH in tests/acceptance.conf.php if you wish to run this test)'
+ );
+ }
+
+ parent::setUp();
+ }
+
+ protected function _initializeBuffer()
+ {
+ $this->_buffer->initialize(array(
+ 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS,
+ 'command' => SWIFT_SENDMAIL_PATH.' -bs',
+ ));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php
new file mode 100644
index 00000000..d550f818
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php
@@ -0,0 +1,67 @@
+markTestSkipped(
+ 'Cannot run test without an SMTP host to connect to (define '.
+ 'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)'
+ );
+ }
+
+ $serverStarted = false;
+ for ($i = 0; $i < 5; ++$i) {
+ $this->_randomHighPort = rand(50000, 65000);
+ $this->_server = stream_socket_server('tcp://127.0.0.1:'.$this->_randomHighPort);
+ if ($this->_server) {
+ $serverStarted = true;
+ }
+ }
+
+ $this->_buffer = new Swift_Transport_StreamBuffer(
+ $this->getMockBuilder('Swift_ReplacementFilterFactory')->getMock()
+ );
+ }
+
+ protected function _initializeBuffer()
+ {
+ $host = '127.0.0.1';
+ $port = $this->_randomHighPort;
+
+ $this->_buffer->initialize(array(
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
+ 'host' => $host,
+ 'port' => $port,
+ 'protocol' => 'tcp',
+ 'blocking' => 1,
+ 'timeout' => 1,
+ ));
+ }
+
+ public function testTimeoutException()
+ {
+ $this->_initializeBuffer();
+ $e = null;
+ try {
+ $line = $this->_buffer->readLine(0);
+ } catch (Exception $e) {
+ }
+ $this->assertInstanceof('Swift_IoException', $e, 'IO Exception Not Thrown On Connection Timeout');
+ $this->assertRegExp('/Connection to .* Timed Out/', $e->getMessage());
+ }
+
+ public function tearDown()
+ {
+ if ($this->_server) {
+ stream_socket_shutdown($this->_server, STREAM_SHUT_RDWR);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php
new file mode 100644
index 00000000..2863f965
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php
@@ -0,0 +1,40 @@
+markTestSkipped(
+ 'SSL is not configured for your system. It is not possible to run this test'
+ );
+ }
+ if (!defined('SWIFT_SSL_HOST')) {
+ $this->markTestSkipped(
+ 'Cannot run test without an SSL enabled SMTP host to connect to (define '.
+ 'SWIFT_SSL_HOST in tests/acceptance.conf.php if you wish to run this test)'
+ );
+ }
+
+ parent::setUp();
+ }
+
+ protected function _initializeBuffer()
+ {
+ $parts = explode(':', SWIFT_SSL_HOST);
+ $host = $parts[0];
+ $port = isset($parts[1]) ? $parts[1] : 25;
+
+ $this->_buffer->initialize(array(
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
+ 'host' => $host,
+ 'port' => $port,
+ 'protocol' => 'ssl',
+ 'blocking' => 1,
+ 'timeout' => 15,
+ ));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php
new file mode 100644
index 00000000..6fc85057
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php
@@ -0,0 +1,39 @@
+markTestSkipped(
+ 'TLS is not configured for your system. It is not possible to run this test'
+ );
+ }
+ if (!defined('SWIFT_TLS_HOST')) {
+ $this->markTestSkipped(
+ 'Cannot run test without a TLS enabled SMTP host to connect to (define '.
+ 'SWIFT_TLS_HOST in tests/acceptance.conf.php if you wish to run this test)'
+ );
+ }
+ parent::setUp();
+ }
+
+ protected function _initializeBuffer()
+ {
+ $parts = explode(':', SWIFT_TLS_HOST);
+ $host = $parts[0];
+ $port = isset($parts[1]) ? $parts[1] : 25;
+
+ $this->_buffer->initialize(array(
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
+ 'host' => $host,
+ 'port' => $port,
+ 'protocol' => 'tls',
+ 'blocking' => 1,
+ 'timeout' => 15,
+ ));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bootstrap.php b/vendor/swiftmailer/swiftmailer/tests/bootstrap.php
new file mode 100644
index 00000000..27091a28
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bootstrap.php
@@ -0,0 +1,21 @@
+allowMockingNonExistentMethods(true);
+
+if (is_file(__DIR__.'/acceptance.conf.php')) {
+ require_once __DIR__.'/acceptance.conf.php';
+}
+if (is_file(__DIR__.'/smoke.conf.php')) {
+ require_once __DIR__.'/smoke.conf.php';
+}
+require_once __DIR__.'/StreamCollector.php';
+require_once __DIR__.'/IdenticalBinaryConstraint.php';
+require_once __DIR__.'/SwiftMailerTestCase.php';
+require_once __DIR__.'/SwiftMailerSmokeTestCase.php';
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug111Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug111Test.php
new file mode 100644
index 00000000..ba29ba87
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug111Test.php
@@ -0,0 +1,42 @@
+ array(
+ 'email1@example.com',
+ 'email2@example.com',
+ 'email3@example.com',
+ 'email4@example.com',
+ 'email5@example.com',
+ ),
+ 'sub' => array(
+ '-name-' => array(
+ 'email1',
+ '"email2"',
+ 'email3\\',
+ 'email4',
+ 'email5',
+ ),
+ '-url-' => array(
+ 'http://google.com',
+ 'http://yahoo.com',
+ 'http://hotmail.com',
+ 'http://aol.com',
+ 'http://facebook.com',
+ ),
+ ),
+ );
+ $json = json_encode($complicated_header);
+
+ $message = new Swift_Message();
+ $headers = $message->getHeaders();
+ $headers->addTextHeader('X-SMTPAPI', $json);
+ $header = $headers->get('X-SMTPAPI');
+
+ $this->assertEquals('Swift_Mime_Headers_UnstructuredHeader', get_class($header));
+ $this->assertEquals($json, $header->getFieldBody());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug118Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug118Test.php
new file mode 100644
index 00000000..bd10c716
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug118Test.php
@@ -0,0 +1,20 @@
+_message = new Swift_Message();
+ }
+
+ public function testCallingGenerateIdChangesTheMessageId()
+ {
+ $currentId = $this->_message->getId();
+ $this->_message->generateId();
+ $newId = $this->_message->getId();
+
+ $this->assertNotEquals($currentId, $newId);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php
new file mode 100644
index 00000000..fdfa5302
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php
@@ -0,0 +1,38 @@
+_factory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $grammar);
+ }
+
+ public function testMailboxHeaderEncoding()
+ {
+ $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Name, Name', ' "Family Name, Name" ');
+ $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé, Name', ' Family =?utf-8?Q?Nam=C3=A9=2C?= Name');
+ $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé , Name', ' Family =?utf-8?Q?Nam=C3=A9_=2C?= Name');
+ $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé ;Name', ' Family =?utf-8?Q?Nam=C3=A9_=3BName?= ');
+ }
+
+ private function _testHeaderIsFullyEncoded($email, $name, $expected)
+ {
+ $mailboxHeader = $this->_factory->createMailboxHeader('To', array(
+ $email => $name,
+ ));
+
+ $headerBody = substr($mailboxHeader->toString(), 3, strlen($expected));
+
+ $this->assertEquals($expected, $headerBody);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug274Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug274Test.php
new file mode 100644
index 00000000..f5f057ae
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug274Test.php
@@ -0,0 +1,21 @@
+setExpectedException('Swift_IoException', 'The path cannot be empty');
+ $message->attach(Swift_Attachment::fromPath(''));
+ }
+
+ public function testNonEmptyFileNameAsAttachment()
+ {
+ $message = new Swift_Message();
+ try {
+ $message->attach(Swift_Attachment::fromPath(__FILE__));
+ } catch (Exception $e) {
+ $this->fail('Path should not be empty');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug34Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug34Test.php
new file mode 100644
index 00000000..9c76ceb3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug34Test.php
@@ -0,0 +1,75 @@
+setCharset('utf-8');
+ }
+
+ public function testEmbeddedFilesWithMultipartDataCreateMultipartRelatedContentAsAnAlternative()
+ {
+ $message = Swift_Message::newInstance();
+ $message->setCharset('utf-8');
+ $message->setSubject('test subject');
+ $message->addPart('plain part', 'text/plain');
+
+ $image = Swift_Image::newInstance('', 'image.gif', 'image/gif');
+ $cid = $message->embed($image);
+
+ $message->setBody('', 'text/html');
+
+ $message->setTo(array('user@domain.tld' => 'User'));
+
+ $message->setFrom(array('other@domain.tld' => 'Other'));
+ $message->setSender(array('other@domain.tld' => 'Other'));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+ $cidVal = $image->getId();
+
+ $this->assertRegExp(
+ '~^'.
+ 'Sender: Other '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: test subject'."\r\n".
+ 'From: Other '."\r\n".
+ 'To: User '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/plain; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'plain part'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/html; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ ''.
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: image/gif; name=image.gif'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.$cidVal.'>'."\r\n".
+ 'Content-Disposition: inline; filename=image.gif'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString()
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug35Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug35Test.php
new file mode 100644
index 00000000..e07ee8f0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug35Test.php
@@ -0,0 +1,73 @@
+setCharset('utf-8');
+ }
+
+ public function testHTMLPartAppearsLastEvenWhenAttachmentsAdded()
+ {
+ $message = Swift_Message::newInstance();
+ $message->setCharset('utf-8');
+ $message->setSubject('test subject');
+ $message->addPart('plain part', 'text/plain');
+
+ $attachment = Swift_Attachment::newInstance('', 'image.gif', 'image/gif');
+ $message->attach($attachment);
+
+ $message->setBody('HTML part', 'text/html');
+
+ $message->setTo(array('user@domain.tld' => 'User'));
+
+ $message->setFrom(array('other@domain.tld' => 'Other'));
+ $message->setSender(array('other@domain.tld' => 'Other'));
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $this->assertRegExp(
+ '~^'.
+ 'Sender: Other '."\r\n".
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: test subject'."\r\n".
+ 'From: Other '."\r\n".
+ 'To: User '."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: multipart/alternative;'."\r\n".
+ ' boundary="(.*?)"'."\r\n".
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/plain; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'plain part'.
+ "\r\n\r\n".
+ '--\\1'."\r\n".
+ 'Content-Type: text/html; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'HTML part'.
+ "\r\n\r\n".
+ '--\\1--'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: image/gif; name=image.gif'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename=image.gif'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $message->toString()
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug38Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug38Test.php
new file mode 100644
index 00000000..a8a9212c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug38Test.php
@@ -0,0 +1,194 @@
+_attFileName = 'data.txt';
+ $this->_attFileType = 'text/plain';
+ $this->_attFile = __DIR__.'/../../_samples/files/data.txt';
+ Swift_Preferences::getInstance()->setCharset('utf-8');
+ }
+
+ public function testWritingMessageToByteStreamProducesCorrectStructure()
+ {
+ $message = new Swift_Message();
+ $message->setSubject('test subject');
+ $message->setTo('user@domain.tld');
+ $message->setCc('other@domain.tld');
+ $message->setFrom('user@domain.tld');
+
+ $image = new Swift_Image('', 'image.gif', 'image/gif');
+
+ $cid = $message->embed($image);
+ $message->setBody('HTML part', 'text/html');
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+ $imgId = $image->getId();
+
+ $stream = new Swift_ByteStream_ArrayByteStream();
+
+ $message->toByteStream($stream);
+
+ $this->assertPatternInStream(
+ '~^'.
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: test subject'."\r\n".
+ 'From: user@domain.tld'."\r\n".
+ 'To: user@domain.tld'."\r\n".
+ 'Cc: other@domain.tld'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'HTML part'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: image/gif; name=image.gif'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.preg_quote($imgId, '~').'>'."\r\n".
+ 'Content-Disposition: inline; filename=image.gif'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D',
+ $stream
+ );
+ }
+
+ public function testWritingMessageToByteStreamTwiceProducesCorrectStructure()
+ {
+ $message = new Swift_Message();
+ $message->setSubject('test subject');
+ $message->setTo('user@domain.tld');
+ $message->setCc('other@domain.tld');
+ $message->setFrom('user@domain.tld');
+
+ $image = new Swift_Image('', 'image.gif', 'image/gif');
+
+ $cid = $message->embed($image);
+ $message->setBody('HTML part', 'text/html');
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+ $imgId = $image->getId();
+
+ $pattern = '~^'.
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: test subject'."\r\n".
+ 'From: user@domain.tld'."\r\n".
+ 'To: user@domain.tld'."\r\n".
+ 'Cc: other@domain.tld'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/related;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'HTML part'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: image/gif; name=image.gif'."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-ID: <'.preg_quote($imgId, '~').'>'."\r\n".
+ 'Content-Disposition: inline; filename=image.gif'."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(''), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D'
+ ;
+
+ $streamA = new Swift_ByteStream_ArrayByteStream();
+ $streamB = new Swift_ByteStream_ArrayByteStream();
+
+ $message->toByteStream($streamA);
+ $message->toByteStream($streamB);
+
+ $this->assertPatternInStream($pattern, $streamA);
+ $this->assertPatternInStream($pattern, $streamB);
+ }
+
+ public function testWritingMessageToByteStreamTwiceUsingAFileAttachment()
+ {
+ $message = new Swift_Message();
+ $message->setSubject('test subject');
+ $message->setTo('user@domain.tld');
+ $message->setCc('other@domain.tld');
+ $message->setFrom('user@domain.tld');
+
+ $attachment = Swift_Attachment::fromPath($this->_attFile);
+
+ $message->attach($attachment);
+
+ $message->setBody('HTML part', 'text/html');
+
+ $id = $message->getId();
+ $date = preg_quote(date('r', $message->getDate()), '~');
+ $boundary = $message->getBoundary();
+
+ $streamA = new Swift_ByteStream_ArrayByteStream();
+ $streamB = new Swift_ByteStream_ArrayByteStream();
+
+ $pattern = '~^'.
+ 'Message-ID: <'.$id.'>'."\r\n".
+ 'Date: '.$date."\r\n".
+ 'Subject: test subject'."\r\n".
+ 'From: user@domain.tld'."\r\n".
+ 'To: user@domain.tld'."\r\n".
+ 'Cc: other@domain.tld'."\r\n".
+ 'MIME-Version: 1.0'."\r\n".
+ 'Content-Type: multipart/mixed;'."\r\n".
+ ' boundary="'.$boundary.'"'."\r\n".
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: text/html; charset=utf-8'."\r\n".
+ 'Content-Transfer-Encoding: quoted-printable'."\r\n".
+ "\r\n".
+ 'HTML part'.
+ "\r\n\r\n".
+ '--'.$boundary."\r\n".
+ 'Content-Type: '.$this->_attFileType.'; name='.$this->_attFileName."\r\n".
+ 'Content-Transfer-Encoding: base64'."\r\n".
+ 'Content-Disposition: attachment; filename='.$this->_attFileName."\r\n".
+ "\r\n".
+ preg_quote(base64_encode(file_get_contents($this->_attFile)), '~').
+ "\r\n\r\n".
+ '--'.$boundary.'--'."\r\n".
+ '$~D'
+ ;
+
+ $message->toByteStream($streamA);
+ $message->toByteStream($streamB);
+
+ $this->assertPatternInStream($pattern, $streamA);
+ $this->assertPatternInStream($pattern, $streamB);
+ }
+
+ // -- Helpers
+
+ public function assertPatternInStream($pattern, $stream, $message = '%s')
+ {
+ $string = '';
+ while (false !== $bytes = $stream->read(8192)) {
+ $string .= $bytes;
+ }
+ $this->assertRegExp($pattern, $string, $message);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug518Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug518Test.php
new file mode 100644
index 00000000..b83984fe
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug518Test.php
@@ -0,0 +1,38 @@
+setTo('foo@bar.com');
+
+ $that = $this;
+ $messageValidation = function ($m) use ($that) {
+ //the getTo should return the same value as we put in
+ $that->assertEquals('foo@bar.com', key($m->getTo()), 'The message has changed after it was put to the memory queue');
+
+ return true;
+ };
+
+ $transport = m::mock('Swift_Transport');
+ $transport->shouldReceive('isStarted')->andReturn(true);
+ $transport->shouldReceive('send')
+ ->with(m::on($messageValidation), $failedRecipients)
+ ->andReturn(1);
+
+ $memorySpool = new Swift_MemorySpool();
+ $memorySpool->queueMessage($message);
+
+ /*
+ * The message is queued in memory.
+ * Lets change the message
+ */
+ $message->setTo('other@value.com');
+
+ $memorySpool->flushQueue($transport, $failedRecipients);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug51Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug51Test.php
new file mode 100644
index 00000000..b9c33b09
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug51Test.php
@@ -0,0 +1,121 @@
+markTestSkipped(
+ 'Cannot run test without a writable directory to use ('.
+ 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)'
+ );
+ }
+
+ $this->_attachmentFile = SWIFT_TMP_DIR.'/attach.rand.bin';
+ file_put_contents($this->_attachmentFile, '');
+
+ $this->_outputFile = SWIFT_TMP_DIR.'/attach.out.bin';
+ file_put_contents($this->_outputFile, '');
+ }
+
+ public function tearDown()
+ {
+ unlink($this->_attachmentFile);
+ unlink($this->_outputFile);
+ }
+
+ public function testAttachmentsDoNotGetTruncatedUsingToByteStream()
+ {
+ //Run 100 times with 10KB attachments
+ for ($i = 0; $i < 10; ++$i) {
+ $message = $this->_createMessageWithRandomAttachment(
+ 10000, $this->_attachmentFile
+ );
+
+ file_put_contents($this->_outputFile, '');
+ $message->toByteStream(
+ new Swift_ByteStream_FileByteStream($this->_outputFile, true)
+ );
+
+ $emailSource = file_get_contents($this->_outputFile);
+
+ $this->assertAttachmentFromSourceMatches(
+ file_get_contents($this->_attachmentFile),
+ $emailSource
+ );
+ }
+ }
+
+ public function testAttachmentsDoNotGetTruncatedUsingToString()
+ {
+ //Run 100 times with 10KB attachments
+ for ($i = 0; $i < 10; ++$i) {
+ $message = $this->_createMessageWithRandomAttachment(
+ 10000, $this->_attachmentFile
+ );
+
+ $emailSource = $message->toString();
+
+ $this->assertAttachmentFromSourceMatches(
+ file_get_contents($this->_attachmentFile),
+ $emailSource
+ );
+ }
+ }
+
+ // -- Custom Assertions
+
+ public function assertAttachmentFromSourceMatches($attachmentData, $source)
+ {
+ $encHeader = 'Content-Transfer-Encoding: base64';
+ $base64declaration = strpos($source, $encHeader);
+
+ $attachmentDataStart = strpos($source, "\r\n\r\n", $base64declaration);
+ $attachmentDataEnd = strpos($source, "\r\n--", $attachmentDataStart);
+
+ if (false === $attachmentDataEnd) {
+ $attachmentBase64 = trim(substr($source, $attachmentDataStart));
+ } else {
+ $attachmentBase64 = trim(substr(
+ $source, $attachmentDataStart,
+ $attachmentDataEnd - $attachmentDataStart
+ ));
+ }
+
+ $this->assertIdenticalBinary($attachmentData, base64_decode($attachmentBase64));
+ }
+
+ // -- Creation Methods
+
+ private function _fillFileWithRandomBytes($byteCount, $file)
+ {
+ // I was going to use dd with if=/dev/random but this way seems more
+ // cross platform even if a hella expensive!!
+
+ file_put_contents($file, '');
+ $fp = fopen($file, 'wb');
+ for ($i = 0; $i < $byteCount; ++$i) {
+ $byteVal = rand(0, 255);
+ fwrite($fp, pack('i', $byteVal));
+ }
+ fclose($fp);
+ }
+
+ private function _createMessageWithRandomAttachment($size, $attachmentPath)
+ {
+ $this->_fillFileWithRandomBytes($size, $attachmentPath);
+
+ $message = Swift_Message::newInstance()
+ ->setSubject('test')
+ ->setBody('test')
+ ->setFrom('a@b.c')
+ ->setTo('d@e.f')
+ ->attach(Swift_Attachment::fromPath($attachmentPath))
+ ;
+
+ return $message;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug534Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug534Test.php
new file mode 100644
index 00000000..263cae51
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug534Test.php
@@ -0,0 +1,38 @@
+setFrom('from@example.com')
+ ->setTo('to@example.com')
+ ->setSubject('test')
+ ;
+ $cid = $message->embed(Swift_Image::fromPath(__DIR__.'/../../_samples/files/swiftmailer.png'));
+ $message->setBody('', 'text/html');
+
+ $that = $this;
+ $messageValidation = function (Swift_Mime_Message $message) use ($that) {
+ preg_match('/cid:(.*)"/', $message->toString(), $matches);
+ $cid = $matches[1];
+ preg_match('/Content-ID: <(.*)>/', $message->toString(), $matches);
+ $contentId = $matches[1];
+ $that->assertEquals($cid, $contentId, 'cid in body and mime part Content-ID differ');
+
+ return true;
+ };
+
+ $failedRecipients = array();
+
+ $transport = m::mock('Swift_Transport');
+ $transport->shouldReceive('isStarted')->andReturn(true);
+ $transport->shouldReceive('send')->with(m::on($messageValidation), $failedRecipients)->andReturn(1);
+
+ $memorySpool = new Swift_MemorySpool();
+ $memorySpool->queueMessage($message);
+ $memorySpool->flushQueue($transport, $failedRecipients);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php
new file mode 100644
index 00000000..3393fb80
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php
@@ -0,0 +1,36 @@
+setCharset('utf-8');
+
+ $header->setNameAddresses(array(
+ 'test@example.com' => $name,
+ ));
+
+ $this->assertSame('To: '.$expectedEncodedName." \r\n", $header->toString());
+ }
+
+ public function encodingDataProvider()
+ {
+ return array(
+ array('this is " a test ö', 'this is =?utf-8?Q?=22?= a test =?utf-8?Q?=C3=B6?='),
+ array(': this is a test ö', '=?utf-8?Q?=3A?= this is a test =?utf-8?Q?=C3=B6?='),
+ array('( test ö', '=?utf-8?Q?=28?= test =?utf-8?Q?=C3=B6?='),
+ array('[ test ö', '=?utf-8?Q?=5B?= test =?utf-8?Q?=C3=B6?='),
+ array('@ test ö)', '=?utf-8?Q?=40?= test =?utf-8?Q?=C3=B6=29?='),
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug71Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug71Test.php
new file mode 100644
index 00000000..4b804537
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug71Test.php
@@ -0,0 +1,20 @@
+_message = new Swift_Message('test');
+ }
+
+ public function testCallingToStringAfterSettingNewBodyReflectsChanges()
+ {
+ $this->_message->setBody('BODY1');
+ $this->assertRegExp('/BODY1/', $this->_message->toString());
+
+ $this->_message->setBody('BODY2');
+ $this->assertRegExp('/BODY2/', $this->_message->toString());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug76Test.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug76Test.php
new file mode 100644
index 00000000..c2b12cb4
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug76Test.php
@@ -0,0 +1,82 @@
+markTestSkipped(
+ 'Cannot run test without a writable directory to use ('.
+ 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)'
+ );
+ }
+
+ $this->_inputFile = SWIFT_TMP_DIR.'/in.bin';
+ file_put_contents($this->_inputFile, '');
+
+ $this->_outputFile = SWIFT_TMP_DIR.'/out.bin';
+ file_put_contents($this->_outputFile, '');
+
+ $this->_encoder = $this->_createEncoder();
+ }
+
+ public function tearDown()
+ {
+ unlink($this->_inputFile);
+ unlink($this->_outputFile);
+ }
+
+ public function testBase64EncodedLineLengthNeverExceeds76CharactersEvenIfArgsDo()
+ {
+ $this->_fillFileWithRandomBytes(1000, $this->_inputFile);
+
+ $os = $this->_createStream($this->_inputFile);
+ $is = $this->_createStream($this->_outputFile);
+
+ $this->_encoder->encodeByteStream($os, $is, 0, 80); //Exceeds 76
+
+ $this->assertMaxLineLength(76, $this->_outputFile,
+ '%s: Line length should not exceed 76 characters'
+ );
+ }
+
+ // -- Custom Assertions
+
+ public function assertMaxLineLength($length, $filePath, $message = '%s')
+ {
+ $lines = file($filePath);
+ foreach ($lines as $line) {
+ $this->assertTrue((strlen(trim($line)) <= 76), $message);
+ }
+ }
+
+ // -- Creation Methods
+
+ private function _fillFileWithRandomBytes($byteCount, $file)
+ {
+ // I was going to use dd with if=/dev/random but this way seems more
+ // cross platform even if a hella expensive!!
+
+ file_put_contents($file, '');
+ $fp = fopen($file, 'wb');
+ for ($i = 0; $i < $byteCount; ++$i) {
+ $byteVal = rand(0, 255);
+ fwrite($fp, pack('i', $byteVal));
+ }
+ fclose($fp);
+ }
+
+ private function _createEncoder()
+ {
+ return new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+ }
+
+ private function _createStream($file)
+ {
+ return new Swift_ByteStream_FileByteStream($file, true);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/bug/Swift/BugFileByteStreamConsecutiveReadCallsTest.php b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/BugFileByteStreamConsecutiveReadCallsTest.php
new file mode 100644
index 00000000..35733ec5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/bug/Swift/BugFileByteStreamConsecutiveReadCallsTest.php
@@ -0,0 +1,19 @@
+read(100);
+ } catch (\Swift_IoException $exc) {
+ $fbs->read(100);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/fixtures/MimeEntityFixture.php b/vendor/swiftmailer/swiftmailer/tests/fixtures/MimeEntityFixture.php
new file mode 100644
index 00000000..e2cf86a5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/fixtures/MimeEntityFixture.php
@@ -0,0 +1,59 @@
+level = $level;
+ $this->string = $string;
+ $this->contentType = $contentType;
+ }
+
+ public function getNestingLevel()
+ {
+ return $this->level;
+ }
+
+ public function toString()
+ {
+ return $this->string;
+ }
+
+ public function getContentType()
+ {
+ return $this->contentType;
+ }
+
+ // These methods are here to account for the implemented interfaces
+ public function getId()
+ {
+ }
+ public function getHeaders()
+ {
+ }
+ public function getBody()
+ {
+ }
+ public function setBody($body, $contentType = null)
+ {
+ }
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ }
+ public function charsetChanged($charset)
+ {
+ }
+ public function encoderChanged(Swift_Mime_ContentEncoder $encoder)
+ {
+ }
+ public function getChildren()
+ {
+ }
+ public function setChildren(array $children)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/smoke.conf.php.default b/vendor/swiftmailer/swiftmailer/tests/smoke.conf.php.default
new file mode 100644
index 00000000..0de2763f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/smoke.conf.php.default
@@ -0,0 +1,63 @@
+_attFile = __DIR__.'/../../../_samples/files/textfile.zip';
+ }
+
+ public function testAttachmentSending()
+ {
+ $mailer = $this->_getMailer();
+ $message = Swift_Message::newInstance()
+ ->setSubject('[Swift Mailer] AttachmentSmokeTest')
+ ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer'))
+ ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS)
+ ->setBody('This message should contain an attached ZIP file (named "textfile.zip").'.PHP_EOL.
+ 'When unzipped, the archive should produce a text file which reads:'.PHP_EOL.
+ '"This is part of a Swift Mailer v4 smoke test."'
+ )
+ ->attach(Swift_Attachment::fromPath($this->_attFile))
+ ;
+ $this->assertEquals(1, $mailer->send($message),
+ '%s: The smoke test should send a single message'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/BasicSmokeTest.php b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/BasicSmokeTest.php
new file mode 100644
index 00000000..c7501d46
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/BasicSmokeTest.php
@@ -0,0 +1,23 @@
+_getMailer();
+ $message = Swift_Message::newInstance()
+ ->setSubject('[Swift Mailer] BasicSmokeTest')
+ ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer'))
+ ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS)
+ ->setBody('One, two, three, four, five...'.PHP_EOL.
+ 'six, seven, eight...'
+ )
+ ;
+ $this->assertEquals(1, $mailer->send($message),
+ '%s: The smoke test should send a single message'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php
new file mode 100644
index 00000000..dca14341
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php
@@ -0,0 +1,31 @@
+_attFile = __DIR__.'/../../../_samples/files/textfile.zip';
+ }
+
+ public function testAttachmentSending()
+ {
+ $mailer = $this->_getMailer();
+ $message = Swift_Message::newInstance('[Swift Mailer] HtmlWithAttachmentSmokeTest')
+ ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer'))
+ ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS)
+ ->attach(Swift_Attachment::fromPath($this->_attFile))
+ ->setBody('This HTML-formatted message should contain an attached ZIP file (named "textfile.zip").'.PHP_EOL.
+ 'When unzipped, the archive should produce a text file which reads:
'.PHP_EOL.
+ 'This is part of a Swift Mailer v4 smoke test.
', 'text/html'
+ )
+ ;
+ $this->assertEquals(1, $mailer->send($message),
+ '%s: The smoke test should send a single message'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/InternationalSmokeTest.php b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/InternationalSmokeTest.php
new file mode 100644
index 00000000..fafd7271
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/InternationalSmokeTest.php
@@ -0,0 +1,40 @@
+_attFile = __DIR__.'/../../../_samples/files/textfile.zip';
+ }
+
+ public function testAttachmentSending()
+ {
+ $mailer = $this->_getMailer();
+ $message = Swift_Message::newInstance()
+ ->setCharset('utf-8')
+ ->setSubject('[Swift Mailer] InternationalSmokeTest (διεθνής)')
+ ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Χριστοφορου (Swift Mailer)'))
+ ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS)
+ ->setBody('This message should contain an attached ZIP file (named "κείμενο, εδάφιο, θέμα.zip").'.PHP_EOL.
+ 'When unzipped, the archive should produce a text file which reads:'.PHP_EOL.
+ '"This is part of a Swift Mailer v4 smoke test."'.PHP_EOL.
+ PHP_EOL.
+ 'Following is some arbitrary Greek text:'.PHP_EOL.
+ 'Δεν βρέθηκαν λέξεις.'
+ )
+ ->attach(Swift_Attachment::fromPath($this->_attFile)
+ ->setContentType('application/zip')
+ ->setFilename('κείμενο, εδάφιο, θέμα.zip')
+ )
+ ;
+ $this->assertEquals(1, $mailer->send($message),
+ '%s: The smoke test should send a single message'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php
new file mode 100644
index 00000000..2a50b190
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php
@@ -0,0 +1,203 @@
+_createArrayStream($input);
+ $output = array();
+ while (false !== $bytes = $bs->read(1)) {
+ $output[] = $bytes;
+ }
+ $this->assertEquals($input, $output,
+ '%s: Bytes read from stream should be the same as bytes in constructor'
+ );
+ }
+
+ public function testReadingMultipleBytesFromBaseInput()
+ {
+ $input = array('a', 'b', 'c', 'd');
+ $bs = $this->_createArrayStream($input);
+ $output = array();
+ while (false !== $bytes = $bs->read(2)) {
+ $output[] = $bytes;
+ }
+ $this->assertEquals(array('ab', 'cd'), $output,
+ '%s: Bytes read from stream should be in pairs'
+ );
+ }
+
+ public function testReadingOddOffsetOnLastByte()
+ {
+ $input = array('a', 'b', 'c', 'd', 'e');
+ $bs = $this->_createArrayStream($input);
+ $output = array();
+ while (false !== $bytes = $bs->read(2)) {
+ $output[] = $bytes;
+ }
+ $this->assertEquals(array('ab', 'cd', 'e'), $output,
+ '%s: Bytes read from stream should be in pairs except final read'
+ );
+ }
+
+ public function testSettingPointerPartway()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+ $bs->setReadPointer(1);
+ $this->assertEquals('b', $bs->read(1),
+ '%s: Byte should be second byte since pointer as at offset 1'
+ );
+ }
+
+ public function testResettingPointerAfterExhaustion()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+ while (false !== $bs->read(1));
+
+ $bs->setReadPointer(0);
+ $this->assertEquals('a', $bs->read(1),
+ '%s: Byte should be first byte since pointer as at offset 0'
+ );
+ }
+
+ public function testPointerNeverSetsBelowZero()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+
+ $bs->setReadPointer(-1);
+ $this->assertEquals('a', $bs->read(1),
+ '%s: Byte should be first byte since pointer should be at offset 0'
+ );
+ }
+
+ public function testPointerNeverSetsAboveStackSize()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+
+ $bs->setReadPointer(3);
+ $this->assertFalse($bs->read(1),
+ '%s: Stream should be at end and thus return false'
+ );
+ }
+
+ public function testBytesCanBeWrittenToStream()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+
+ $bs->write('de');
+
+ $output = array();
+ while (false !== $bytes = $bs->read(1)) {
+ $output[] = $bytes;
+ }
+ $this->assertEquals(array('a', 'b', 'c', 'd', 'e'), $output,
+ '%s: Bytes read from stream should be from initial stack + written'
+ );
+ }
+
+ public function testContentsCanBeFlushed()
+ {
+ $input = array('a', 'b', 'c');
+ $bs = $this->_createArrayStream($input);
+
+ $bs->flushBuffers();
+
+ $this->assertFalse($bs->read(1),
+ '%s: Contents have been flushed so read() should return false'
+ );
+ }
+
+ public function testConstructorCanTakeStringArgument()
+ {
+ $bs = $this->_createArrayStream('abc');
+ $output = array();
+ while (false !== $bytes = $bs->read(1)) {
+ $output[] = $bytes;
+ }
+ $this->assertEquals(array('a', 'b', 'c'), $output,
+ '%s: Bytes read from stream should be the same as bytes in constructor'
+ );
+ }
+
+ public function testBindingOtherStreamsMirrorsWriteOperations()
+ {
+ $bs = $this->_createArrayStream('');
+ $is1 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ $is2 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is2->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+
+ $bs->bind($is1);
+ $bs->bind($is2);
+
+ $bs->write('x');
+ $bs->write('y');
+ }
+
+ public function testBindingOtherStreamsMirrorsFlushOperations()
+ {
+ $bs = $this->_createArrayStream('');
+ $is1 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ $is2 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+
+ $is1->expects($this->once())
+ ->method('flushBuffers');
+ $is2->expects($this->once())
+ ->method('flushBuffers');
+
+ $bs->bind($is1);
+ $bs->bind($is2);
+
+ $bs->flushBuffers();
+ }
+
+ public function testUnbindingStreamPreventsFurtherWrites()
+ {
+ $bs = $this->_createArrayStream('');
+ $is1 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ $is2 = $this->getMockBuilder('Swift_InputByteStream')->getMock();
+
+ $is1->expects($this->at(0))
+ ->method('write')
+ ->with('x');
+ $is1->expects($this->at(1))
+ ->method('write')
+ ->with('y');
+ $is2->expects($this->once())
+ ->method('write')
+ ->with('x');
+
+ $bs->bind($is1);
+ $bs->bind($is2);
+
+ $bs->write('x');
+
+ $bs->unbind($is2);
+
+ $bs->write('y');
+ }
+
+ // -- Creation Methods
+
+ private function _createArrayStream($input)
+ {
+ return new Swift_ByteStream_ArrayByteStream($input);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php
new file mode 100644
index 00000000..3f7a46cf
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php
@@ -0,0 +1,43 @@
+assertSame(1, $reader->getInitialByteSize());
+
+ $reader = new Swift_CharacterReader_GenericFixedWidthReader(4);
+ $this->assertSame(4, $reader->getInitialByteSize());
+ }
+
+ public function testValidationValueIsBasedOnOctetCount()
+ {
+ $reader = new Swift_CharacterReader_GenericFixedWidthReader(4);
+
+ $this->assertSame(
+ 1, $reader->validateByteSequence(array(0x01, 0x02, 0x03), 3)
+ ); //3 octets
+
+ $this->assertSame(
+ 2, $reader->validateByteSequence(array(0x01, 0x0A), 2)
+ ); //2 octets
+
+ $this->assertSame(
+ 3, $reader->validateByteSequence(array(0xFE), 1)
+ ); //1 octet
+
+ $this->assertSame(
+ 0, $reader->validateByteSequence(array(0xFE, 0x03, 0x67, 0x9A), 4)
+ ); //All 4 octets
+ }
+
+ public function testValidationFailsIfTooManyOctets()
+ {
+ $reader = new Swift_CharacterReader_GenericFixedWidthReader(6);
+
+ $this->assertSame(-1, $reader->validateByteSequence(
+ array(0xFE, 0x03, 0x67, 0x9A, 0x10, 0x09, 0x85), 7
+ )); //7 octets
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php
new file mode 100644
index 00000000..41f8f703
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php
@@ -0,0 +1,52 @@
+read($size); ) {
+ $c .= $bytes;
+ $size = $v->validateCharacter($c);
+ if (-1 == $size) {
+ throw new Exception( ... invalid char .. );
+ } elseif (0 == $size) {
+ return $c; //next character in $os
+ }
+ }
+
+ */
+
+ private $_reader;
+
+ public function setUp()
+ {
+ $this->_reader = new Swift_CharacterReader_UsAsciiReader();
+ }
+
+ public function testAllValidAsciiCharactersReturnZero()
+ {
+ for ($ordinal = 0x00; $ordinal <= 0x7F; ++$ordinal) {
+ $this->assertSame(
+ 0, $this->_reader->validateByteSequence(array($ordinal), 1)
+ );
+ }
+ }
+
+ public function testMultipleBytesAreInvalid()
+ {
+ for ($ordinal = 0x00; $ordinal <= 0x7F; $ordinal += 2) {
+ $this->assertSame(
+ -1, $this->_reader->validateByteSequence(array($ordinal, $ordinal + 1), 2)
+ );
+ }
+ }
+
+ public function testBytesAboveAsciiRangeAreInvalid()
+ {
+ for ($ordinal = 0x80; $ordinal <= 0xFF; ++$ordinal) {
+ $this->assertSame(
+ -1, $this->_reader->validateByteSequence(array($ordinal), 1)
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php
new file mode 100644
index 00000000..34e9c91d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php
@@ -0,0 +1,65 @@
+_reader = new Swift_CharacterReader_Utf8Reader();
+ }
+
+ public function testLeading7BitOctetCausesReturnZero()
+ {
+ for ($ordinal = 0x00; $ordinal <= 0x7F; ++$ordinal) {
+ $this->assertSame(
+ 0, $this->_reader->validateByteSequence(array($ordinal), 1)
+ );
+ }
+ }
+
+ public function testLeadingByteOf2OctetCharCausesReturn1()
+ {
+ for ($octet = 0xC0; $octet <= 0xDF; ++$octet) {
+ $this->assertSame(
+ 1, $this->_reader->validateByteSequence(array($octet), 1)
+ );
+ }
+ }
+
+ public function testLeadingByteOf3OctetCharCausesReturn2()
+ {
+ for ($octet = 0xE0; $octet <= 0xEF; ++$octet) {
+ $this->assertSame(
+ 2, $this->_reader->validateByteSequence(array($octet), 1)
+ );
+ }
+ }
+
+ public function testLeadingByteOf4OctetCharCausesReturn3()
+ {
+ for ($octet = 0xF0; $octet <= 0xF7; ++$octet) {
+ $this->assertSame(
+ 3, $this->_reader->validateByteSequence(array($octet), 1)
+ );
+ }
+ }
+
+ public function testLeadingByteOf5OctetCharCausesReturn4()
+ {
+ for ($octet = 0xF8; $octet <= 0xFB; ++$octet) {
+ $this->assertSame(
+ 4, $this->_reader->validateByteSequence(array($octet), 1)
+ );
+ }
+ }
+
+ public function testLeadingByteOf6OctetCharCausesReturn5()
+ {
+ for ($octet = 0xFC; $octet <= 0xFD; ++$octet) {
+ $this->assertSame(
+ 5, $this->_reader->validateByteSequence(array($octet), 1)
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php
new file mode 100644
index 00000000..cbd412bd
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php
@@ -0,0 +1,360 @@
+_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importString(pack('C*',
+ 0xD0, 0x94,
+ 0xD0, 0xB6,
+ 0xD0, 0xBE,
+ 0xD1, 0x8D,
+ 0xD0, 0xBB,
+ 0xD0, 0xB0
+ )
+ );
+ }
+
+ public function testCharactersWrittenUseValidator()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $stream->write(pack('C*',
+ 0xD0, 0xBB,
+ 0xD1, 0x8E,
+ 0xD0, 0xB1,
+ 0xD1, 0x8B,
+ 0xD1, 0x85
+ )
+ );
+ }
+
+ public function testReadCharactersAreInTact()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ //String
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ //Stream
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $stream->write(pack('C*',
+ 0xD0, 0xBB,
+ 0xD1, 0x8E,
+ 0xD0, 0xB1,
+ 0xD1, 0x8B,
+ 0xD1, 0x85
+ )
+ );
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1));
+ $this->assertIdenticalBinary(
+ pack('C*', 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(2)
+ );
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBB), $stream->read(1));
+ $this->assertIdenticalBinary(
+ pack('C*', 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->read(3)
+ );
+ $this->assertIdenticalBinary(pack('C*', 0xD1, 0x85), $stream->read(1));
+
+ $this->assertFalse($stream->read(1));
+ }
+
+ public function testCharactersCanBeReadAsByteArrays()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ //String
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ //Stream
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $stream->write(pack('C*',
+ 0xD0, 0xBB,
+ 0xD1, 0x8E,
+ 0xD0, 0xB1,
+ 0xD1, 0x8B,
+ 0xD1, 0x85
+ )
+ );
+
+ $this->assertEquals(array(0xD0, 0x94), $stream->readBytes(1));
+ $this->assertEquals(array(0xD0, 0xB6, 0xD0, 0xBE), $stream->readBytes(2));
+ $this->assertEquals(array(0xD0, 0xBB), $stream->readBytes(1));
+ $this->assertEquals(
+ array(0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->readBytes(3)
+ );
+ $this->assertEquals(array(0xD1, 0x85), $stream->readBytes(1));
+
+ $this->assertFalse($stream->readBytes(1));
+ }
+
+ public function testRequestingLargeCharCountPastEndOfStream()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE),
+ $stream->read(100)
+ );
+
+ $this->assertFalse($stream->read(1));
+ }
+
+ public function testRequestingByteArrayCountPastEndOfStream()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $this->assertEquals(array(0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE),
+ $stream->readBytes(100)
+ );
+
+ $this->assertFalse($stream->readBytes(1));
+ }
+
+ public function testPointerOffsetCanBeSet()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1));
+
+ $stream->setPointer(0);
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1));
+
+ $stream->setPointer(2);
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBE), $stream->read(1));
+ }
+
+ public function testContentsCanBeFlushed()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
+
+ $stream->flushContents();
+
+ $this->assertFalse($stream->read(1));
+ }
+
+ public function testByteStreamCanBeImportingUsesValidator()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+ $os = $this->_getByteStream();
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $os->shouldReceive('setReadPointer')
+ ->between(0, 1)
+ ->with(0);
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0x94));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xB6));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xBE));
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importByteStream($os);
+ }
+
+ public function testImportingStreamProducesCorrectCharArray()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+ $os = $this->_getByteStream();
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8');
+
+ $os->shouldReceive('setReadPointer')
+ ->between(0, 1)
+ ->with(0);
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0x94));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xB6));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xD0));
+ $os->shouldReceive('read')->once()->andReturn(pack('C*', 0xBE));
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0), 1)->andReturn(1);
+
+ $stream->importByteStream($os);
+
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1));
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xB6), $stream->read(1));
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBE), $stream->read(1));
+
+ $this->assertFalse($stream->read(1));
+ }
+
+ public function testAlgorithmWithFixedWidthCharsets()
+ {
+ $reader = $this->_getReader();
+ $factory = $this->_getFactory($reader);
+
+ $reader->shouldReceive('getInitialByteSize')
+ ->zeroOrMoreTimes()
+ ->andReturn(2);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD1, 0x8D), 2);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0, 0xBB), 2);
+ $reader->shouldReceive('validateByteSequence')->once()->with(array(0xD0, 0xB0), 2);
+
+ $stream = new Swift_CharacterStream_ArrayCharacterStream(
+ $factory, 'utf-8'
+ );
+ $stream->importString(pack('C*', 0xD1, 0x8D, 0xD0, 0xBB, 0xD0, 0xB0));
+
+ $this->assertIdenticalBinary(pack('C*', 0xD1, 0x8D), $stream->read(1));
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBB), $stream->read(1));
+ $this->assertIdenticalBinary(pack('C*', 0xD0, 0xB0), $stream->read(1));
+
+ $this->assertFalse($stream->read(1));
+ }
+
+ // -- Creation methods
+
+ private function _getReader()
+ {
+ return $this->getMockery('Swift_CharacterReader');
+ }
+
+ private function _getFactory($reader)
+ {
+ $factory = $this->getMockery('Swift_CharacterReaderFactory');
+ $factory->shouldReceive('getReaderFor')
+ ->zeroOrMoreTimes()
+ ->with('utf-8')
+ ->andReturn($reader);
+
+ return $factory;
+ }
+
+ private function _getByteStream()
+ {
+ return $this->getMockery('Swift_OutputByteStream');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/DependencyContainerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/DependencyContainerTest.php
new file mode 100644
index 00000000..70690e2d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/DependencyContainerTest.php
@@ -0,0 +1,175 @@
+arg1 = $arg1;
+ $this->arg2 = $arg2;
+ }
+}
+
+class Swift_DependencyContainerTest extends \PHPUnit_Framework_TestCase
+{
+ private $_container;
+
+ public function setUp()
+ {
+ $this->_container = new Swift_DependencyContainer();
+ }
+
+ public function testRegisterAndLookupValue()
+ {
+ $this->_container->register('foo')->asValue('bar');
+ $this->assertEquals('bar', $this->_container->lookup('foo'));
+ }
+
+ public function testHasReturnsTrueForRegisteredValue()
+ {
+ $this->_container->register('foo')->asValue('bar');
+ $this->assertTrue($this->_container->has('foo'));
+ }
+
+ public function testHasReturnsFalseForUnregisteredValue()
+ {
+ $this->assertFalse($this->_container->has('foo'));
+ }
+
+ public function testRegisterAndLookupNewInstance()
+ {
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $this->assertInstanceof('One', $this->_container->lookup('one'));
+ }
+
+ public function testHasReturnsTrueForRegisteredInstance()
+ {
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $this->assertTrue($this->_container->has('one'));
+ }
+
+ public function testNewInstanceIsAlwaysNew()
+ {
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $a = $this->_container->lookup('one');
+ $b = $this->_container->lookup('one');
+ $this->assertEquals($a, $b);
+ }
+
+ public function testRegisterAndLookupSharedInstance()
+ {
+ $this->_container->register('one')->asSharedInstanceOf('One');
+ $this->assertInstanceof('One', $this->_container->lookup('one'));
+ }
+
+ public function testHasReturnsTrueForSharedInstance()
+ {
+ $this->_container->register('one')->asSharedInstanceOf('One');
+ $this->assertTrue($this->_container->has('one'));
+ }
+
+ public function testMultipleSharedInstancesAreSameInstance()
+ {
+ $this->_container->register('one')->asSharedInstanceOf('One');
+ $a = $this->_container->lookup('one');
+ $b = $this->_container->lookup('one');
+ $this->assertEquals($a, $b);
+ }
+
+ public function testNewInstanceWithDependencies()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('one')->asNewInstanceOf('One')
+ ->withDependencies(array('foo'));
+ $obj = $this->_container->lookup('one');
+ $this->assertSame('FOO', $obj->arg1);
+ }
+
+ public function testNewInstanceWithMultipleDependencies()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('bar')->asValue(42);
+ $this->_container->register('one')->asNewInstanceOf('One')
+ ->withDependencies(array('foo', 'bar'));
+ $obj = $this->_container->lookup('one');
+ $this->assertSame('FOO', $obj->arg1);
+ $this->assertSame(42, $obj->arg2);
+ }
+
+ public function testNewInstanceWithInjectedObjects()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $this->_container->register('two')->asNewInstanceOf('One')
+ ->withDependencies(array('one', 'foo'));
+ $obj = $this->_container->lookup('two');
+ $this->assertEquals($this->_container->lookup('one'), $obj->arg1);
+ $this->assertSame('FOO', $obj->arg2);
+ }
+
+ public function testNewInstanceWithAddConstructorValue()
+ {
+ $this->_container->register('one')->asNewInstanceOf('One')
+ ->addConstructorValue('x')
+ ->addConstructorValue(99);
+ $obj = $this->_container->lookup('one');
+ $this->assertSame('x', $obj->arg1);
+ $this->assertSame(99, $obj->arg2);
+ }
+
+ public function testNewInstanceWithAddConstructorLookup()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('bar')->asValue(42);
+ $this->_container->register('one')->asNewInstanceOf('One')
+ ->addConstructorLookup('foo')
+ ->addConstructorLookup('bar');
+
+ $obj = $this->_container->lookup('one');
+ $this->assertSame('FOO', $obj->arg1);
+ $this->assertSame(42, $obj->arg2);
+ }
+
+ public function testResolvedDependenciesCanBeLookedUp()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $this->_container->register('two')->asNewInstanceOf('One')
+ ->withDependencies(array('one', 'foo'));
+ $deps = $this->_container->createDependenciesFor('two');
+ $this->assertEquals(
+ array($this->_container->lookup('one'), 'FOO'), $deps
+ );
+ }
+
+ public function testArrayOfDependenciesCanBeSpecified()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('one')->asNewInstanceOf('One');
+ $this->_container->register('two')->asNewInstanceOf('One')
+ ->withDependencies(array(array('one', 'foo'), 'foo'));
+
+ $obj = $this->_container->lookup('two');
+ $this->assertEquals(array($this->_container->lookup('one'), 'FOO'), $obj->arg1);
+ $this->assertSame('FOO', $obj->arg2);
+ }
+
+ public function testAliasCanBeSet()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('bar')->asAliasOf('foo');
+
+ $this->assertSame('FOO', $this->_container->lookup('bar'));
+ }
+
+ public function testAliasOfAliasCanBeSet()
+ {
+ $this->_container->register('foo')->asValue('FOO');
+ $this->_container->register('bar')->asAliasOf('foo');
+ $this->_container->register('zip')->asAliasOf('bar');
+ $this->_container->register('button')->asAliasOf('zip');
+
+ $this->assertSame('FOO', $this->_container->lookup('button'));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Base64EncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Base64EncoderTest.php
new file mode 100644
index 00000000..1e712fe5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Base64EncoderTest.php
@@ -0,0 +1,173 @@
+_encoder = new Swift_Encoder_Base64Encoder();
+ }
+
+ /*
+ There's really no point in testing the entire base64 encoding to the
+ level QP encoding has been tested. base64_encode() has been in PHP for
+ years.
+ */
+
+ public function testInputOutputRatioIs3to4Bytes()
+ {
+ /*
+ RFC 2045, 6.8
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+ */
+
+ $this->assertEquals(
+ 'MTIz', $this->_encoder->encodeString('123'),
+ '%s: 3 bytes of input should yield 4 bytes of output'
+ );
+ $this->assertEquals(
+ 'MTIzNDU2', $this->_encoder->encodeString('123456'),
+ '%s: 6 bytes in input should yield 8 bytes of output'
+ );
+ $this->assertEquals(
+ 'MTIzNDU2Nzg5', $this->_encoder->encodeString('123456789'),
+ '%s: 9 bytes in input should yield 12 bytes of output'
+ );
+ }
+
+ public function testPadLength()
+ {
+ /*
+ RFC 2045, 6.8
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a body. When fewer than 24 input bits
+ are available in an input group, zero bits are added (on the right)
+ to form an integral number of 6-bit groups. Padding at the end of
+ the data is performed using the "=" character. Since all base64
+ input is an integral number of octets, only the following cases can
+ arise: (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded output will be
+ an integral multiple of 4 characters with no "=" padding, (2) the
+ final quantum of encoding input is exactly 8 bits; here, the final
+ unit of encoded output will be two characters followed by two "="
+ padding characters, or (3) the final quantum of encoding input is
+ exactly 16 bits; here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+ for ($i = 0; $i < 30; ++$i) {
+ $input = pack('C', rand(0, 255));
+ $this->assertRegExp(
+ '~^[a-zA-Z0-9/\+]{2}==$~', $this->_encoder->encodeString($input),
+ '%s: A single byte should have 2 bytes of padding'
+ );
+ }
+
+ for ($i = 0; $i < 30; ++$i) {
+ $input = pack('C*', rand(0, 255), rand(0, 255));
+ $this->assertRegExp(
+ '~^[a-zA-Z0-9/\+]{3}=$~', $this->_encoder->encodeString($input),
+ '%s: Two bytes should have 1 byte of padding'
+ );
+ }
+
+ for ($i = 0; $i < 30; ++$i) {
+ $input = pack('C*', rand(0, 255), rand(0, 255), rand(0, 255));
+ $this->assertRegExp(
+ '~^[a-zA-Z0-9/\+]{4}$~', $this->_encoder->encodeString($input),
+ '%s: Three bytes should have no padding'
+ );
+ }
+ }
+
+ public function testMaximumLineLengthIs76Characters()
+ {
+ /*
+ The encoded output stream must be represented in lines of no more
+ than 76 characters each. All line breaks or other characters not
+ found in Table 1 must be ignored by decoding software.
+ */
+
+ $input =
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ $output =
+ 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
+ 'NERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1'."\r\n".//76 *
+ 'Njc4OTBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3'.//38
+ 'h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFla'."\r\n".//76 *
+ 'MTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BRUl'.//38
+ 'NUVVZXWFla'; //48
+
+ $this->assertEquals(
+ $output, $this->_encoder->encodeString($input),
+ '%s: Lines should be no more than 76 characters'
+ );
+ }
+
+ public function testMaximumLineLengthCanBeSpecified()
+ {
+ $input =
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ $output =
+ 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
+ 'NERUZHSElKS0'."\r\n".//50 *
+ 'xNTk9QUVJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNk'.//38
+ 'ZWZnaGlqa2xt'."\r\n".//50 *
+ 'bm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1'.//38
+ 'BRUlNUVVZXWF'."\r\n".//50 *
+ 'laMTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BR'.//38
+ 'UlNUVVZXWFla'; //50 *
+
+ $this->assertEquals(
+ $output, $this->_encoder->encodeString($input, 0, 50),
+ '%s: Lines should be no more than 100 characters'
+ );
+ }
+
+ public function testFirstLineLengthCanBeDifferent()
+ {
+ $input =
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'abcdefghijklmnopqrstuvwxyz'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+ '1234567890'.
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ $output =
+ 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
+ 'NERUZHSElKS0xNTk9QU'."\r\n".//57 *
+ 'VJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNkZWZnaGl'.//38
+ 'qa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLT'."\r\n".//76 *
+ 'E1OT1BRUlNUVVZXWFlaMTIzNDU2Nzg5MEFCQ0R'.//38
+ 'FRkdISUpLTE1OT1BRUlNUVVZXWFla'; //67
+
+ $this->assertEquals(
+ $output, $this->_encoder->encodeString($input, 19),
+ '%s: First line offset is 19 so first line should be 57 chars long'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php
new file mode 100644
index 00000000..0bf4d181
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php
@@ -0,0 +1,402 @@
+_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($char);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+
+ $this->assertIdenticalBinary($char, $encoder->encodeString($char));
+ }
+ }
+
+ public function testWhiteSpaceAtLineEndingIsEncoded()
+ {
+ /* -- RFC 2045, 6.7 --
+ (3) (White Space) Octets with values of 9 and 32 MAY be
+ represented as US-ASCII TAB (HT) and SPACE characters,
+ respectively, but MUST NOT be so represented at the end
+ of an encoded line. Any TAB (HT) or SPACE characters
+ on an encoded line MUST thus be followed on that line
+ by a printable character. In particular, an "=" at the
+ end of an encoded line, indicating a soft line break
+ (see rule #5) may follow one or more TAB (HT) or SPACE
+ characters. It follows that an octet with decimal
+ value 9 or 32 appearing at the end of an encoded line
+ must be represented according to Rule #1. This rule is
+ necessary because some MTAs (Message Transport Agents,
+ programs which transport messages from one user to
+ another, or perform a portion of such transfers) are
+ known to pad lines of text with SPACEs, and others are
+ known to remove "white space" characters from the end
+ of a line. Therefore, when decoding a Quoted-Printable
+ body, any trailing white space on a line must be
+ deleted, as it will necessarily have been added by
+ intermediate transport agents.
+ */
+
+ $HT = chr(0x09); //9
+ $SPACE = chr(0x20); //32
+
+ //HT
+ $string = 'a'.$HT.$HT."\r\n".'b';
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x09));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x09));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals(
+ 'a'.$HT.'=09'."\r\n".'b',
+ $encoder->encodeString($string)
+ );
+
+ //SPACE
+ $string = 'a'.$SPACE.$SPACE."\r\n".'b';
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x20));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x20));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals(
+ 'a'.$SPACE.'=20'."\r\n".'b',
+ $encoder->encodeString($string)
+ );
+ }
+
+ public function testCRLFIsLeftAlone()
+ {
+ /*
+ (4) (Line Breaks) A line break in a text body, represented
+ as a CRLF sequence in the text canonical form, must be
+ represented by a (RFC 822) line break, which is also a
+ CRLF sequence, in the Quoted-Printable encoding. Since
+ the canonical representation of media types other than
+ text do not generally include the representation of
+ line breaks as CRLF sequences, no hard line breaks
+ (i.e. line breaks that are intended to be meaningful
+ and to be displayed to the user) can occur in the
+ quoted-printable encoding of such types. Sequences
+ like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely
+ appear in non-text data represented in quoted-
+ printable, of course.
+
+ Note that many implementations may elect to encode the
+ local representation of various content types directly
+ rather than converting to canonical form first,
+ encoding, and then converting back to local
+ representation. In particular, this may apply to plain
+ text material on systems that use newline conventions
+ other than a CRLF terminator sequence. Such an
+ implementation optimization is permissible, but only
+ when the combined canonicalization-encoding step is
+ equivalent to performing the three steps separately.
+ */
+
+ $string = 'a'."\r\n".'b'."\r\n".'c'."\r\n";
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(ord('c')));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')->once()->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals($string, $encoder->encodeString($string));
+ }
+
+ public function testLinesLongerThan76CharactersAreSoftBroken()
+ {
+ /*
+ (5) (Soft Line Breaks) The Quoted-Printable encoding
+ REQUIRES that encoded lines be no more than 76
+ characters long. If longer lines are to be encoded
+ with the Quoted-Printable encoding, "soft" line breaks
+ must be used. An equal sign as the last character on a
+ encoded line indicates such a non-significant ("soft")
+ line break in the encoded text.
+ */
+
+ $input = str_repeat('a', 140);
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($input);
+
+ $output = '';
+ for ($i = 0; $i < 140; ++$i) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+
+ if (75 == $i) {
+ $output .= "=\r\n";
+ }
+ $output .= 'a';
+ }
+
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals($output, $encoder->encodeString($input));
+ }
+
+ public function testMaxLineLengthCanBeSpecified()
+ {
+ $input = str_repeat('a', 100);
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($input);
+
+ $output = '';
+ for ($i = 0; $i < 100; ++$i) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+
+ if (53 == $i) {
+ $output .= "=\r\n";
+ }
+ $output .= 'a';
+ }
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals($output, $encoder->encodeString($input, 0, 54));
+ }
+
+ public function testBytesBelowPermittedRangeAreEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ foreach (range(0, 32) as $ordinal) {
+ $char = chr($ordinal);
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($char);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+
+ $this->assertEquals(
+ sprintf('=%02X', $ordinal), $encoder->encodeString($char)
+ );
+ }
+ }
+
+ public function testDecimalByte61IsEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ $char = '=';
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($char);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(61));
+ $charStream->shouldReceive('readBytes')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+
+ $this->assertEquals('=3D', $encoder->encodeString('='));
+ }
+
+ public function testBytesAbovePermittedRangeAreEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ foreach (range(127, 255) as $ordinal) {
+ $char = chr($ordinal);
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($char);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+
+ $this->assertEquals(
+ sprintf('=%02X', $ordinal), $encoder->encodeString($char)
+ );
+ }
+ }
+
+ public function testFirstLineLengthCanBeDifferent()
+ {
+ $input = str_repeat('a', 140);
+
+ $charStream = $this->_createCharStream();
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($input);
+
+ $output = '';
+ for ($i = 0; $i < 140; ++$i) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+
+ if (53 == $i || 53 + 75 == $i) {
+ $output .= "=\r\n";
+ }
+ $output .= 'a';
+ }
+
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_QpEncoder($charStream);
+ $this->assertEquals(
+ $output, $encoder->encodeString($input, 22),
+ '%s: First line should start at offset 22 so can only have max length 54'
+ );
+ }
+
+ public function testTextIsPreWrapped()
+ {
+ $encoder = $this->createEncoder();
+
+ $input = str_repeat('a', 70)."\r\n".
+ str_repeat('a', 70)."\r\n".
+ str_repeat('a', 70);
+
+ $this->assertEquals(
+ $input, $encoder->encodeString($input)
+ );
+ }
+
+ // -- Creation methods
+
+ private function _createCharStream()
+ {
+ return $this->getMockery('Swift_CharacterStream')->shouldIgnoreMissing();
+ }
+
+ private function createEncoder()
+ {
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
+
+ return new Swift_Encoder_QpEncoder($charStream);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php
new file mode 100644
index 00000000..28eae6f8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php
@@ -0,0 +1,141 @@
+getMockery('Swift_CharacterStream');
+
+ $string = '';
+ foreach (range(0x00, 0x7F) as $octet) {
+ $char = pack('C', $octet);
+ $string .= $char;
+ $charStream->shouldReceive('read')
+ ->once()
+ ->andReturn($char);
+ }
+
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+ $charStream->shouldReceive('read')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+
+ $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
+ $encoded = $encoder->encodeString($string);
+
+ foreach (explode("\r\n", $encoded) as $line) {
+ $this->assertRegExp($this->_rfc2045Token, $line,
+ '%s: Encoder should always return a valid RFC 2045 token.');
+ }
+ }
+
+ public function testEncodingNonAsciiCharactersProducesValidToken()
+ {
+ $charStream = $this->getMockery('Swift_CharacterStream');
+
+ $string = '';
+ foreach (range(0x80, 0xFF) as $octet) {
+ $char = pack('C', $octet);
+ $string .= $char;
+ $charStream->shouldReceive('read')
+ ->once()
+ ->andReturn($char);
+ }
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+ $charStream->shouldReceive('read')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+ $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
+
+ $encoded = $encoder->encodeString($string);
+
+ foreach (explode("\r\n", $encoded) as $line) {
+ $this->assertRegExp($this->_rfc2045Token, $line,
+ '%s: Encoder should always return a valid RFC 2045 token.');
+ }
+ }
+
+ public function testMaximumLineLengthCanBeSet()
+ {
+ $charStream = $this->getMockery('Swift_CharacterStream');
+
+ $string = '';
+ for ($x = 0; $x < 200; ++$x) {
+ $char = 'a';
+ $string .= $char;
+ $charStream->shouldReceive('read')
+ ->once()
+ ->andReturn($char);
+ }
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+ $charStream->shouldReceive('read')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+ $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
+
+ $encoded = $encoder->encodeString($string, 0, 75);
+
+ $this->assertEquals(
+ str_repeat('a', 75)."\r\n".
+ str_repeat('a', 75)."\r\n".
+ str_repeat('a', 50),
+ $encoded,
+ '%s: Lines should be wrapped at each 75 characters'
+ );
+ }
+
+ public function testFirstLineCanHaveShorterLength()
+ {
+ $charStream = $this->getMockery('Swift_CharacterStream');
+
+ $string = '';
+ for ($x = 0; $x < 200; ++$x) {
+ $char = 'a';
+ $string .= $char;
+ $charStream->shouldReceive('read')
+ ->once()
+ ->andReturn($char);
+ }
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importString')
+ ->once()
+ ->with($string);
+ $charStream->shouldReceive('read')
+ ->atLeast()->times(1)
+ ->andReturn(false);
+ $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
+ $encoded = $encoder->encodeString($string, 25, 75);
+
+ $this->assertEquals(
+ str_repeat('a', 50)."\r\n".
+ str_repeat('a', 75)."\r\n".
+ str_repeat('a', 75),
+ $encoded,
+ '%s: First line should be 25 bytes shorter than the others.'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/CommandEventTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/CommandEventTest.php
new file mode 100644
index 00000000..3849e09e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/CommandEventTest.php
@@ -0,0 +1,36 @@
+_createEvent($this->_createTransport(), "FOO\r\n");
+ $this->assertEquals("FOO\r\n", $evt->getCommand());
+ }
+
+ public function testSuccessCodesCanBeFetchedViaGetter()
+ {
+ $evt = $this->_createEvent($this->_createTransport(), "FOO\r\n", array(250));
+ $this->assertEquals(array(250), $evt->getSuccessCodes());
+ }
+
+ public function testSourceIsBuffer()
+ {
+ $transport = $this->_createTransport();
+ $evt = $this->_createEvent($transport, "FOO\r\n");
+ $ref = $evt->getSource();
+ $this->assertEquals($transport, $ref);
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent(Swift_Transport $source, $command, $successCodes = array())
+ {
+ return new Swift_Events_CommandEvent($source, $command, $successCodes);
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/EventObjectTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/EventObjectTest.php
new file mode 100644
index 00000000..62a91be5
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/EventObjectTest.php
@@ -0,0 +1,34 @@
+_createEvent($source);
+ $ref = $evt->getSource();
+ $this->assertEquals($source, $ref);
+ }
+
+ public function testEventDoesNotHaveCancelledBubbleWhenNew()
+ {
+ $source = new stdClass();
+ $evt = $this->_createEvent($source);
+ $this->assertFalse($evt->bubbleCancelled());
+ }
+
+ public function testBubbleCanBeCancelledInEvent()
+ {
+ $source = new stdClass();
+ $evt = $this->_createEvent($source);
+ $evt->cancelBubble();
+ $this->assertTrue($evt->bubbleCancelled());
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent($source)
+ {
+ return new Swift_Events_EventObject($source);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/ResponseEventTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/ResponseEventTest.php
new file mode 100644
index 00000000..1028e8e9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/ResponseEventTest.php
@@ -0,0 +1,40 @@
+_createEvent($this->_createTransport(), "250 Ok\r\n", true);
+ $this->assertEquals("250 Ok\r\n", $evt->getResponse(),
+ '%s: Response should be available via getResponse()'
+ );
+ }
+
+ public function testResultCanBeFetchedViaGetter()
+ {
+ $evt = $this->_createEvent($this->_createTransport(), "250 Ok\r\n", false);
+ $this->assertFalse($evt->isValid(),
+ '%s: Result should be checkable via isValid()'
+ );
+ }
+
+ public function testSourceIsBuffer()
+ {
+ $transport = $this->_createTransport();
+ $evt = $this->_createEvent($transport, "250 Ok\r\n", true);
+ $ref = $evt->getSource();
+ $this->assertEquals($transport, $ref);
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent(Swift_Transport $source, $response, $result)
+ {
+ return new Swift_Events_ResponseEvent($source, $response, $result);
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SendEventTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SendEventTest.php
new file mode 100644
index 00000000..8a3fe92f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SendEventTest.php
@@ -0,0 +1,99 @@
+_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+
+ $ref = $evt->getMessage();
+ $this->assertEquals($message, $ref,
+ '%s: Message should be returned from getMessage()'
+ );
+ }
+
+ public function testTransportCanBeFetchViaGetter()
+ {
+ $message = $this->_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+
+ $ref = $evt->getTransport();
+ $this->assertEquals($transport, $ref,
+ '%s: Transport should be returned from getTransport()'
+ );
+ }
+
+ public function testTransportCanBeFetchViaGetSource()
+ {
+ $message = $this->_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+
+ $ref = $evt->getSource();
+ $this->assertEquals($transport, $ref,
+ '%s: Transport should be returned from getSource()'
+ );
+ }
+
+ public function testResultCanBeSetAndGet()
+ {
+ $message = $this->_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+
+ $evt->setResult(
+ Swift_Events_SendEvent::RESULT_SUCCESS | Swift_Events_SendEvent::RESULT_TENTATIVE
+ );
+
+ $this->assertTrue((bool) ($evt->getResult() & Swift_Events_SendEvent::RESULT_SUCCESS));
+ $this->assertTrue((bool) ($evt->getResult() & Swift_Events_SendEvent::RESULT_TENTATIVE));
+ }
+
+ public function testFailedRecipientsCanBeSetAndGet()
+ {
+ $message = $this->_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+
+ $evt->setFailedRecipients(array('foo@bar', 'zip@button'));
+
+ $this->assertEquals(array('foo@bar', 'zip@button'), $evt->getFailedRecipients(),
+ '%s: FailedRecipients should be returned from getter'
+ );
+ }
+
+ public function testFailedRecipientsGetsPickedUpCorrectly()
+ {
+ $message = $this->_createMessage();
+ $transport = $this->_createTransport();
+
+ $evt = $this->_createEvent($transport, $message);
+ $this->assertEquals(array(), $evt->getFailedRecipients());
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent(Swift_Transport $source,
+ Swift_Mime_Message $message)
+ {
+ return new Swift_Events_SendEvent($source, $message);
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+
+ private function _createMessage()
+ {
+ return $this->getMockBuilder('Swift_Mime_Message')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SimpleEventDispatcherTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SimpleEventDispatcherTest.php
new file mode 100644
index 00000000..fdc9c138
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SimpleEventDispatcherTest.php
@@ -0,0 +1,142 @@
+_dispatcher = new Swift_Events_SimpleEventDispatcher();
+ }
+
+ public function testSendEventCanBeCreated()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+ $message = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+ $evt = $this->_dispatcher->createSendEvent($transport, $message);
+ $this->assertInstanceof('Swift_Events_SendEvent', $evt);
+ $this->assertSame($message, $evt->getMessage());
+ $this->assertSame($transport, $evt->getTransport());
+ }
+
+ public function testCommandEventCanBeCreated()
+ {
+ $buf = $this->getMockBuilder('Swift_Transport')->getMock();
+ $evt = $this->_dispatcher->createCommandEvent($buf, "FOO\r\n", array(250));
+ $this->assertInstanceof('Swift_Events_CommandEvent', $evt);
+ $this->assertSame($buf, $evt->getSource());
+ $this->assertEquals("FOO\r\n", $evt->getCommand());
+ $this->assertEquals(array(250), $evt->getSuccessCodes());
+ }
+
+ public function testResponseEventCanBeCreated()
+ {
+ $buf = $this->getMockBuilder('Swift_Transport')->getMock();
+ $evt = $this->_dispatcher->createResponseEvent($buf, "250 Ok\r\n", true);
+ $this->assertInstanceof('Swift_Events_ResponseEvent', $evt);
+ $this->assertSame($buf, $evt->getSource());
+ $this->assertEquals("250 Ok\r\n", $evt->getResponse());
+ $this->assertTrue($evt->isValid());
+ }
+
+ public function testTransportChangeEventCanBeCreated()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+ $evt = $this->_dispatcher->createTransportChangeEvent($transport);
+ $this->assertInstanceof('Swift_Events_TransportChangeEvent', $evt);
+ $this->assertSame($transport, $evt->getSource());
+ }
+
+ public function testTransportExceptionEventCanBeCreated()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+ $ex = new Swift_TransportException('');
+ $evt = $this->_dispatcher->createTransportExceptionEvent($transport, $ex);
+ $this->assertInstanceof('Swift_Events_TransportExceptionEvent', $evt);
+ $this->assertSame($transport, $evt->getSource());
+ $this->assertSame($ex, $evt->getException());
+ }
+
+ public function testListenersAreNotifiedOfDispatchedEvent()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+
+ $evt = $this->_dispatcher->createTransportChangeEvent($transport);
+
+ $listenerA = $this->getMockBuilder('Swift_Events_TransportChangeListener')->getMock();
+ $listenerB = $this->getMockBuilder('Swift_Events_TransportChangeListener')->getMock();
+
+ $this->_dispatcher->bindEventListener($listenerA);
+ $this->_dispatcher->bindEventListener($listenerB);
+
+ $listenerA->expects($this->once())
+ ->method('transportStarted')
+ ->with($evt);
+ $listenerB->expects($this->once())
+ ->method('transportStarted')
+ ->with($evt);
+
+ $this->_dispatcher->dispatchEvent($evt, 'transportStarted');
+ }
+
+ public function testListenersAreOnlyCalledIfImplementingCorrectInterface()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+ $message = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+
+ $evt = $this->_dispatcher->createSendEvent($transport, $message);
+
+ $targetListener = $this->getMockBuilder('Swift_Events_SendListener')->getMock();
+ $otherListener = $this->getMockBuilder('DummyListener')->getMock();
+
+ $this->_dispatcher->bindEventListener($targetListener);
+ $this->_dispatcher->bindEventListener($otherListener);
+
+ $targetListener->expects($this->once())
+ ->method('sendPerformed')
+ ->with($evt);
+ $otherListener->expects($this->never())
+ ->method('sendPerformed');
+
+ $this->_dispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ public function testListenersCanCancelBubblingOfEvent()
+ {
+ $transport = $this->getMockBuilder('Swift_Transport')->getMock();
+ $message = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+
+ $evt = $this->_dispatcher->createSendEvent($transport, $message);
+
+ $listenerA = $this->getMockBuilder('Swift_Events_SendListener')->getMock();
+ $listenerB = $this->getMockBuilder('Swift_Events_SendListener')->getMock();
+
+ $this->_dispatcher->bindEventListener($listenerA);
+ $this->_dispatcher->bindEventListener($listenerB);
+
+ $listenerA->expects($this->once())
+ ->method('sendPerformed')
+ ->with($evt)
+ ->will($this->returnCallback(function ($object) {
+ $object->cancelBubble(true);
+ }));
+ $listenerB->expects($this->never())
+ ->method('sendPerformed');
+
+ $this->_dispatcher->dispatchEvent($evt, 'sendPerformed');
+
+ $this->assertTrue($evt->bubbleCancelled());
+ }
+
+ private function _createDispatcher(array $map)
+ {
+ return new Swift_Events_SimpleEventDispatcher($map);
+ }
+}
+
+class DummyListener implements Swift_Events_EventListener
+{
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportChangeEventTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportChangeEventTest.php
new file mode 100644
index 00000000..8d7b2376
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportChangeEventTest.php
@@ -0,0 +1,32 @@
+_createTransport();
+ $evt = $this->_createEvent($transport);
+ $ref = $evt->getTransport();
+ $this->assertEquals($transport, $ref);
+ }
+
+ public function testSourceIsTransport()
+ {
+ $transport = $this->_createTransport();
+ $evt = $this->_createEvent($transport);
+ $ref = $evt->getSource();
+ $this->assertEquals($transport, $ref);
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent(Swift_Transport $source)
+ {
+ return new Swift_Events_TransportChangeEvent($source);
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportExceptionEventTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportExceptionEventTest.php
new file mode 100644
index 00000000..0324cdb8
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportExceptionEventTest.php
@@ -0,0 +1,43 @@
+_createException();
+ $transport = $this->_createTransport();
+ $evt = $this->_createEvent($transport, $ex);
+ $ref = $evt->getException();
+ $this->assertEquals($ex, $ref,
+ '%s: Exception should be available via getException()'
+ );
+ }
+
+ public function testSourceIsTransport()
+ {
+ $ex = $this->_createException();
+ $transport = $this->_createTransport();
+ $evt = $this->_createEvent($transport, $ex);
+ $ref = $evt->getSource();
+ $this->assertEquals($transport, $ref,
+ '%s: Transport should be available via getSource()'
+ );
+ }
+
+ // -- Creation Methods
+
+ private function _createEvent(Swift_Transport $transport, Swift_TransportException $ex)
+ {
+ return new Swift_Events_TransportExceptionEvent($transport, $ex);
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+
+ private function _createException()
+ {
+ return new Swift_TransportException('');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php
new file mode 100644
index 00000000..634b7ad0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php
@@ -0,0 +1,242 @@
+_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('test', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeOverwritten()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $cache->setString(
+ $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE
+ );
+
+ $this->assertEquals('whatever', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testStringDataCanBeAppended()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $cache->setString(
+ $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND
+ );
+
+ $this->assertEquals('testing', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testHasKeyReturnValue()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+
+ $this->assertTrue($cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyIsWellPartitioned()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $cache->setString(
+ $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+
+ $this->assertEquals('test', $cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $cache->getString($this->_key2, 'foo'));
+ }
+
+ public function testItemKeyIsWellPartitioned()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $cache->setString(
+ $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE
+ );
+
+ $this->assertEquals('test', $cache->getString($this->_key1, 'foo'));
+ $this->assertEquals('ing', $cache->getString($this->_key1, 'bar'));
+ }
+
+ public function testByteStreamCanBeImported()
+ {
+ $os = $this->_createOutputStream();
+ $os->expects($this->at(0))
+ ->method('read')
+ ->will($this->returnValue('abc'));
+ $os->expects($this->at(1))
+ ->method('read')
+ ->will($this->returnValue('def'));
+ $os->expects($this->at(2))
+ ->method('read')
+ ->will($this->returnValue(false));
+
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+ $cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertEquals('abcdef', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamCanBeAppended()
+ {
+ $os1 = $this->_createOutputStream();
+ $os1->expects($this->at(0))
+ ->method('read')
+ ->will($this->returnValue('abc'));
+ $os1->expects($this->at(1))
+ ->method('read')
+ ->will($this->returnValue('def'));
+ $os1->expects($this->at(2))
+ ->method('read')
+ ->will($this->returnValue(false));
+
+ $os2 = $this->_createOutputStream();
+ $os2->expects($this->at(0))
+ ->method('read')
+ ->will($this->returnValue('xyz'));
+ $os2->expects($this->at(1))
+ ->method('read')
+ ->will($this->returnValue('uvw'));
+ $os2->expects($this->at(2))
+ ->method('read')
+ ->will($this->returnValue(false));
+
+ $is = $this->_createKeyCacheInputStream(true);
+
+ $cache = $this->_createCache($is);
+
+ $cache->importFromByteStream(
+ $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND
+ );
+ $cache->importFromByteStream(
+ $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND
+ );
+
+ $this->assertEquals('abcdefxyzuvw', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testByteStreamAndStringCanBeAppended()
+ {
+ $os = $this->_createOutputStream();
+ $os->expects($this->at(0))
+ ->method('read')
+ ->will($this->returnValue('abc'));
+ $os->expects($this->at(1))
+ ->method('read')
+ ->will($this->returnValue('def'));
+ $os->expects($this->at(2))
+ ->method('read')
+ ->will($this->returnValue(false));
+
+ $is = $this->_createKeyCacheInputStream(true);
+
+ $cache = $this->_createCache($is);
+
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND
+ );
+ $cache->importFromByteStream(
+ $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND
+ );
+ $this->assertEquals('testabcdef', $cache->getString($this->_key1, 'foo'));
+ }
+
+ public function testDataCanBeExportedToByteStream()
+ {
+ //See acceptance test for more detail
+ $is = $this->_createInputStream();
+ $is->expects($this->atLeastOnce())
+ ->method('write');
+
+ $kcis = $this->_createKeyCacheInputStream(true);
+
+ $cache = $this->_createCache($kcis);
+
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+
+ $cache->exportToByteStream($this->_key1, 'foo', $is);
+ }
+
+ public function testKeyCanBeCleared()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($cache->hasKey($this->_key1, 'foo'));
+ $cache->clearKey($this->_key1, 'foo');
+ $this->assertFalse($cache->hasKey($this->_key1, 'foo'));
+ }
+
+ public function testNsKeyCanBeCleared()
+ {
+ $is = $this->_createKeyCacheInputStream();
+ $cache = $this->_createCache($is);
+
+ $cache->setString(
+ $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE
+ );
+ $cache->setString(
+ $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE
+ );
+ $this->assertTrue($cache->hasKey($this->_key1, 'foo'));
+ $this->assertTrue($cache->hasKey($this->_key1, 'bar'));
+ $cache->clearAll($this->_key1);
+ $this->assertFalse($cache->hasKey($this->_key1, 'foo'));
+ $this->assertFalse($cache->hasKey($this->_key1, 'bar'));
+ }
+
+ // -- Creation methods
+
+ private function _createCache($is)
+ {
+ return new Swift_KeyCache_ArrayKeyCache($is);
+ }
+
+ private function _createKeyCacheInputStream()
+ {
+ return $this->getMockBuilder('Swift_KeyCache_KeyCacheInputStream')->getMock();
+ }
+
+ private function _createOutputStream()
+ {
+ return $this->getMockBuilder('Swift_OutputByteStream')->getMock();
+ }
+
+ private function _createInputStream()
+ {
+ return $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php
new file mode 100644
index 00000000..38fbc0df
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php
@@ -0,0 +1,73 @@
+getMockBuilder('Swift_KeyCache')->getMock();
+ $cache->expects($this->at(0))
+ ->method('setString')
+ ->with($this->_nsKey, 'foo', 'a', Swift_KeyCache::MODE_APPEND);
+ $cache->expects($this->at(1))
+ ->method('setString')
+ ->with($this->_nsKey, 'foo', 'b', Swift_KeyCache::MODE_APPEND);
+ $cache->expects($this->at(2))
+ ->method('setString')
+ ->with($this->_nsKey, 'foo', 'c', Swift_KeyCache::MODE_APPEND);
+
+ $stream = new Swift_KeyCache_SimpleKeyCacheInputStream();
+ $stream->setKeyCache($cache);
+ $stream->setNsKey($this->_nsKey);
+ $stream->setItemKey('foo');
+
+ $stream->write('a');
+ $stream->write('b');
+ $stream->write('c');
+ }
+
+ public function testFlushContentClearsKey()
+ {
+ $cache = $this->getMockBuilder('Swift_KeyCache')->getMock();
+ $cache->expects($this->once())
+ ->method('clearKey')
+ ->with($this->_nsKey, 'foo');
+
+ $stream = new Swift_KeyCache_SimpleKeyCacheInputStream();
+ $stream->setKeyCache($cache);
+ $stream->setNsKey($this->_nsKey);
+ $stream->setItemKey('foo');
+
+ $stream->flushBuffers();
+ }
+
+ public function testClonedStreamStillReferencesSameCache()
+ {
+ $cache = $this->getMockBuilder('Swift_KeyCache')->getMock();
+ $cache->expects($this->at(0))
+ ->method('setString')
+ ->with($this->_nsKey, 'foo', 'a', Swift_KeyCache::MODE_APPEND);
+ $cache->expects($this->at(1))
+ ->method('setString')
+ ->with($this->_nsKey, 'foo', 'b', Swift_KeyCache::MODE_APPEND);
+ $cache->expects($this->at(2))
+ ->method('setString')
+ ->with('test', 'bar', 'x', Swift_KeyCache::MODE_APPEND);
+
+ $stream = new Swift_KeyCache_SimpleKeyCacheInputStream();
+ $stream->setKeyCache($cache);
+ $stream->setNsKey($this->_nsKey);
+ $stream->setItemKey('foo');
+
+ $stream->write('a');
+ $stream->write('b');
+
+ $newStream = clone $stream;
+ $newStream->setKeyCache($cache);
+ $newStream->setNsKey('test');
+ $newStream->setItemKey('bar');
+
+ $newStream->write('x');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php
new file mode 100644
index 00000000..ff0bce4f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php
@@ -0,0 +1,42 @@
+assertFalse($it->hasNext());
+ }
+
+ public function testHasNextReturnsTrueIfItemsLeft()
+ {
+ $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo'));
+ $this->assertTrue($it->hasNext());
+ }
+
+ public function testReadingToEndOfListCausesHasNextToReturnFalse()
+ {
+ $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo'));
+ $this->assertTrue($it->hasNext());
+ $it->nextRecipient();
+ $this->assertFalse($it->hasNext());
+ }
+
+ public function testReturnedValueHasPreservedKeyValuePair()
+ {
+ $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo'));
+ $this->assertEquals(array('foo@bar' => 'Foo'), $it->nextRecipient());
+ }
+
+ public function testIteratorMovesNextAfterEachIteration()
+ {
+ $it = new Swift_Mailer_ArrayRecipientIterator(array(
+ 'foo@bar' => 'Foo',
+ 'zip@button' => 'Zip thing',
+ 'test@test' => null,
+ ));
+ $this->assertEquals(array('foo@bar' => 'Foo'), $it->nextRecipient());
+ $this->assertEquals(array('zip@button' => 'Zip thing'), $it->nextRecipient());
+ $this->assertEquals(array('test@test' => null), $it->nextRecipient());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MailerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MailerTest.php
new file mode 100644
index 00000000..389264fb
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MailerTest.php
@@ -0,0 +1,147 @@
+_createTransport();
+ $message = $this->_createMessage();
+
+ $started = false;
+ $transport->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$started) {
+ return $started;
+ });
+ $transport->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$started) {
+ $started = true;
+
+ return;
+ });
+
+ $mailer = $this->_createMailer($transport);
+ $mailer->send($message);
+ }
+
+ public function testTransportIsOnlyStartedOnce()
+ {
+ $transport = $this->_createTransport();
+ $message = $this->_createMessage();
+
+ $started = false;
+ $transport->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$started) {
+ return $started;
+ });
+ $transport->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$started) {
+ $started = true;
+
+ return;
+ });
+
+ $mailer = $this->_createMailer($transport);
+ for ($i = 0; $i < 10; ++$i) {
+ $mailer->send($message);
+ }
+ }
+
+ public function testMessageIsPassedToTransport()
+ {
+ $transport = $this->_createTransport();
+ $message = $this->_createMessage();
+ $transport->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any());
+
+ $mailer = $this->_createMailer($transport);
+ $mailer->send($message);
+ }
+
+ public function testSendReturnsCountFromTransport()
+ {
+ $transport = $this->_createTransport();
+ $message = $this->_createMessage();
+ $transport->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturn(57);
+
+ $mailer = $this->_createMailer($transport);
+ $this->assertEquals(57, $mailer->send($message));
+ }
+
+ public function testFailedRecipientReferenceIsPassedToTransport()
+ {
+ $failures = array();
+
+ $transport = $this->_createTransport();
+ $message = $this->_createMessage();
+ $transport->shouldReceive('send')
+ ->once()
+ ->with($message, $failures)
+ ->andReturn(57);
+
+ $mailer = $this->_createMailer($transport);
+ $mailer->send($message, $failures);
+ }
+
+ public function testSendRecordsRfcComplianceExceptionAsEntireSendFailure()
+ {
+ $failures = array();
+
+ $rfcException = new Swift_RfcComplianceException('test');
+ $transport = $this->_createTransport();
+ $message = $this->_createMessage();
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo&invalid' => 'Foo', 'bar@valid.tld' => 'Bar'));
+ $transport->shouldReceive('send')
+ ->once()
+ ->with($message, $failures)
+ ->andThrow($rfcException);
+
+ $mailer = $this->_createMailer($transport);
+ $this->assertEquals(0, $mailer->send($message, $failures), '%s: Should return 0');
+ $this->assertEquals(array('foo&invalid', 'bar@valid.tld'), $failures, '%s: Failures should contain all addresses since the entire message failed to compile');
+ }
+
+ public function testRegisterPluginDelegatesToTransport()
+ {
+ $plugin = $this->_createPlugin();
+ $transport = $this->_createTransport();
+ $mailer = $this->_createMailer($transport);
+
+ $transport->shouldReceive('registerPlugin')
+ ->once()
+ ->with($plugin);
+
+ $mailer->registerPlugin($plugin);
+ }
+
+ // -- Creation methods
+
+ private function _createPlugin()
+ {
+ return $this->getMockery('Swift_Events_EventListener')->shouldIgnoreMissing();
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockery('Swift_Transport')->shouldIgnoreMissing();
+ }
+
+ private function _createMessage()
+ {
+ return $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ }
+
+ private function _createMailer(Swift_Transport $transport)
+ {
+ return new Swift_Mailer($transport);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MessageTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MessageTest.php
new file mode 100644
index 00000000..00039f10
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MessageTest.php
@@ -0,0 +1,130 @@
+_recursiveObjectCloningCheck($message1, $message2, $message1_clone);
+ }
+
+ public function testCloningWithSigners()
+ {
+ $message1 = new Swift_Message('subj', 'body', 'ctype');
+ $signer = new Swift_Signers_DKIMSigner(dirname(dirname(__DIR__)).'/_samples/dkim/dkim.test.priv', 'test.example', 'example');
+ $message1->attachSigner($signer);
+ $message2 = new Swift_Message('subj', 'body', 'ctype');
+ $signer = new Swift_Signers_DKIMSigner(dirname(dirname(__DIR__)).'/_samples/dkim/dkim.test.priv', 'test.example', 'example');
+ $message2->attachSigner($signer);
+ $message1_clone = clone $message1;
+
+ $this->_recursiveObjectCloningCheck($message1, $message2, $message1_clone);
+ }
+
+ public function testBodySwap()
+ {
+ $message1 = new Swift_Message('Test');
+ $html = Swift_MimePart::newInstance('', 'text/html');
+ $html->getHeaders()->addTextHeader('X-Test-Remove', 'Test-Value');
+ $html->getHeaders()->addTextHeader('X-Test-Alter', 'Test-Value');
+ $message1->attach($html);
+ $source = $message1->toString();
+ $message2 = clone $message1;
+ $message2->setSubject('Message2');
+ foreach ($message2->getChildren() as $child) {
+ $child->setBody('Test');
+ $child->getHeaders()->removeAll('X-Test-Remove');
+ $child->getHeaders()->get('X-Test-Alter')->setValue('Altered');
+ }
+ $final = $message1->toString();
+ if ($source != $final) {
+ $this->fail("Difference although object cloned \n [".$source."]\n[".$final."]\n");
+ }
+ $final = $message2->toString();
+ if ($final == $source) {
+ $this->fail('Two body matches although they should differ'."\n [".$source."]\n[".$final."]\n");
+ }
+ $id_1 = $message1->getId();
+ $id_2 = $message2->getId();
+ $this->assertEquals($id_1, $id_2, 'Message Ids differ');
+ $id_2 = $message2->generateId();
+ $this->assertNotEquals($id_1, $id_2, 'Message Ids are the same');
+ }
+
+ // -- Private helpers
+ protected function _recursiveObjectCloningCheck($obj1, $obj2, $obj1_clone)
+ {
+ $obj1_properties = (array) $obj1;
+ $obj2_properties = (array) $obj2;
+ $obj1_clone_properties = (array) $obj1_clone;
+
+ foreach ($obj1_properties as $property => $value) {
+ if (is_object($value)) {
+ $obj1_value = $obj1_properties[$property];
+ $obj2_value = $obj2_properties[$property];
+ $obj1_clone_value = $obj1_clone_properties[$property];
+
+ if ($obj1_value !== $obj2_value) {
+ // two separetely instanciated objects property not referencing same object
+ $this->assertFalse(
+ // but object's clone does - not everything copied
+ $obj1_value === $obj1_clone_value,
+ "Property `$property` cloning error: source and cloned objects property is referencing same object"
+ );
+ } else {
+ // two separetely instanciated objects have same reference
+ $this->assertFalse(
+ // but object's clone doesn't - overdone making copies
+ $obj1_value !== $obj1_clone_value,
+ "Property `$property` not properly cloned: it should reference same object as cloning source (overdone copping)"
+ );
+ }
+ // recurse
+ $this->_recursiveObjectCloningCheck($obj1_value, $obj2_value, $obj1_clone_value);
+ } elseif (is_array($value)) {
+ $obj1_value = $obj1_properties[$property];
+ $obj2_value = $obj2_properties[$property];
+ $obj1_clone_value = $obj1_clone_properties[$property];
+
+ return $this->_recursiveArrayCloningCheck($obj1_value, $obj2_value, $obj1_clone_value);
+ }
+ }
+ }
+
+ protected function _recursiveArrayCloningCheck($array1, $array2, $array1_clone)
+ {
+ foreach ($array1 as $key => $value) {
+ if (is_object($value)) {
+ $arr1_value = $array1[$key];
+ $arr2_value = $array2[$key];
+ $arr1_clone_value = $array1_clone[$key];
+ if ($arr1_value !== $arr2_value) {
+ // two separetely instanciated objects property not referencing same object
+ $this->assertFalse(
+ // but object's clone does - not everything copied
+ $arr1_value === $arr1_clone_value,
+ "Key `$key` cloning error: source and cloned objects property is referencing same object"
+ );
+ } else {
+ // two separetely instanciated objects have same reference
+ $this->assertFalse(
+ // but object's clone doesn't - overdone making copies
+ $arr1_value !== $arr1_clone_value,
+ "Key `$key` not properly cloned: it should reference same object as cloning source (overdone copping)"
+ );
+ }
+ // recurse
+ $this->_recursiveObjectCloningCheck($arr1_value, $arr2_value, $arr1_clone_value);
+ } elseif (is_array($value)) {
+ $arr1_value = $array1[$key];
+ $arr2_value = $array2[$key];
+ $arr1_clone_value = $array1_clone[$key];
+
+ return $this->_recursiveArrayCloningCheck($arr1_value, $arr2_value, $arr1_clone_value);
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AbstractMimeEntityTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AbstractMimeEntityTest.php
new file mode 100644
index 00000000..ffe9cd8d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AbstractMimeEntityTest.php
@@ -0,0 +1,1054 @@
+_createHeaderSet();
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $this->assertSame($headers, $entity->getHeaders());
+ }
+
+ public function testContentTypeIsReturnedFromHeader()
+ {
+ $ctype = $this->_createHeader('Content-Type', 'image/jpeg-test');
+ $headers = $this->_createHeaderSet(array('Content-Type' => $ctype));
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $this->assertEquals('image/jpeg-test', $entity->getContentType());
+ }
+
+ public function testContentTypeIsSetInHeader()
+ {
+ $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $headers = $this->_createHeaderSet(array('Content-Type' => $ctype));
+
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('image/jpeg');
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes()
+ ->with(\Mockery::not('image/jpeg'));
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setContentType('image/jpeg');
+ }
+
+ public function testContentTypeHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addParameterizedHeader')
+ ->once()
+ ->with('Content-Type', 'image/jpeg');
+ $headers->shouldReceive('addParameterizedHeader')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setContentType('image/jpeg');
+ }
+
+ public function testContentTypeCanBeSetViaSetBody()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addParameterizedHeader')
+ ->once()
+ ->with('Content-Type', 'text/html');
+ $headers->shouldReceive('addParameterizedHeader')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBody('foo', 'text/html');
+ }
+
+ public function testGetEncoderFromConstructor()
+ {
+ $encoder = $this->_createEncoder('base64');
+ $entity = $this->_createEntity($this->_createHeaderSet(), $encoder,
+ $this->_createCache()
+ );
+ $this->assertSame($encoder, $entity->getEncoder());
+ }
+
+ public function testSetAndGetEncoder()
+ {
+ $encoder = $this->_createEncoder('base64');
+ $headers = $this->_createHeaderSet();
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setEncoder($encoder);
+ $this->assertSame($encoder, $entity->getEncoder());
+ }
+
+ public function testSettingEncoderUpdatesTransferEncoding()
+ {
+ $encoder = $this->_createEncoder('base64');
+ $encoding = $this->_createHeader(
+ 'Content-Transfer-Encoding', '8bit', array(), false
+ );
+ $headers = $this->_createHeaderSet(array(
+ 'Content-Transfer-Encoding' => $encoding,
+ ));
+ $encoding->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('base64');
+ $encoding->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setEncoder($encoder);
+ }
+
+ public function testSettingEncoderAddsEncodingHeaderIfNonePresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addTextHeader')
+ ->once()
+ ->with('Content-Transfer-Encoding', 'something');
+ $headers->shouldReceive('addTextHeader')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setEncoder($this->_createEncoder('something'));
+ }
+
+ public function testIdIsReturnedFromHeader()
+ {
+ /* -- RFC 2045, 7.
+ In constructing a high-level user agent, it may be desirable to allow
+ one body to make reference to another. Accordingly, bodies may be
+ labelled using the "Content-ID" header field, which is syntactically
+ identical to the "Message-ID" header field
+ */
+
+ $cid = $this->_createHeader('Content-ID', 'zip@button');
+ $headers = $this->_createHeaderSet(array('Content-ID' => $cid));
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $this->assertEquals('zip@button', $entity->getId());
+ }
+
+ public function testIdIsSetInHeader()
+ {
+ $cid = $this->_createHeader('Content-ID', 'zip@button', array(), false);
+ $headers = $this->_createHeaderSet(array('Content-ID' => $cid));
+
+ $cid->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('foo@bar');
+ $cid->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setId('foo@bar');
+ }
+
+ public function testIdIsAutoGenerated()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertRegExp('/^.*?@.*?$/D', $entity->getId());
+ }
+
+ public function testGenerateIdCreatesNewId()
+ {
+ $headers = $this->_createHeaderSet();
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $id1 = $entity->generateId();
+ $id2 = $entity->generateId();
+ $this->assertNotEquals($id1, $id2);
+ }
+
+ public function testGenerateIdSetsNewId()
+ {
+ $headers = $this->_createHeaderSet();
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $id = $entity->generateId();
+ $this->assertEquals($id, $entity->getId());
+ }
+
+ public function testDescriptionIsReadFromHeader()
+ {
+ /* -- RFC 2045, 8.
+ The ability to associate some descriptive information with a given
+ body is often desirable. For example, it may be useful to mark an
+ "image" body as "a picture of the Space Shuttle Endeavor." Such text
+ may be placed in the Content-Description header field. This header
+ field is always optional.
+ */
+
+ $desc = $this->_createHeader('Content-Description', 'something');
+ $headers = $this->_createHeaderSet(array('Content-Description' => $desc));
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $this->assertEquals('something', $entity->getDescription());
+ }
+
+ public function testDescriptionIsSetInHeader()
+ {
+ $desc = $this->_createHeader('Content-Description', '', array(), false);
+ $desc->shouldReceive('setFieldBodyModel')->once()->with('whatever');
+
+ $headers = $this->_createHeaderSet(array('Content-Description' => $desc));
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setDescription('whatever');
+ }
+
+ public function testDescriptionHeaderIsAddedIfNotPresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addTextHeader')
+ ->once()
+ ->with('Content-Description', 'whatever');
+ $headers->shouldReceive('addTextHeader')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setDescription('whatever');
+ }
+
+ public function testSetAndGetMaxLineLength()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setMaxLineLength(60);
+ $this->assertEquals(60, $entity->getMaxLineLength());
+ }
+
+ public function testEncoderIsUsedForStringGeneration()
+ {
+ $encoder = $this->_createEncoder('base64', false);
+ $encoder->expects($this->once())
+ ->method('encodeString')
+ ->with('blah');
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $encoder, $this->_createCache()
+ );
+ $entity->setBody('blah');
+ $entity->toString();
+ }
+
+ public function testMaxLineLengthIsProvidedWhenEncoding()
+ {
+ $encoder = $this->_createEncoder('base64', false);
+ $encoder->expects($this->once())
+ ->method('encodeString')
+ ->with('blah', 0, 65);
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $encoder, $this->_createCache()
+ );
+ $entity->setBody('blah');
+ $entity->setMaxLineLength(65);
+ $entity->toString();
+ }
+
+ public function testHeadersAppearInString()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->once()
+ ->andReturn(
+ "Content-Type: text/plain; charset=utf-8\r\n".
+ "X-MyHeader: foobar\r\n"
+ );
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $this->assertEquals(
+ "Content-Type: text/plain; charset=utf-8\r\n".
+ "X-MyHeader: foobar\r\n",
+ $entity->toString()
+ );
+ }
+
+ public function testSetAndGetBody()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setBody("blah\r\nblah!");
+ $this->assertEquals("blah\r\nblah!", $entity->getBody());
+ }
+
+ public function testBodyIsAppended()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->once()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBody("blah\r\nblah!");
+ $this->assertEquals(
+ "Content-Type: text/plain; charset=utf-8\r\n".
+ "\r\n".
+ "blah\r\nblah!",
+ $entity->toString()
+ );
+ }
+
+ public function testGetBodyReturnsStringFromByteStream()
+ {
+ $os = $this->_createOutputStream('byte stream string');
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setBody($os);
+ $this->assertEquals('byte stream string', $entity->getBody());
+ }
+
+ public function testByteStreamBodyIsAppended()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $os = $this->_createOutputStream('streamed');
+ $headers->shouldReceive('toString')
+ ->once()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBody($os);
+ $this->assertEquals(
+ "Content-Type: text/plain; charset=utf-8\r\n".
+ "\r\n".
+ 'streamed',
+ $entity->toString()
+ );
+ }
+
+ public function testBoundaryCanBeRetrieved()
+ {
+ /* -- RFC 2046, 5.1.1.
+ boundary := 0*69 bcharsnospace
+
+ bchars := bcharsnospace / " "
+
+ bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+ "+" / "_" / "," / "-" / "." /
+ "/" / ":" / "=" / "?"
+ */
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertRegExp(
+ '/^[a-zA-Z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-zA-Z0-9\'\(\)\+_\-,\.\/:=\?]$/D',
+ $entity->getBoundary()
+ );
+ }
+
+ public function testBoundaryNeverChanges()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $firstBoundary = $entity->getBoundary();
+ for ($i = 0; $i < 10; ++$i) {
+ $this->assertEquals($firstBoundary, $entity->getBoundary());
+ }
+ }
+
+ public function testBoundaryCanBeSet()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setBoundary('foobar');
+ $this->assertEquals('foobar', $entity->getBoundary());
+ }
+
+ public function testAddingChildrenGeneratesBoundaryInHeaders()
+ {
+ $child = $this->_createChild();
+ $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $cType->shouldReceive('setParameter')
+ ->once()
+ ->with('boundary', \Mockery::any());
+ $cType->shouldReceive('setParameter')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($this->_createHeaderSet(array(
+ 'Content-Type' => $cType,
+ )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ }
+
+ public function testChildrenOfLevelAttachmentAndLessCauseMultipartMixed()
+ {
+ for ($level = Swift_Mime_MimeEntity::LEVEL_MIXED;
+ $level > Swift_Mime_MimeEntity::LEVEL_TOP; $level /= 2) {
+ $child = $this->_createChild($level);
+ $cType = $this->_createHeader(
+ 'Content-Type', 'text/plain', array(), false
+ );
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('multipart/mixed');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ }
+ }
+
+ public function testChildrenOfLevelAlternativeAndLessCauseMultipartAlternative()
+ {
+ for ($level = Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE;
+ $level > Swift_Mime_MimeEntity::LEVEL_MIXED; $level /= 2) {
+ $child = $this->_createChild($level);
+ $cType = $this->_createHeader(
+ 'Content-Type', 'text/plain', array(), false
+ );
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('multipart/alternative');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ }
+ }
+
+ public function testChildrenOfLevelRelatedAndLessCauseMultipartRelated()
+ {
+ for ($level = Swift_Mime_MimeEntity::LEVEL_RELATED;
+ $level > Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE; $level /= 2) {
+ $child = $this->_createChild($level);
+ $cType = $this->_createHeader(
+ 'Content-Type', 'text/plain', array(), false
+ );
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('multipart/related');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $entity = $this->_createEntity($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ }
+ }
+
+ public function testHighestLevelChildDeterminesContentType()
+ {
+ $combinations = array(
+ array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED,
+ Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ Swift_Mime_MimeEntity::LEVEL_RELATED,
+ ),
+ 'type' => 'multipart/mixed',
+ ),
+ array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED,
+ Swift_Mime_MimeEntity::LEVEL_RELATED,
+ ),
+ 'type' => 'multipart/mixed',
+ ),
+ array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED,
+ Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ ),
+ 'type' => 'multipart/mixed',
+ ),
+ array('levels' => array(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ Swift_Mime_MimeEntity::LEVEL_RELATED,
+ ),
+ 'type' => 'multipart/alternative',
+ ),
+ );
+
+ foreach ($combinations as $combination) {
+ $children = array();
+ foreach ($combination['levels'] as $level) {
+ $children[] = $this->_createChild($level);
+ }
+
+ $cType = $this->_createHeader(
+ 'Content-Type', 'text/plain', array(), false
+ );
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with($combination['type']);
+
+ $headerSet = $this->_createHeaderSet(array('Content-Type' => $cType));
+ $headerSet->shouldReceive('newInstance')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use ($headerSet) {
+ return $headerSet;
+ });
+ $entity = $this->_createEntity($headerSet,
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren($children);
+ }
+ }
+
+ public function testChildrenAppearNestedInString()
+ {
+ /* -- RFC 2046, 5.1.1.
+ (excerpt too verbose to paste here)
+ */
+
+ $headers = $this->_createHeaderSet(array(), false);
+
+ $child1 = new MimeEntityFixture(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ 'foobar', 'text/plain'
+ );
+
+ $child2 = new MimeEntityFixture(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ "Content-Type: text/html\r\n".
+ "\r\n".
+ 'foobar', 'text/html'
+ );
+
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: multipart/alternative; boundary=\"xxx\"\r\n");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBoundary('xxx');
+ $entity->setChildren(array($child1, $child2));
+
+ $this->assertEquals(
+ "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n".
+ "\r\n".
+ "\r\n--xxx\r\n".
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ "foobar\r\n".
+ "\r\n--xxx\r\n".
+ "Content-Type: text/html\r\n".
+ "\r\n".
+ "foobar\r\n".
+ "\r\n--xxx--\r\n",
+ $entity->toString()
+ );
+ }
+
+ public function testMixingLevelsIsHierarchical()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $newHeaders = $this->_createHeaderSet(array(), false);
+
+ $part = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ 'foobar'
+ );
+
+ $attachment = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_MIXED,
+ "Content-Type: application/octet-stream\r\n".
+ "\r\n".
+ 'data'
+ );
+
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: multipart/mixed; boundary=\"xxx\"\r\n");
+ $headers->shouldReceive('newInstance')
+ ->zeroOrMoreTimes()
+ ->andReturn($newHeaders);
+ $newHeaders->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: multipart/alternative; boundary=\"yyy\"\r\n");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBoundary('xxx');
+ $entity->setChildren(array($part, $attachment));
+
+ $this->assertRegExp(
+ '~^'.
+ "Content-Type: multipart/mixed; boundary=\"xxx\"\r\n".
+ "\r\n\r\n--xxx\r\n".
+ "Content-Type: multipart/alternative; boundary=\"yyy\"\r\n".
+ "\r\n\r\n--(.*?)\r\n".
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ 'foobar'.
+ "\r\n\r\n--\\1--\r\n".
+ "\r\n\r\n--xxx\r\n".
+ "Content-Type: application/octet-stream\r\n".
+ "\r\n".
+ 'data'.
+ "\r\n\r\n--xxx--\r\n".
+ '$~',
+ $entity->toString()
+ );
+ }
+
+ public function testSettingEncoderNotifiesChildren()
+ {
+ $child = $this->_createChild(0, '', false);
+ $encoder = $this->_createEncoder('base64');
+
+ $child->shouldReceive('encoderChanged')
+ ->once()
+ ->with($encoder);
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ $entity->setEncoder($encoder);
+ }
+
+ public function testReceiptOfEncoderChangeNotifiesChildren()
+ {
+ $child = $this->_createChild(0, '', false);
+ $encoder = $this->_createEncoder('base64');
+
+ $child->shouldReceive('encoderChanged')
+ ->once()
+ ->with($encoder);
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ $entity->encoderChanged($encoder);
+ }
+
+ public function testReceiptOfCharsetChangeNotifiesChildren()
+ {
+ $child = $this->_createChild(0, '', false);
+ $child->shouldReceive('charsetChanged')
+ ->once()
+ ->with('windows-874');
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $entity->setChildren(array($child));
+ $entity->charsetChanged('windows-874');
+ }
+
+ public function testEntityIsWrittenToByteStream()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $is = $this->_createInputStream(false);
+ $is->expects($this->atLeastOnce())
+ ->method('write');
+
+ $entity->toByteStream($is);
+ }
+
+ public function testEntityHeadersAreComittedToByteStream()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $is = $this->_createInputStream(false);
+ $is->expects($this->atLeastOnce())
+ ->method('write');
+ $is->expects($this->atLeastOnce())
+ ->method('commit');
+
+ $entity->toByteStream($is);
+ }
+
+ public function testOrderingTextBeforeHtml()
+ {
+ $htmlChild = new MimeEntityFixture(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ "Content-Type: text/html\r\n".
+ "\r\n".
+ 'HTML PART',
+ 'text/html'
+ );
+ $textChild = new MimeEntityFixture(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE,
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ 'TEXT PART',
+ 'text/plain'
+ );
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: multipart/alternative; boundary=\"xxx\"\r\n");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $entity->setBoundary('xxx');
+ $entity->setChildren(array($htmlChild, $textChild));
+
+ $this->assertEquals(
+ "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n".
+ "\r\n\r\n--xxx\r\n".
+ "Content-Type: text/plain\r\n".
+ "\r\n".
+ 'TEXT PART'.
+ "\r\n\r\n--xxx\r\n".
+ "Content-Type: text/html\r\n".
+ "\r\n".
+ 'HTML PART'.
+ "\r\n\r\n--xxx--\r\n",
+ $entity->toString()
+ );
+ }
+
+ public function testUnsettingChildrenRestoresContentType()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $child = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE);
+
+ $cType->shouldReceive('setFieldBodyModel')
+ ->twice()
+ ->with('image/jpeg');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('multipart/alternative');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes()
+ ->with(\Mockery::not('multipart/alternative', 'image/jpeg'));
+
+ $entity = $this->_createEntity($this->_createHeaderSet(array(
+ 'Content-Type' => $cType,
+ )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $entity->setContentType('image/jpeg');
+ $entity->setChildren(array($child));
+ $entity->setChildren(array());
+ }
+
+ public function testBodyIsReadFromCacheWhenUsingToStringIfPresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+ $cache->shouldReceive('hasKey')
+ ->once()
+ ->with(\Mockery::any(), 'body')
+ ->andReturn(true);
+ $cache->shouldReceive('getString')
+ ->once()
+ ->with(\Mockery::any(), 'body')
+ ->andReturn("\r\ncache\r\ncache!");
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $this->assertEquals(
+ "Content-Type: text/plain; charset=utf-8\r\n".
+ "\r\n".
+ "cache\r\ncache!",
+ $entity->toString()
+ );
+ }
+
+ public function testBodyIsAddedToCacheWhenUsingToString()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+ $cache->shouldReceive('hasKey')
+ ->once()
+ ->with(\Mockery::any(), 'body')
+ ->andReturn(false);
+ $cache->shouldReceive('setString')
+ ->once()
+ ->with(\Mockery::any(), 'body', "\r\nblah\r\nblah!", Swift_KeyCache::MODE_WRITE);
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $entity->toString();
+ }
+
+ public function testBodyIsClearedFromCacheIfNewBodySet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $entity->toString();
+
+ // We set the expectation at this point because we only care what happens when calling setBody()
+ $cache->shouldReceive('clearKey')
+ ->once()
+ ->with(\Mockery::any(), 'body');
+
+ $entity->setBody("new\r\nnew!");
+ }
+
+ public function testBodyIsNotClearedFromCacheIfSameBodySet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $entity->toString();
+
+ // We set the expectation at this point because we only care what happens when calling setBody()
+ $cache->shouldReceive('clearKey')
+ ->never();
+
+ $entity->setBody("blah\r\nblah!");
+ }
+
+ public function testBodyIsClearedFromCacheIfNewEncoderSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+ $otherEncoder = $this->_createEncoder();
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $entity->toString();
+
+ // We set the expectation at this point because we only care what happens when calling setEncoder()
+ $cache->shouldReceive('clearKey')
+ ->once()
+ ->with(\Mockery::any(), 'body');
+
+ $entity->setEncoder($otherEncoder);
+ }
+
+ public function testBodyIsReadFromCacheWhenUsingToByteStreamIfPresent()
+ {
+ $is = $this->_createInputStream();
+ $cache = $this->_createCache(false);
+ $cache->shouldReceive('hasKey')
+ ->once()
+ ->with(\Mockery::any(), 'body')
+ ->andReturn(true);
+ $cache->shouldReceive('exportToByteStream')
+ ->once()
+ ->with(\Mockery::any(), 'body', $is);
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $cache
+ );
+ $entity->setBody('foo');
+
+ $entity->toByteStream($is);
+ }
+
+ public function testBodyIsAddedToCacheWhenUsingToByteStream()
+ {
+ $is = $this->_createInputStream();
+ $cache = $this->_createCache(false);
+ $cache->shouldReceive('hasKey')
+ ->once()
+ ->with(\Mockery::any(), 'body')
+ ->andReturn(false);
+ $cache->shouldReceive('getInputByteStream')
+ ->once()
+ ->with(\Mockery::any(), 'body');
+
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $cache
+ );
+ $entity->setBody('foo');
+
+ $entity->toByteStream($is);
+ }
+
+ public function testFluidInterface()
+ {
+ $entity = $this->_createEntity($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $this->assertSame($entity,
+ $entity
+ ->setContentType('text/plain')
+ ->setEncoder($this->_createEncoder())
+ ->setId('foo@bar')
+ ->setDescription('my description')
+ ->setMaxLineLength(998)
+ ->setBody('xx')
+ ->setBoundary('xyz')
+ ->setChildren(array())
+ );
+ }
+
+ // -- Private helpers
+
+ abstract protected function _createEntity($headers, $encoder, $cache);
+
+ protected function _createChild($level = null, $string = '', $stub = true)
+ {
+ $child = $this->getMockery('Swift_Mime_MimeEntity')->shouldIgnoreMissing();
+ if (isset($level)) {
+ $child->shouldReceive('getNestingLevel')
+ ->zeroOrMoreTimes()
+ ->andReturn($level);
+ }
+ $child->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn($string);
+
+ return $child;
+ }
+
+ protected function _createEncoder($name = 'quoted-printable', $stub = true)
+ {
+ $encoder = $this->getMockBuilder('Swift_Mime_ContentEncoder')->getMock();
+ $encoder->expects($this->any())
+ ->method('getName')
+ ->will($this->returnValue($name));
+ $encoder->expects($this->any())
+ ->method('encodeString')
+ ->will($this->returnCallback(function () {
+ $args = func_get_args();
+
+ return array_shift($args);
+ }));
+
+ return $encoder;
+ }
+
+ protected function _createCache($stub = true)
+ {
+ return $this->getMockery('Swift_KeyCache')->shouldIgnoreMissing();
+ }
+
+ protected function _createHeaderSet($headers = array(), $stub = true)
+ {
+ $set = $this->getMockery('Swift_Mime_HeaderSet')->shouldIgnoreMissing();
+ $set->shouldReceive('get')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function ($key) use ($headers) {
+ return $headers[$key];
+ });
+ $set->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function ($key) use ($headers) {
+ return array_key_exists($key, $headers);
+ });
+
+ return $set;
+ }
+
+ protected function _createHeader($name, $model = null, $params = array(), $stub = true)
+ {
+ $header = $this->getMockery('Swift_Mime_ParameterizedHeader')->shouldIgnoreMissing();
+ $header->shouldReceive('getFieldName')
+ ->zeroOrMoreTimes()
+ ->andReturn($name);
+ $header->shouldReceive('getFieldBodyModel')
+ ->zeroOrMoreTimes()
+ ->andReturn($model);
+ $header->shouldReceive('getParameter')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function ($key) use ($params) {
+ return $params[$key];
+ });
+
+ return $header;
+ }
+
+ protected function _createOutputStream($data = null, $stub = true)
+ {
+ $os = $this->getMockery('Swift_OutputByteStream');
+ if (isset($data)) {
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use ($data) {
+ static $first = true;
+ if (!$first) {
+ return false;
+ }
+
+ $first = false;
+
+ return $data;
+ });
+ $os->shouldReceive('setReadPointer')
+ ->zeroOrMoreTimes();
+ }
+
+ return $os;
+ }
+
+ protected function _createInputStream($stub = true)
+ {
+ return $this->getMockBuilder('Swift_InputByteStream')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AttachmentTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AttachmentTest.php
new file mode 100644
index 00000000..bd2499c0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AttachmentTest.php
@@ -0,0 +1,320 @@
+_createAttachment($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(
+ Swift_Mime_MimeEntity::LEVEL_MIXED, $attachment->getNestingLevel()
+ );
+ }
+
+ public function testDispositionIsReturnedFromHeader()
+ {
+ /* -- RFC 2183, 2.1, 2.2.
+ */
+
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment');
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('attachment', $attachment->getDisposition());
+ }
+
+ public function testDispositionIsSetInHeader()
+ {
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array(), false
+ );
+ $disposition->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('inline');
+ $disposition->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setDisposition('inline');
+ }
+
+ public function testDispositionIsAddedIfNonePresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addParameterizedHeader')
+ ->once()
+ ->with('Content-Disposition', 'inline');
+ $headers->shouldReceive('addParameterizedHeader')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $attachment->setDisposition('inline');
+ }
+
+ public function testDispositionIsAutoDefaultedToAttachment()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addParameterizedHeader')
+ ->once()
+ ->with('Content-Disposition', 'attachment');
+ $headers->shouldReceive('addParameterizedHeader')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ }
+
+ public function testDefaultContentTypeInitializedToOctetStream()
+ {
+ $cType = $this->_createHeader('Content-Type', '',
+ array(), false
+ );
+ $cType->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('application/octet-stream');
+ $cType->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ }
+
+ public function testFilenameIsReturnedFromHeader()
+ {
+ /* -- RFC 2183, 2.3.
+ */
+
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('filename' => 'foo.txt')
+ );
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('foo.txt', $attachment->getFilename());
+ }
+
+ public function testFilenameIsSetInHeader()
+ {
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('filename' => 'foo.txt'), false
+ );
+ $disposition->shouldReceive('setParameter')
+ ->once()
+ ->with('filename', 'bar.txt');
+ $disposition->shouldReceive('setParameter')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setFilename('bar.txt');
+ }
+
+ public function testSettingFilenameSetsNameInContentType()
+ {
+ /*
+ This is a legacy requirement which isn't covered by up-to-date RFCs.
+ */
+
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array(), false
+ );
+ $cType->shouldReceive('setParameter')
+ ->once()
+ ->with('name', 'bar.txt');
+ $cType->shouldReceive('setParameter')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setFilename('bar.txt');
+ }
+
+ public function testSizeIsReturnedFromHeader()
+ {
+ /* -- RFC 2183, 2.7.
+ */
+
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('size' => 1234)
+ );
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(1234, $attachment->getSize());
+ }
+
+ public function testSizeIsSetInHeader()
+ {
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array(), false
+ );
+ $disposition->shouldReceive('setParameter')
+ ->once()
+ ->with('size', 12345);
+ $disposition->shouldReceive('setParameter')
+ ->zeroOrMoreTimes();
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setSize(12345);
+ }
+
+ public function testFilnameCanBeReadFromFileStream()
+ {
+ $file = $this->_createFileStream('/bar/file.ext', '');
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('filename' => 'foo.txt'), false
+ );
+ $disposition->shouldReceive('setParameter')
+ ->once()
+ ->with('filename', 'file.ext');
+
+ $attachment = $this->_createAttachment($this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setFile($file);
+ }
+
+ public function testContentTypeCanBeSetViaSetFile()
+ {
+ $file = $this->_createFileStream('/bar/file.ext', '');
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('filename' => 'foo.txt'), false
+ );
+ $disposition->shouldReceive('setParameter')
+ ->once()
+ ->with('filename', 'file.ext');
+
+ $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('text/html');
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $headers = $this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition,
+ 'Content-Type' => $ctype,
+ ));
+
+ $attachment = $this->_createAttachment($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $attachment->setFile($file, 'text/html');
+ }
+
+ public function XtestContentTypeCanBeLookedUpFromCommonListIfNotProvided()
+ {
+ $file = $this->_createFileStream('/bar/file.zip', '');
+ $disposition = $this->_createHeader('Content-Disposition', 'attachment',
+ array('filename' => 'foo.zip'), false
+ );
+ $disposition->shouldReceive('setParameter')
+ ->once()
+ ->with('filename', 'file.zip');
+
+ $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('application/zip');
+ $ctype->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $headers = $this->_createHeaderSet(array(
+ 'Content-Disposition' => $disposition,
+ 'Content-Type' => $ctype,
+ ));
+
+ $attachment = $this->_createAttachment($headers, $this->_createEncoder(),
+ $this->_createCache(), array('zip' => 'application/zip', 'txt' => 'text/plain')
+ );
+ $attachment->setFile($file);
+ }
+
+ public function testDataCanBeReadFromFile()
+ {
+ $file = $this->_createFileStream('/foo/file.ext', '');
+ $attachment = $this->_createAttachment($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $attachment->setFile($file);
+ $this->assertEquals('', $attachment->getBody());
+ }
+
+ public function testFluidInterface()
+ {
+ $attachment = $this->_createAttachment($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertSame($attachment,
+ $attachment
+ ->setContentType('application/pdf')
+ ->setEncoder($this->_createEncoder())
+ ->setId('foo@bar')
+ ->setDescription('my pdf')
+ ->setMaxLineLength(998)
+ ->setBody('xx')
+ ->setBoundary('xyz')
+ ->setChildren(array())
+ ->setDisposition('inline')
+ ->setFilename('afile.txt')
+ ->setSize(123)
+ ->setFile($this->_createFileStream('foo.txt', ''))
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createEntity($headers, $encoder, $cache)
+ {
+ return $this->_createAttachment($headers, $encoder, $cache);
+ }
+
+ protected function _createAttachment($headers, $encoder, $cache, $mimeTypes = array())
+ {
+ return new Swift_Mime_Attachment($headers, $encoder, $cache, new Swift_Mime_Grammar(), $mimeTypes);
+ }
+
+ protected function _createFileStream($path, $data, $stub = true)
+ {
+ $file = $this->getMockery('Swift_FileStream');
+ $file->shouldReceive('getPath')
+ ->zeroOrMoreTimes()
+ ->andReturn($path);
+ $file->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use ($data) {
+ static $first = true;
+ if (!$first) {
+ return false;
+ }
+
+ $first = false;
+
+ return $data;
+ });
+ $file->shouldReceive('setReadPointer')
+ ->zeroOrMoreTimes();
+
+ return $file;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php
new file mode 100644
index 00000000..0442af33
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php
@@ -0,0 +1,323 @@
+_encoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+ }
+
+ public function testNameIsBase64()
+ {
+ $this->assertEquals('base64', $this->_encoder->getName());
+ }
+
+ /*
+ There's really no point in testing the entire base64 encoding to the
+ level QP encoding has been tested. base64_encode() has been in PHP for
+ years.
+ */
+
+ public function testInputOutputRatioIs3to4Bytes()
+ {
+ /*
+ RFC 2045, 6.8
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+ */
+
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('123');
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is);
+ $this->assertEquals('MTIz', $collection->content);
+ }
+
+ public function testPadLength()
+ {
+ /*
+ RFC 2045, 6.8
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a body. When fewer than 24 input bits
+ are available in an input group, zero bits are added (on the right)
+ to form an integral number of 6-bit groups. Padding at the end of
+ the data is performed using the "=" character. Since all base64
+ input is an integral number of octets, only the following cases can
+ arise: (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded output will be
+ an integral multiple of 4 characters with no "=" padding, (2) the
+ final quantum of encoding input is exactly 8 bits; here, the final
+ unit of encoded output will be two characters followed by two "="
+ padding characters, or (3) the final quantum of encoding input is
+ exactly 16 bits; here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+ for ($i = 0; $i < 30; ++$i) {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn(pack('C', rand(0, 255)));
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is);
+ $this->assertRegExp('~^[a-zA-Z0-9/\+]{2}==$~', $collection->content,
+ '%s: A single byte should have 2 bytes of padding'
+ );
+ }
+
+ for ($i = 0; $i < 30; ++$i) {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn(pack('C*', rand(0, 255), rand(0, 255)));
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is);
+ $this->assertRegExp('~^[a-zA-Z0-9/\+]{3}=$~', $collection->content,
+ '%s: Two bytes should have 1 byte of padding'
+ );
+ }
+
+ for ($i = 0; $i < 30; ++$i) {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn(pack('C*', rand(0, 255), rand(0, 255), rand(0, 255)));
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is);
+ $this->assertRegExp('~^[a-zA-Z0-9/\+]{4}$~', $collection->content,
+ '%s: Three bytes should have no padding'
+ );
+ }
+ }
+
+ public function testMaximumLineLengthIs76Characters()
+ {
+ /*
+ The encoded output stream must be represented in lines of no more
+ than 76 characters each. All line breaks or other characters not
+ found in Table 1 must be ignored by decoding software.
+ */
+
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //12
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('mnopqrstuvwx'); //24
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('yzabc1234567'); //36
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('890ABCDEFGHI'); //48
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('JKLMNOPQRSTU'); //60
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('VWXYZ1234567'); //72
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //84
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is);
+ $this->assertEquals(
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFS\r\n".
+ 'U1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts',
+ $collection->content
+ );
+ }
+
+ public function testMaximumLineLengthCanBeDifferent()
+ {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //12
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('mnopqrstuvwx'); //24
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('yzabc1234567'); //36
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('890ABCDEFGHI'); //48
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('JKLMNOPQRSTU'); //60
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('VWXYZ1234567'); //72
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //84
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is, 0, 50);
+ $this->assertEquals(
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3OD\r\n".
+ "kwQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVoxMjM0NTY3YWJj\r\n".
+ 'ZGVmZ2hpamts',
+ $collection->content
+ );
+ }
+
+ public function testMaximumLineLengthIsNeverMoreThan76Chars()
+ {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //12
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('mnopqrstuvwx'); //24
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('yzabc1234567'); //36
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('890ABCDEFGHI'); //48
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('JKLMNOPQRSTU'); //60
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('VWXYZ1234567'); //72
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //84
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is, 0, 100);
+ $this->assertEquals(
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFS\r\n".
+ 'U1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts',
+ $collection->content
+ );
+ }
+
+ public function testFirstLineLengthCanBeDifferent()
+ {
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //12
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('mnopqrstuvwx'); //24
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('yzabc1234567'); //36
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('890ABCDEFGHI'); //48
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('JKLMNOPQRSTU'); //60
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('VWXYZ1234567'); //72
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('abcdefghijkl'); //84
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_encoder->encodeByteStream($os, $is, 19);
+ $this->assertEquals(
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDR\r\n".
+ 'EVGR0hJSktMTU5PUFFSU1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts',
+ $collection->content
+ );
+ }
+
+ private function _createOutputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_OutputByteStream')->shouldIgnoreMissing();
+ }
+
+ private function _createInputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_InputByteStream')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php
new file mode 100644
index 00000000..b523a64c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php
@@ -0,0 +1,173 @@
+_getEncoder('7bit');
+ $this->assertEquals('7bit', $encoder->getName());
+
+ $encoder = $this->_getEncoder('8bit');
+ $this->assertEquals('8bit', $encoder->getName());
+ }
+
+ public function testNoOctetsAreModifiedInString()
+ {
+ $encoder = $this->_getEncoder('7bit');
+ foreach (range(0x00, 0xFF) as $octet) {
+ $byte = pack('C', $octet);
+ $this->assertIdenticalBinary($byte, $encoder->encodeString($byte));
+ }
+ }
+
+ public function testNoOctetsAreModifiedInByteStream()
+ {
+ $encoder = $this->_getEncoder('7bit');
+ foreach (range(0x00, 0xFF) as $octet) {
+ $byte = pack('C', $octet);
+
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn($byte);
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder->encodeByteStream($os, $is);
+ $this->assertIdenticalBinary($byte, $collection->content);
+ }
+ }
+
+ public function testLineLengthCanBeSpecified()
+ {
+ $encoder = $this->_getEncoder('7bit');
+
+ $chars = array();
+ for ($i = 0; $i < 50; ++$i) {
+ $chars[] = 'a';
+ }
+ $input = implode(' ', $chars); //99 chars long
+
+ $this->assertEquals(
+ 'a a a a a a a a a a a a a a a a a a a a a a a a a '."\r\n".//50 *
+ 'a a a a a a a a a a a a a a a a a a a a a a a a a', //99
+ $encoder->encodeString($input, 0, 50),
+ '%s: Lines should be wrapped at 50 chars'
+ );
+ }
+
+ public function testLineLengthCanBeSpecifiedInByteStream()
+ {
+ $encoder = $this->_getEncoder('7bit');
+
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+
+ for ($i = 0; $i < 50; ++$i) {
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('a ');
+ }
+
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder->encodeByteStream($os, $is, 0, 50);
+ $this->assertEquals(
+ str_repeat('a ', 25)."\r\n".str_repeat('a ', 25),
+ $collection->content
+ );
+ }
+
+ public function testencodeStringGeneratesCorrectCrlf()
+ {
+ $encoder = $this->_getEncoder('7bit', true);
+ $this->assertEquals("a\r\nb", $encoder->encodeString("a\rb"),
+ '%s: Line endings should be standardized'
+ );
+ $this->assertEquals("a\r\nb", $encoder->encodeString("a\nb"),
+ '%s: Line endings should be standardized'
+ );
+ $this->assertEquals("a\r\n\r\nb", $encoder->encodeString("a\n\rb"),
+ '%s: Line endings should be standardized'
+ );
+ $this->assertEquals("a\r\n\r\nb", $encoder->encodeString("a\r\rb"),
+ '%s: Line endings should be standardized'
+ );
+ $this->assertEquals("a\r\n\r\nb", $encoder->encodeString("a\n\nb"),
+ '%s: Line endings should be standardized'
+ );
+ }
+
+ public function crlfProvider()
+ {
+ return array(
+ array("\r", "a\r\nb"),
+ array("\n", "a\r\nb"),
+ array("\n\r", "a\r\n\r\nb"),
+ array("\n\n", "a\r\n\r\nb"),
+ array("\r\r", "a\r\n\r\nb"),
+ );
+ }
+
+ /**
+ * @dataProvider crlfProvider
+ */
+ public function testCanonicEncodeByteStreamGeneratesCorrectCrlf($test, $expected)
+ {
+ $encoder = $this->_getEncoder('7bit', true);
+
+ $os = $this->_createOutputByteStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('a');
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn($test);
+ $os->shouldReceive('read')
+ ->once()
+ ->andReturn('b');
+ $os->shouldReceive('read')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals($expected, $collection->content);
+ }
+
+ // -- Private helpers
+
+ private function _getEncoder($name, $canonical = false)
+ {
+ return new Swift_Mime_ContentEncoder_PlainContentEncoder($name, $canonical);
+ }
+
+ private function _createOutputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_OutputByteStream')->shouldIgnoreMissing();
+ }
+
+ private function _createInputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_InputByteStream')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php
new file mode 100644
index 00000000..81992891
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php
@@ -0,0 +1,518 @@
+_createCharacterStream(true)
+ );
+ $this->assertEquals('quoted-printable', $encoder->getName());
+ }
+
+ /* -- RFC 2045, 6.7 --
+ (1) (General 8bit representation) Any octet, except a CR or
+ LF that is part of a CRLF line break of the canonical
+ (standard) form of the data being encoded, may be
+ represented by an "=" followed by a two digit
+ hexadecimal representation of the octet's value. The
+ digits of the hexadecimal alphabet, for this purpose,
+ are "0123456789ABCDEF". Uppercase letters must be
+ used; lowercase letters are not allowed. Thus, for
+ example, the decimal value 12 (US-ASCII form feed) can
+ be represented by "=0C", and the decimal value 61 (US-
+ ASCII EQUAL SIGN) can be represented by "=3D". This
+ rule must be followed except when the following rules
+ allow an alternative encoding.
+ */
+
+ public function testPermittedCharactersAreNotEncoded()
+ {
+ /* -- RFC 2045, 6.7 --
+ (2) (Literal representation) Octets with decimal values of
+ 33 through 60 inclusive, and 62 through 126, inclusive,
+ MAY be represented as the US-ASCII characters which
+ correspond to those octets (EXCLAMATION POINT through
+ LESS THAN, and GREATER THAN through TILDE,
+ respectively).
+ */
+
+ foreach (array_merge(range(33, 60), range(62, 126)) as $ordinal) {
+ $char = chr($ordinal);
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertIdenticalBinary($char, $collection->content);
+ }
+ }
+
+ public function testLinearWhiteSpaceAtLineEndingIsEncoded()
+ {
+ /* -- RFC 2045, 6.7 --
+ (3) (White Space) Octets with values of 9 and 32 MAY be
+ represented as US-ASCII TAB (HT) and SPACE characters,
+ respectively, but MUST NOT be so represented at the end
+ of an encoded line. Any TAB (HT) or SPACE characters
+ on an encoded line MUST thus be followed on that line
+ by a printable character. In particular, an "=" at the
+ end of an encoded line, indicating a soft line break
+ (see rule #5) may follow one or more TAB (HT) or SPACE
+ characters. It follows that an octet with decimal
+ value 9 or 32 appearing at the end of an encoded line
+ must be represented according to Rule #1. This rule is
+ necessary because some MTAs (Message Transport Agents,
+ programs which transport messages from one user to
+ another, or perform a portion of such transfers) are
+ known to pad lines of text with SPACEs, and others are
+ known to remove "white space" characters from the end
+ of a line. Therefore, when decoding a Quoted-Printable
+ body, any trailing white space on a line must be
+ deleted, as it will necessarily have been added by
+ intermediate transport agents.
+ */
+
+ $HT = chr(0x09); //9
+ $SPACE = chr(0x20); //32
+
+ //HT
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x09));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x09));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+
+ $this->assertEquals("a\t=09\r\nb", $collection->content);
+
+ //SPACE
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x20));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x20));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+
+ $this->assertEquals("a =20\r\nb", $collection->content);
+ }
+
+ public function testCRLFIsLeftAlone()
+ {
+ /*
+ (4) (Line Breaks) A line break in a text body, represented
+ as a CRLF sequence in the text canonical form, must be
+ represented by a (RFC 822) line break, which is also a
+ CRLF sequence, in the Quoted-Printable encoding. Since
+ the canonical representation of media types other than
+ text do not generally include the representation of
+ line breaks as CRLF sequences, no hard line breaks
+ (i.e. line breaks that are intended to be meaningful
+ and to be displayed to the user) can occur in the
+ quoted-printable encoding of such types. Sequences
+ like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely
+ appear in non-text data represented in quoted-
+ printable, of course.
+
+ Note that many implementations may elect to encode the
+ local representation of various content types directly
+ rather than converting to canonical form first,
+ encoding, and then converting back to local
+ representation. In particular, this may apply to plain
+ text material on systems that use newline conventions
+ other than a CRLF terminator sequence. Such an
+ implementation optimization is permissible, but only
+ when the combined canonicalization-encoding step is
+ equivalent to performing the three steps separately.
+ */
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('c')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0D));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x0A));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals("a\r\nb\r\nc\r\n", $collection->content);
+ }
+
+ public function testLinesLongerThan76CharactersAreSoftBroken()
+ {
+ /*
+ (5) (Soft Line Breaks) The Quoted-Printable encoding
+ REQUIRES that encoded lines be no more than 76
+ characters long. If longer lines are to be encoded
+ with the Quoted-Printable encoding, "soft" line breaks
+ must be used. An equal sign as the last character on a
+ encoded line indicates such a non-significant ("soft")
+ line break in the encoded text.
+ */
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+
+ for ($seq = 0; $seq <= 140; ++$seq) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ }
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals(str_repeat('a', 75)."=\r\n".str_repeat('a', 66), $collection->content);
+ }
+
+ public function testMaxLineLengthCanBeSpecified()
+ {
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+
+ for ($seq = 0; $seq <= 100; ++$seq) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ }
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is, 0, 54);
+ $this->assertEquals(str_repeat('a', 53)."=\r\n".str_repeat('a', 48), $collection->content);
+ }
+
+ public function testBytesBelowPermittedRangeAreEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ foreach (range(0, 32) as $ordinal) {
+ $char = chr($ordinal);
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals(sprintf('=%02X', $ordinal), $collection->content);
+ }
+ }
+
+ public function testDecimalByte61IsEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ $char = chr(61);
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(61));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals(sprintf('=%02X', 61), $collection->content);
+ }
+
+ public function testBytesAbovePermittedRangeAreEncoded()
+ {
+ /*
+ According to Rule (1 & 2)
+ */
+
+ foreach (range(127, 255) as $ordinal) {
+ $char = chr($ordinal);
+
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($ordinal));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is);
+ $this->assertEquals(sprintf('=%02X', $ordinal), $collection->content);
+ }
+ }
+
+ public function testFirstLineLengthCanBeDifferent()
+ {
+ $os = $this->_createOutputByteStream(true);
+ $charStream = $this->_createCharacterStream();
+ $is = $this->_createInputByteStream();
+ $collection = new Swift_StreamCollector();
+
+ $is->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing($collection);
+ $charStream->shouldReceive('flushContents')
+ ->once();
+ $charStream->shouldReceive('importByteStream')
+ ->once()
+ ->with($os);
+
+ for ($seq = 0; $seq <= 140; ++$seq) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ }
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ $encoder->encodeByteStream($os, $is, 22);
+ $this->assertEquals(
+ str_repeat('a', 53)."=\r\n".str_repeat('a', 75)."=\r\n".str_repeat('a', 13),
+ $collection->content
+ );
+ }
+
+ public function testObserverInterfaceCanChangeCharset()
+ {
+ $stream = $this->_createCharacterStream();
+ $stream->shouldReceive('setCharacterSet')
+ ->once()
+ ->with('windows-1252');
+
+ $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($stream);
+ $encoder->charsetChanged('windows-1252');
+ }
+
+ public function testTextIsPreWrapped()
+ {
+ $encoder = $this->createEncoder();
+
+ $input = str_repeat('a', 70)."\r\n".
+ str_repeat('a', 70)."\r\n".
+ str_repeat('a', 70);
+
+ $os = new Swift_ByteStream_ArrayByteStream();
+ $is = new Swift_ByteStream_ArrayByteStream();
+ $is->write($input);
+
+ $encoder->encodeByteStream($is, $os);
+
+ $this->assertEquals(
+ $input, $os->read(PHP_INT_MAX)
+ );
+ }
+
+ // -- Creation Methods
+
+ private function _createCharacterStream($stub = false)
+ {
+ return $this->getMockery('Swift_CharacterStream')->shouldIgnoreMissing();
+ }
+
+ private function createEncoder()
+ {
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
+
+ return new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
+ }
+
+ private function _createOutputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_OutputByteStream')->shouldIgnoreMissing();
+ }
+
+ private function _createInputByteStream($stub = false)
+ {
+ return $this->getMockery('Swift_InputByteStream')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/EmbeddedFileTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/EmbeddedFileTest.php
new file mode 100644
index 00000000..f4c3ac89
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/EmbeddedFileTest.php
@@ -0,0 +1,57 @@
+_createEmbeddedFile($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(
+ Swift_Mime_MimeEntity::LEVEL_RELATED, $file->getNestingLevel()
+ );
+ }
+
+ public function testIdIsAutoGenerated()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addIdHeader')
+ ->once()
+ ->with('Content-ID', '/^.*?@.*?$/D');
+
+ $file = $this->_createEmbeddedFile($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ }
+
+ public function testDefaultDispositionIsInline()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addParameterizedHeader')
+ ->once()
+ ->with('Content-Disposition', 'inline');
+ $headers->shouldReceive('addParameterizedHeader')
+ ->zeroOrMoreTimes();
+
+ $file = $this->_createEmbeddedFile($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ }
+
+ // -- Private helpers
+
+ protected function _createAttachment($headers, $encoder, $cache, $mimeTypes = array())
+ {
+ return $this->_createEmbeddedFile($headers, $encoder, $cache, $mimeTypes);
+ }
+
+ private function _createEmbeddedFile($headers, $encoder, $cache)
+ {
+ return new Swift_Mime_EmbeddedFile($headers, $encoder, $cache, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php
new file mode 100644
index 00000000..35801556
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php
@@ -0,0 +1,13 @@
+assertEquals('B', $encoder->getName());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php
new file mode 100644
index 00000000..54a792a6
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php
@@ -0,0 +1,223 @@
+_createEncoder(
+ $this->_createCharacterStream(true)
+ );
+ $this->assertEquals('Q', $encoder->getName());
+ }
+
+ public function testSpaceAndTabNeverAppear()
+ {
+ /* -- RFC 2047, 4.
+ Only a subset of the printable ASCII characters may be used in
+ 'encoded-text'. Space and tab characters are not allowed, so that
+ the beginning and end of an 'encoded-word' are obvious.
+ */
+
+ $charStream = $this->_createCharacterStream();
+ $charStream->shouldReceive('readBytes')
+ ->atLeast()->times(6)
+ ->andReturn(array(ord('a')), array(0x20), array(0x09), array(0x20), array(ord('b')), false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $this->assertNotRegExp('~[ \t]~', $encoder->encodeString("a \t b"),
+ '%s: encoded-words in headers cannot contain LWSP as per RFC 2047.'
+ );
+ }
+
+ public function testSpaceIsRepresentedByUnderscore()
+ {
+ /* -- RFC 2047, 4.2.
+ (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
+ represented as "_" (underscore, ASCII 95.). (This character may
+ not pass through some internetwork mail gateways, but its use
+ will greatly enhance readability of "Q" encoded data with mail
+ readers that do not support this encoding.) Note that the "_"
+ always represents hexadecimal 20, even if the SPACE character
+ occupies a different code position in the character set in use.
+ */
+ $charStream = $this->_createCharacterStream();
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(0x20));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('b')));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $this->assertEquals('a_b', $encoder->encodeString('a b'),
+ '%s: Spaces can be represented by more readable underscores as per RFC 2047.'
+ );
+ }
+
+ public function testEqualsAndQuestionAndUnderscoreAreEncoded()
+ {
+ /* -- RFC 2047, 4.2.
+ (3) 8-bit values which correspond to printable ASCII characters other
+ than "=", "?", and "_" (underscore), MAY be represented as those
+ characters. (But see section 5 for restrictions.) In
+ particular, SPACE and TAB MUST NOT be represented as themselves
+ within encoded words.
+ */
+ $charStream = $this->_createCharacterStream();
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('=')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('?')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('_')));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $this->assertEquals('=3D=3F=5F', $encoder->encodeString('=?_'),
+ '%s: Chars =, ? and _ (underscore) may not appear as per RFC 2047.'
+ );
+ }
+
+ public function testParensAndQuotesAreEncoded()
+ {
+ /* -- RFC 2047, 5 (2).
+ A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT
+ contain the characters "(", ")" or "
+ */
+
+ $charStream = $this->_createCharacterStream();
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('(')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('"')));
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord(')')));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $this->assertEquals('=28=22=29', $encoder->encodeString('(")'),
+ '%s: Chars (, " (DQUOTE) and ) may not appear as per RFC 2047.'
+ );
+ }
+
+ public function testOnlyCharactersAllowedInPhrasesAreUsed()
+ {
+ /* -- RFC 2047, 5.
+ (3) As a replacement for a 'word' entity within a 'phrase', for example,
+ one that precedes an address in a From, To, or Cc header. The ABNF
+ definition for 'phrase' from RFC 822 thus becomes:
+
+ phrase = 1*( encoded-word / word )
+
+ In this case the set of characters that may be used in a "Q"-encoded
+ 'encoded-word' is restricted to: . An 'encoded-word' that appears within a
+ 'phrase' MUST be separated from any adjacent 'word', 'text' or
+ 'special' by 'linear-white-space'.
+ */
+
+ $allowedBytes = array_merge(
+ range(ord('a'), ord('z')), range(ord('A'), ord('Z')),
+ range(ord('0'), ord('9')),
+ array(ord('!'), ord('*'), ord('+'), ord('-'), ord('/'))
+ );
+
+ foreach (range(0x00, 0xFF) as $byte) {
+ $char = pack('C', $byte);
+
+ $charStream = $this->_createCharacterStream();
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array($byte));
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $encodedChar = $encoder->encodeString($char);
+
+ if (in_array($byte, $allowedBytes)) {
+ $this->assertEquals($char, $encodedChar,
+ '%s: Character '.$char.' should not be encoded.'
+ );
+ } elseif (0x20 == $byte) {
+ //Special case
+ $this->assertEquals('_', $encodedChar,
+ '%s: Space character should be replaced.'
+ );
+ } else {
+ $this->assertEquals(sprintf('=%02X', $byte), $encodedChar,
+ '%s: Byte '.$byte.' should be encoded.'
+ );
+ }
+ }
+ }
+
+ public function testEqualsNeverAppearsAtEndOfLine()
+ {
+ /* -- RFC 2047, 5 (3).
+ The 'encoded-text' in an 'encoded-word' must be self-contained;
+ 'encoded-text' MUST NOT be continued from one 'encoded-word' to
+ another. This implies that the 'encoded-text' portion of a "B"
+ 'encoded-word' will be a multiple of 4 characters long; for a "Q"
+ 'encoded-word', any "=" character that appears in the 'encoded-text'
+ portion will be followed by two hexadecimal characters.
+ */
+
+ $input = str_repeat('a', 140);
+
+ $charStream = $this->_createCharacterStream();
+
+ $output = '';
+ $seq = 0;
+ for (; $seq < 140; ++$seq) {
+ $charStream->shouldReceive('readBytes')
+ ->once()
+ ->andReturn(array(ord('a')));
+
+ if (75 == $seq) {
+ $output .= "\r\n"; // =\r\n
+ }
+ $output .= 'a';
+ }
+
+ $charStream->shouldReceive('readBytes')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $encoder = $this->_createEncoder($charStream);
+ $this->assertEquals($output, $encoder->encodeString($input));
+ }
+
+ // -- Creation Methods
+
+ private function _createEncoder($charStream)
+ {
+ return new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream);
+ }
+
+ private function _createCharacterStream($stub = false)
+ {
+ return $this->getMockery('Swift_CharacterStream')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/DateHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/DateHeaderTest.php
new file mode 100644
index 00000000..1822ea68
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/DateHeaderTest.php
@@ -0,0 +1,69 @@
+_getHeader('Date');
+ $this->assertEquals(Swift_Mime_Header::TYPE_DATE, $header->getFieldType());
+ }
+
+ public function testGetTimestamp()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setTimestamp($timestamp);
+ $this->assertSame($timestamp, $header->getTimestamp());
+ }
+
+ public function testTimestampCanBeSetBySetter()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setTimestamp($timestamp);
+ $this->assertSame($timestamp, $header->getTimestamp());
+ }
+
+ public function testIntegerTimestampIsConvertedToRfc2822Date()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setTimestamp($timestamp);
+ $this->assertEquals(date('r', $timestamp), $header->getFieldBody());
+ }
+
+ public function testSetBodyModel()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setFieldBodyModel($timestamp);
+ $this->assertEquals(date('r', $timestamp), $header->getFieldBody());
+ }
+
+ public function testGetBodyModel()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setTimestamp($timestamp);
+ $this->assertEquals($timestamp, $header->getFieldBodyModel());
+ }
+
+ public function testToString()
+ {
+ $timestamp = time();
+ $header = $this->_getHeader('Date');
+ $header->setTimestamp($timestamp);
+ $this->assertEquals('Date: '.date('r', $timestamp)."\r\n",
+ $header->toString()
+ );
+ }
+
+ private function _getHeader($name)
+ {
+ return new Swift_Mime_Headers_DateHeader($name, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php
new file mode 100644
index 00000000..93b3f609
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php
@@ -0,0 +1,189 @@
+_getHeader('Message-ID');
+ $this->assertEquals(Swift_Mime_Header::TYPE_ID, $header->getFieldType());
+ }
+
+ public function testValueMatchesMsgIdSpec()
+ {
+ /* -- RFC 2822, 3.6.4.
+ message-id = "Message-ID:" msg-id CRLF
+
+ in-reply-to = "In-Reply-To:" 1*msg-id CRLF
+
+ references = "References:" 1*msg-id CRLF
+
+ msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
+
+ id-left = dot-atom-text / no-fold-quote / obs-id-left
+
+ id-right = dot-atom-text / no-fold-literal / obs-id-right
+
+ no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
+
+ no-fold-literal = "[" *(dtext / quoted-pair) "]"
+ */
+
+ $header = $this->_getHeader('Message-ID');
+ $header->setId('id-left@id-right');
+ $this->assertEquals('', $header->getFieldBody());
+ }
+
+ public function testIdCanBeRetrievedVerbatim()
+ {
+ $header = $this->_getHeader('Message-ID');
+ $header->setId('id-left@id-right');
+ $this->assertEquals('id-left@id-right', $header->getId());
+ }
+
+ public function testMultipleIdsCanBeSet()
+ {
+ $header = $this->_getHeader('References');
+ $header->setIds(array('a@b', 'x@y'));
+ $this->assertEquals(array('a@b', 'x@y'), $header->getIds());
+ }
+
+ public function testSettingMultipleIdsProducesAListValue()
+ {
+ /* -- RFC 2822, 3.6.4.
+ The "References:" and "In-Reply-To:" field each contain one or more
+ unique message identifiers, optionally separated by CFWS.
+
+ .. SNIP ..
+
+ in-reply-to = "In-Reply-To:" 1*msg-id CRLF
+
+ references = "References:" 1*msg-id CRLF
+ */
+
+ $header = $this->_getHeader('References');
+ $header->setIds(array('a@b', 'x@y'));
+ $this->assertEquals(' ', $header->getFieldBody());
+ }
+
+ public function testIdLeftCanBeQuoted()
+ {
+ /* -- RFC 2822, 3.6.4.
+ id-left = dot-atom-text / no-fold-quote / obs-id-left
+ */
+
+ $header = $this->_getHeader('References');
+ $header->setId('"ab"@c');
+ $this->assertEquals('"ab"@c', $header->getId());
+ $this->assertEquals('<"ab"@c>', $header->getFieldBody());
+ }
+
+ public function testIdLeftCanContainAnglesAsQuotedPairs()
+ {
+ /* -- RFC 2822, 3.6.4.
+ no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
+ */
+
+ $header = $this->_getHeader('References');
+ $header->setId('"a\\<\\>b"@c');
+ $this->assertEquals('"a\\<\\>b"@c', $header->getId());
+ $this->assertEquals('<"a\\<\\>b"@c>', $header->getFieldBody());
+ }
+
+ public function testIdLeftCanBeDotAtom()
+ {
+ $header = $this->_getHeader('References');
+ $header->setId('a.b+&%$.c@d');
+ $this->assertEquals('a.b+&%$.c@d', $header->getId());
+ $this->assertEquals('', $header->getFieldBody());
+ }
+
+ public function testInvalidIdLeftThrowsException()
+ {
+ try {
+ $header = $this->_getHeader('References');
+ $header->setId('a b c@d');
+ $this->fail(
+ 'Exception should be thrown since "a b c" is not valid id-left.'
+ );
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testIdRightCanBeDotAtom()
+ {
+ /* -- RFC 2822, 3.6.4.
+ id-right = dot-atom-text / no-fold-literal / obs-id-right
+ */
+
+ $header = $this->_getHeader('References');
+ $header->setId('a@b.c+&%$.d');
+ $this->assertEquals('a@b.c+&%$.d', $header->getId());
+ $this->assertEquals('', $header->getFieldBody());
+ }
+
+ public function testIdRightCanBeLiteral()
+ {
+ /* -- RFC 2822, 3.6.4.
+ no-fold-literal = "[" *(dtext / quoted-pair) "]"
+ */
+
+ $header = $this->_getHeader('References');
+ $header->setId('a@[1.2.3.4]');
+ $this->assertEquals('a@[1.2.3.4]', $header->getId());
+ $this->assertEquals('', $header->getFieldBody());
+ }
+
+ public function testInvalidIdRightThrowsException()
+ {
+ try {
+ $header = $this->_getHeader('References');
+ $header->setId('a@b c d');
+ $this->fail(
+ 'Exception should be thrown since "b c d" is not valid id-right.'
+ );
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testMissingAtSignThrowsException()
+ {
+ /* -- RFC 2822, 3.6.4.
+ msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
+ */
+
+ try {
+ $header = $this->_getHeader('References');
+ $header->setId('abc');
+ $this->fail(
+ 'Exception should be thrown since "abc" is does not contain @.'
+ );
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testSetBodyModel()
+ {
+ $header = $this->_getHeader('Message-ID');
+ $header->setFieldBodyModel('a@b');
+ $this->assertEquals(array('a@b'), $header->getIds());
+ }
+
+ public function testGetBodyModel()
+ {
+ $header = $this->_getHeader('Message-ID');
+ $header->setId('a@b');
+ $this->assertEquals(array('a@b'), $header->getFieldBodyModel());
+ }
+
+ public function testStringValue()
+ {
+ $header = $this->_getHeader('References');
+ $header->setIds(array('a@b', 'x@y'));
+ $this->assertEquals('References: '."\r\n", $header->toString());
+ }
+
+ private function _getHeader($name)
+ {
+ return new Swift_Mime_Headers_IdentificationHeader($name, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php
new file mode 100644
index 00000000..0713ff4e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php
@@ -0,0 +1,327 @@
+_getHeader('To', $this->_getEncoder('Q', true));
+ $this->assertEquals(Swift_Mime_Header::TYPE_MAILBOX, $header->getFieldType());
+ }
+
+ public function testMailboxIsSetForAddress()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses('chris@swiftmailer.org');
+ $this->assertEquals(array('chris@swiftmailer.org'),
+ $header->getNameAddressStrings()
+ );
+ }
+
+ public function testMailboxIsRenderedForNameAddress()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn'));
+ $this->assertEquals(
+ array('Chris Corbyn '), $header->getNameAddressStrings()
+ );
+ }
+
+ public function testAddressCanBeReturnedForAddress()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses('chris@swiftmailer.org');
+ $this->assertEquals(array('chris@swiftmailer.org'), $header->getAddresses());
+ }
+
+ public function testAddressCanBeReturnedForNameAddress()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn'));
+ $this->assertEquals(array('chris@swiftmailer.org'), $header->getAddresses());
+ }
+
+ public function testQuotesInNameAreQuoted()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn, "DHE"',
+ ));
+ $this->assertEquals(
+ array('"Chris Corbyn, \"DHE\"" '),
+ $header->getNameAddressStrings()
+ );
+ }
+
+ public function testEscapeCharsInNameAreQuoted()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn, \\escaped\\',
+ ));
+ $this->assertEquals(
+ array('"Chris Corbyn, \\\\escaped\\\\" '),
+ $header->getNameAddressStrings()
+ );
+ }
+
+ public function testGetMailboxesReturnsNameValuePairs()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn, DHE',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org' => 'Chris Corbyn, DHE'), $header->getNameAddresses()
+ );
+ }
+
+ public function testMultipleAddressesCanBeSetAndFetched()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses(array(
+ 'chris@swiftmailer.org', 'mark@swiftmailer.org',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
+ $header->getAddresses()
+ );
+ }
+
+ public function testMultipleAddressesAsMailboxes()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses(array(
+ 'chris@swiftmailer.org', 'mark@swiftmailer.org',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org' => null, 'mark@swiftmailer.org' => null),
+ $header->getNameAddresses()
+ );
+ }
+
+ public function testMultipleAddressesAsMailboxStrings()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses(array(
+ 'chris@swiftmailer.org', 'mark@swiftmailer.org',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
+ $header->getNameAddressStrings()
+ );
+ }
+
+ public function testMultipleNamedMailboxesReturnsMultipleAddresses()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
+ $header->getAddresses()
+ );
+ }
+
+ public function testMultipleNamedMailboxesReturnsMultipleMailboxes()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ),
+ $header->getNameAddresses()
+ );
+ }
+
+ public function testMultipleMailboxesProducesMultipleMailboxStrings()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(array(
+ 'Chris Corbyn ',
+ 'Mark Corbyn ',
+ ),
+ $header->getNameAddressStrings()
+ );
+ }
+
+ public function testSetAddressesOverwritesAnyMailboxes()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(
+ array('chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn', ),
+ $header->getNameAddresses()
+ );
+ $this->assertEquals(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
+ $header->getAddresses()
+ );
+
+ $header->setAddresses(array('chris@swiftmailer.org', 'mark@swiftmailer.org'));
+
+ $this->assertEquals(
+ array('chris@swiftmailer.org' => null, 'mark@swiftmailer.org' => null),
+ $header->getNameAddresses()
+ );
+ $this->assertEquals(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
+ $header->getAddresses()
+ );
+ }
+
+ public function testNameIsEncodedIfNonAscii()
+ {
+ $name = 'C'.pack('C', 0x8F).'rbyn';
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($name, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('C=8Frbyn');
+
+ $header = $this->_getHeader('From', $encoder);
+ $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris '.$name));
+
+ $addresses = $header->getNameAddressStrings();
+ $this->assertEquals(
+ 'Chris =?'.$this->_charset.'?Q?C=8Frbyn?= ',
+ array_shift($addresses)
+ );
+ }
+
+ public function testEncodingLineLengthCalculations()
+ {
+ /* -- RFC 2047, 2.
+ An 'encoded-word' may not be more than 75 characters long, including
+ 'charset', 'encoding', 'encoded-text', and delimiters.
+ */
+
+ $name = 'C'.pack('C', 0x8F).'rbyn';
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($name, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('C=8Frbyn');
+
+ $header = $this->_getHeader('From', $encoder);
+ $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris '.$name));
+
+ $header->getNameAddressStrings();
+ }
+
+ public function testGetValueReturnsMailboxStringValue()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ ));
+ $this->assertEquals(
+ 'Chris Corbyn ', $header->getFieldBody()
+ );
+ }
+
+ public function testGetValueReturnsMailboxStringValueForMultipleMailboxes()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(
+ 'Chris Corbyn , Mark Corbyn ',
+ $header->getFieldBody()
+ );
+ }
+
+ public function testRemoveAddressesWithSingleValue()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $header->removeAddresses('chris@swiftmailer.org');
+ $this->assertEquals(array('mark@swiftmailer.org'),
+ $header->getAddresses()
+ );
+ }
+
+ public function testRemoveAddressesWithList()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $header->removeAddresses(
+ array('chris@swiftmailer.org', 'mark@swiftmailer.org')
+ );
+ $this->assertEquals(array(), $header->getAddresses());
+ }
+
+ public function testSetBodyModel()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setFieldBodyModel('chris@swiftmailer.org');
+ $this->assertEquals(array('chris@swiftmailer.org' => null), $header->getNameAddresses());
+ }
+
+ public function testGetBodyModel()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setAddresses(array('chris@swiftmailer.org'));
+ $this->assertEquals(array('chris@swiftmailer.org' => null), $header->getFieldBodyModel());
+ }
+
+ public function testToString()
+ {
+ $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
+ $header->setNameAddresses(array(
+ 'chris@swiftmailer.org' => 'Chris Corbyn',
+ 'mark@swiftmailer.org' => 'Mark Corbyn',
+ ));
+ $this->assertEquals(
+ 'From: Chris Corbyn , '.
+ 'Mark Corbyn '."\r\n",
+ $header->toString()
+ );
+ }
+
+ private function _getHeader($name, $encoder)
+ {
+ $header = new Swift_Mime_Headers_MailboxHeader($name, $encoder, new Swift_Mime_Grammar());
+ $header->setCharset($this->_charset);
+
+ return $header;
+ }
+
+ private function _getEncoder($type, $stub = false)
+ {
+ $encoder = $this->getMockery('Swift_Mime_HeaderEncoder')->shouldIgnoreMissing();
+ $encoder->shouldReceive('getName')
+ ->zeroOrMoreTimes()
+ ->andReturn($type);
+
+ return $encoder;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php
new file mode 100644
index 00000000..0f3fe145
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php
@@ -0,0 +1,400 @@
+_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $this->assertEquals(Swift_Mime_Header::TYPE_PARAMETERIZED, $header->getFieldType());
+ }
+
+ public function testValueIsReturnedVerbatim()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setValue('text/plain');
+ $this->assertEquals('text/plain', $header->getValue());
+ }
+
+ public function testParametersAreAppended()
+ {
+ /* -- RFC 2045, 5.1
+ parameter := attribute "=" value
+
+ attribute := token
+ ; Matching of attributes
+ ; is ALWAYS case-insensitive.
+
+ value := token / quoted-string
+
+ token := 1*
+
+ tspecials := "(" / ")" / "<" / ">" / "@" /
+ "," / ";" / ":" / "\" / <">
+ "/" / "[" / "]" / "?" / "="
+ ; Must be in quoted-string,
+ ; to use within parameter values
+ */
+
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setValue('text/plain');
+ $header->setParameters(array('charset' => 'utf-8'));
+ $this->assertEquals('text/plain; charset=utf-8', $header->getFieldBody());
+ }
+
+ public function testSpaceInParamResultsInQuotedString()
+ {
+ $header = $this->_getHeader('Content-Disposition',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setValue('attachment');
+ $header->setParameters(array('filename' => 'my file.txt'));
+ $this->assertEquals('attachment; filename="my file.txt"',
+ $header->getFieldBody()
+ );
+ }
+
+ public function testLongParamsAreBrokenIntoMultipleAttributeStrings()
+ {
+ /* -- RFC 2231, 3.
+ The asterisk character ("*") followed
+ by a decimal count is employed to indicate that multiple parameters
+ are being used to encapsulate a single parameter value. The count
+ starts at 0 and increments by 1 for each subsequent section of the
+ parameter value. Decimal values are used and neither leading zeroes
+ nor gaps in the sequence are allowed.
+
+ The original parameter value is recovered by concatenating the
+ various sections of the parameter, in order. For example, the
+ content-type field
+
+ Content-Type: message/external-body; access-type=URL;
+ URL*0="ftp://";
+ URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
+
+ is semantically identical to
+
+ Content-Type: message/external-body; access-type=URL;
+ URL="ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
+
+ Note that quotes around parameter values are part of the value
+ syntax; they are NOT part of the value itself. Furthermore, it is
+ explicitly permitted to have a mixture of quoted and unquoted
+ continuation fields.
+ */
+
+ $value = str_repeat('a', 180);
+
+ $encoder = $this->_getParameterEncoder();
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), 63, \Mockery::any())
+ ->andReturn(str_repeat('a', 63)."\r\n".
+ str_repeat('a', 63)."\r\n".str_repeat('a', 54));
+
+ $header = $this->_getHeader('Content-Disposition',
+ $this->_getHeaderEncoder('Q', true), $encoder
+ );
+ $header->setValue('attachment');
+ $header->setParameters(array('filename' => $value));
+ $header->setMaxLineLength(78);
+ $this->assertEquals(
+ 'attachment; '.
+ 'filename*0*=utf-8\'\''.str_repeat('a', 63).";\r\n ".
+ 'filename*1*='.str_repeat('a', 63).";\r\n ".
+ 'filename*2*='.str_repeat('a', 54),
+ $header->getFieldBody()
+ );
+ }
+
+ public function testEncodedParamDataIncludesCharsetAndLanguage()
+ {
+ /* -- RFC 2231, 4.
+ Asterisks ("*") are reused to provide the indicator that language and
+ character set information is present and encoding is being used. A
+ single quote ("'") is used to delimit the character set and language
+ information at the beginning of the parameter value. Percent signs
+ ("%") are used as the encoding flag, which agrees with RFC 2047.
+
+ Specifically, an asterisk at the end of a parameter name acts as an
+ indicator that character set and language information may appear at
+ the beginning of the parameter value. A single quote is used to
+ separate the character set, language, and actual value information in
+ the parameter value string, and an percent sign is used to flag
+ octets encoded in hexadecimal. For example:
+
+ Content-Type: application/x-stuff;
+ title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A
+
+ Note that it is perfectly permissible to leave either the character
+ set or language field blank. Note also that the single quote
+ delimiters MUST be present even when one of the field values is
+ omitted.
+ */
+
+ $value = str_repeat('a', 20).pack('C', 0x8F).str_repeat('a', 10);
+
+ $encoder = $this->_getParameterEncoder();
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, 12, 62, \Mockery::any())
+ ->andReturn(str_repeat('a', 20).'%8F'.str_repeat('a', 10));
+
+ $header = $this->_getHeader('Content-Disposition',
+ $this->_getHeaderEncoder('Q', true), $encoder
+ );
+ $header->setValue('attachment');
+ $header->setParameters(array('filename' => $value));
+ $header->setMaxLineLength(78);
+ $header->setLanguage($this->_lang);
+ $this->assertEquals(
+ 'attachment; filename*='.$this->_charset."'".$this->_lang."'".
+ str_repeat('a', 20).'%8F'.str_repeat('a', 10),
+ $header->getFieldBody()
+ );
+ }
+
+ public function testMultipleEncodedParamLinesAreFormattedCorrectly()
+ {
+ /* -- RFC 2231, 4.1.
+ Character set and language information may be combined with the
+ parameter continuation mechanism. For example:
+
+ Content-Type: application/x-stuff
+ title*0*=us-ascii'en'This%20is%20even%20more%20
+ title*1*=%2A%2A%2Afun%2A%2A%2A%20
+ title*2="isn't it!"
+
+ Note that:
+
+ (1) Language and character set information only appear at
+ the beginning of a given parameter value.
+
+ (2) Continuations do not provide a facility for using more
+ than one character set or language in the same
+ parameter value.
+
+ (3) A value presented using multiple continuations may
+ contain a mixture of encoded and unencoded segments.
+
+ (4) The first segment of a continuation MUST be encoded if
+ language and character set information are given.
+
+ (5) If the first segment of a continued parameter value is
+ encoded the language and character set field delimiters
+ MUST be present even when the fields are left blank.
+ */
+
+ $value = str_repeat('a', 20).pack('C', 0x8F).str_repeat('a', 60);
+
+ $encoder = $this->_getParameterEncoder();
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, 12, 62, \Mockery::any())
+ ->andReturn(str_repeat('a', 20).'%8F'.str_repeat('a', 28)."\r\n".
+ str_repeat('a', 32));
+
+ $header = $this->_getHeader('Content-Disposition',
+ $this->_getHeaderEncoder('Q', true), $encoder
+ );
+ $header->setValue('attachment');
+ $header->setParameters(array('filename' => $value));
+ $header->setMaxLineLength(78);
+ $header->setLanguage($this->_lang);
+ $this->assertEquals(
+ 'attachment; filename*0*='.$this->_charset."'".$this->_lang."'".
+ str_repeat('a', 20).'%8F'.str_repeat('a', 28).";\r\n ".
+ 'filename*1*='.str_repeat('a', 32),
+ $header->getFieldBody()
+ );
+ }
+
+ public function testToString()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setValue('text/html');
+ $header->setParameters(array('charset' => 'utf-8'));
+ $this->assertEquals('Content-Type: text/html; charset=utf-8'."\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testValueCanBeEncodedIfNonAscii()
+ {
+ $value = 'fo'.pack('C', 0x8F).'bar';
+
+ $encoder = $this->_getHeaderEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo=8Fbar');
+
+ $header = $this->_getHeader('X-Foo', $encoder, $this->_getParameterEncoder(true));
+ $header->setValue($value);
+ $header->setParameters(array('lookslike' => 'foobar'));
+ $this->assertEquals('X-Foo: =?utf-8?Q?fo=8Fbar?=; lookslike=foobar'."\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testValueAndParamCanBeEncodedIfNonAscii()
+ {
+ $value = 'fo'.pack('C', 0x8F).'bar';
+
+ $encoder = $this->_getHeaderEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo=8Fbar');
+
+ $paramEncoder = $this->_getParameterEncoder();
+ $paramEncoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo%8Fbar');
+
+ $header = $this->_getHeader('X-Foo', $encoder, $paramEncoder);
+ $header->setValue($value);
+ $header->setParameters(array('says' => $value));
+ $this->assertEquals("X-Foo: =?utf-8?Q?fo=8Fbar?=; says*=utf-8''fo%8Fbar\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testParamsAreEncodedWithEncodedWordsIfNoParamEncoderSet()
+ {
+ $value = 'fo'.pack('C', 0x8F).'bar';
+
+ $encoder = $this->_getHeaderEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo=8Fbar');
+
+ $header = $this->_getHeader('X-Foo', $encoder, null);
+ $header->setValue('bar');
+ $header->setParameters(array('says' => $value));
+ $this->assertEquals("X-Foo: bar; says=\"=?utf-8?Q?fo=8Fbar?=\"\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testLanguageInformationAppearsInEncodedWords()
+ {
+ /* -- RFC 2231, 5.
+ 5. Language specification in Encoded Words
+
+ RFC 2047 provides support for non-US-ASCII character sets in RFC 822
+ message header comments, phrases, and any unstructured text field.
+ This is done by defining an encoded word construct which can appear
+ in any of these places. Given that these are fields intended for
+ display, it is sometimes necessary to associate language information
+ with encoded words as well as just the character set. This
+ specification extends the definition of an encoded word to allow the
+ inclusion of such information. This is simply done by suffixing the
+ character set specification with an asterisk followed by the language
+ tag. For example:
+
+ From: =?US-ASCII*EN?Q?Keith_Moore?=
+ */
+
+ $value = 'fo'.pack('C', 0x8F).'bar';
+
+ $encoder = $this->_getHeaderEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo=8Fbar');
+
+ $paramEncoder = $this->_getParameterEncoder();
+ $paramEncoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo%8Fbar');
+
+ $header = $this->_getHeader('X-Foo', $encoder, $paramEncoder);
+ $header->setLanguage('en');
+ $header->setValue($value);
+ $header->setParameters(array('says' => $value));
+ $this->assertEquals("X-Foo: =?utf-8*en?Q?fo=8Fbar?=; says*=utf-8'en'fo%8Fbar\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testSetBodyModel()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setFieldBodyModel('text/html');
+ $this->assertEquals('text/html', $header->getValue());
+ }
+
+ public function testGetBodyModel()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setValue('text/plain');
+ $this->assertEquals('text/plain', $header->getFieldBodyModel());
+ }
+
+ public function testSetParameter()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setParameters(array('charset' => 'utf-8', 'delsp' => 'yes'));
+ $header->setParameter('delsp', 'no');
+ $this->assertEquals(array('charset' => 'utf-8', 'delsp' => 'no'),
+ $header->getParameters()
+ );
+ }
+
+ public function testGetParameter()
+ {
+ $header = $this->_getHeader('Content-Type',
+ $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true)
+ );
+ $header->setParameters(array('charset' => 'utf-8', 'delsp' => 'yes'));
+ $this->assertEquals('utf-8', $header->getParameter('charset'));
+ }
+
+ // -- Private helper
+
+ private function _getHeader($name, $encoder, $paramEncoder)
+ {
+ $header = new Swift_Mime_Headers_ParameterizedHeader($name, $encoder,
+ $paramEncoder, new Swift_Mime_Grammar()
+ );
+ $header->setCharset($this->_charset);
+
+ return $header;
+ }
+
+ private function _getHeaderEncoder($type, $stub = false)
+ {
+ $encoder = $this->getMockery('Swift_Mime_HeaderEncoder')->shouldIgnoreMissing();
+ $encoder->shouldReceive('getName')
+ ->zeroOrMoreTimes()
+ ->andReturn($type);
+
+ return $encoder;
+ }
+
+ private function _getParameterEncoder($stub = false)
+ {
+ return $this->getMockery('Swift_Encoder')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/PathHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/PathHeaderTest.php
new file mode 100644
index 00000000..a9f35e9d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/PathHeaderTest.php
@@ -0,0 +1,77 @@
+_getHeader('Return-Path');
+ $this->assertEquals(Swift_Mime_Header::TYPE_PATH, $header->getFieldType());
+ }
+
+ public function testSingleAddressCanBeSetAndFetched()
+ {
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('chris@swiftmailer.org');
+ $this->assertEquals('chris@swiftmailer.org', $header->getAddress());
+ }
+
+ public function testAddressMustComplyWithRfc2822()
+ {
+ try {
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('chr is@swiftmailer.org');
+ $this->fail('Addresses not valid according to RFC 2822 addr-spec grammar must be rejected.');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testValueIsAngleAddrWithValidAddress()
+ {
+ /* -- RFC 2822, 3.6.7.
+
+ return = "Return-Path:" path CRLF
+
+ path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
+ obs-path
+ */
+
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('chris@swiftmailer.org');
+ $this->assertEquals('', $header->getFieldBody());
+ }
+
+ public function testValueIsEmptyAngleBracketsIfEmptyAddressSet()
+ {
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('');
+ $this->assertEquals('<>', $header->getFieldBody());
+ }
+
+ public function testSetBodyModel()
+ {
+ $header = $this->_getHeader('Return-Path');
+ $header->setFieldBodyModel('foo@bar.tld');
+ $this->assertEquals('foo@bar.tld', $header->getAddress());
+ }
+
+ public function testGetBodyModel()
+ {
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('foo@bar.tld');
+ $this->assertEquals('foo@bar.tld', $header->getFieldBodyModel());
+ }
+
+ public function testToString()
+ {
+ $header = $this->_getHeader('Return-Path');
+ $header->setAddress('chris@swiftmailer.org');
+ $this->assertEquals('Return-Path: '."\r\n",
+ $header->toString()
+ );
+ }
+
+ private function _getHeader($name)
+ {
+ return new Swift_Mime_Headers_PathHeader($name, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php
new file mode 100644
index 00000000..2e1dc8ca
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php
@@ -0,0 +1,355 @@
+_getHeader('Subject', $this->_getEncoder('Q', true));
+ $this->assertEquals(Swift_Mime_Header::TYPE_TEXT, $header->getFieldType());
+ }
+
+ public function testGetNameReturnsNameVerbatim()
+ {
+ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true));
+ $this->assertEquals('Subject', $header->getFieldName());
+ }
+
+ public function testGetValueReturnsValueVerbatim()
+ {
+ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true));
+ $header->setValue('Test');
+ $this->assertEquals('Test', $header->getValue());
+ }
+
+ public function testBasicStructureIsKeyValuePair()
+ {
+ /* -- RFC 2822, 2.2
+ Header fields are lines composed of a field name, followed by a colon
+ (":"), followed by a field body, and terminated by CRLF.
+ */
+ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true));
+ $header->setValue('Test');
+ $this->assertEquals('Subject: Test'."\r\n", $header->toString());
+ }
+
+ public function testLongHeadersAreFoldedAtWordBoundary()
+ {
+ /* -- RFC 2822, 2.2.3
+ Each header field is logically a single line of characters comprising
+ the field name, the colon, and the field body. For convenience
+ however, and to deal with the 998/78 character limitations per line,
+ the field body portion of a header field can be split into a multiple
+ line representation; this is called "folding". The general rule is
+ that wherever this standard allows for folding white space (not
+ simply WSP characters), a CRLF may be inserted before any WSP.
+ */
+
+ $value = 'The quick brown fox jumped over the fence, he was a very very '.
+ 'scary brown fox with a bushy tail';
+ $header = $this->_getHeader('X-Custom-Header',
+ $this->_getEncoder('Q', true)
+ );
+ $header->setValue($value);
+ $header->setMaxLineLength(78); //A safe [RFC 2822, 2.2.3] default
+ /*
+ X-Custom-Header: The quick brown fox jumped over the fence, he was a very very
+ scary brown fox with a bushy tail
+ */
+ $this->assertEquals(
+ 'X-Custom-Header: The quick brown fox jumped over the fence, he was a'.
+ ' very very'."\r\n".//Folding
+ ' scary brown fox with a bushy tail'."\r\n",
+ $header->toString(), '%s: The header should have been folded at 78th char'
+ );
+ }
+
+ public function testPrintableAsciiOnlyAppearsInHeaders()
+ {
+ /* -- RFC 2822, 2.2.
+ A field name MUST be composed of printable US-ASCII characters (i.e.,
+ characters that have values between 33 and 126, inclusive), except
+ colon. A field body may be composed of any US-ASCII characters,
+ except for CR and LF.
+ */
+
+ $nonAsciiChar = pack('C', 0x8F);
+ $header = $this->_getHeader('X-Test', $this->_getEncoder('Q', true));
+ $header->setValue($nonAsciiChar);
+ $this->assertRegExp(
+ '~^[^:\x00-\x20\x80-\xFF]+: [^\x80-\xFF\r\n]+\r\n$~s',
+ $header->toString()
+ );
+ }
+
+ public function testEncodedWordsFollowGeneralStructure()
+ {
+ /* -- RFC 2047, 1.
+ Generally, an "encoded-word" is a sequence of printable ASCII
+ characters that begins with "=?", ends with "?=", and has two "?"s in
+ between.
+ */
+
+ $nonAsciiChar = pack('C', 0x8F);
+ $header = $this->_getHeader('X-Test', $this->_getEncoder('Q', true));
+ $header->setValue($nonAsciiChar);
+ $this->assertRegExp(
+ '~^X-Test: \=?.*?\?.*?\?.*?\?=\r\n$~s',
+ $header->toString()
+ );
+ }
+
+ public function testEncodedWordIncludesCharsetAndEncodingMethodAndText()
+ {
+ /* -- RFC 2047, 2.
+ An 'encoded-word' is defined by the following ABNF grammar. The
+ notation of RFC 822 is used, with the exception that white space
+ characters MUST NOT appear between components of an 'encoded-word'.
+
+ encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
+ */
+
+ $nonAsciiChar = pack('C', 0x8F);
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($nonAsciiChar, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('=8F');
+
+ $header = $this->_getHeader('X-Test', $encoder);
+ $header->setValue($nonAsciiChar);
+ $this->assertEquals(
+ 'X-Test: =?'.$this->_charset.'?Q?=8F?='."\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testEncodedWordsAreUsedToEncodedNonPrintableAscii()
+ {
+ //SPACE and TAB permitted
+ $nonPrintableBytes = array_merge(
+ range(0x00, 0x08), range(0x10, 0x19), array(0x7F)
+ );
+
+ foreach ($nonPrintableBytes as $byte) {
+ $char = pack('C', $byte);
+ $encodedChar = sprintf('=%02X', $byte);
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($char, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn($encodedChar);
+
+ $header = $this->_getHeader('X-A', $encoder);
+ $header->setValue($char);
+
+ $this->assertEquals(
+ 'X-A: =?'.$this->_charset.'?Q?'.$encodedChar.'?='."\r\n",
+ $header->toString(), '%s: Non-printable ascii should be encoded'
+ );
+ }
+ }
+
+ public function testEncodedWordsAreUsedToEncode8BitOctets()
+ {
+ $_8BitBytes = range(0x80, 0xFF);
+
+ foreach ($_8BitBytes as $byte) {
+ $char = pack('C', $byte);
+ $encodedChar = sprintf('=%02X', $byte);
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($char, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn($encodedChar);
+
+ $header = $this->_getHeader('X-A', $encoder);
+ $header->setValue($char);
+
+ $this->assertEquals(
+ 'X-A: =?'.$this->_charset.'?Q?'.$encodedChar.'?='."\r\n",
+ $header->toString(), '%s: 8-bit octets should be encoded'
+ );
+ }
+ }
+
+ public function testEncodedWordsAreNoMoreThan75CharsPerLine()
+ {
+ /* -- RFC 2047, 2.
+ An 'encoded-word' may not be more than 75 characters long, including
+ 'charset', 'encoding', 'encoded-text', and delimiters.
+
+ ... SNIP ...
+
+ While there is no limit to the length of a multiple-line header
+ field, each line of a header field that contains one or more
+ 'encoded-word's is limited to 76 characters.
+ */
+
+ $nonAsciiChar = pack('C', 0x8F);
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($nonAsciiChar, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('=8F');
+ //Note that multi-line headers begin with LWSP which makes 75 + 1 = 76
+ //Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63
+
+ //* X-Test: is 8 chars
+ $header = $this->_getHeader('X-Test', $encoder);
+ $header->setValue($nonAsciiChar);
+
+ $this->assertEquals(
+ 'X-Test: =?'.$this->_charset.'?Q?=8F?='."\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testFWSPIsUsedWhenEncoderReturnsMultipleLines()
+ {
+ /* --RFC 2047, 2.
+ If it is desirable to encode more text than will fit in an 'encoded-word' of
+ 75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may
+ be used.
+ */
+
+ //Note the Mock does NOT return 8F encoded, the 8F merely triggers
+ // encoding for the sake of testing
+ $nonAsciiChar = pack('C', 0x8F);
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($nonAsciiChar, 8, 63, \Mockery::any())
+ ->andReturn('line_one_here'."\r\n".'line_two_here');
+
+ //Note that multi-line headers begin with LWSP which makes 75 + 1 = 76
+ //Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63
+
+ //* X-Test: is 8 chars
+ $header = $this->_getHeader('X-Test', $encoder);
+ $header->setValue($nonAsciiChar);
+
+ $this->assertEquals(
+ 'X-Test: =?'.$this->_charset.'?Q?line_one_here?='."\r\n".
+ ' =?'.$this->_charset.'?Q?line_two_here?='."\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testAdjacentWordsAreEncodedTogether()
+ {
+ /* -- RFC 2047, 5 (1)
+ Ordinary ASCII text and 'encoded-word's may appear together in the
+ same header field. However, an 'encoded-word' that appears in a
+ header field defined as '*text' MUST be separated from any adjacent
+ 'encoded-word' or 'text' by 'linear-white-space'.
+
+ -- RFC 2047, 2.
+ IMPORTANT: 'encoded-word's are designed to be recognized as 'atom's
+ by an RFC 822 parser. As a consequence, unencoded white space
+ characters (such as SPACE and HTAB) are FORBIDDEN within an
+ 'encoded-word'.
+ */
+
+ //It would be valid to encode all words needed, however it's probably
+ // easiest to encode the longest amount required at a time
+
+ $word = 'w'.pack('C', 0x8F).'rd';
+ $text = 'start '.$word.' '.$word.' then end '.$word;
+ // 'start', ' word word', ' and end', ' word'
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($word.' '.$word, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('w=8Frd_w=8Frd');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($word, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('w=8Frd');
+
+ $header = $this->_getHeader('X-Test', $encoder);
+ $header->setValue($text);
+
+ $headerString = $header->toString();
+
+ $this->assertEquals('X-Test: start =?'.$this->_charset.'?Q?'.
+ 'w=8Frd_w=8Frd?= then end =?'.$this->_charset.'?Q?'.
+ 'w=8Frd?='."\r\n", $headerString,
+ '%s: Adjacent encoded words should appear grouped with WSP encoded'
+ );
+ }
+
+ public function testLanguageInformationAppearsInEncodedWords()
+ {
+ /* -- RFC 2231, 5.
+ 5. Language specification in Encoded Words
+
+ RFC 2047 provides support for non-US-ASCII character sets in RFC 822
+ message header comments, phrases, and any unstructured text field.
+ This is done by defining an encoded word construct which can appear
+ in any of these places. Given that these are fields intended for
+ display, it is sometimes necessary to associate language information
+ with encoded words as well as just the character set. This
+ specification extends the definition of an encoded word to allow the
+ inclusion of such information. This is simply done by suffixing the
+ character set specification with an asterisk followed by the language
+ tag. For example:
+
+ From: =?US-ASCII*EN?Q?Keith_Moore?=
+ */
+
+ $value = 'fo'.pack('C', 0x8F).'bar';
+
+ $encoder = $this->_getEncoder('Q');
+ $encoder->shouldReceive('encodeString')
+ ->once()
+ ->with($value, \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn('fo=8Fbar');
+
+ $header = $this->_getHeader('Subject', $encoder);
+ $header->setLanguage('en');
+ $header->setValue($value);
+ $this->assertEquals("Subject: =?utf-8*en?Q?fo=8Fbar?=\r\n",
+ $header->toString()
+ );
+ }
+
+ public function testSetBodyModel()
+ {
+ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true));
+ $header->setFieldBodyModel('test');
+ $this->assertEquals('test', $header->getValue());
+ }
+
+ public function testGetBodyModel()
+ {
+ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true));
+ $header->setValue('test');
+ $this->assertEquals('test', $header->getFieldBodyModel());
+ }
+
+ private function _getHeader($name, $encoder)
+ {
+ $header = new Swift_Mime_Headers_UnstructuredHeader($name, $encoder, new Swift_Mime_Grammar());
+ $header->setCharset($this->_charset);
+
+ return $header;
+ }
+
+ private function _getEncoder($type, $stub = false)
+ {
+ $encoder = $this->getMockery('Swift_Mime_HeaderEncoder')->shouldIgnoreMissing();
+ $encoder->shouldReceive('getName')
+ ->zeroOrMoreTimes()
+ ->andReturn($type);
+
+ return $encoder;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/MimePartTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/MimePartTest.php
new file mode 100644
index 00000000..7e91134f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/MimePartTest.php
@@ -0,0 +1,233 @@
+_createMimePart($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(
+ Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, $part->getNestingLevel()
+ );
+ }
+
+ public function testCharsetIsReturnedFromHeader()
+ {
+ /* -- RFC 2046, 4.1.2.
+ A critical parameter that may be specified in the Content-Type field
+ for "text/plain" data is the character set. This is specified with a
+ "charset" parameter, as in:
+
+ Content-type: text/plain; charset=iso-8859-1
+
+ Unlike some other parameter values, the values of the charset
+ parameter are NOT case sensitive. The default character set, which
+ must be assumed in the absence of a charset parameter, is US-ASCII.
+ */
+
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('charset' => 'iso-8859-1')
+ );
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('iso-8859-1', $part->getCharset());
+ }
+
+ public function testCharsetIsSetInHeader()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('charset' => 'iso-8859-1'), false
+ );
+ $cType->shouldReceive('setParameter')->once()->with('charset', 'utf-8');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->setCharset('utf-8');
+ }
+
+ public function testCharsetIsSetInHeaderIfPassedToSetBody()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('charset' => 'iso-8859-1'), false
+ );
+ $cType->shouldReceive('setParameter')->once()->with('charset', 'utf-8');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->setBody('', 'text/plian', 'utf-8');
+ }
+
+ public function testSettingCharsetNotifiesEncoder()
+ {
+ $encoder = $this->_createEncoder('quoted-printable', false);
+ $encoder->expects($this->once())
+ ->method('charsetChanged')
+ ->with('utf-8');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(),
+ $encoder, $this->_createCache()
+ );
+ $part->setCharset('utf-8');
+ }
+
+ public function testSettingCharsetNotifiesHeaders()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('charsetChanged')
+ ->zeroOrMoreTimes()
+ ->with('utf-8');
+
+ $part = $this->_createMimePart($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $part->setCharset('utf-8');
+ }
+
+ public function testSettingCharsetNotifiesChildren()
+ {
+ $child = $this->_createChild(0, '', false);
+ $child->shouldReceive('charsetChanged')
+ ->once()
+ ->with('windows-874');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->setChildren(array($child));
+ $part->setCharset('windows-874');
+ }
+
+ public function testCharsetChangeUpdatesCharset()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('charset' => 'iso-8859-1'), false
+ );
+ $cType->shouldReceive('setParameter')->once()->with('charset', 'utf-8');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->charsetChanged('utf-8');
+ }
+
+ public function testSettingCharsetClearsCache()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn("Content-Type: text/plain; charset=utf-8\r\n");
+
+ $cache = $this->_createCache(false);
+
+ $entity = $this->_createEntity($headers, $this->_createEncoder(),
+ $cache
+ );
+
+ $entity->setBody("blah\r\nblah!");
+ $entity->toString();
+
+ // Initialize the expectation here because we only care about what happens in setCharset()
+ $cache->shouldReceive('clearKey')
+ ->once()
+ ->with(\Mockery::any(), 'body');
+
+ $entity->setCharset('iso-2022');
+ }
+
+ public function testFormatIsReturnedFromHeader()
+ {
+ /* -- RFC 3676.
+ */
+
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('format' => 'flowed')
+ );
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('flowed', $part->getFormat());
+ }
+
+ public function testFormatIsSetInHeader()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $cType->shouldReceive('setParameter')->once()->with('format', 'fixed');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->setFormat('fixed');
+ }
+
+ public function testDelSpIsReturnedFromHeader()
+ {
+ /* -- RFC 3676.
+ */
+
+ $cType = $this->_createHeader('Content-Type', 'text/plain',
+ array('delsp' => 'no')
+ );
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertFalse($part->getDelSp());
+ }
+
+ public function testDelSpIsSetInHeader()
+ {
+ $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
+ $cType->shouldReceive('setParameter')->once()->with('delsp', 'yes');
+
+ $part = $this->_createMimePart($this->_createHeaderSet(array(
+ 'Content-Type' => $cType, )),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $part->setDelSp(true);
+ }
+
+ public function testFluidInterface()
+ {
+ $part = $this->_createMimePart($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $this->assertSame($part,
+ $part
+ ->setContentType('text/plain')
+ ->setEncoder($this->_createEncoder())
+ ->setId('foo@bar')
+ ->setDescription('my description')
+ ->setMaxLineLength(998)
+ ->setBody('xx')
+ ->setBoundary('xyz')
+ ->setChildren(array())
+ ->setCharset('utf-8')
+ ->setFormat('flowed')
+ ->setDelSp(true)
+ );
+ }
+
+ // -- Private helpers
+
+ //abstract
+ protected function _createEntity($headers, $encoder, $cache)
+ {
+ return $this->_createMimePart($headers, $encoder, $cache);
+ }
+
+ protected function _createMimePart($headers, $encoder, $cache)
+ {
+ return new Swift_Mime_MimePart($headers, $encoder, $cache, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php
new file mode 100644
index 00000000..4ee62963
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php
@@ -0,0 +1,168 @@
+_factory = $this->_createFactory();
+ }
+
+ public function testMailboxHeaderIsCorrectType()
+ {
+ $header = $this->_factory->createMailboxHeader('X-Foo');
+ $this->assertInstanceof('Swift_Mime_Headers_MailboxHeader', $header);
+ }
+
+ public function testMailboxHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createMailboxHeader('X-Foo');
+ $this->assertEquals('X-Foo', $header->getFieldName());
+ }
+
+ public function testMailboxHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createMailboxHeader('X-Foo',
+ array('foo@bar' => 'FooBar')
+ );
+ $this->assertEquals(array('foo@bar' => 'FooBar'), $header->getFieldBodyModel());
+ }
+
+ public function testDateHeaderHasCorrectType()
+ {
+ $header = $this->_factory->createDateHeader('X-Date');
+ $this->assertInstanceof('Swift_Mime_Headers_DateHeader', $header);
+ }
+
+ public function testDateHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createDateHeader('X-Date');
+ $this->assertEquals('X-Date', $header->getFieldName());
+ }
+
+ public function testDateHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createDateHeader('X-Date', 123);
+ $this->assertEquals(123, $header->getFieldBodyModel());
+ }
+
+ public function testTextHeaderHasCorrectType()
+ {
+ $header = $this->_factory->createTextHeader('X-Foo');
+ $this->assertInstanceof('Swift_Mime_Headers_UnstructuredHeader', $header);
+ }
+
+ public function testTextHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createTextHeader('X-Foo');
+ $this->assertEquals('X-Foo', $header->getFieldName());
+ }
+
+ public function testTextHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createTextHeader('X-Foo', 'bar');
+ $this->assertEquals('bar', $header->getFieldBodyModel());
+ }
+
+ public function testParameterizedHeaderHasCorrectType()
+ {
+ $header = $this->_factory->createParameterizedHeader('X-Foo');
+ $this->assertInstanceof('Swift_Mime_Headers_ParameterizedHeader', $header);
+ }
+
+ public function testParameterizedHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createParameterizedHeader('X-Foo');
+ $this->assertEquals('X-Foo', $header->getFieldName());
+ }
+
+ public function testParameterizedHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createParameterizedHeader('X-Foo', 'bar');
+ $this->assertEquals('bar', $header->getFieldBodyModel());
+ }
+
+ public function testParameterizedHeaderHasCorrectParams()
+ {
+ $header = $this->_factory->createParameterizedHeader('X-Foo', 'bar',
+ array('zip' => 'button')
+ );
+ $this->assertEquals(array('zip' => 'button'), $header->getParameters());
+ }
+
+ public function testIdHeaderHasCorrectType()
+ {
+ $header = $this->_factory->createIdHeader('X-ID');
+ $this->assertInstanceof('Swift_Mime_Headers_IdentificationHeader', $header);
+ }
+
+ public function testIdHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createIdHeader('X-ID');
+ $this->assertEquals('X-ID', $header->getFieldName());
+ }
+
+ public function testIdHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createIdHeader('X-ID', 'xyz@abc');
+ $this->assertEquals(array('xyz@abc'), $header->getFieldBodyModel());
+ }
+
+ public function testPathHeaderHasCorrectType()
+ {
+ $header = $this->_factory->createPathHeader('X-Path');
+ $this->assertInstanceof('Swift_Mime_Headers_PathHeader', $header);
+ }
+
+ public function testPathHeaderHasCorrectName()
+ {
+ $header = $this->_factory->createPathHeader('X-Path');
+ $this->assertEquals('X-Path', $header->getFieldName());
+ }
+
+ public function testPathHeaderHasCorrectModel()
+ {
+ $header = $this->_factory->createPathHeader('X-Path', 'foo@bar');
+ $this->assertEquals('foo@bar', $header->getFieldBodyModel());
+ }
+
+ public function testCharsetChangeNotificationNotifiesEncoders()
+ {
+ $encoder = $this->_createHeaderEncoder();
+ $encoder->expects($this->once())
+ ->method('charsetChanged')
+ ->with('utf-8');
+ $paramEncoder = $this->_createParamEncoder();
+ $paramEncoder->expects($this->once())
+ ->method('charsetChanged')
+ ->with('utf-8');
+
+ $factory = $this->_createFactory($encoder, $paramEncoder);
+
+ $factory->charsetChanged('utf-8');
+ }
+
+ // -- Creation methods
+
+ private function _createFactory($encoder = null, $paramEncoder = null)
+ {
+ return new Swift_Mime_SimpleHeaderFactory(
+ $encoder
+ ? $encoder : $this->_createHeaderEncoder(),
+ $paramEncoder
+ ? $paramEncoder : $this->_createParamEncoder(),
+ new Swift_Mime_Grammar()
+ );
+ }
+
+ private function _createHeaderEncoder()
+ {
+ return $this->getMockBuilder('Swift_Mime_HeaderEncoder')->getMock();
+ }
+
+ private function _createParamEncoder()
+ {
+ return $this->getMockBuilder('Swift_Encoder')->getMock();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderSetTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderSetTest.php
new file mode 100644
index 00000000..9682f37e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderSetTest.php
@@ -0,0 +1,739 @@
+_createFactory();
+ $factory->expects($this->once())
+ ->method('createMailboxHeader')
+ ->with('From', array('person@domain' => 'Person'))
+ ->will($this->returnValue($this->_createHeader('From')));
+
+ $set = $this->_createSet($factory);
+ $set->addMailboxHeader('From', array('person@domain' => 'Person'));
+ }
+
+ public function testAddDateHeaderDelegatesToFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createDateHeader')
+ ->with('Date', 1234)
+ ->will($this->returnValue($this->_createHeader('Date')));
+
+ $set = $this->_createSet($factory);
+ $set->addDateHeader('Date', 1234);
+ }
+
+ public function testAddTextHeaderDelegatesToFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createTextHeader')
+ ->with('Subject', 'some text')
+ ->will($this->returnValue($this->_createHeader('Subject')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Subject', 'some text');
+ }
+
+ public function testAddParameterizedHeaderDelegatesToFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createParameterizedHeader')
+ ->with('Content-Type', 'text/plain', array('charset' => 'utf-8'))
+ ->will($this->returnValue($this->_createHeader('Content-Type')));
+
+ $set = $this->_createSet($factory);
+ $set->addParameterizedHeader('Content-Type', 'text/plain',
+ array('charset' => 'utf-8')
+ );
+ }
+
+ public function testAddIdHeaderDelegatesToFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ }
+
+ public function testAddPathHeaderDelegatesToFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createPathHeader')
+ ->with('Return-Path', 'some@path')
+ ->will($this->returnValue($this->_createHeader('Return-Path')));
+
+ $set = $this->_createSet($factory);
+ $set->addPathHeader('Return-Path', 'some@path');
+ }
+
+ public function testHasReturnsFalseWhenNoHeaders()
+ {
+ $set = $this->_createSet($this->_createFactory());
+ $this->assertFalse($set->has('Some-Header'));
+ }
+
+ public function testAddedMailboxHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createMailboxHeader')
+ ->with('From', array('person@domain' => 'Person'))
+ ->will($this->returnValue($this->_createHeader('From')));
+
+ $set = $this->_createSet($factory);
+ $set->addMailboxHeader('From', array('person@domain' => 'Person'));
+ $this->assertTrue($set->has('From'));
+ }
+
+ public function testAddedDateHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createDateHeader')
+ ->with('Date', 1234)
+ ->will($this->returnValue($this->_createHeader('Date')));
+
+ $set = $this->_createSet($factory);
+ $set->addDateHeader('Date', 1234);
+ $this->assertTrue($set->has('Date'));
+ }
+
+ public function testAddedTextHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createTextHeader')
+ ->with('Subject', 'some text')
+ ->will($this->returnValue($this->_createHeader('Subject')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Subject', 'some text');
+ $this->assertTrue($set->has('Subject'));
+ }
+
+ public function testAddedParameterizedHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createParameterizedHeader')
+ ->with('Content-Type', 'text/plain', array('charset' => 'utf-8'))
+ ->will($this->returnValue($this->_createHeader('Content-Type')));
+
+ $set = $this->_createSet($factory);
+ $set->addParameterizedHeader('Content-Type', 'text/plain',
+ array('charset' => 'utf-8')
+ );
+ $this->assertTrue($set->has('Content-Type'));
+ }
+
+ public function testAddedIdHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertTrue($set->has('Message-ID'));
+ }
+
+ public function testAddedPathHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createPathHeader')
+ ->with('Return-Path', 'some@path')
+ ->will($this->returnValue($this->_createHeader('Return-Path')));
+
+ $set = $this->_createSet($factory);
+ $set->addPathHeader('Return-Path', 'some@path');
+ $this->assertTrue($set->has('Return-Path'));
+ }
+
+ public function testNewlySetHeaderIsSeenByHas()
+ {
+ $factory = $this->_createFactory();
+ $header = $this->_createHeader('X-Foo', 'bar');
+ $set = $this->_createSet($factory);
+ $set->set($header);
+ $this->assertTrue($set->has('X-Foo'));
+ }
+
+ public function testHasCanAcceptOffset()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertTrue($set->has('Message-ID', 0));
+ }
+
+ public function testHasWithIllegalOffsetReturnsFalse()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertFalse($set->has('Message-ID', 1));
+ }
+
+ public function testHasCanDistinguishMultipleHeaders()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($this->_createHeader('Message-ID')));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $this->assertTrue($set->has('Message-ID', 1));
+ }
+
+ public function testGetWithUnspecifiedOffset()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertSame($header, $set->get('Message-ID'));
+ }
+
+ public function testGetWithSpeiciedOffset()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Message-ID');
+ $header2 = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($header1));
+ $factory->expects($this->at(2))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'more@id')
+ ->will($this->returnValue($header2));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $set->addIdHeader('Message-ID', 'more@id');
+ $this->assertSame($header1, $set->get('Message-ID', 1));
+ }
+
+ public function testGetReturnsNullIfHeaderNotSet()
+ {
+ $set = $this->_createSet($this->_createFactory());
+ $this->assertNull($set->get('Message-ID', 99));
+ }
+
+ public function testGetAllReturnsAllHeadersMatchingName()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Message-ID');
+ $header2 = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($header1));
+ $factory->expects($this->at(2))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'more@id')
+ ->will($this->returnValue($header2));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $set->addIdHeader('Message-ID', 'more@id');
+
+ $this->assertEquals(array($header0, $header1, $header2),
+ $set->getAll('Message-ID')
+ );
+ }
+
+ public function testGetAllReturnsAllHeadersIfNoArguments()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Subject');
+ $header2 = $this->_createHeader('To');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Subject', 'thing')
+ ->will($this->returnValue($header1));
+ $factory->expects($this->at(2))
+ ->method('createIdHeader')
+ ->with('To', 'person@example.org')
+ ->will($this->returnValue($header2));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Subject', 'thing');
+ $set->addIdHeader('To', 'person@example.org');
+
+ $this->assertEquals(array($header0, $header1, $header2),
+ $set->getAll()
+ );
+ }
+
+ public function testGetAllReturnsEmptyArrayIfNoneSet()
+ {
+ $set = $this->_createSet($this->_createFactory());
+ $this->assertEquals(array(), $set->getAll('Received'));
+ }
+
+ public function testRemoveWithUnspecifiedOffset()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->remove('Message-ID');
+ $this->assertFalse($set->has('Message-ID'));
+ }
+
+ public function testRemoveWithSpecifiedIndexRemovesHeader()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($header1));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $set->remove('Message-ID', 0);
+ $this->assertFalse($set->has('Message-ID', 0));
+ $this->assertTrue($set->has('Message-ID', 1));
+ $this->assertTrue($set->has('Message-ID'));
+ $set->remove('Message-ID', 1);
+ $this->assertFalse($set->has('Message-ID', 1));
+ $this->assertFalse($set->has('Message-ID'));
+ }
+
+ public function testRemoveWithSpecifiedIndexLeavesOtherHeaders()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($header1));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $set->remove('Message-ID', 1);
+ $this->assertTrue($set->has('Message-ID', 0));
+ }
+
+ public function testRemoveWithInvalidOffsetDoesNothing()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->remove('Message-ID', 50);
+ $this->assertTrue($set->has('Message-ID'));
+ }
+
+ public function testRemoveAllRemovesAllHeadersWithName()
+ {
+ $header0 = $this->_createHeader('Message-ID');
+ $header1 = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header0));
+ $factory->expects($this->at(1))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'other@id')
+ ->will($this->returnValue($header1));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->addIdHeader('Message-ID', 'other@id');
+ $set->removeAll('Message-ID');
+ $this->assertFalse($set->has('Message-ID', 0));
+ $this->assertFalse($set->has('Message-ID', 1));
+ }
+
+ public function testHasIsNotCaseSensitive()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertTrue($set->has('message-id'));
+ }
+
+ public function testGetIsNotCaseSensitive()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertSame($header, $set->get('message-id'));
+ }
+
+ public function testGetAllIsNotCaseSensitive()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $this->assertEquals(array($header), $set->getAll('message-id'));
+ }
+
+ public function testRemoveIsNotCaseSensitive()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->remove('message-id');
+ $this->assertFalse($set->has('Message-ID'));
+ }
+
+ public function testRemoveAllIsNotCaseSensitive()
+ {
+ $header = $this->_createHeader('Message-ID');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createIdHeader')
+ ->with('Message-ID', 'some@id')
+ ->will($this->returnValue($header));
+
+ $set = $this->_createSet($factory);
+ $set->addIdHeader('Message-ID', 'some@id');
+ $set->removeAll('message-id');
+ $this->assertFalse($set->has('Message-ID'));
+ }
+
+ public function testNewInstance()
+ {
+ $set = $this->_createSet($this->_createFactory());
+ $instance = $set->newInstance();
+ $this->assertInstanceof('Swift_Mime_HeaderSet', $instance);
+ }
+
+ public function testToStringJoinsHeadersTogether()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Foo', 'bar')
+ ->will($this->returnValue($this->_createHeader('Foo', 'bar')));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('Zip', 'buttons')
+ ->will($this->returnValue($this->_createHeader('Zip', 'buttons')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Foo', 'bar');
+ $set->addTextHeader('Zip', 'buttons');
+ $this->assertEquals(
+ "Foo: bar\r\n".
+ "Zip: buttons\r\n",
+ $set->toString()
+ );
+ }
+
+ public function testHeadersWithoutBodiesAreNotDisplayed()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Foo', 'bar')
+ ->will($this->returnValue($this->_createHeader('Foo', 'bar')));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('Zip', '')
+ ->will($this->returnValue($this->_createHeader('Zip', '')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Foo', 'bar');
+ $set->addTextHeader('Zip', '');
+ $this->assertEquals(
+ "Foo: bar\r\n",
+ $set->toString()
+ );
+ }
+
+ public function testHeadersWithoutBodiesCanBeForcedToDisplay()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Foo', '')
+ ->will($this->returnValue($this->_createHeader('Foo', '')));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('Zip', '')
+ ->will($this->returnValue($this->_createHeader('Zip', '')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Foo', '');
+ $set->addTextHeader('Zip', '');
+ $set->setAlwaysDisplayed(array('Foo', 'Zip'));
+ $this->assertEquals(
+ "Foo: \r\n".
+ "Zip: \r\n",
+ $set->toString()
+ );
+ }
+
+ public function testHeaderSequencesCanBeSpecified()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Third', 'three')
+ ->will($this->returnValue($this->_createHeader('Third', 'three')));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('First', 'one')
+ ->will($this->returnValue($this->_createHeader('First', 'one')));
+ $factory->expects($this->at(2))
+ ->method('createTextHeader')
+ ->with('Second', 'two')
+ ->will($this->returnValue($this->_createHeader('Second', 'two')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Third', 'three');
+ $set->addTextHeader('First', 'one');
+ $set->addTextHeader('Second', 'two');
+
+ $set->defineOrdering(array('First', 'Second', 'Third'));
+
+ $this->assertEquals(
+ "First: one\r\n".
+ "Second: two\r\n".
+ "Third: three\r\n",
+ $set->toString()
+ );
+ }
+
+ public function testUnsortedHeadersAppearAtEnd()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Fourth', 'four')
+ ->will($this->returnValue($this->_createHeader('Fourth', 'four')));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('Fifth', 'five')
+ ->will($this->returnValue($this->_createHeader('Fifth', 'five')));
+ $factory->expects($this->at(2))
+ ->method('createTextHeader')
+ ->with('Third', 'three')
+ ->will($this->returnValue($this->_createHeader('Third', 'three')));
+ $factory->expects($this->at(3))
+ ->method('createTextHeader')
+ ->with('First', 'one')
+ ->will($this->returnValue($this->_createHeader('First', 'one')));
+ $factory->expects($this->at(4))
+ ->method('createTextHeader')
+ ->with('Second', 'two')
+ ->will($this->returnValue($this->_createHeader('Second', 'two')));
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Fourth', 'four');
+ $set->addTextHeader('Fifth', 'five');
+ $set->addTextHeader('Third', 'three');
+ $set->addTextHeader('First', 'one');
+ $set->addTextHeader('Second', 'two');
+
+ $set->defineOrdering(array('First', 'Second', 'Third'));
+
+ $this->assertEquals(
+ "First: one\r\n".
+ "Second: two\r\n".
+ "Third: three\r\n".
+ "Fourth: four\r\n".
+ "Fifth: five\r\n",
+ $set->toString()
+ );
+ }
+
+ public function testSettingCharsetNotifiesAlreadyExistingHeaders()
+ {
+ $subject = $this->_createHeader('Subject', 'some text');
+ $xHeader = $this->_createHeader('X-Header', 'some text');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Subject', 'some text')
+ ->will($this->returnValue($subject));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('X-Header', 'some text')
+ ->will($this->returnValue($xHeader));
+ $subject->expects($this->once())
+ ->method('setCharset')
+ ->with('utf-8');
+ $xHeader->expects($this->once())
+ ->method('setCharset')
+ ->with('utf-8');
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Subject', 'some text');
+ $set->addTextHeader('X-Header', 'some text');
+
+ $set->setCharset('utf-8');
+ }
+
+ public function testCharsetChangeNotifiesAlreadyExistingHeaders()
+ {
+ $subject = $this->_createHeader('Subject', 'some text');
+ $xHeader = $this->_createHeader('X-Header', 'some text');
+ $factory = $this->_createFactory();
+ $factory->expects($this->at(0))
+ ->method('createTextHeader')
+ ->with('Subject', 'some text')
+ ->will($this->returnValue($subject));
+ $factory->expects($this->at(1))
+ ->method('createTextHeader')
+ ->with('X-Header', 'some text')
+ ->will($this->returnValue($xHeader));
+ $subject->expects($this->once())
+ ->method('setCharset')
+ ->with('utf-8');
+ $xHeader->expects($this->once())
+ ->method('setCharset')
+ ->with('utf-8');
+
+ $set = $this->_createSet($factory);
+ $set->addTextHeader('Subject', 'some text');
+ $set->addTextHeader('X-Header', 'some text');
+
+ $set->charsetChanged('utf-8');
+ }
+
+ public function testCharsetChangeNotifiesFactory()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->once())
+ ->method('charsetChanged')
+ ->with('utf-8');
+
+ $set = $this->_createSet($factory);
+
+ $set->setCharset('utf-8');
+ }
+
+ // -- Creation methods
+
+ private function _createSet($factory)
+ {
+ return new Swift_Mime_SimpleHeaderSet($factory);
+ }
+
+ private function _createFactory()
+ {
+ return $this->getMockBuilder('Swift_Mime_HeaderFactory')->getMock();
+ }
+
+ private function _createHeader($name, $body = '')
+ {
+ $header = $this->getMockBuilder('Swift_Mime_Header')->getMock();
+ $header->expects($this->any())
+ ->method('getFieldName')
+ ->will($this->returnValue($name));
+ $header->expects($this->any())
+ ->method('toString')
+ ->will($this->returnValue(sprintf("%s: %s\r\n", $name, $body)));
+ $header->expects($this->any())
+ ->method('getFieldBody')
+ ->will($this->returnValue($body));
+
+ return $header;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMessageTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMessageTest.php
new file mode 100644
index 00000000..267d2764
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMessageTest.php
@@ -0,0 +1,829 @@
+_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(
+ Swift_Mime_MimeEntity::LEVEL_TOP, $message->getNestingLevel()
+ );
+ }
+
+ public function testDateIsReturnedFromHeader()
+ {
+ $date = $this->_createHeader('Date', 123);
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Date' => $date)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(123, $message->getDate());
+ }
+
+ public function testDateIsSetInHeader()
+ {
+ $date = $this->_createHeader('Date', 123, array(), false);
+ $date->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(1234);
+ $date->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Date' => $date)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setDate(1234);
+ }
+
+ public function testDateHeaderIsCreatedIfNonePresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addDateHeader')
+ ->once()
+ ->with('Date', 1234);
+ $headers->shouldReceive('addDateHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setDate(1234);
+ }
+
+ public function testDateHeaderIsAddedDuringConstruction()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addDateHeader')
+ ->once()
+ ->with('Date', '/^[0-9]+$/D');
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ }
+
+ public function testIdIsReturnedFromHeader()
+ {
+ /* -- RFC 2045, 7.
+ In constructing a high-level user agent, it may be desirable to allow
+ one body to make reference to another. Accordingly, bodies may be
+ labelled using the "Content-ID" header field, which is syntactically
+ identical to the "Message-ID" header field
+ */
+
+ $messageId = $this->_createHeader('Message-ID', 'a@b');
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Message-ID' => $messageId)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('a@b', $message->getId());
+ }
+
+ public function testIdIsSetInHeader()
+ {
+ $messageId = $this->_createHeader('Message-ID', 'a@b', array(), false);
+ $messageId->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('x@y');
+ $messageId->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Message-ID' => $messageId)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setId('x@y');
+ }
+
+ public function testIdIsAutoGenerated()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addIdHeader')
+ ->once()
+ ->with('Message-ID', '/^.*?@.*?$/D');
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ }
+
+ public function testSubjectIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.5.
+ */
+
+ $subject = $this->_createHeader('Subject', 'example subject');
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Subject' => $subject)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('example subject', $message->getSubject());
+ }
+
+ public function testSubjectIsSetInHeader()
+ {
+ $subject = $this->_createHeader('Subject', '', array(), false);
+ $subject->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('foo');
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Subject' => $subject)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setSubject('foo');
+ }
+
+ public function testSubjectHeaderIsCreatedIfNotPresent()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addTextHeader')
+ ->once()
+ ->with('Subject', 'example subject');
+ $headers->shouldReceive('addTextHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setSubject('example subject');
+ }
+
+ public function testReturnPathIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.7.
+ */
+
+ $path = $this->_createHeader('Return-Path', 'bounces@domain');
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Return-Path' => $path)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals('bounces@domain', $message->getReturnPath());
+ }
+
+ public function testReturnPathIsSetInHeader()
+ {
+ $path = $this->_createHeader('Return-Path', '', array(), false);
+ $path->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('bounces@domain');
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Return-Path' => $path)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setReturnPath('bounces@domain');
+ }
+
+ public function testReturnPathHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addPathHeader')
+ ->once()
+ ->with('Return-Path', 'bounces@domain');
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setReturnPath('bounces@domain');
+ }
+
+ public function testSenderIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.2.
+ */
+
+ $sender = $this->_createHeader('Sender', array('sender@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Sender' => $sender)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('sender@domain' => 'Name'), $message->getSender());
+ }
+
+ public function testSenderIsSetInHeader()
+ {
+ $sender = $this->_createHeader('Sender', array('sender@domain' => 'Name'),
+ array(), false
+ );
+ $sender->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Sender' => $sender)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setSender(array('other@domain' => 'Other'));
+ }
+
+ public function testSenderHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Sender', (array) 'sender@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setSender('sender@domain');
+ }
+
+ public function testNameCanBeUsedInSenderHeader()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Sender', array('sender@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setSender('sender@domain', 'Name');
+ }
+
+ public function testFromIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.2.
+ */
+
+ $from = $this->_createHeader('From', array('from@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('From' => $from)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('from@domain' => 'Name'), $message->getFrom());
+ }
+
+ public function testFromIsSetInHeader()
+ {
+ $from = $this->_createHeader('From', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $from->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('From' => $from)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setFrom(array('other@domain' => 'Other'));
+ }
+
+ public function testFromIsAddedToHeadersDuringAddFrom()
+ {
+ $from = $this->_createHeader('From', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $from->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('from@domain' => 'Name', 'other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('From' => $from)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->addFrom('other@domain', 'Other');
+ }
+
+ public function testFromHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('From', (array) 'from@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setFrom('from@domain');
+ }
+
+ public function testPersonalNameCanBeUsedInFromAddress()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('From', array('from@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setFrom('from@domain', 'Name');
+ }
+
+ public function testReplyToIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.2.
+ */
+
+ $reply = $this->_createHeader('Reply-To', array('reply@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Reply-To' => $reply)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('reply@domain' => 'Name'), $message->getReplyTo());
+ }
+
+ public function testReplyToIsSetInHeader()
+ {
+ $reply = $this->_createHeader('Reply-To', array('reply@domain' => 'Name'),
+ array(), false
+ );
+ $reply->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Reply-To' => $reply)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setReplyTo(array('other@domain' => 'Other'));
+ }
+
+ public function testReplyToIsAddedToHeadersDuringAddReplyTo()
+ {
+ $replyTo = $this->_createHeader('Reply-To', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $replyTo->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('from@domain' => 'Name', 'other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Reply-To' => $replyTo)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->addReplyTo('other@domain', 'Other');
+ }
+
+ public function testReplyToHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Reply-To', (array) 'reply@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setReplyTo('reply@domain');
+ }
+
+ public function testNameCanBeUsedInReplyTo()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Reply-To', array('reply@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setReplyTo('reply@domain', 'Name');
+ }
+
+ public function testToIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.3.
+ */
+
+ $to = $this->_createHeader('To', array('to@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('To' => $to)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('to@domain' => 'Name'), $message->getTo());
+ }
+
+ public function testToIsSetInHeader()
+ {
+ $to = $this->_createHeader('To', array('to@domain' => 'Name'),
+ array(), false
+ );
+ $to->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('To' => $to)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setTo(array('other@domain' => 'Other'));
+ }
+
+ public function testToIsAddedToHeadersDuringAddTo()
+ {
+ $to = $this->_createHeader('To', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $to->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('from@domain' => 'Name', 'other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('To' => $to)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->addTo('other@domain', 'Other');
+ }
+
+ public function testToHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('To', (array) 'to@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setTo('to@domain');
+ }
+
+ public function testNameCanBeUsedInToHeader()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('To', array('to@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setTo('to@domain', 'Name');
+ }
+
+ public function testCcIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.3.
+ */
+
+ $cc = $this->_createHeader('Cc', array('cc@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Cc' => $cc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('cc@domain' => 'Name'), $message->getCc());
+ }
+
+ public function testCcIsSetInHeader()
+ {
+ $cc = $this->_createHeader('Cc', array('cc@domain' => 'Name'),
+ array(), false
+ );
+ $cc->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Cc' => $cc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setCc(array('other@domain' => 'Other'));
+ }
+
+ public function testCcIsAddedToHeadersDuringAddCc()
+ {
+ $cc = $this->_createHeader('Cc', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $cc->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('from@domain' => 'Name', 'other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Cc' => $cc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->addCc('other@domain', 'Other');
+ }
+
+ public function testCcHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Cc', (array) 'cc@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setCc('cc@domain');
+ }
+
+ public function testNameCanBeUsedInCcHeader()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Cc', array('cc@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setCc('cc@domain', 'Name');
+ }
+
+ public function testBccIsReturnedFromHeader()
+ {
+ /* -- RFC 2822, 3.6.3.
+ */
+
+ $bcc = $this->_createHeader('Bcc', array('bcc@domain' => 'Name'));
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Bcc' => $bcc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('bcc@domain' => 'Name'), $message->getBcc());
+ }
+
+ public function testBccIsSetInHeader()
+ {
+ $bcc = $this->_createHeader('Bcc', array('bcc@domain' => 'Name'),
+ array(), false
+ );
+ $bcc->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Bcc' => $bcc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setBcc(array('other@domain' => 'Other'));
+ }
+
+ public function testBccIsAddedToHeadersDuringAddBcc()
+ {
+ $bcc = $this->_createHeader('Bcc', array('from@domain' => 'Name'),
+ array(), false
+ );
+ $bcc->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with(array('from@domain' => 'Name', 'other@domain' => 'Other'));
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Bcc' => $bcc)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->addBcc('other@domain', 'Other');
+ }
+
+ public function testBccHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Bcc', (array) 'bcc@domain');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setBcc('bcc@domain');
+ }
+
+ public function testNameCanBeUsedInBcc()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Bcc', array('bcc@domain' => 'Name'));
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setBcc('bcc@domain', 'Name');
+ }
+
+ public function testPriorityIsReadFromHeader()
+ {
+ $prio = $this->_createHeader('X-Priority', '2 (High)');
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('X-Priority' => $prio)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(2, $message->getPriority());
+ }
+
+ public function testPriorityIsSetInHeader()
+ {
+ $prio = $this->_createHeader('X-Priority', '2 (High)', array(), false);
+ $prio->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('5 (Lowest)');
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('X-Priority' => $prio)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setPriority($message::PRIORITY_LOWEST);
+ }
+
+ public function testPriorityHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addTextHeader')
+ ->once()
+ ->with('X-Priority', '4 (Low)');
+ $headers->shouldReceive('addTextHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setPriority($message::PRIORITY_LOW);
+ }
+
+ public function testReadReceiptAddressReadFromHeader()
+ {
+ $rcpt = $this->_createHeader('Disposition-Notification-To',
+ array('chris@swiftmailer.org' => 'Chris')
+ );
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Disposition-Notification-To' => $rcpt)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertEquals(array('chris@swiftmailer.org' => 'Chris'),
+ $message->getReadReceiptTo()
+ );
+ }
+
+ public function testReadReceiptIsSetInHeader()
+ {
+ $rcpt = $this->_createHeader('Disposition-Notification-To', array(), array(), false);
+ $rcpt->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('mark@swiftmailer.org');
+
+ $message = $this->_createMessage(
+ $this->_createHeaderSet(array('Disposition-Notification-To' => $rcpt)),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $message->setReadReceiptTo('mark@swiftmailer.org');
+ }
+
+ public function testReadReceiptHeaderIsAddedIfNoneSet()
+ {
+ $headers = $this->_createHeaderSet(array(), false);
+ $headers->shouldReceive('addMailboxHeader')
+ ->once()
+ ->with('Disposition-Notification-To', 'mark@swiftmailer.org');
+ $headers->shouldReceive('addMailboxHeader')
+ ->zeroOrMoreTimes();
+
+ $message = $this->_createMessage($headers, $this->_createEncoder(),
+ $this->_createCache()
+ );
+ $message->setReadReceiptTo('mark@swiftmailer.org');
+ }
+
+ public function testChildrenCanBeAttached()
+ {
+ $child1 = $this->_createChild();
+ $child2 = $this->_createChild();
+
+ $message = $this->_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $message->attach($child1);
+ $message->attach($child2);
+
+ $this->assertEquals(array($child1, $child2), $message->getChildren());
+ }
+
+ public function testChildrenCanBeDetached()
+ {
+ $child1 = $this->_createChild();
+ $child2 = $this->_createChild();
+
+ $message = $this->_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $message->attach($child1);
+ $message->attach($child2);
+
+ $message->detach($child1);
+
+ $this->assertEquals(array($child2), $message->getChildren());
+ }
+
+ public function testEmbedAttachesChild()
+ {
+ $child = $this->_createChild();
+
+ $message = $this->_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $message->embed($child);
+
+ $this->assertEquals(array($child), $message->getChildren());
+ }
+
+ public function testEmbedReturnsValidCid()
+ {
+ $child = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_RELATED, '',
+ false
+ );
+ $child->shouldReceive('getId')
+ ->zeroOrMoreTimes()
+ ->andReturn('foo@bar');
+
+ $message = $this->_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+
+ $this->assertEquals('cid:foo@bar', $message->embed($child));
+ }
+
+ public function testFluidInterface()
+ {
+ $child = $this->_createChild();
+ $message = $this->_createMessage($this->_createHeaderSet(),
+ $this->_createEncoder(), $this->_createCache()
+ );
+ $this->assertSame($message,
+ $message
+ ->setContentType('text/plain')
+ ->setEncoder($this->_createEncoder())
+ ->setId('foo@bar')
+ ->setDescription('my description')
+ ->setMaxLineLength(998)
+ ->setBody('xx')
+ ->setBoundary('xyz')
+ ->setChildren(array())
+ ->setCharset('iso-8859-1')
+ ->setFormat('flowed')
+ ->setDelSp(false)
+ ->setSubject('subj')
+ ->setDate(123)
+ ->setReturnPath('foo@bar')
+ ->setSender('foo@bar')
+ ->setFrom(array('x@y' => 'XY'))
+ ->setReplyTo(array('ab@cd' => 'ABCD'))
+ ->setTo(array('chris@site.tld', 'mark@site.tld'))
+ ->setCc('john@somewhere.tld')
+ ->setBcc(array('one@site', 'two@site' => 'Two'))
+ ->setPriority($message::PRIORITY_LOW)
+ ->setReadReceiptTo('a@b')
+ ->attach($child)
+ ->detach($child)
+ );
+ }
+
+ // -- Private helpers
+
+ //abstract
+ protected function _createEntity($headers, $encoder, $cache)
+ {
+ return $this->_createMessage($headers, $encoder, $cache);
+ }
+
+ protected function _createMimePart($headers, $encoder, $cache)
+ {
+ return $this->_createMessage($headers, $encoder, $cache);
+ }
+
+ private function _createMessage($headers, $encoder, $cache)
+ {
+ return new Swift_Mime_SimpleMessage($headers, $encoder, $cache, new Swift_Mime_Grammar());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMimeEntityTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMimeEntityTest.php
new file mode 100644
index 00000000..b54d7f87
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMimeEntityTest.php
@@ -0,0 +1,11 @@
+assertEquals(10, $plugin->getThreshold());
+ $plugin->setThreshold(100);
+ $this->assertEquals(100, $plugin->getThreshold());
+ }
+
+ public function testSleepTimeCanBeSetAndFetched()
+ {
+ $plugin = new Swift_Plugins_AntiFloodPlugin(10, 5);
+ $this->assertEquals(5, $plugin->getSleepTime());
+ $plugin->setSleepTime(1);
+ $this->assertEquals(1, $plugin->getSleepTime());
+ }
+
+ public function testPluginStopsConnectionAfterThreshold()
+ {
+ $transport = $this->_createTransport();
+ $transport->expects($this->once())
+ ->method('start');
+ $transport->expects($this->once())
+ ->method('stop');
+
+ $evt = $this->_createSendEvent($transport);
+
+ $plugin = new Swift_Plugins_AntiFloodPlugin(10);
+ for ($i = 0; $i < 12; ++$i) {
+ $plugin->sendPerformed($evt);
+ }
+ }
+
+ public function testPluginCanStopAndStartMultipleTimes()
+ {
+ $transport = $this->_createTransport();
+ $transport->expects($this->exactly(5))
+ ->method('start');
+ $transport->expects($this->exactly(5))
+ ->method('stop');
+
+ $evt = $this->_createSendEvent($transport);
+
+ $plugin = new Swift_Plugins_AntiFloodPlugin(2);
+ for ($i = 0; $i < 11; ++$i) {
+ $plugin->sendPerformed($evt);
+ }
+ }
+
+ public function testPluginCanSleepDuringRestart()
+ {
+ $sleeper = $this->getMockBuilder('Swift_Plugins_Sleeper')->getMock();
+ $sleeper->expects($this->once())
+ ->method('sleep')
+ ->with(10);
+
+ $transport = $this->_createTransport();
+ $transport->expects($this->once())
+ ->method('start');
+ $transport->expects($this->once())
+ ->method('stop');
+
+ $evt = $this->_createSendEvent($transport);
+
+ $plugin = new Swift_Plugins_AntiFloodPlugin(99, 10, $sleeper);
+ for ($i = 0; $i < 101; ++$i) {
+ $plugin->sendPerformed($evt);
+ }
+ }
+
+ // -- Creation Methods
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+
+ private function _createSendEvent($transport)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_SendEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getSource')
+ ->will($this->returnValue($transport));
+ $evt->expects($this->any())
+ ->method('getTransport')
+ ->will($this->returnValue($transport));
+
+ return $evt;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php
new file mode 100644
index 00000000..bb01a92c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php
@@ -0,0 +1,130 @@
+_monitor = new Swift_Plugins_BandwidthMonitorPlugin();
+ }
+
+ public function testBytesOutIncreasesWhenCommandsSent()
+ {
+ $evt = $this->_createCommandEvent("RCPT TO:\r\n");
+
+ $this->assertEquals(0, $this->_monitor->getBytesOut());
+ $this->_monitor->commandSent($evt);
+ $this->assertEquals(23, $this->_monitor->getBytesOut());
+ $this->_monitor->commandSent($evt);
+ $this->assertEquals(46, $this->_monitor->getBytesOut());
+ }
+
+ public function testBytesInIncreasesWhenResponsesReceived()
+ {
+ $evt = $this->_createResponseEvent("250 Ok\r\n");
+
+ $this->assertEquals(0, $this->_monitor->getBytesIn());
+ $this->_monitor->responseReceived($evt);
+ $this->assertEquals(8, $this->_monitor->getBytesIn());
+ $this->_monitor->responseReceived($evt);
+ $this->assertEquals(16, $this->_monitor->getBytesIn());
+ }
+
+ public function testCountersCanBeReset()
+ {
+ $evt = $this->_createResponseEvent("250 Ok\r\n");
+
+ $this->assertEquals(0, $this->_monitor->getBytesIn());
+ $this->_monitor->responseReceived($evt);
+ $this->assertEquals(8, $this->_monitor->getBytesIn());
+ $this->_monitor->responseReceived($evt);
+ $this->assertEquals(16, $this->_monitor->getBytesIn());
+
+ $evt = $this->_createCommandEvent("RCPT TO:\r\n");
+
+ $this->assertEquals(0, $this->_monitor->getBytesOut());
+ $this->_monitor->commandSent($evt);
+ $this->assertEquals(23, $this->_monitor->getBytesOut());
+ $this->_monitor->commandSent($evt);
+ $this->assertEquals(46, $this->_monitor->getBytesOut());
+
+ $this->_monitor->reset();
+
+ $this->assertEquals(0, $this->_monitor->getBytesOut());
+ $this->assertEquals(0, $this->_monitor->getBytesIn());
+ }
+
+ public function testBytesOutIncreasesAccordingToMessageLength()
+ {
+ $message = $this->_createMessageWithByteCount(6);
+ $evt = $this->_createSendEvent($message);
+
+ $this->assertEquals(0, $this->_monitor->getBytesOut());
+ $this->_monitor->sendPerformed($evt);
+ $this->assertEquals(6, $this->_monitor->getBytesOut());
+ $this->_monitor->sendPerformed($evt);
+ $this->assertEquals(12, $this->_monitor->getBytesOut());
+ }
+
+ // -- Creation Methods
+
+ private function _createSendEvent($message)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_SendEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getMessage')
+ ->will($this->returnValue($message));
+
+ return $evt;
+ }
+
+ private function _createCommandEvent($command)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_CommandEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getCommand')
+ ->will($this->returnValue($command));
+
+ return $evt;
+ }
+
+ private function _createResponseEvent($response)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_ResponseEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ return $evt;
+ }
+
+ private function _createMessageWithByteCount($bytes)
+ {
+ $this->_bytes = $bytes;
+ $msg = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+ $msg->expects($this->any())
+ ->method('toByteStream')
+ ->will($this->returnCallback(array($this, '_write')));
+ /* $this->_checking(Expectations::create()
+ -> ignoring($msg)->toByteStream(any()) -> calls(array($this, '_write'))
+ ); */
+
+ return $msg;
+ }
+
+ public function _write($is)
+ {
+ for ($i = 0; $i < $this->_bytes; ++$i) {
+ $is->write('x');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/DecoratorPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/DecoratorPluginTest.php
new file mode 100644
index 00000000..7f4cdef1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/DecoratorPluginTest.php
@@ -0,0 +1,269 @@
+_createMessage(
+ $this->_createHeaders(),
+ array('zip@button.tld' => 'Zipathon'),
+ array('chris.corbyn@swiftmailer.org' => 'Chris'),
+ 'Subject',
+ 'Hello {name}, you are customer #{id}'
+ );
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Hello Zip, you are customer #456');
+ $message->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+
+ $plugin = $this->_createPlugin(
+ array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
+ );
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReplacementsCanBeAppliedToSameMessageMultipleTimes()
+ {
+ $message = $this->_createMessage(
+ $this->_createHeaders(),
+ array('zip@button.tld' => 'Zipathon', 'foo@bar.tld' => 'Foo'),
+ array('chris.corbyn@swiftmailer.org' => 'Chris'),
+ 'Subject',
+ 'Hello {name}, you are customer #{id}'
+ );
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Hello Zip, you are customer #456');
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Hello {name}, you are customer #{id}');
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Hello Foo, you are customer #123');
+ $message->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+
+ $plugin = $this->_createPlugin(
+ array(
+ 'foo@bar.tld' => array('{name}' => 'Foo', '{id}' => '123'),
+ 'zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'),
+ )
+ );
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReplacementsCanBeMadeInHeaders()
+ {
+ $headers = $this->_createHeaders(array(
+ $returnPathHeader = $this->_createHeader('Return-Path', 'foo-{id}@swiftmailer.org'),
+ $toHeader = $this->_createHeader('Subject', 'A message for {name}!'),
+ ));
+
+ $message = $this->_createMessage(
+ $headers,
+ array('zip@button.tld' => 'Zipathon'),
+ array('chris.corbyn@swiftmailer.org' => 'Chris'),
+ 'A message for {name}!',
+ 'Hello {name}, you are customer #{id}'
+ );
+
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Hello Zip, you are customer #456');
+ $toHeader->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('A message for Zip!');
+ $returnPathHeader->shouldReceive('setFieldBodyModel')
+ ->once()
+ ->with('foo-456@swiftmailer.org');
+ $message->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+ $toHeader->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+ $returnPathHeader->shouldReceive('setFieldBodyModel')
+ ->zeroOrMoreTimes();
+
+ $plugin = $this->_createPlugin(
+ array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
+ );
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReplacementsAreMadeOnSubparts()
+ {
+ $part1 = $this->_createPart('text/plain', 'Your name is {name}?', '1@x');
+ $part2 = $this->_createPart('text/html', 'Your name is {name}?', '2@x');
+ $message = $this->_createMessage(
+ $this->_createHeaders(),
+ array('zip@button.tld' => 'Zipathon'),
+ array('chris.corbyn@swiftmailer.org' => 'Chris'),
+ 'A message for {name}!',
+ 'Subject'
+ );
+ $message->shouldReceive('getChildren')
+ ->zeroOrMoreTimes()
+ ->andReturn(array($part1, $part2));
+ $part1->shouldReceive('setBody')
+ ->once()
+ ->with('Your name is Zip?');
+ $part2->shouldReceive('setBody')
+ ->once()
+ ->with('Your name is Zip?');
+ $part1->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+ $part2->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+
+ $plugin = $this->_createPlugin(
+ array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
+ );
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReplacementsCanBeTakenFromCustomReplacementsObject()
+ {
+ $message = $this->_createMessage(
+ $this->_createHeaders(),
+ array('foo@bar' => 'Foobar', 'zip@zap' => 'Zip zap'),
+ array('chris.corbyn@swiftmailer.org' => 'Chris'),
+ 'Subject',
+ 'Something {a}'
+ );
+
+ $replacements = $this->_createReplacements();
+
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Something b');
+ $message->shouldReceive('setBody')
+ ->once()
+ ->with('Something c');
+ $message->shouldReceive('setBody')
+ ->zeroOrMoreTimes();
+ $replacements->shouldReceive('getReplacementsFor')
+ ->once()
+ ->with('foo@bar')
+ ->andReturn(array('{a}' => 'b'));
+ $replacements->shouldReceive('getReplacementsFor')
+ ->once()
+ ->with('zip@zap')
+ ->andReturn(array('{a}' => 'c'));
+
+ $plugin = $this->_createPlugin($replacements);
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+
+ // -- Creation methods
+
+ private function _createMessage($headers, $to = array(), $from = null, $subject = null,
+ $body = null)
+ {
+ $message = $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ foreach ($to as $addr => $name) {
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array($addr => $name));
+ }
+ $message->shouldReceive('getHeaders')
+ ->zeroOrMoreTimes()
+ ->andReturn($headers);
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn($from);
+ $message->shouldReceive('getSubject')
+ ->zeroOrMoreTimes()
+ ->andReturn($subject);
+ $message->shouldReceive('getBody')
+ ->zeroOrMoreTimes()
+ ->andReturn($body);
+
+ return $message;
+ }
+
+ private function _createPlugin($replacements)
+ {
+ return new Swift_Plugins_DecoratorPlugin($replacements);
+ }
+
+ private function _createReplacements()
+ {
+ return $this->getMockery('Swift_Plugins_Decorator_Replacements')->shouldIgnoreMissing();
+ }
+
+ private function _createSendEvent(Swift_Mime_Message $message)
+ {
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $evt->shouldReceive('getMessage')
+ ->zeroOrMoreTimes()
+ ->andReturn($message);
+
+ return $evt;
+ }
+
+ private function _createPart($type, $body, $id)
+ {
+ $part = $this->getMockery('Swift_Mime_MimeEntity')->shouldIgnoreMissing();
+ $part->shouldReceive('getContentType')
+ ->zeroOrMoreTimes()
+ ->andReturn($type);
+ $part->shouldReceive('getBody')
+ ->zeroOrMoreTimes()
+ ->andReturn($body);
+ $part->shouldReceive('getId')
+ ->zeroOrMoreTimes()
+ ->andReturn($id);
+
+ return $part;
+ }
+
+ private function _createHeaders($headers = array())
+ {
+ $set = $this->getMockery('Swift_Mime_HeaderSet')->shouldIgnoreMissing();
+ $set->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->andReturn($headers);
+
+ foreach ($headers as $header) {
+ $set->set($header);
+ }
+
+ return $set;
+ }
+
+ private function _createHeader($name, $body = '')
+ {
+ $header = $this->getMockery('Swift_Mime_Header')->shouldIgnoreMissing();
+ $header->shouldReceive('getFieldName')
+ ->zeroOrMoreTimes()
+ ->andReturn($name);
+ $header->shouldReceive('getFieldBodyModel')
+ ->zeroOrMoreTimes()
+ ->andReturn($body);
+
+ return $header;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/LoggerPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/LoggerPluginTest.php
new file mode 100644
index 00000000..15d7014b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/LoggerPluginTest.php
@@ -0,0 +1,190 @@
+_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with('foo');
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->add('foo');
+ }
+
+ public function testLoggerDelegatesDumpingEntries()
+ {
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('dump')
+ ->will($this->returnValue('foobar'));
+
+ $plugin = $this->_createPlugin($logger);
+ $this->assertEquals('foobar', $plugin->dump());
+ }
+
+ public function testLoggerDelegatesClearingEntries()
+ {
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('clear');
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->clear();
+ }
+
+ public function testCommandIsSentToLogger()
+ {
+ $evt = $this->_createCommandEvent("foo\r\n");
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->regExp('~foo\r\n~'));
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->commandSent($evt);
+ }
+
+ public function testResponseIsSentToLogger()
+ {
+ $evt = $this->_createResponseEvent("354 Go ahead\r\n");
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->regExp('~354 Go ahead\r\n~'));
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->responseReceived($evt);
+ }
+
+ public function testTransportBeforeStartChangeIsSentToLogger()
+ {
+ $evt = $this->_createTransportChangeEvent();
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->anything());
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->beforeTransportStarted($evt);
+ }
+
+ public function testTransportStartChangeIsSentToLogger()
+ {
+ $evt = $this->_createTransportChangeEvent();
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->anything());
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->transportStarted($evt);
+ }
+
+ public function testTransportStopChangeIsSentToLogger()
+ {
+ $evt = $this->_createTransportChangeEvent();
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->anything());
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->transportStopped($evt);
+ }
+
+ public function testTransportBeforeStopChangeIsSentToLogger()
+ {
+ $evt = $this->_createTransportChangeEvent();
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->anything());
+
+ $plugin = $this->_createPlugin($logger);
+ $plugin->beforeTransportStopped($evt);
+ }
+
+ public function testExceptionsArePassedToDelegateAndLeftToBubbleUp()
+ {
+ $transport = $this->_createTransport();
+ $evt = $this->_createTransportExceptionEvent();
+ $logger = $this->_createLogger();
+ $logger->expects($this->once())
+ ->method('add')
+ ->with($this->anything());
+
+ $plugin = $this->_createPlugin($logger);
+ try {
+ $plugin->exceptionThrown($evt);
+ $this->fail('Exception should bubble up.');
+ } catch (Swift_TransportException $ex) {
+ }
+ }
+
+ // -- Creation Methods
+
+ private function _createLogger()
+ {
+ return $this->getMockBuilder('Swift_Plugins_Logger')->getMock();
+ }
+
+ private function _createPlugin($logger)
+ {
+ return new Swift_Plugins_LoggerPlugin($logger);
+ }
+
+ private function _createCommandEvent($command)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_CommandEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getCommand')
+ ->will($this->returnValue($command));
+
+ return $evt;
+ }
+
+ private function _createResponseEvent($response)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_ResponseEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ return $evt;
+ }
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+
+ private function _createTransportChangeEvent()
+ {
+ $evt = $this->getMockBuilder('Swift_Events_TransportChangeEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getSource')
+ ->will($this->returnValue($this->_createTransport()));
+
+ return $evt;
+ }
+
+ public function _createTransportExceptionEvent()
+ {
+ $evt = $this->getMockBuilder('Swift_Events_TransportExceptionEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getException')
+ ->will($this->returnValue(new Swift_TransportException('')));
+
+ return $evt;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php
new file mode 100644
index 00000000..880bb32c
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php
@@ -0,0 +1,65 @@
+add(">> Foo\r\n");
+ $this->assertEquals(">> Foo\r\n", $logger->dump());
+ }
+
+ public function testAddingMultipleEntriesDumpsMultipleLines()
+ {
+ $logger = new Swift_Plugins_Loggers_ArrayLogger();
+ $logger->add(">> FOO\r\n");
+ $logger->add("<< 502 That makes no sense\r\n");
+ $logger->add(">> RSET\r\n");
+ $logger->add("<< 250 OK\r\n");
+
+ $this->assertEquals(
+ ">> FOO\r\n".PHP_EOL.
+ "<< 502 That makes no sense\r\n".PHP_EOL.
+ ">> RSET\r\n".PHP_EOL.
+ "<< 250 OK\r\n",
+ $logger->dump()
+ );
+ }
+
+ public function testLogCanBeCleared()
+ {
+ $logger = new Swift_Plugins_Loggers_ArrayLogger();
+ $logger->add(">> FOO\r\n");
+ $logger->add("<< 502 That makes no sense\r\n");
+ $logger->add(">> RSET\r\n");
+ $logger->add("<< 250 OK\r\n");
+
+ $this->assertEquals(
+ ">> FOO\r\n".PHP_EOL.
+ "<< 502 That makes no sense\r\n".PHP_EOL.
+ ">> RSET\r\n".PHP_EOL.
+ "<< 250 OK\r\n",
+ $logger->dump()
+ );
+
+ $logger->clear();
+
+ $this->assertEquals('', $logger->dump());
+ }
+
+ public function testLengthCanBeTruncated()
+ {
+ $logger = new Swift_Plugins_Loggers_ArrayLogger(2);
+ $logger->add(">> FOO\r\n");
+ $logger->add("<< 502 That makes no sense\r\n");
+ $logger->add(">> RSET\r\n");
+ $logger->add("<< 250 OK\r\n");
+
+ $this->assertEquals(
+ ">> RSET\r\n".PHP_EOL.
+ "<< 250 OK\r\n",
+ $logger->dump(),
+ '%s: Log should be truncated to last 2 entries'
+ );
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php
new file mode 100644
index 00000000..6134fe64
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php
@@ -0,0 +1,24 @@
+add('>> Foo');
+ $data = ob_get_clean();
+
+ $this->assertEquals('>> Foo'.PHP_EOL, $data);
+ }
+
+ public function testAddingEntryDumpsEscapedLineWithHtml()
+ {
+ $logger = new Swift_Plugins_Loggers_EchoLogger(true);
+ ob_start();
+ $logger->add('>> Foo');
+ $data = ob_get_clean();
+
+ $this->assertEquals('>> Foo
'.PHP_EOL, $data);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php
new file mode 100644
index 00000000..d7c55afc
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php
@@ -0,0 +1,103 @@
+_createConnection();
+ $connection->expects($this->once())
+ ->method('connect');
+
+ $plugin = $this->_createPlugin('pop.host.tld', 110);
+ $plugin->setConnection($connection);
+
+ $transport = $this->_createTransport();
+ $evt = $this->_createTransportChangeEvent($transport);
+
+ $plugin->beforeTransportStarted($evt);
+ }
+
+ public function testPluginDisconnectsFromPop3HostBeforeTransportStarts()
+ {
+ $connection = $this->_createConnection();
+ $connection->expects($this->once())
+ ->method('disconnect');
+
+ $plugin = $this->_createPlugin('pop.host.tld', 110);
+ $plugin->setConnection($connection);
+
+ $transport = $this->_createTransport();
+ $evt = $this->_createTransportChangeEvent($transport);
+
+ $plugin->beforeTransportStarted($evt);
+ }
+
+ public function testPluginDoesNotConnectToSmtpIfBoundToDifferentTransport()
+ {
+ $connection = $this->_createConnection();
+ $connection->expects($this->never())
+ ->method('disconnect');
+ $connection->expects($this->never())
+ ->method('connect');
+
+ $smtp = $this->_createTransport();
+
+ $plugin = $this->_createPlugin('pop.host.tld', 110);
+ $plugin->setConnection($connection);
+ $plugin->bindSmtp($smtp);
+
+ $transport = $this->_createTransport();
+ $evt = $this->_createTransportChangeEvent($transport);
+
+ $plugin->beforeTransportStarted($evt);
+ }
+
+ public function testPluginCanBindToSpecificTransport()
+ {
+ $connection = $this->_createConnection();
+ $connection->expects($this->once())
+ ->method('connect');
+
+ $smtp = $this->_createTransport();
+
+ $plugin = $this->_createPlugin('pop.host.tld', 110);
+ $plugin->setConnection($connection);
+ $plugin->bindSmtp($smtp);
+
+ $evt = $this->_createTransportChangeEvent($smtp);
+
+ $plugin->beforeTransportStarted($evt);
+ }
+
+ // -- Creation Methods
+
+ private function _createTransport()
+ {
+ return $this->getMockBuilder('Swift_Transport')->getMock();
+ }
+
+ private function _createTransportChangeEvent($transport)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_TransportChangeEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getSource')
+ ->will($this->returnValue($transport));
+ $evt->expects($this->any())
+ ->method('getTransport')
+ ->will($this->returnValue($transport));
+
+ return $evt;
+ }
+
+ public function _createConnection()
+ {
+ return $this->getMockBuilder('Swift_Plugins_Pop_Pop3Connection')->getMock();
+ }
+
+ public function _createPlugin($host, $port, $crypto = null)
+ {
+ return new Swift_Plugins_PopBeforeSmtpPlugin($host, $port, $crypto);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/RedirectingPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/RedirectingPluginTest.php
new file mode 100644
index 00000000..4cc7e89f
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/RedirectingPluginTest.php
@@ -0,0 +1,185 @@
+assertEquals('fabien@example.com', $plugin->getRecipient());
+ $plugin->setRecipient('chris@example.com');
+ $this->assertEquals('chris@example.com', $plugin->getRecipient());
+ }
+
+ public function testPluginChangesRecipients()
+ {
+ $message = Swift_Message::newInstance()
+ ->setSubject('...')
+ ->setFrom(array('john@example.com' => 'John Doe'))
+ ->setTo($to = array(
+ 'fabien-to@example.com' => 'Fabien (To)',
+ 'chris-to@example.com' => 'Chris (To)',
+ ))
+ ->setCc($cc = array(
+ 'fabien-cc@example.com' => 'Fabien (Cc)',
+ 'chris-cc@example.com' => 'Chris (Cc)',
+ ))
+ ->setBcc($bcc = array(
+ 'fabien-bcc@example.com' => 'Fabien (Bcc)',
+ 'chris-bcc@example.com' => 'Chris (Bcc)',
+ ))
+ ->setBody('...')
+ ;
+
+ $plugin = new Swift_Plugins_RedirectingPlugin('god@example.com');
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), array('god@example.com' => ''));
+ $this->assertEquals($message->getCc(), array());
+ $this->assertEquals($message->getBcc(), array());
+
+ $plugin->sendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), $to);
+ $this->assertEquals($message->getCc(), $cc);
+ $this->assertEquals($message->getBcc(), $bcc);
+ }
+
+ public function testPluginRespectsUnsetToList()
+ {
+ $message = Swift_Message::newInstance()
+ ->setSubject('...')
+ ->setFrom(array('john@example.com' => 'John Doe'))
+ ->setCc($cc = array(
+ 'fabien-cc@example.com' => 'Fabien (Cc)',
+ 'chris-cc@example.com' => 'Chris (Cc)',
+ ))
+ ->setBcc($bcc = array(
+ 'fabien-bcc@example.com' => 'Fabien (Bcc)',
+ 'chris-bcc@example.com' => 'Chris (Bcc)',
+ ))
+ ->setBody('...')
+ ;
+
+ $plugin = new Swift_Plugins_RedirectingPlugin('god@example.com');
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), array('god@example.com' => ''));
+ $this->assertEquals($message->getCc(), array());
+ $this->assertEquals($message->getBcc(), array());
+
+ $plugin->sendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), array());
+ $this->assertEquals($message->getCc(), $cc);
+ $this->assertEquals($message->getBcc(), $bcc);
+ }
+
+ public function testPluginRespectsAWhitelistOfPatterns()
+ {
+ $message = Swift_Message::newInstance()
+ ->setSubject('...')
+ ->setFrom(array('john@example.com' => 'John Doe'))
+ ->setTo($to = array(
+ 'fabien-to@example.com' => 'Fabien (To)',
+ 'chris-to@example.com' => 'Chris (To)',
+ 'lars-to@internal.com' => 'Lars (To)',
+ ))
+ ->setCc($cc = array(
+ 'fabien-cc@example.com' => 'Fabien (Cc)',
+ 'chris-cc@example.com' => 'Chris (Cc)',
+ 'lars-cc@internal.org' => 'Lars (Cc)',
+ ))
+ ->setBcc($bcc = array(
+ 'fabien-bcc@example.com' => 'Fabien (Bcc)',
+ 'chris-bcc@example.com' => 'Chris (Bcc)',
+ 'john-bcc@example.org' => 'John (Bcc)',
+ ))
+ ->setBody('...')
+ ;
+
+ $recipient = 'god@example.com';
+ $patterns = array('/^.*@internal.[a-z]+$/', '/^john-.*$/');
+
+ $plugin = new Swift_Plugins_RedirectingPlugin($recipient, $patterns);
+
+ $this->assertEquals($recipient, $plugin->getRecipient());
+ $this->assertEquals($plugin->getWhitelist(), $patterns);
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), array('lars-to@internal.com' => 'Lars (To)', 'god@example.com' => null));
+ $this->assertEquals($message->getCc(), array('lars-cc@internal.org' => 'Lars (Cc)'));
+ $this->assertEquals($message->getBcc(), array('john-bcc@example.org' => 'John (Bcc)'));
+
+ $plugin->sendPerformed($evt);
+
+ $this->assertEquals($message->getTo(), $to);
+ $this->assertEquals($message->getCc(), $cc);
+ $this->assertEquals($message->getBcc(), $bcc);
+ }
+
+ public function testArrayOfRecipientsCanBeExplicitlyDefined()
+ {
+ $message = Swift_Message::newInstance()
+ ->setSubject('...')
+ ->setFrom(array('john@example.com' => 'John Doe'))
+ ->setTo(array(
+ 'fabien@example.com' => 'Fabien',
+ 'chris@example.com' => 'Chris (To)',
+ 'lars-to@internal.com' => 'Lars (To)',
+ ))
+ ->setCc(array(
+ 'fabien@example.com' => 'Fabien',
+ 'chris-cc@example.com' => 'Chris (Cc)',
+ 'lars-cc@internal.org' => 'Lars (Cc)',
+ ))
+ ->setBcc(array(
+ 'fabien@example.com' => 'Fabien',
+ 'chris-bcc@example.com' => 'Chris (Bcc)',
+ 'john-bcc@example.org' => 'John (Bcc)',
+ ))
+ ->setBody('...')
+ ;
+
+ $recipients = array('god@example.com', 'fabien@example.com');
+ $patterns = array('/^.*@internal.[a-z]+$/');
+
+ $plugin = new Swift_Plugins_RedirectingPlugin($recipients, $patterns);
+
+ $evt = $this->_createSendEvent($message);
+
+ $plugin->beforeSendPerformed($evt);
+
+ $this->assertEquals(
+ $message->getTo(),
+ array('fabien@example.com' => 'Fabien', 'lars-to@internal.com' => 'Lars (To)', 'god@example.com' => null)
+ );
+ $this->assertEquals(
+ $message->getCc(),
+ array('fabien@example.com' => 'Fabien', 'lars-cc@internal.org' => 'Lars (Cc)')
+ );
+ $this->assertEquals($message->getBcc(), array('fabien@example.com' => 'Fabien'));
+ }
+
+ // -- Creation Methods
+
+ private function _createSendEvent(Swift_Mime_Message $message)
+ {
+ $evt = $this->getMockBuilder('Swift_Events_SendEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $evt->expects($this->any())
+ ->method('getMessage')
+ ->will($this->returnValue($message));
+
+ return $evt;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ReporterPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ReporterPluginTest.php
new file mode 100644
index 00000000..81018830
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ReporterPluginTest.php
@@ -0,0 +1,88 @@
+_createMessage();
+ $evt = $this->_createSendEvent();
+ $reporter = $this->_createReporter();
+
+ $message->shouldReceive('getTo')->zeroOrMoreTimes()->andReturn(array('foo@bar.tld' => 'Foo'));
+ $evt->shouldReceive('getMessage')->zeroOrMoreTimes()->andReturn($message);
+ $evt->shouldReceive('getFailedRecipients')->zeroOrMoreTimes()->andReturn(array());
+ $reporter->shouldReceive('notify')->once()->with($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS);
+
+ $plugin = new Swift_Plugins_ReporterPlugin($reporter);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReportingFailedTo()
+ {
+ $message = $this->_createMessage();
+ $evt = $this->_createSendEvent();
+ $reporter = $this->_createReporter();
+
+ $message->shouldReceive('getTo')->zeroOrMoreTimes()->andReturn(array('foo@bar.tld' => 'Foo', 'zip@button' => 'Zip'));
+ $evt->shouldReceive('getMessage')->zeroOrMoreTimes()->andReturn($message);
+ $evt->shouldReceive('getFailedRecipients')->zeroOrMoreTimes()->andReturn(array('zip@button'));
+ $reporter->shouldReceive('notify')->once()->with($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS);
+ $reporter->shouldReceive('notify')->once()->with($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL);
+
+ $plugin = new Swift_Plugins_ReporterPlugin($reporter);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReportingFailedCc()
+ {
+ $message = $this->_createMessage();
+ $evt = $this->_createSendEvent();
+ $reporter = $this->_createReporter();
+
+ $message->shouldReceive('getTo')->zeroOrMoreTimes()->andReturn(array('foo@bar.tld' => 'Foo'));
+ $message->shouldReceive('getCc')->zeroOrMoreTimes()->andReturn(array('zip@button' => 'Zip', 'test@test.com' => 'Test'));
+ $evt->shouldReceive('getMessage')->zeroOrMoreTimes()->andReturn($message);
+ $evt->shouldReceive('getFailedRecipients')->zeroOrMoreTimes()->andReturn(array('zip@button'));
+ $reporter->shouldReceive('notify')->once()->with($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS);
+ $reporter->shouldReceive('notify')->once()->with($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL);
+ $reporter->shouldReceive('notify')->once()->with($message, 'test@test.com', Swift_Plugins_Reporter::RESULT_PASS);
+
+ $plugin = new Swift_Plugins_ReporterPlugin($reporter);
+ $plugin->sendPerformed($evt);
+ }
+
+ public function testReportingFailedBcc()
+ {
+ $message = $this->_createMessage();
+ $evt = $this->_createSendEvent();
+ $reporter = $this->_createReporter();
+
+ $message->shouldReceive('getTo')->zeroOrMoreTimes()->andReturn(array('foo@bar.tld' => 'Foo'));
+ $message->shouldReceive('getBcc')->zeroOrMoreTimes()->andReturn(array('zip@button' => 'Zip', 'test@test.com' => 'Test'));
+ $evt->shouldReceive('getMessage')->zeroOrMoreTimes()->andReturn($message);
+ $evt->shouldReceive('getFailedRecipients')->zeroOrMoreTimes()->andReturn(array('zip@button'));
+ $reporter->shouldReceive('notify')->once()->with($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS);
+ $reporter->shouldReceive('notify')->once()->with($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL);
+ $reporter->shouldReceive('notify')->once()->with($message, 'test@test.com', Swift_Plugins_Reporter::RESULT_PASS);
+
+ $plugin = new Swift_Plugins_ReporterPlugin($reporter);
+ $plugin->sendPerformed($evt);
+ }
+
+ // -- Creation Methods
+
+ private function _createMessage()
+ {
+ return $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ }
+
+ private function _createSendEvent()
+ {
+ return $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ }
+
+ private function _createReporter()
+ {
+ return $this->getMockery('Swift_Plugins_Reporter')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php
new file mode 100644
index 00000000..33dcc750
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php
@@ -0,0 +1,64 @@
+_hitReporter = new Swift_Plugins_Reporters_HitReporter();
+ $this->_message = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+ }
+
+ public function testReportingFail()
+ {
+ $this->_hitReporter->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->assertEquals(array('foo@bar.tld'),
+ $this->_hitReporter->getFailedRecipients()
+ );
+ }
+
+ public function testMultipleReports()
+ {
+ $this->_hitReporter->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->_hitReporter->notify($this->_message, 'zip@button',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->assertEquals(array('foo@bar.tld', 'zip@button'),
+ $this->_hitReporter->getFailedRecipients()
+ );
+ }
+
+ public function testReportingPassIsIgnored()
+ {
+ $this->_hitReporter->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->_hitReporter->notify($this->_message, 'zip@button',
+ Swift_Plugins_Reporter::RESULT_PASS
+ );
+ $this->assertEquals(array('foo@bar.tld'),
+ $this->_hitReporter->getFailedRecipients()
+ );
+ }
+
+ public function testBufferCanBeCleared()
+ {
+ $this->_hitReporter->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->_hitReporter->notify($this->_message, 'zip@button',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $this->assertEquals(array('foo@bar.tld', 'zip@button'),
+ $this->_hitReporter->getFailedRecipients()
+ );
+ $this->_hitReporter->clear();
+ $this->assertEquals(array(), $this->_hitReporter->getFailedRecipients());
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php
new file mode 100644
index 00000000..a6c6a277
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php
@@ -0,0 +1,54 @@
+_html = new Swift_Plugins_Reporters_HtmlReporter();
+ $this->_message = $this->getMockBuilder('Swift_Mime_Message')->getMock();
+ }
+
+ public function testReportingPass()
+ {
+ ob_start();
+ $this->_html->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_PASS
+ );
+ $html = ob_get_clean();
+
+ $this->assertRegExp('~ok|pass~i', $html, '%s: Reporter should indicate pass');
+ $this->assertRegExp('~foo@bar\.tld~', $html, '%s: Reporter should show address');
+ }
+
+ public function testReportingFail()
+ {
+ ob_start();
+ $this->_html->notify($this->_message, 'zip@button',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $html = ob_get_clean();
+
+ $this->assertRegExp('~fail~i', $html, '%s: Reporter should indicate fail');
+ $this->assertRegExp('~zip@button~', $html, '%s: Reporter should show address');
+ }
+
+ public function testMultipleReports()
+ {
+ ob_start();
+ $this->_html->notify($this->_message, 'foo@bar.tld',
+ Swift_Plugins_Reporter::RESULT_PASS
+ );
+ $this->_html->notify($this->_message, 'zip@button',
+ Swift_Plugins_Reporter::RESULT_FAIL
+ );
+ $html = ob_get_clean();
+
+ $this->assertRegExp('~ok|pass~i', $html, '%s: Reporter should indicate pass');
+ $this->assertRegExp('~foo@bar\.tld~', $html, '%s: Reporter should show address');
+ $this->assertRegExp('~fail~i', $html, '%s: Reporter should indicate fail');
+ $this->assertRegExp('~zip@button~', $html, '%s: Reporter should show address');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ThrottlerPluginTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ThrottlerPluginTest.php
new file mode 100644
index 00000000..a50f14f9
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ThrottlerPluginTest.php
@@ -0,0 +1,104 @@
+_createSleeper();
+ $timer = $this->_createTimer();
+
+ //10MB/min
+ $plugin = new Swift_Plugins_ThrottlerPlugin(
+ 10000000, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE,
+ $sleeper, $timer
+ );
+
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(0);
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(1); //expected 0.6
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(1); //expected 1.2 (sleep 1)
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(2); //expected 1.8
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(2); //expected 2.4 (sleep 1)
+ $sleeper->shouldReceive('sleep')->twice()->with(1);
+
+ //10,000,000 bytes per minute
+ //100,000 bytes per email
+
+ // .: (10,000,000/100,000)/60 emails per second = 1.667 emais/sec
+
+ $message = $this->_createMessageWithByteCount(100000); //100KB
+
+ $evt = $this->_createSendEvent($message);
+
+ for ($i = 0; $i < 5; ++$i) {
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+ }
+
+ public function testMessagesPerMinuteThrottling()
+ {
+ $sleeper = $this->_createSleeper();
+ $timer = $this->_createTimer();
+
+ //60/min
+ $plugin = new Swift_Plugins_ThrottlerPlugin(
+ 60, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE,
+ $sleeper, $timer
+ );
+
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(0);
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(0); //expected 1 (sleep 1)
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(2); //expected 2
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(2); //expected 3 (sleep 1)
+ $timer->shouldReceive('getTimestamp')->once()->andReturn(4); //expected 4
+ $sleeper->shouldReceive('sleep')->twice()->with(1);
+
+ //60 messages per minute
+ //1 message per second
+
+ $message = $this->_createMessageWithByteCount(10);
+
+ $evt = $this->_createSendEvent($message);
+
+ for ($i = 0; $i < 5; ++$i) {
+ $plugin->beforeSendPerformed($evt);
+ $plugin->sendPerformed($evt);
+ }
+ }
+
+ // -- Creation Methods
+
+ private function _createSleeper()
+ {
+ return $this->getMockery('Swift_Plugins_Sleeper');
+ }
+
+ private function _createTimer()
+ {
+ return $this->getMockery('Swift_Plugins_Timer');
+ }
+
+ private function _createMessageWithByteCount($bytes)
+ {
+ $msg = $this->getMockery('Swift_Mime_Message');
+ $msg->shouldReceive('toByteStream')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function ($is) use ($bytes) {
+ for ($i = 0; $i < $bytes; ++$i) {
+ $is->write('x');
+ }
+ });
+
+ return $msg;
+ }
+
+ private function _createSendEvent($message)
+ {
+ $evt = $this->getMockery('Swift_Events_SendEvent');
+ $evt->shouldReceive('getMessage')
+ ->zeroOrMoreTimes()
+ ->andReturn($message);
+
+ return $evt;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/DKIMSignerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/DKIMSignerTest.php
new file mode 100644
index 00000000..13c1b4c1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/DKIMSignerTest.php
@@ -0,0 +1,227 @@
+markTestSkipped(
+ 'skipping because of https://bugs.php.net/bug.php?id=61421'
+ );
+ }
+ }
+
+ public function testBasicSigningHeaderManipulation()
+ {
+ $headers = $this->_createHeaders();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ /* @var $signer Swift_Signers_HeaderSigner */
+ $altered = $signer->getAlteredHeaders();
+ $signer->reset();
+ // Headers
+ $signer->setHeaders($headers);
+ // Body
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ // Signing
+ $signer->addSignature($headers);
+ }
+
+ // Default Signing
+ public function testSigningDefaults()
+ {
+ $headerSet = $this->_createHeaderSet();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ $signer->setSignatureTimestamp('1299879181');
+ $altered = $signer->getAlteredHeaders();
+ $this->assertEquals(array('DKIM-Signature'), $altered);
+ $signer->reset();
+ $signer->setHeaders($headerSet);
+ $this->assertFalse($headerSet->has('DKIM-Signature'));
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ $signer->addSignature($headerSet);
+ $this->assertTrue($headerSet->has('DKIM-Signature'));
+ $dkim = $headerSet->getAll('DKIM-Signature');
+ $sig = reset($dkim);
+ $this->assertEquals($sig->getValue(), 'v=1; a=rsa-sha1; bh=wlbYcY9O9OPInGJ4D0E/rGsvMLE=; d=dummy.nxdomain.be; h=; i=@dummy.nxdomain.be; s=dummySelector; t=1299879181; b=RMSNelzM2O5MAAnMjT3G3/VF36S3DGJXoPCXR001F1WDReu0prGphWjuzK/m6V1pwqQL8cCNg Hi74mTx2bvyAvmkjvQtJf1VMUOCc9WHGcm1Yec66I3ZWoNMGSWZ1EKAm2CtTzyG0IFw4ml9DI wSkyAFxlgicckDD6FibhqwX4w=');
+ }
+
+ // SHA256 Signing
+ public function testSigning256()
+ {
+ $headerSet = $this->_createHeaderSet();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ $signer->setHashAlgorithm('rsa-sha256');
+ $signer->setSignatureTimestamp('1299879181');
+ $altered = $signer->getAlteredHeaders();
+ $this->assertEquals(array('DKIM-Signature'), $altered);
+ $signer->reset();
+ $signer->setHeaders($headerSet);
+ $this->assertFalse($headerSet->has('DKIM-Signature'));
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ $signer->addSignature($headerSet);
+ $this->assertTrue($headerSet->has('DKIM-Signature'));
+ $dkim = $headerSet->getAll('DKIM-Signature');
+ $sig = reset($dkim);
+ $this->assertEquals($sig->getValue(), 'v=1; a=rsa-sha256; bh=f+W+hu8dIhf2VAni89o8lF6WKTXi7nViA4RrMdpD5/U=; d=dummy.nxdomain.be; h=; i=@dummy.nxdomain.be; s=dummySelector; t=1299879181; b=jqPmieHzF5vR9F4mXCAkowuphpO4iJ8IAVuioh1BFZ3VITXZj5jlOFxULJMBiiApm2keJirnh u4mzogj444QkpT3lJg8/TBGAYQPdcvkG3KC0jdyN6QpSgpITBJG2BwWa+keXsv2bkQgLRAzNx qRhP45vpHCKun0Tg9LrwW/KCg=');
+ }
+
+ // Relaxed/Relaxed Hash Signing
+ public function testSigningRelaxedRelaxed256()
+ {
+ $headerSet = $this->_createHeaderSet();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ $signer->setHashAlgorithm('rsa-sha256');
+ $signer->setSignatureTimestamp('1299879181');
+ $signer->setBodyCanon('relaxed');
+ $signer->setHeaderCanon('relaxed');
+ $altered = $signer->getAlteredHeaders();
+ $this->assertEquals(array('DKIM-Signature'), $altered);
+ $signer->reset();
+ $signer->setHeaders($headerSet);
+ $this->assertFalse($headerSet->has('DKIM-Signature'));
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ $signer->addSignature($headerSet);
+ $this->assertTrue($headerSet->has('DKIM-Signature'));
+ $dkim = $headerSet->getAll('DKIM-Signature');
+ $sig = reset($dkim);
+ $this->assertEquals($sig->getValue(), 'v=1; a=rsa-sha256; bh=f+W+hu8dIhf2VAni89o8lF6WKTXi7nViA4RrMdpD5/U=; d=dummy.nxdomain.be; h=; i=@dummy.nxdomain.be; s=dummySelector; c=relaxed/relaxed; t=1299879181; b=gzOI+PX6HpZKQFzwwmxzcVJsyirdLXOS+4pgfCpVHQIdqYusKLrhlLeFBTNoz75HrhNvGH6T0 Rt3w5aTqkrWfUuAEYt0Ns14GowLM7JojaFN+pZ4eYnRB3CBBgW6fee4NEMD5WPca3uS09tr1E 10RYh9ILlRtl+84sovhx5id3Y=');
+ }
+
+ // Relaxed/Simple Hash Signing
+ public function testSigningRelaxedSimple256()
+ {
+ $headerSet = $this->_createHeaderSet();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ $signer->setHashAlgorithm('rsa-sha256');
+ $signer->setSignatureTimestamp('1299879181');
+ $signer->setHeaderCanon('relaxed');
+ $altered = $signer->getAlteredHeaders();
+ $this->assertEquals(array('DKIM-Signature'), $altered);
+ $signer->reset();
+ $signer->setHeaders($headerSet);
+ $this->assertFalse($headerSet->has('DKIM-Signature'));
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ $signer->addSignature($headerSet);
+ $this->assertTrue($headerSet->has('DKIM-Signature'));
+ $dkim = $headerSet->getAll('DKIM-Signature');
+ $sig = reset($dkim);
+ $this->assertEquals($sig->getValue(), 'v=1; a=rsa-sha256; bh=f+W+hu8dIhf2VAni89o8lF6WKTXi7nViA4RrMdpD5/U=; d=dummy.nxdomain.be; h=; i=@dummy.nxdomain.be; s=dummySelector; c=relaxed; t=1299879181; b=dLPJNec5v81oelyzGOY0qPqTlGnQeNfUNBOrV/JKbStr3NqWGI9jH4JAe2YvO2V32lfPNoby1 4MMzZ6EPkaZkZDDSPa+53YbCPQAlqiD9QZZIUe2UNM33HN8yAMgiWEF5aP7MbQnxeVZMfVLEl 9S8qOImu+K5JZqhQQTL0dgLwA=');
+ }
+
+ // Simple/Relaxed Hash Signing
+ public function testSigningSimpleRelaxed256()
+ {
+ $headerSet = $this->_createHeaderSet();
+ $messageContent = 'Hello World';
+ $signer = new Swift_Signers_DKIMSigner(file_get_contents(dirname(dirname(dirname(__DIR__))).'/_samples/dkim/dkim.test.priv'), 'dummy.nxdomain.be', 'dummySelector');
+ $signer->setHashAlgorithm('rsa-sha256');
+ $signer->setSignatureTimestamp('1299879181');
+ $signer->setBodyCanon('relaxed');
+ $altered = $signer->getAlteredHeaders();
+ $this->assertEquals(array('DKIM-Signature'), $altered);
+ $signer->reset();
+ $signer->setHeaders($headerSet);
+ $this->assertFalse($headerSet->has('DKIM-Signature'));
+ $signer->startBody();
+ $signer->write($messageContent);
+ $signer->endBody();
+ $signer->addSignature($headerSet);
+ $this->assertTrue($headerSet->has('DKIM-Signature'));
+ $dkim = $headerSet->getAll('DKIM-Signature');
+ $sig = reset($dkim);
+ $this->assertEquals($sig->getValue(), 'v=1; a=rsa-sha256; bh=f+W+hu8dIhf2VAni89o8lF6WKTXi7nViA4RrMdpD5/U=; d=dummy.nxdomain.be; h=; i=@dummy.nxdomain.be; s=dummySelector; c=simple/relaxed; t=1299879181; b=M5eomH/zamyzix9kOes+6YLzQZxuJdBP4x3nP9zF2N26eMLG2/cBKbnNyqiOTDhJdYfWPbLIa 1CWnjST0j5p4CpeOkGYuiE+M4TWEZwhRmRWootlPO3Ii6XpbBJKFk1o9zviS7OmXblUUE4aqb yRSIMDhtLdCK5GlaCneFLN7RQ=');
+ }
+
+ // -- Creation Methods
+ private function _createHeaderSet()
+ {
+ $cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream());
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+
+ $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
+ $paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
+ $grammar = new Swift_Mime_Grammar();
+ $headers = new Swift_Mime_SimpleHeaderSet(new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $grammar));
+
+ return $headers;
+ }
+
+ /**
+ * @return Swift_Mime_Headers
+ */
+ private function _createHeaders()
+ {
+ $x = 0;
+ $cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream());
+ $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
+ $contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
+
+ $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
+ $paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
+ $grammar = new Swift_Mime_Grammar();
+ $headerFactory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $grammar);
+ $headers = $this->getMockery('Swift_Mime_HeaderSet');
+
+ $headers->shouldReceive('listAll')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('From', 'To', 'Date', 'Subject'));
+ $headers->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->with('From')
+ ->andReturn(true);
+ $headers->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->with('From')
+ ->andReturn(array($headerFactory->createMailboxHeader('From', 'test@test.test')));
+ $headers->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->with('To')
+ ->andReturn(true);
+ $headers->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->with('To')
+ ->andReturn(array($headerFactory->createMailboxHeader('To', 'test@test.test')));
+ $headers->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->with('Date')
+ ->andReturn(true);
+ $headers->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->with('Date')
+ ->andReturn(array($headerFactory->createTextHeader('Date', 'Fri, 11 Mar 2011 20:56:12 +0000 (GMT)')));
+ $headers->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->with('Subject')
+ ->andReturn(true);
+ $headers->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->with('Subject')
+ ->andReturn(array($headerFactory->createTextHeader('Subject', 'Foo Bar Text Message')));
+ $headers->shouldReceive('addTextHeader')
+ ->zeroOrMoreTimes()
+ ->with('DKIM-Signature', \Mockery::any())
+ ->andReturn(true);
+ $headers->shouldReceive('getAll')
+ ->zeroOrMoreTimes()
+ ->with('DKIM-Signature')
+ ->andReturn(array($headerFactory->createTextHeader('DKIM-Signature', 'Foo Bar Text Message')));
+
+ return $headers;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/OpenDKIMSignerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/OpenDKIMSignerTest.php
new file mode 100644
index 00000000..00e48c13
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/OpenDKIMSignerTest.php
@@ -0,0 +1,45 @@
+markTestSkipped(
+ 'Need OpenDKIM extension run these tests.'
+ );
+ }
+ }
+
+ public function testBasicSigningHeaderManipulation()
+ {
+ }
+
+ // Default Signing
+ public function testSigningDefaults()
+ {
+ }
+
+ // SHA256 Signing
+ public function testSigning256()
+ {
+ }
+
+ // Relaxed/Relaxed Hash Signing
+ public function testSigningRelaxedRelaxed256()
+ {
+ }
+
+ // Relaxed/Simple Hash Signing
+ public function testSigningRelaxedSimple256()
+ {
+ }
+
+ // Simple/Relaxed Hash Signing
+ public function testSigningSimpleRelaxed256()
+ {
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/SMimeSignerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/SMimeSignerTest.php
new file mode 100644
index 00000000..df745ef2
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/SMimeSignerTest.php
@@ -0,0 +1,554 @@
+replacementFactory = Swift_DependencyContainer::getInstance()
+ ->lookup('transport.replacementfactory');
+
+ $this->samplesDir = str_replace('\\', '/', realpath(__DIR__.'/../../../_samples/')).'/';
+ }
+
+ public function testUnSingedMessage()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $this->assertEquals('Here is the message itself', $message->getBody());
+ }
+
+ public function testSingedMessage()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign.crt', $this->samplesDir.'smime/sign.key');
+ $message->attachSigner($signer);
+
+ $messageStream = $this->newFilteredStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!($boundary = $this->getBoundary($headers['content-type']))) {
+ return false;
+ }
+
+ $expectedBody = <<assertValidVerify($expectedBody, $messageStream);
+ unset($messageStream);
+ }
+
+ public function testSingedMessageExtraCerts()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign2.crt', $this->samplesDir.'smime/sign2.key', PKCS7_DETACHED, $this->samplesDir.'smime/intermediate.crt');
+ $message->attachSigner($signer);
+
+ $messageStream = $this->newFilteredStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!($boundary = $this->getBoundary($headers['content-type']))) {
+ return false;
+ }
+
+ $expectedBody = <<assertValidVerify($expectedBody, $messageStream);
+ unset($messageStream);
+ }
+
+ public function testSingedMessageBinary()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign.crt', $this->samplesDir.'smime/sign.key', PKCS7_BINARY);
+ $message->attachSigner($signer);
+
+ $messageStream = $this->newFilteredStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!preg_match('#^application/(x\-)?pkcs7-mime; smime-type=signed\-data;#', $headers['content-type'])) {
+ $this->fail('Content-type does not match.');
+
+ return false;
+ }
+
+ $this->assertEquals($headers['content-transfer-encoding'], 'base64');
+ $this->assertEquals($headers['content-disposition'], 'attachment; filename="smime.p7m"');
+
+ $expectedBody = '(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})';
+
+ $messageStreamClean = $this->newFilteredStream();
+
+ $this->assertValidVerify($expectedBody, $messageStream);
+ unset($messageStreamClean, $messageStream);
+ }
+
+ public function testSingedMessageWithAttachments()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $message->attach(Swift_Attachment::fromPath($this->samplesDir.'/files/textfile.zip'));
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign.crt', $this->samplesDir.'smime/sign.key');
+ $message->attachSigner($signer);
+
+ $messageStream = $this->newFilteredStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!($boundary = $this->getBoundary($headers['content-type']))) {
+ return false;
+ }
+
+ $expectedBody = <<assertValidVerify($expectedBody, $messageStream);
+ unset($messageStream);
+ }
+
+ public function testEncryptedMessage()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $originalMessage = $this->cleanMessage($message->toString());
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setEncryptCertificate($this->samplesDir.'smime/encrypt.crt');
+ $message->attachSigner($signer);
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!preg_match('#^application/(x\-)?pkcs7-mime; smime-type=enveloped\-data;#', $headers['content-type'])) {
+ $this->fail('Content-type does not match.');
+
+ return false;
+ }
+
+ $expectedBody = '(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})';
+
+ $decryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_decrypt($messageStream->getPath(), $decryptedMessageStream->getPath(), 'file://'.$this->samplesDir.'smime/encrypt.crt', array('file://'.$this->samplesDir.'smime/encrypt.key', 'swift'))) {
+ $this->fail(sprintf('Decrypt of the message failed. Internal error "%s".', openssl_error_string()));
+ }
+
+ $this->assertEquals($originalMessage, $decryptedMessageStream->getContent());
+ unset($decryptedMessageStream, $messageStream);
+ }
+
+ public function testEncryptedMessageWithMultipleCerts()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $originalMessage = $this->cleanMessage($message->toString());
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setEncryptCertificate(array($this->samplesDir.'smime/encrypt.crt', $this->samplesDir.'smime/encrypt2.crt'));
+ $message->attachSigner($signer);
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!preg_match('#^application/(x\-)?pkcs7-mime; smime-type=enveloped\-data;#', $headers['content-type'])) {
+ $this->fail('Content-type does not match.');
+
+ return false;
+ }
+
+ $expectedBody = '(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})';
+
+ $decryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_decrypt($messageStream->getPath(), $decryptedMessageStream->getPath(), 'file://'.$this->samplesDir.'smime/encrypt.crt', array('file://'.$this->samplesDir.'smime/encrypt.key', 'swift'))) {
+ $this->fail(sprintf('Decrypt of the message failed. Internal error "%s".', openssl_error_string()));
+ }
+
+ $this->assertEquals($originalMessage, $decryptedMessageStream->getContent());
+ unset($decryptedMessageStream);
+
+ $decryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_decrypt($messageStream->getPath(), $decryptedMessageStream->getPath(), 'file://'.$this->samplesDir.'smime/encrypt2.crt', array('file://'.$this->samplesDir.'smime/encrypt2.key', 'swift'))) {
+ $this->fail(sprintf('Decrypt of the message failed. Internal error "%s".', openssl_error_string()));
+ }
+
+ $this->assertEquals($originalMessage, $decryptedMessageStream->getContent());
+ unset($decryptedMessageStream, $messageStream);
+ }
+
+ public function testSignThenEncryptedMessage()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $signer = new Swift_Signers_SMimeSigner();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign.crt', $this->samplesDir.'smime/sign.key');
+ $signer->setEncryptCertificate($this->samplesDir.'smime/encrypt.crt');
+ $message->attachSigner($signer);
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!preg_match('#^application/(x\-)?pkcs7-mime; smime-type=enveloped\-data;#', $headers['content-type'])) {
+ $this->fail('Content-type does not match.');
+
+ return false;
+ }
+
+ $expectedBody = '(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})';
+
+ $decryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_decrypt($messageStream->getPath(), $decryptedMessageStream->getPath(), 'file://'.$this->samplesDir.'smime/encrypt.crt', array('file://'.$this->samplesDir.'smime/encrypt.key', 'swift'))) {
+ $this->fail(sprintf('Decrypt of the message failed. Internal error "%s".', openssl_error_string()));
+ }
+
+ $entityString = $decryptedMessageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!($boundary = $this->getBoundary($headers['content-type']))) {
+ return false;
+ }
+
+ $expectedBody = <<assertValidVerify($expectedBody, $decryptedMessageStream)) {
+ return false;
+ }
+
+ unset($decryptedMessageStream, $messageStream);
+ }
+
+ public function testEncryptThenSignMessage()
+ {
+ $message = Swift_SignedMessage::newInstance('Wonderful Subject')
+ ->setFrom(array('john@doe.com' => 'John Doe'))
+ ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
+ ->setBody('Here is the message itself');
+
+ $originalMessage = $this->cleanMessage($message->toString());
+
+ $signer = Swift_Signers_SMimeSigner::newInstance();
+ $signer->setSignCertificate($this->samplesDir.'smime/sign.crt', $this->samplesDir.'smime/sign.key');
+ $signer->setEncryptCertificate($this->samplesDir.'smime/encrypt.crt');
+ $signer->setSignThenEncrypt(false);
+ $message->attachSigner($signer);
+
+ $messageStream = $this->newFilteredStream();
+ $message->toByteStream($messageStream);
+ $messageStream->commit();
+
+ $entityString = $messageStream->getContent();
+ $headers = self::getHeadersOfMessage($entityString);
+
+ if (!($boundary = $this->getBoundary($headers['content-type']))) {
+ return false;
+ }
+
+ $expectedBody = <<MIME-Version: 1\.0
+Content-Disposition: attachment; filename="smime\.p7m"
+Content-Type: application/(x\-)?pkcs7-mime; smime-type=enveloped-data; name="smime\.p7m"
+Content-Transfer-Encoding: base64
+
+(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})
+
+
+)--$boundary
+Content-Type: application/(x\-)?pkcs7-signature; name="smime\.p7s"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="smime\.p7s"
+
+(?:^[a-zA-Z0-9\/\\r\\n+]*={0,2})
+
+--$boundary--
+OEL;
+
+ if (!$this->assertValidVerify($expectedBody, $messageStream)) {
+ return false;
+ }
+
+ $expectedBody = str_replace("\n", "\r\n", $expectedBody);
+ if (!preg_match('%'.$expectedBody.'*%m', $entityString, $entities)) {
+ $this->fail('Failed regex match.');
+
+ return false;
+ }
+
+ $messageStreamClean = new Swift_ByteStream_TemporaryFileByteStream();
+ $messageStreamClean->write($entities['encrypted_message']);
+
+ $decryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_decrypt($messageStreamClean->getPath(), $decryptedMessageStream->getPath(), 'file://'.$this->samplesDir.'smime/encrypt.crt', array('file://'.$this->samplesDir.'smime/encrypt.key', 'swift'))) {
+ $this->fail(sprintf('Decrypt of the message failed. Internal error "%s".', openssl_error_string()));
+ }
+
+ $this->assertEquals($originalMessage, $decryptedMessageStream->getContent());
+ unset($messageStreamClean, $messageStream, $decryptedMessageStream);
+ }
+
+ protected function assertValidVerify($expected, Swift_ByteStream_TemporaryFileByteStream $messageStream)
+ {
+ $actual = $messageStream->getContent();
+
+ // File is UNIX encoded so convert them to correct line ending
+ $expected = str_replace("\n", "\r\n", $expected);
+
+ $actual = trim(self::getBodyOfMessage($actual));
+ if (!$this->assertRegExp('%^'.$expected.'$\s*%m', $actual)) {
+ return false;
+ }
+
+ $opensslOutput = new Swift_ByteStream_TemporaryFileByteStream();
+ $verify = openssl_pkcs7_verify($messageStream->getPath(), null, $opensslOutput->getPath(), array($this->samplesDir.'smime/ca.crt'));
+
+ if (false === $verify) {
+ $this->fail('Verification of the message failed.');
+
+ return false;
+ } elseif (-1 === $verify) {
+ $this->fail(sprintf('Verification of the message failed. Internal error "%s".', openssl_error_string()));
+
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function getBoundary($contentType)
+ {
+ if (!preg_match('/boundary=("[^"]+"|(?:[^\s]+|$))/is', $contentType, $contentTypeData)) {
+ $this->fail('Failed to find Boundary parameter');
+
+ return false;
+ }
+
+ return trim($contentTypeData[1], '"');
+ }
+
+ protected function newFilteredStream()
+ {
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $messageStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
+ $messageStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
+
+ return $messageStream;
+ }
+
+ protected static function getBodyOfMessage($message)
+ {
+ return substr($message, strpos($message, "\r\n\r\n"));
+ }
+
+ /**
+ * Strips of the sender headers and Mime-Version.
+ *
+ * @param Swift_ByteStream_TemporaryFileByteStream $messageStream
+ * @param Swift_ByteStream_TemporaryFileByteStream $inputStream
+ */
+ protected function cleanMessage($content)
+ {
+ $newContent = '';
+
+ $headers = self::getHeadersOfMessage($content);
+ foreach ($headers as $headerName => $value) {
+ if (!in_array($headerName, array('content-type', 'content-transfer-encoding', 'content-disposition'))) {
+ continue;
+ }
+
+ $headerName = explode('-', $headerName);
+ $headerName = array_map('ucfirst', $headerName);
+ $headerName = implode('-', $headerName);
+
+ if (strlen($value) > 62) {
+ $value = wordwrap($value, 62, "\n ");
+ }
+
+ $newContent .= "$headerName: $value\r\n";
+ }
+
+ return $newContent."\r\n".ltrim(self::getBodyOfMessage($content));
+ }
+
+ /**
+ * Returns the headers of the message.
+ *
+ * Header-names are lowercase.
+ *
+ * @param string $message
+ *
+ * @return array
+ */
+ protected static function getHeadersOfMessage($message)
+ {
+ $headersPosEnd = strpos($message, "\r\n\r\n");
+ $headerData = substr($message, 0, $headersPosEnd);
+ $headerLines = explode("\r\n", $headerData);
+
+ if (empty($headerLines)) {
+ return array();
+ }
+
+ $headers = array();
+
+ foreach ($headerLines as $headerLine) {
+ if (ctype_space($headerLines[0]) || false === strpos($headerLine, ':')) {
+ $headers[$currentHeaderName] .= ' '.trim($headerLine);
+ continue;
+ }
+
+ $header = explode(':', $headerLine, 2);
+ $currentHeaderName = strtolower($header[0]);
+ $headers[$currentHeaderName] = trim($header[1]);
+ }
+
+ return $headers;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php
new file mode 100644
index 00000000..e4d4f48d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php
@@ -0,0 +1,131 @@
+_createFilter(array(0x61, 0x62), array(0x63, 0x64));
+ $this->assertEquals(
+ array(0x59, 0x60, 0x63, 0x64, 0x65),
+ $filter->filter(array(0x59, 0x60, 0x61, 0x62, 0x65))
+ );
+ }
+
+ public function testShouldBufferReturnsTrueIfPartialMatchAtEndOfBuffer()
+ {
+ $filter = $this->_createFilter(array(0x61, 0x62), array(0x63, 0x64));
+ $this->assertTrue($filter->shouldBuffer(array(0x59, 0x60, 0x61)),
+ '%s: Filter should buffer since 0x61 0x62 is the needle and the ending '.
+ '0x61 could be from 0x61 0x62'
+ );
+ }
+
+ public function testFilterCanMakeMultipleReplacements()
+ {
+ $filter = $this->_createFilter(array(array(0x61), array(0x62)), array(0x63));
+ $this->assertEquals(
+ array(0x60, 0x63, 0x60, 0x63, 0x60),
+ $filter->filter(array(0x60, 0x61, 0x60, 0x62, 0x60))
+ );
+ }
+
+ public function testMultipleReplacementsCanBeDifferent()
+ {
+ $filter = $this->_createFilter(array(array(0x61), array(0x62)), array(array(0x63), array(0x64)));
+ $this->assertEquals(
+ array(0x60, 0x63, 0x60, 0x64, 0x60),
+ $filter->filter(array(0x60, 0x61, 0x60, 0x62, 0x60))
+ );
+ }
+
+ public function testShouldBufferReturnsFalseIfPartialMatchNotAtEndOfString()
+ {
+ $filter = $this->_createFilter(array(0x0D, 0x0A), array(0x0A));
+ $this->assertFalse($filter->shouldBuffer(array(0x61, 0x62, 0x0D, 0x0A, 0x63)),
+ '%s: Filter should not buffer since x0Dx0A is the needle and is not at EOF'
+ );
+ }
+
+ public function testShouldBufferReturnsTrueIfAnyOfMultipleMatchesAtEndOfString()
+ {
+ $filter = $this->_createFilter(array(array(0x61, 0x62), array(0x63)), array(0x64));
+ $this->assertTrue($filter->shouldBuffer(array(0x59, 0x60, 0x61)),
+ '%s: Filter should buffer since 0x61 0x62 is a needle and the ending '.
+ '0x61 could be from 0x61 0x62'
+ );
+ }
+
+ public function testConvertingAllLineEndingsToCRLFWhenInputIsLF()
+ {
+ $filter = $this->_createFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ );
+
+ $this->assertEquals(
+ array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63),
+ $filter->filter(array(0x60, 0x0A, 0x61, 0x0A, 0x62, 0x0A, 0x63))
+ );
+ }
+
+ public function testConvertingAllLineEndingsToCRLFWhenInputIsCR()
+ {
+ $filter = $this->_createFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ );
+
+ $this->assertEquals(
+ array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63),
+ $filter->filter(array(0x60, 0x0D, 0x61, 0x0D, 0x62, 0x0D, 0x63))
+ );
+ }
+
+ public function testConvertingAllLineEndingsToCRLFWhenInputIsCRLF()
+ {
+ $filter = $this->_createFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ );
+
+ $this->assertEquals(
+ array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63),
+ $filter->filter(array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63))
+ );
+ }
+
+ public function testConvertingAllLineEndingsToCRLFWhenInputIsLFCR()
+ {
+ $filter = $this->_createFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ );
+
+ $this->assertEquals(
+ array(0x60, 0x0D, 0x0A, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x0D, 0x0A, 0x63),
+ $filter->filter(array(0x60, 0x0A, 0x0D, 0x61, 0x0A, 0x0D, 0x62, 0x0A, 0x0D, 0x63))
+ );
+ }
+
+ public function testConvertingAllLineEndingsToCRLFWhenInputContainsLFLF()
+ {
+ //Lighthouse Bug #23
+
+ $filter = $this->_createFilter(
+ array(array(0x0D, 0x0A), array(0x0D), array(0x0A)),
+ array(array(0x0A), array(0x0A), array(0x0D, 0x0A))
+ );
+
+ $this->assertEquals(
+ array(0x60, 0x0D, 0x0A, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x0D, 0x0A, 0x63),
+ $filter->filter(array(0x60, 0x0A, 0x0A, 0x61, 0x0A, 0x0A, 0x62, 0x0A, 0x0A, 0x63))
+ );
+ }
+
+ // -- Creation methods
+
+ private function _createFilter($search, $replace)
+ {
+ return new Swift_StreamFilters_ByteArrayReplacementFilter($search, $replace);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php
new file mode 100644
index 00000000..bd44f5c7
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php
@@ -0,0 +1,38 @@
+_createFactory();
+ $this->assertInstanceof(
+ 'Swift_StreamFilters_StringReplacementFilter',
+ $factory->createFilter('a', 'b')
+ );
+ }
+
+ public function testSameInstancesAreCached()
+ {
+ $factory = $this->_createFactory();
+ $filter1 = $factory->createFilter('a', 'b');
+ $filter2 = $factory->createFilter('a', 'b');
+ $this->assertSame($filter1, $filter2, '%s: Instances should be cached');
+ }
+
+ public function testDifferingInstancesAreNotCached()
+ {
+ $factory = $this->_createFactory();
+ $filter1 = $factory->createFilter('a', 'b');
+ $filter2 = $factory->createFilter('a', 'c');
+ $this->assertNotEquals($filter1, $filter2,
+ '%s: Differing instances should not be cached'
+ );
+ }
+
+ // -- Creation methods
+
+ private function _createFactory()
+ {
+ return new Swift_StreamFilters_StringReplacementFilterFactory();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php
new file mode 100644
index 00000000..7a98a2f2
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php
@@ -0,0 +1,55 @@
+_createFilter('foo', 'bar');
+ $this->assertEquals('XbarYbarZ', $filter->filter('XfooYfooZ'));
+ }
+
+ public function testShouldBufferReturnsTrueIfPartialMatchAtEndOfBuffer()
+ {
+ $filter = $this->_createFilter('foo', 'bar');
+ $this->assertTrue($filter->shouldBuffer('XfooYf'),
+ '%s: Filter should buffer since "foo" is the needle and the ending '.
+ '"f" could be from "foo"'
+ );
+ }
+
+ public function testFilterCanMakeMultipleReplacements()
+ {
+ $filter = $this->_createFilter(array('a', 'b'), 'foo');
+ $this->assertEquals('XfooYfooZ', $filter->filter('XaYbZ'));
+ }
+
+ public function testMultipleReplacementsCanBeDifferent()
+ {
+ $filter = $this->_createFilter(array('a', 'b'), array('foo', 'zip'));
+ $this->assertEquals('XfooYzipZ', $filter->filter('XaYbZ'));
+ }
+
+ public function testShouldBufferReturnsFalseIfPartialMatchNotAtEndOfString()
+ {
+ $filter = $this->_createFilter("\r\n", "\n");
+ $this->assertFalse($filter->shouldBuffer("foo\r\nbar"),
+ '%s: Filter should not buffer since x0Dx0A is the needle and is not at EOF'
+ );
+ }
+
+ public function testShouldBufferReturnsTrueIfAnyOfMultipleMatchesAtEndOfString()
+ {
+ $filter = $this->_createFilter(array('foo', 'zip'), 'bar');
+ $this->assertTrue($filter->shouldBuffer('XfooYzi'),
+ '%s: Filter should buffer since "zip" is a needle and the ending '.
+ '"zi" could be from "zip"'
+ );
+ }
+
+ // -- Creation methods
+
+ private function _createFilter($search, $replace)
+ {
+ return new Swift_StreamFilters_StringReplacementFilter($search, $replace);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php
new file mode 100644
index 00000000..121aaba0
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php
@@ -0,0 +1,560 @@
+_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $listener = $this->getMockery('Swift_Events_EventListener');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $dispatcher->shouldReceive('bindEventListener')
+ ->once()
+ ->with($listener);
+
+ $smtp->registerPlugin($listener);
+ }
+
+ public function testSendingDispatchesBeforeSendEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $message = $this->_createMessage();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('mark@swiftmailer.org' => 'Mark'));
+ $dispatcher->shouldReceive('createSendEvent')
+ ->once()
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeSendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(1, $smtp->send($message));
+ }
+
+ public function testSendingDispatchesSendEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $message = $this->_createMessage();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('mark@swiftmailer.org' => 'Mark'));
+ $dispatcher->shouldReceive('createSendEvent')
+ ->once()
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'sendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(1, $smtp->send($message));
+ }
+
+ public function testSendEventCapturesFailures()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('mark@swiftmailer.org' => 'Mark'));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("500 Not now\r\n");
+ $dispatcher->shouldReceive('createSendEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'sendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ $evt->shouldReceive('setFailedRecipients')
+ ->once()
+ ->with(array('mark@swiftmailer.org'));
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(0, $smtp->send($message));
+ }
+
+ public function testSendEventHasResultFailedIfAllFailures()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('mark@swiftmailer.org' => 'Mark'));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("500 Not now\r\n");
+ $dispatcher->shouldReceive('createSendEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'sendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ $evt->shouldReceive('setResult')
+ ->once()
+ ->with(Swift_Events_SendEvent::RESULT_FAILED);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(0, $smtp->send($message));
+ }
+
+ public function testSendEventHasResultTentativeIfSomeFailures()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'mark@swiftmailer.org' => 'Mark',
+ 'chris@site.tld' => 'Chris',
+ ));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("500 Not now\r\n");
+ $dispatcher->shouldReceive('createSendEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'sendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ $evt->shouldReceive('setResult')
+ ->once()
+ ->with(Swift_Events_SendEvent::RESULT_TENTATIVE);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(1, $smtp->send($message));
+ }
+
+ public function testSendEventHasResultSuccessIfNoFailures()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'mark@swiftmailer.org' => 'Mark',
+ 'chris@site.tld' => 'Chris',
+ ));
+ $dispatcher->shouldReceive('createSendEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'sendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ $evt->shouldReceive('setResult')
+ ->once()
+ ->with(Swift_Events_SendEvent::RESULT_SUCCESS);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(2, $smtp->send($message));
+ }
+
+ public function testCancellingEventBubbleBeforeSendStopsEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_SendEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('chris@swiftmailer.org' => null));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('mark@swiftmailer.org' => 'Mark'));
+ $dispatcher->shouldReceive('createSendEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeSendPerformed');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(true);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(0, $smtp->send($message));
+ }
+
+ public function testStartingTransportDispatchesTransportChangeEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'transportStarted');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(false);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ }
+
+ public function testStartingTransportDispatchesBeforeTransportChangeEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeTransportStarted');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(false);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ }
+
+ public function testCancellingBubbleBeforeTransportStartStopsEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeTransportStarted');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(true);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+
+ $this->assertFalse($smtp->isStarted(),
+ '%s: Transport should not be started since event bubble was cancelled'
+ );
+ }
+
+ public function testStoppingTransportDispatchesTransportChangeEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'transportStopped');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->stop();
+ }
+
+ public function testStoppingTransportDispatchesBeforeTransportChangeEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent')->shouldIgnoreMissing();
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeTransportStopped');
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->stop();
+ }
+
+ public function testCancellingBubbleBeforeTransportStoppedStopsEvent()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportChangeEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $hasRun = false;
+ $dispatcher->shouldReceive('createTransportChangeEvent')
+ ->atLeast()->once()
+ ->with($smtp)
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'beforeTransportStopped')
+ ->andReturnUsing(function () use (&$hasRun) {
+ $hasRun = true;
+ });
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->zeroOrMoreTimes();
+ $evt->shouldReceive('bubbleCancelled')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$hasRun) {
+ return $hasRun;
+ });
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->stop();
+
+ $this->assertTrue($smtp->isStarted(),
+ '%s: Transport should not be stopped since event bubble was cancelled'
+ );
+ }
+
+ public function testResponseEventsAreGenerated()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_ResponseEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createResponseEvent')
+ ->atLeast()->once()
+ ->with($smtp, \Mockery::any(), \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->atLeast()->once()
+ ->with($evt, 'responseReceived');
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ }
+
+ public function testCommandEventsAreGenerated()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_CommandEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $dispatcher->shouldReceive('createCommandEvent')
+ ->once()
+ ->with($smtp, \Mockery::any(), \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'commandSent');
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ }
+
+ public function testExceptionsCauseExceptionEvents()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportExceptionEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $buf->shouldReceive('readLine')
+ ->atLeast()->once()
+ ->andReturn("503 I'm sleepy, go away!\r\n");
+ $dispatcher->shouldReceive('createTransportExceptionEvent')
+ ->zeroOrMoreTimes()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->once()
+ ->with($evt, 'exceptionThrown');
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(false);
+
+ try {
+ $smtp->start();
+ $this->fail('TransportException should be thrown on invalid response');
+ } catch (Swift_TransportException $e) {
+ }
+ }
+
+ public function testExceptionBubblesCanBeCancelled()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher(false);
+ $evt = $this->getMockery('Swift_Events_TransportExceptionEvent');
+ $smtp = $this->_getTransport($buf, $dispatcher);
+
+ $buf->shouldReceive('readLine')
+ ->atLeast()->once()
+ ->andReturn("503 I'm sleepy, go away!\r\n");
+ $dispatcher->shouldReceive('createTransportExceptionEvent')
+ ->twice()
+ ->with($smtp, \Mockery::any())
+ ->andReturn($evt);
+ $dispatcher->shouldReceive('dispatchEvent')
+ ->twice()
+ ->with($evt, 'exceptionThrown');
+ $evt->shouldReceive('bubbleCancelled')
+ ->atLeast()->once()
+ ->andReturn(true);
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ }
+
+ // -- Creation Methods
+
+ protected function _createEventDispatcher($stub = true)
+ {
+ return $this->getMockery('Swift_Events_EventDispatcher')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpTest.php
new file mode 100644
index 00000000..f49b489e
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpTest.php
@@ -0,0 +1,1249 @@
+_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started');
+ $smtp->start();
+ $this->assertTrue($smtp->isStarted(), '%s: start() should have started connection');
+ } catch (Exception $e) {
+ $this->fail('220 is a valid SMTP greeting and should be accepted');
+ }
+ }
+
+ public function testBadGreetingCausesException()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("554 I'm busy\r\n");
+ $this->_finishBuffer($buf);
+ try {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started');
+ $smtp->start();
+ $this->fail('554 greeting indicates an error and should cause an exception');
+ } catch (Exception $e) {
+ $this->assertFalse($smtp->isStarted(), '%s: start() should have failed');
+ }
+ }
+
+ public function testStartSendsHeloToInitiate()
+ {
+ /* -- RFC 2821, 3.2.
+
+ 3.2 Client Initiation
+
+ Once the server has sent the welcoming message and the client has
+ received it, the client normally sends the EHLO command to the
+ server, indicating the client's identity. In addition to opening the
+ session, use of EHLO indicates that the client is able to process
+ service extensions and requests that the server provide a list of the
+ extensions it supports. Older SMTP systems which are unable to
+ support service extensions and contemporary clients which do not
+ require service extensions in the mail session being initiated, MAY
+ use HELO instead of EHLO. Servers MUST NOT return the extended
+ EHLO-style response to a HELO command. For a particular connection
+ attempt, if the server returns a "command not recognized" response to
+ EHLO, the client SHOULD be able to fall back and send HELO.
+
+ In the EHLO command the host sending the command identifies itself;
+ the command may be interpreted as saying "Hello, I am " (and,
+ in the case of EHLO, "and I support service extension requests").
+
+ -- RFC 2281, 4.1.1.1.
+
+ ehlo = "EHLO" SP Domain CRLF
+ helo = "HELO" SP Domain CRLF
+
+ -- RFC 2821, 4.3.2.
+
+ EHLO or HELO
+ S: 250
+ E: 504, 550
+
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^HELO .*?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 ServerName'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ } catch (Exception $e) {
+ $this->fail('Starting SMTP should send HELO and accept 250 response');
+ }
+ }
+
+ public function testInvalidHeloResponseCausesException()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^HELO .*?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('504 WTF'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started');
+ $smtp->start();
+ $this->fail('Non 250 HELO response should raise Exception');
+ } catch (Exception $e) {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP start() should have failed');
+ }
+ }
+
+ public function testDomainNameIsPlacedInHelo()
+ {
+ /* -- RFC 2821, 4.1.4.
+
+ The SMTP client MUST, if possible, ensure that the domain parameter
+ to the EHLO command is a valid principal host name (not a CNAME or MX
+ name) for its host. If this is not possible (e.g., when the client's
+ address is dynamically assigned and the client does not have an
+ obvious name), an address literal SHOULD be substituted for the
+ domain name and supplemental information provided that will assist in
+ identifying the client.
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("HELO mydomain.com\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 ServerName'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->setLocalDomain('mydomain.com');
+ $smtp->start();
+ }
+
+ public function testSuccessfulMailCommand()
+ {
+ /* -- RFC 2821, 3.3.
+
+ There are three steps to SMTP mail transactions. The transaction
+ starts with a MAIL command which gives the sender identification.
+
+ .....
+
+ The first step in the procedure is the MAIL command.
+
+ MAIL FROM: [SP ]
+
+ -- RFC 2821, 4.1.1.2.
+
+ Syntax:
+
+ "MAIL FROM:" ("<>" / Reverse-Path)
+ [SP Mail-parameters] CRLF
+ -- RFC 2821, 4.1.2.
+
+ Reverse-path = Path
+ Forward-path = Path
+ Path = "<" [ A-d-l ":" ] Mailbox ">"
+ A-d-l = At-domain *( "," A-d-l )
+ ; Note that this form, the so-called "source route",
+ ; MUST BE accepted, SHOULD NOT be generated, and SHOULD be
+ ; ignored.
+ At-domain = "@" domain
+
+ -- RFC 2821, 4.3.2.
+
+ MAIL
+ S: 250
+ E: 552, 451, 452, 550, 553, 503
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ } catch (Exception $e) {
+ $this->fail('MAIL FROM should accept a 250 response');
+ }
+ }
+
+ public function testInvalidResponseCodeFromMailCausesException()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('553 Bad'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ $this->fail('MAIL FROM should accept a 250 response');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testSenderIsPreferredOverFrom()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getSender')
+ ->once()
+ ->andReturn(array('another@domain.com' => 'Someone'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testReturnPathIsPreferredOverSender()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getSender')
+ ->once()
+ ->andReturn(array('another@domain.com' => 'Someone'));
+ $message->shouldReceive('getReturnPath')
+ ->once()
+ ->andReturn('more@domain.com');
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testSuccessfulRcptCommandWith250Response()
+ {
+ /* -- RFC 2821, 3.3.
+
+ The second step in the procedure is the RCPT command.
+
+ RCPT TO: [ SP ]
+
+ The first or only argument to this command includes a forward-path
+ (normally a mailbox and domain, always surrounded by "<" and ">"
+ brackets) identifying one recipient. If accepted, the SMTP server
+ returns a 250 OK reply and stores the forward-path. If the recipient
+ is known not to be a deliverable address, the SMTP server returns a
+ 550 reply, typically with a string such as "no such user - " and the
+ mailbox name (other circumstances and reply codes are possible).
+ This step of the procedure can be repeated any number of times.
+
+ -- RFC 2821, 4.1.1.3.
+
+ This command is used to identify an individual recipient of the mail
+ data; multiple recipients are specified by multiple use of this
+ command. The argument field contains a forward-path and may contain
+ optional parameters.
+
+ The forward-path normally consists of the required destination
+ mailbox. Sending systems SHOULD not generate the optional list of
+ hosts known as a source route.
+
+ .......
+
+ "RCPT TO:" ("" / "" / Forward-Path)
+ [SP Rcpt-parameters] CRLF
+
+ -- RFC 2821, 4.2.2.
+
+ 250 Requested mail action okay, completed
+ 251 User not local; will forward to
+ (See section 3.4)
+ 252 Cannot VRFY user, but will accept message and attempt
+ delivery
+
+ -- RFC 2821, 4.3.2.
+
+ RCPT
+ S: 250, 251 (but see section 3.4 for discussion of 251 and 551)
+ E: 550, 551, 552, 553, 450, 451, 452, 503, 550
+ */
+
+ //We'll treat 252 as accepted since it isn't really a failure
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ } catch (Exception $e) {
+ $this->fail('RCPT TO should accept a 250 response');
+ }
+ }
+
+ public function testMailFromCommandIsOnlySentOncePerMessage()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->never()
+ ->with("MAIL FROM:\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testMultipleRecipientsSendsMultipleRcpt()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array(
+ 'foo@bar' => null,
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testCcRecipientsSendsMultipleRcpt()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getCc')
+ ->once()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testSendReturnsNumberOfSuccessfulRecipients()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getCc')
+ ->once()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('501 Nobody here'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(2, $smtp->send($message),
+ '%s: 1 of 3 recipients failed so 2 should be returned'
+ );
+ }
+
+ public function testRsetIsSentIfNoSuccessfulRecipients()
+ {
+ /* --RFC 2821, 4.1.1.5.
+
+ This command specifies that the current mail transaction will be
+ aborted. Any stored sender, recipients, and mail data MUST be
+ discarded, and all buffers and state tables cleared. The receiver
+ MUST send a "250 OK" reply to a RSET command with no arguments. A
+ reset command may be issued by the client at any time.
+
+ -- RFC 2821, 4.3.2.
+
+ RSET
+ S: 250
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('503 Bad'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RSET\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(0, $smtp->send($message),
+ '%s: 1 of 1 recipients failed so 0 should be returned'
+ );
+ }
+
+ public function testSuccessfulDataCommand()
+ {
+ /* -- RFC 2821, 3.3.
+
+ The third step in the procedure is the DATA command (or some
+ alternative specified in a service extension).
+
+ DATA
+
+ If accepted, the SMTP server returns a 354 Intermediate reply and
+ considers all succeeding lines up to but not including the end of
+ mail data indicator to be the message text.
+
+ -- RFC 2821, 4.1.1.4.
+
+ The receiver normally sends a 354 response to DATA, and then treats
+ the lines (strings ending in sequences, as described in
+ section 2.3.7) following the command as mail data from the sender.
+ This command causes the mail data to be appended to the mail data
+ buffer. The mail data may contain any of the 128 ASCII character
+ codes, although experience has indicated that use of control
+ characters other than SP, HT, CR, and LF may cause problems and
+ SHOULD be avoided when possible.
+
+ -- RFC 2821, 4.3.2.
+
+ DATA
+ I: 354 -> data -> S: 250
+ E: 552, 554, 451, 452
+ E: 451, 554, 503
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("DATA\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('354 Go ahead'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ } catch (Exception $e) {
+ $this->fail('354 is the expected response to DATA');
+ }
+ }
+
+ public function testBadDataResponseCausesException()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("DATA\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('451 Bad'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ $this->fail('354 is the expected response to DATA (not observed)');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testMessageIsStreamedToBufferForData()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("DATA\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('354 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("\r\n.\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 OK'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testBadResponseAfterDataTransmissionCausesException()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->once()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->once()
+ ->andReturn(array('foo@bar' => null));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("DATA\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('354 OK'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("\r\n.\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('554 Error'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ $smtp->send($message);
+ $this->fail('250 is the expected response after a DATA transmission (not observed)');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testBccRecipientsAreRemovedFromHeaders()
+ {
+ /* -- RFC 2821, 7.2.
+
+ Addresses that do not appear in the message headers may appear in the
+ RCPT commands to an SMTP server for a number of reasons. The two
+ most common involve the use of a mailing address as a "list exploder"
+ (a single address that resolves into multiple addresses) and the
+ appearance of "blind copies". Especially when more than one RCPT
+ command is present, and in order to avoid defeating some of the
+ purpose of these mechanisms, SMTP clients and servers SHOULD NOT copy
+ the full set of RCPT command arguments into the headers, either as
+ part of trace headers or as informational or private-extension
+ headers. Since this rule is often violated in practice, and cannot
+ be enforced, sending SMTP systems that are aware of "bcc" use MAY
+ find it helpful to send each blind copy as a separate message
+ transaction containing only a single RCPT command.
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getBcc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array());
+ $message->shouldReceive('setBcc')
+ ->zeroOrMoreTimes();
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testEachBccRecipientIsSentASeparateMessage()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getBcc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $message->shouldReceive('setBcc')
+ ->atLeast()->once()
+ ->with(array());
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array('zip@button' => 'Zip Button'));
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array('test@domain' => 'Test user'));
+ $message->shouldReceive('setBcc')
+ ->atLeast()->once()
+ ->with(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(1);
+ $buf->shouldReceive('readLine')->once()->with(1)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(2);
+ $buf->shouldReceive('readLine')->once()->with(2)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("DATA\r\n")->andReturn(3);
+ $buf->shouldReceive('readLine')->once()->with(3)->andReturn("354 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("\r\n.\r\n")->andReturn(4);
+ $buf->shouldReceive('readLine')->once()->with(4)->andReturn("250 OK\r\n");
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(5);
+ $buf->shouldReceive('readLine')->once()->with(5)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(6);
+ $buf->shouldReceive('readLine')->once()->with(6)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("DATA\r\n")->andReturn(7);
+ $buf->shouldReceive('readLine')->once()->with(7)->andReturn("354 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("\r\n.\r\n")->andReturn(8);
+ $buf->shouldReceive('readLine')->once()->with(8)->andReturn("250 OK\r\n");
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(9);
+ $buf->shouldReceive('readLine')->once()->with(9)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(10);
+ $buf->shouldReceive('readLine')->once()->with(10)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("DATA\r\n")->andReturn(11);
+ $buf->shouldReceive('readLine')->once()->with(11)->andReturn("354 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("\r\n.\r\n")->andReturn(12);
+ $buf->shouldReceive('readLine')->once()->with(12)->andReturn("250 OK\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(3, $smtp->send($message));
+ }
+
+ public function testMessageStateIsRestoredOnFailure()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getBcc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array());
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("DATA\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn("451 No\r\n");
+
+ $this->_finishBuffer($buf);
+
+ $smtp->start();
+ try {
+ $smtp->send($message);
+ $this->fail('A bad response was given so exception is expected');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testStopSendsQuitCommand()
+ {
+ /* -- RFC 2821, 4.1.1.10.
+
+ This command specifies that the receiver MUST send an OK reply, and
+ then close the transmission channel.
+
+ The receiver MUST NOT intentionally close the transmission channel
+ until it receives and replies to a QUIT command (even if there was an
+ error). The sender MUST NOT intentionally close the transmission
+ channel until it sends a QUIT command and SHOULD wait until it
+ receives the reply (even if there was an error response to a previous
+ command). If the connection is closed prematurely due to violations
+ of the above or system or network failure, the server MUST cancel any
+ pending transaction, but not undo any previously completed
+ transaction, and generally MUST act as if the command or transaction
+ in progress had received a temporary error (i.e., a 4yz response).
+
+ The QUIT command may be issued at any time.
+
+ Syntax:
+ "QUIT" CRLF
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("QUIT\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("221 Bye\r\n");
+ $buf->shouldReceive('terminate')
+ ->once();
+
+ $this->_finishBuffer($buf);
+
+ $this->assertFalse($smtp->isStarted());
+ $smtp->start();
+ $this->assertTrue($smtp->isStarted());
+ $smtp->stop();
+ $this->assertFalse($smtp->isStarted());
+ }
+
+ public function testBufferCanBeFetched()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ref = $smtp->getBuffer();
+ $this->assertEquals($buf, $ref);
+ }
+
+ public function testBufferCanBeWrittenToUsingExecuteCommand()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with("FOO\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with(1)
+ ->andReturn("250 OK\r\n");
+
+ $res = $smtp->executeCommand("FOO\r\n");
+ $this->assertEquals("250 OK\r\n", $res);
+ }
+
+ public function testResponseCodesAreValidated()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with("FOO\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with(1)
+ ->andReturn("551 Not ok\r\n");
+
+ try {
+ $smtp->executeCommand("FOO\r\n", array(250, 251));
+ $this->fail('A 250 or 251 response was needed but 551 was returned.');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testFailedRecipientsCanBeCollectedByReference()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('getBcc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+ $message->shouldReceive('setBcc')
+ ->atLeast()->once()
+ ->with(array());
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array('zip@button' => 'Zip Button'));
+ $message->shouldReceive('setBcc')
+ ->once()
+ ->with(array('test@domain' => 'Test user'));
+ $message->shouldReceive('setBcc')
+ ->atLeast()->once()
+ ->with(array(
+ 'zip@button' => 'Zip Button',
+ 'test@domain' => 'Test user',
+ ));
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(1);
+ $buf->shouldReceive('readLine')->once()->with(1)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(2);
+ $buf->shouldReceive('readLine')->once()->with(2)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("DATA\r\n")->andReturn(3);
+ $buf->shouldReceive('readLine')->once()->with(3)->andReturn("354 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("\r\n.\r\n")->andReturn(4);
+ $buf->shouldReceive('readLine')->once()->with(4)->andReturn("250 OK\r\n");
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(5);
+ $buf->shouldReceive('readLine')->once()->with(5)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(6);
+ $buf->shouldReceive('readLine')->once()->with(6)->andReturn("500 Bad\r\n");
+ $buf->shouldReceive('write')->once()->with("RSET\r\n")->andReturn(7);
+ $buf->shouldReceive('readLine')->once()->with(7)->andReturn("250 OK\r\n");
+
+ $buf->shouldReceive('write')->once()->with("MAIL FROM:\r\n")->andReturn(9);
+ $buf->shouldReceive('readLine')->once()->with(9)->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')->once()->with("RCPT TO:\r\n")->andReturn(10);
+ $buf->shouldReceive('readLine')->once()->with(10)->andReturn("500 Bad\r\n");
+ $buf->shouldReceive('write')->once()->with("RSET\r\n")->andReturn(11);
+ $buf->shouldReceive('readLine')->once()->with(11)->andReturn("250 OK\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $this->assertEquals(1, $smtp->send($message, $failures));
+ $this->assertEquals(array('zip@button', 'test@domain'), $failures,
+ '%s: Failures should be caught in an array'
+ );
+ }
+
+ public function testSendingRegeneratesMessageId()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $message = $this->_createMessage();
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain.com' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+ $message->shouldReceive('generateId')
+ ->once();
+
+ $this->_finishBuffer($buf);
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ protected function _getBuffer()
+ {
+ return $this->getMockery('Swift_Transport_IoBuffer')->shouldIgnoreMissing();
+ }
+
+ protected function _createMessage()
+ {
+ return $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ }
+
+ protected function _finishBuffer($buf)
+ {
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with(0)
+ ->andReturn('220 server.com foo'."\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with('~^(EH|HE)LO .*?\r\n$~D')
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn('250 ServerName'."\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with('~^MAIL FROM:<.*?>\r\n$~D')
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with('~^RCPT TO:<.*?>\r\n$~D')
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with("DATA\r\n")
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn("354 OK\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with("\r\n.\r\n")
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->with("RSET\r\n")
+ ->andReturn($x = uniqid());
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->with($x)
+ ->andReturn("250 OK\r\n");
+
+ $buf->shouldReceive('write')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ $buf->shouldReceive('readLine')
+ ->zeroOrMoreTimes()
+ ->andReturn(false);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php
new file mode 100644
index 00000000..f64b0716
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php
@@ -0,0 +1,66 @@
+_agent = $this->getMockery('Swift_Transport_SmtpAgent')->shouldIgnoreMissing();
+ }
+
+ public function testKeywordIsCramMd5()
+ {
+ /* -- RFC 2195, 2.
+ The authentication type associated with CRAM is "CRAM-MD5".
+ */
+
+ $cram = $this->_getAuthenticator();
+ $this->assertEquals('CRAM-MD5', $cram->getAuthKeyword());
+ }
+
+ public function testSuccessfulAuthentication()
+ {
+ $cram = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("AUTH CRAM-MD5\r\n", array(334))
+ ->andReturn('334 '.base64_encode('')."\r\n");
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(\Mockery::any(), array(235));
+
+ $this->assertTrue($cram->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: The buffer accepted all commands authentication should succeed'
+ );
+ }
+
+ public function testAuthenticationFailureSendRsetAndReturnFalse()
+ {
+ $cram = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("AUTH CRAM-MD5\r\n", array(334))
+ ->andReturn('334 '.base64_encode('')."\r\n");
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(\Mockery::any(), array(235))
+ ->andThrow(new Swift_TransportException(''));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("RSET\r\n", array(250));
+
+ $this->assertFalse($cram->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: Authentication fails, so RSET should be sent'
+ );
+ }
+
+ // -- Private helpers
+
+ private function _getAuthenticator()
+ {
+ return new Swift_Transport_Esmtp_Auth_CramMd5Authenticator();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php
new file mode 100644
index 00000000..fc6e8069
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php
@@ -0,0 +1,66 @@
+_agent = $this->getMockery('Swift_Transport_SmtpAgent')->shouldIgnoreMissing();
+ }
+
+ public function testKeywordIsLogin()
+ {
+ $login = $this->_getAuthenticator();
+ $this->assertEquals('LOGIN', $login->getAuthKeyword());
+ }
+
+ public function testSuccessfulAuthentication()
+ {
+ $login = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("AUTH LOGIN\r\n", array(334));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(base64_encode('jack')."\r\n", array(334));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(base64_encode('pass')."\r\n", array(235));
+
+ $this->assertTrue($login->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: The buffer accepted all commands authentication should succeed'
+ );
+ }
+
+ public function testAuthenticationFailureSendRsetAndReturnFalse()
+ {
+ $login = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("AUTH LOGIN\r\n", array(334));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(base64_encode('jack')."\r\n", array(334));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(base64_encode('pass')."\r\n", array(235))
+ ->andThrow(new Swift_TransportException(''));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("RSET\r\n", array(250));
+
+ $this->assertFalse($login->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: Authentication fails, so RSET should be sent'
+ );
+ }
+
+ // -- Private helpers
+
+ private function _getAuthenticator()
+ {
+ return new Swift_Transport_Esmtp_Auth_LoginAuthenticator();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/NTLMAuthenticatorTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/NTLMAuthenticatorTest.php
new file mode 100644
index 00000000..09ace834
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/NTLMAuthenticatorTest.php
@@ -0,0 +1,235 @@
+markTestSkipped(
+ 'One of the required functions is not available.'
+ );
+ }
+ }
+
+ public function testKeywordIsNtlm()
+ {
+ $login = $this->_getAuthenticator();
+ $this->assertEquals('NTLM', $login->getAuthKeyword());
+ }
+
+ public function testMessage1Generator()
+ {
+ $login = $this->_getAuthenticator();
+ $message1 = $this->_invokePrivateMethod('createMessage1', $login);
+
+ $this->assertEquals($this->_message1, bin2hex($message1),
+ '%s: We send the smallest ntlm message which should never fail.'
+ );
+ }
+
+ public function testLMv1Generator()
+ {
+ $password = 'test1234';
+ $challenge = 'b019d38bad875c9d';
+ $lmv1 = '1879f60127f8a877022132ec221bcbf3ca016a9f76095606';
+
+ $login = $this->_getAuthenticator();
+ $lmv1Result = $this->_invokePrivateMethod('createLMPassword', $login, array($password, $this->hex2bin($challenge)));
+
+ $this->assertEquals($lmv1, bin2hex($lmv1Result),
+ '%s: The keys should be the same cause we use the same values to generate them.'
+ );
+ }
+
+ public function testLMv2Generator()
+ {
+ $username = 'user';
+ $password = 'SecREt01';
+ $domain = 'DOMAIN';
+ $challenge = '0123456789abcdef';
+ $lmv2 = 'd6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344';
+
+ $login = $this->_getAuthenticator();
+ $lmv2Result = $this->_invokePrivateMethod('createLMv2Password', $login, array($password, $username, $domain, $this->hex2bin($challenge), $this->hex2bin('ffffff0011223344')));
+
+ $this->assertEquals($lmv2, bin2hex($lmv2Result),
+ '%s: The keys should be the same cause we use the same values to generate them.'
+ );
+ }
+
+ public function testMessage3v1Generator()
+ {
+ $username = 'test';
+ $domain = 'TESTNT';
+ $workstation = 'MEMBER';
+ $lmResponse = '1879f60127f8a877022132ec221bcbf3ca016a9f76095606';
+ $ntlmResponse = 'e6285df3287c5d194f84df1a94817c7282d09754b6f9e02a';
+ $message3T = '4e544c4d5353500003000000180018006000000018001800780000000c000c0040000000080008004c0000000c000c0054000000000000009a0000000102000054004500530054004e00540074006500730074004d0045004d004200450052001879f60127f8a877022132ec221bcbf3ca016a9f76095606e6285df3287c5d194f84df1a94817c7282d09754b6f9e02a';
+
+ $login = $this->_getAuthenticator();
+ $message3 = $this->_invokePrivateMethod('createMessage3', $login, array($domain, $username, $workstation, $this->hex2bin($lmResponse), $this->hex2bin($ntlmResponse)));
+
+ $this->assertEquals($message3T, bin2hex($message3),
+ '%s: We send the same information as the example is created with so this should be the same'
+ );
+ }
+
+ public function testMessage3v2Generator()
+ {
+ $username = 'test';
+ $domain = 'TESTNT';
+ $workstation = 'MEMBER';
+ $lmResponse = 'bf2e015119f6bdb3f6fdb768aa12d478f5ce3d2401c8f6e9';
+ $ntlmResponse = 'caa4da8f25d5e840974ed8976d3ada46010100000000000030fa7e3c677bc301f5ce3d2401c8f6e90000000002000c0054004500530054004e00540001000c004d0045004d0042004500520003001e006d0065006d006200650072002e0074006500730074002e0063006f006d000000000000000000';
+
+ $login = $this->_getAuthenticator();
+ $message3 = $this->_invokePrivateMethod('createMessage3', $login, array($domain, $username, $workstation, $this->hex2bin($lmResponse), $this->hex2bin($ntlmResponse)));
+
+ $this->assertEquals($this->_message3, bin2hex($message3),
+ '%s: We send the same information as the example is created with so this should be the same'
+ );
+ }
+
+ public function testGetDomainAndUsername()
+ {
+ $username = "DOMAIN\user";
+
+ $login = $this->_getAuthenticator();
+ list($domain, $user) = $this->_invokePrivateMethod('getDomainAndUsername', $login, array($username));
+
+ $this->assertEquals('DOMAIN', $domain,
+ '%s: the fetched domain did not match'
+ );
+ $this->assertEquals('user', $user,
+ '%s: the fetched user did not match'
+ );
+ }
+
+ public function testGetDomainAndUsernameWithExtension()
+ {
+ $username = "domain.com\user";
+
+ $login = $this->_getAuthenticator();
+ list($domain, $user) = $this->_invokePrivateMethod('getDomainAndUsername', $login, array($username));
+
+ $this->assertEquals('domain.com', $domain,
+ '%s: the fetched domain did not match'
+ );
+ $this->assertEquals('user', $user,
+ '%s: the fetched user did not match'
+ );
+ }
+
+ public function testGetDomainAndUsernameWithAtSymbol()
+ {
+ $username = 'user@DOMAIN';
+
+ $login = $this->_getAuthenticator();
+ list($domain, $user) = $this->_invokePrivateMethod('getDomainAndUsername', $login, array($username));
+
+ $this->assertEquals('DOMAIN', $domain,
+ '%s: the fetched domain did not match'
+ );
+ $this->assertEquals('user', $user,
+ '%s: the fetched user did not match'
+ );
+ }
+
+ public function testGetDomainAndUsernameWithAtSymbolAndExtension()
+ {
+ $username = 'user@domain.com';
+
+ $login = $this->_getAuthenticator();
+ list($domain, $user) = $this->_invokePrivateMethod('getDomainAndUsername', $login, array($username));
+
+ $this->assertEquals('domain.com', $domain,
+ '%s: the fetched domain did not match'
+ );
+ $this->assertEquals('user', $user,
+ '%s: the fetched user did not match'
+ );
+ }
+
+ public function testSuccessfulAuthentication()
+ {
+ $domain = 'TESTNT';
+ $username = 'test';
+ $secret = 'test1234';
+
+ $ntlm = $this->_getAuthenticator();
+ $agent = $this->_getAgent();
+ $agent->shouldReceive('executeCommand')
+ ->once()
+ ->with('AUTH NTLM '.base64_encode(
+ $this->_invokePrivateMethod('createMessage1', $ntlm)
+ )."\r\n", array(334))
+ ->andReturn('334 '.base64_encode($this->hex2bin('4e544c4d53535000020000000c000c003000000035828980514246973ea892c10000000000000000460046003c00000054004500530054004e00540002000c0054004500530054004e00540001000c004d0045004d0042004500520003001e006d0065006d006200650072002e0074006500730074002e0063006f006d0000000000')));
+ $agent->shouldReceive('executeCommand')
+ ->once()
+ ->with(base64_encode(
+ $this->_invokePrivateMethod('createMessage3', $ntlm, array($domain, $username, $this->hex2bin('4d0045004d00420045005200'), $this->hex2bin('bf2e015119f6bdb3f6fdb768aa12d478f5ce3d2401c8f6e9'), $this->hex2bin('caa4da8f25d5e840974ed8976d3ada46010100000000000030fa7e3c677bc301f5ce3d2401c8f6e90000000002000c0054004500530054004e00540001000c004d0045004d0042004500520003001e006d0065006d006200650072002e0074006500730074002e0063006f006d000000000000000000'))
+ ))."\r\n", array(235));
+
+ $this->assertTrue($ntlm->authenticate($agent, $username.'@'.$domain, $secret, $this->hex2bin('30fa7e3c677bc301'), $this->hex2bin('f5ce3d2401c8f6e9')),
+ '%s: The buffer accepted all commands authentication should succeed'
+ );
+ }
+
+ public function testAuthenticationFailureSendRsetAndReturnFalse()
+ {
+ $domain = 'TESTNT';
+ $username = 'test';
+ $secret = 'test1234';
+
+ $ntlm = $this->_getAuthenticator();
+ $agent = $this->_getAgent();
+ $agent->shouldReceive('executeCommand')
+ ->once()
+ ->with('AUTH NTLM '.base64_encode(
+ $this->_invokePrivateMethod('createMessage1', $ntlm)
+ )."\r\n", array(334))
+ ->andThrow(new Swift_TransportException(''));
+ $agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("RSET\r\n", array(250));
+
+ $this->assertFalse($ntlm->authenticate($agent, $username.'@'.$domain, $secret, $this->hex2bin('30fa7e3c677bc301'), $this->hex2bin('f5ce3d2401c8f6e9')),
+ '%s: Authentication fails, so RSET should be sent'
+ );
+ }
+
+ // -- Private helpers
+ private function _getAuthenticator()
+ {
+ return new Swift_Transport_Esmtp_Auth_NTLMAuthenticator();
+ }
+
+ private function _getAgent()
+ {
+ return $this->getMockery('Swift_Transport_SmtpAgent')->shouldIgnoreMissing();
+ }
+
+ private function _invokePrivateMethod($method, $instance, array $args = array())
+ {
+ $methodC = new ReflectionMethod($instance, trim($method));
+ $methodC->setAccessible(true);
+
+ return $methodC->invokeArgs($instance, $args);
+ }
+
+ /**
+ * Hex2bin replacement for < PHP 5.4.
+ *
+ * @param string $hex
+ *
+ * @return string Binary
+ */
+ protected function hex2bin($hex)
+ {
+ return function_exists('hex2bin') ? hex2bin($hex) : pack('H*', $hex);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php
new file mode 100644
index 00000000..4fe9db80
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php
@@ -0,0 +1,69 @@
+_agent = $this->getMockery('Swift_Transport_SmtpAgent')->shouldIgnoreMissing();
+ }
+
+ public function testKeywordIsPlain()
+ {
+ /* -- RFC 4616, 1.
+ The name associated with this mechanism is "PLAIN".
+ */
+
+ $login = $this->_getAuthenticator();
+ $this->assertEquals('PLAIN', $login->getAuthKeyword());
+ }
+
+ public function testSuccessfulAuthentication()
+ {
+ /* -- RFC 4616, 2.
+ The client presents the authorization identity (identity to act as),
+ followed by a NUL (U+0000) character, followed by the authentication
+ identity (identity whose password will be used), followed by a NUL
+ (U+0000) character, followed by the clear-text password.
+ */
+
+ $plain = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with('AUTH PLAIN '.base64_encode(
+ 'jack'.chr(0).'jack'.chr(0).'pass'
+ )."\r\n", array(235));
+
+ $this->assertTrue($plain->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: The buffer accepted all commands authentication should succeed'
+ );
+ }
+
+ public function testAuthenticationFailureSendRsetAndReturnFalse()
+ {
+ $plain = $this->_getAuthenticator();
+
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with('AUTH PLAIN '.base64_encode(
+ 'jack'.chr(0).'jack'.chr(0).'pass'
+ )."\r\n", array(235))
+ ->andThrow(new Swift_TransportException(''));
+ $this->_agent->shouldReceive('executeCommand')
+ ->once()
+ ->with("RSET\r\n", array(250));
+
+ $this->assertFalse($plain->authenticate($this->_agent, 'jack', 'pass'),
+ '%s: Authentication fails, so RSET should be sent'
+ );
+ }
+
+ // -- Private helpers
+
+ private function _getAuthenticator()
+ {
+ return new Swift_Transport_Esmtp_Auth_PlainAuthenticator();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php
new file mode 100644
index 00000000..64327d47
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php
@@ -0,0 +1,167 @@
+_agent = $this->getMockery('Swift_Transport_SmtpAgent')->shouldIgnoreMissing();
+ }
+
+ public function testKeywordIsAuth()
+ {
+ $auth = $this->_createHandler(array());
+ $this->assertEquals('AUTH', $auth->getHandledKeyword());
+ }
+
+ public function testUsernameCanBeSetAndFetched()
+ {
+ $auth = $this->_createHandler(array());
+ $auth->setUsername('jack');
+ $this->assertEquals('jack', $auth->getUsername());
+ }
+
+ public function testPasswordCanBeSetAndFetched()
+ {
+ $auth = $this->_createHandler(array());
+ $auth->setPassword('pass');
+ $this->assertEquals('pass', $auth->getPassword());
+ }
+
+ public function testAuthModeCanBeSetAndFetched()
+ {
+ $auth = $this->_createHandler(array());
+ $auth->setAuthMode('PLAIN');
+ $this->assertEquals('PLAIN', $auth->getAuthMode());
+ }
+
+ public function testMixinMethods()
+ {
+ $auth = $this->_createHandler(array());
+ $mixins = $auth->exposeMixinMethods();
+ $this->assertTrue(in_array('getUsername', $mixins),
+ '%s: getUsername() should be accessible via mixin'
+ );
+ $this->assertTrue(in_array('setUsername', $mixins),
+ '%s: setUsername() should be accessible via mixin'
+ );
+ $this->assertTrue(in_array('getPassword', $mixins),
+ '%s: getPassword() should be accessible via mixin'
+ );
+ $this->assertTrue(in_array('setPassword', $mixins),
+ '%s: setPassword() should be accessible via mixin'
+ );
+ $this->assertTrue(in_array('setAuthMode', $mixins),
+ '%s: setAuthMode() should be accessible via mixin'
+ );
+ $this->assertTrue(in_array('getAuthMode', $mixins),
+ '%s: getAuthMode() should be accessible via mixin'
+ );
+ }
+
+ public function testAuthenticatorsAreCalledAccordingToParamsAfterEhlo()
+ {
+ $a1 = $this->_createMockAuthenticator('PLAIN');
+ $a2 = $this->_createMockAuthenticator('LOGIN');
+
+ $a1->shouldReceive('authenticate')
+ ->never()
+ ->with($this->_agent, 'jack', 'pass');
+ $a2->shouldReceive('authenticate')
+ ->once()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(true);
+
+ $auth = $this->_createHandler(array($a1, $a2));
+ $auth->setUsername('jack');
+ $auth->setPassword('pass');
+
+ $auth->setKeywordParams(array('CRAM-MD5', 'LOGIN'));
+ $auth->afterEhlo($this->_agent);
+ }
+
+ public function testAuthenticatorsAreNotUsedIfNoUsernameSet()
+ {
+ $a1 = $this->_createMockAuthenticator('PLAIN');
+ $a2 = $this->_createMockAuthenticator('LOGIN');
+
+ $a1->shouldReceive('authenticate')
+ ->never()
+ ->with($this->_agent, 'jack', 'pass');
+ $a2->shouldReceive('authenticate')
+ ->never()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(true);
+
+ $auth = $this->_createHandler(array($a1, $a2));
+
+ $auth->setKeywordParams(array('CRAM-MD5', 'LOGIN'));
+ $auth->afterEhlo($this->_agent);
+ }
+
+ public function testSeveralAuthenticatorsAreTriedIfNeeded()
+ {
+ $a1 = $this->_createMockAuthenticator('PLAIN');
+ $a2 = $this->_createMockAuthenticator('LOGIN');
+
+ $a1->shouldReceive('authenticate')
+ ->once()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(false);
+ $a2->shouldReceive('authenticate')
+ ->once()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(true);
+
+ $auth = $this->_createHandler(array($a1, $a2));
+ $auth->setUsername('jack');
+ $auth->setPassword('pass');
+
+ $auth->setKeywordParams(array('PLAIN', 'LOGIN'));
+ $auth->afterEhlo($this->_agent);
+ }
+
+ public function testFirstAuthenticatorToPassBreaksChain()
+ {
+ $a1 = $this->_createMockAuthenticator('PLAIN');
+ $a2 = $this->_createMockAuthenticator('LOGIN');
+ $a3 = $this->_createMockAuthenticator('CRAM-MD5');
+
+ $a1->shouldReceive('authenticate')
+ ->once()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(false);
+ $a2->shouldReceive('authenticate')
+ ->once()
+ ->with($this->_agent, 'jack', 'pass')
+ ->andReturn(true);
+ $a3->shouldReceive('authenticate')
+ ->never()
+ ->with($this->_agent, 'jack', 'pass');
+
+ $auth = $this->_createHandler(array($a1, $a2));
+ $auth->setUsername('jack');
+ $auth->setPassword('pass');
+
+ $auth->setKeywordParams(array('PLAIN', 'LOGIN', 'CRAM-MD5'));
+ $auth->afterEhlo($this->_agent);
+ }
+
+ // -- Private helpers
+
+ private function _createHandler($authenticators)
+ {
+ return new Swift_Transport_Esmtp_AuthHandler($authenticators);
+ }
+
+ private function _createMockAuthenticator($type)
+ {
+ $authenticator = $this->getMockery('Swift_Transport_Esmtp_Authenticator')->shouldIgnoreMissing();
+ $authenticator->shouldReceive('getAuthKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn($type);
+
+ return $authenticator;
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php
new file mode 100644
index 00000000..8d6321f3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php
@@ -0,0 +1,528 @@
+_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('STARTTLS')
+ ->andReturn(1);
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext2->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('AUTH')
+ ->andReturn(-1);
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2));
+ $this->assertEquals(array($ext2, $ext1), $smtp->getExtensionHandlers());
+ }
+
+ public function testHandlersAreNotifiedOfParams()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .*?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('setKeywordParams')
+ ->once()
+ ->with(array('PLAIN', 'LOGIN'));
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('setKeywordParams')
+ ->zeroOrMoreTimes()
+ ->with(array('123456'));
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2));
+ $smtp->start();
+ }
+
+ public function testSupportedExtensionHandlersAreRunAfterEhlo()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext3 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .*?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('afterEhlo')
+ ->once()
+ ->with($smtp);
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('afterEhlo')
+ ->zeroOrMoreTimes()
+ ->with($smtp);
+ $ext3->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext3->shouldReceive('afterEhlo')
+ ->never()
+ ->with($smtp);
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3));
+ $smtp->start();
+ }
+
+ public function testExtensionsCanModifyMailFromParams()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher();
+ $smtp = new Swift_Transport_EsmtpTransport($buf, array(), $dispatcher);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext3 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .*?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM: FOO ZIP\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO:\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn("250 OK\r\n");
+ $this->_finishBuffer($buf);
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('getMailParams')
+ ->once()
+ ->andReturn('FOO');
+ $ext1->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('AUTH')
+ ->andReturn(-1);
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('getMailParams')
+ ->once()
+ ->andReturn('ZIP');
+ $ext2->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('AUTH')
+ ->andReturn(1);
+ $ext3->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext3->shouldReceive('getMailParams')
+ ->never();
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3));
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testExtensionsCanModifyRcptParams()
+ {
+ $buf = $this->_getBuffer();
+ $dispatcher = $this->_createEventDispatcher();
+ $smtp = new Swift_Transport_EsmtpTransport($buf, array(), $dispatcher);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext3 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('me@domain' => 'Me'));
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null));
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("MAIL FROM:\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("250 OK\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("RCPT TO: FOO ZIP\r\n")
+ ->andReturn(3);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(3)
+ ->andReturn("250 OK\r\n");
+ $this->_finishBuffer($buf);
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('getRcptParams')
+ ->once()
+ ->andReturn('FOO');
+ $ext1->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('AUTH')
+ ->andReturn(-1);
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('getRcptParams')
+ ->once()
+ ->andReturn('ZIP');
+ $ext2->shouldReceive('getPriorityOver')
+ ->zeroOrMoreTimes()
+ ->with('AUTH')
+ ->andReturn(1);
+ $ext3->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext3->shouldReceive('getRcptParams')
+ ->never();
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3));
+ $smtp->start();
+ $smtp->send($message);
+ }
+
+ public function testExtensionsAreNotifiedOnCommand()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext3 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("FOO\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn("250 Cool\r\n");
+ $this->_finishBuffer($buf);
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('onCommand')
+ ->once()
+ ->with($smtp, "FOO\r\n", array(250, 251), \Mockery::any(), \Mockery::any());
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('onCommand')
+ ->once()
+ ->with($smtp, "FOO\r\n", array(250, 251), \Mockery::any(), \Mockery::any());
+ $ext3->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext3->shouldReceive('onCommand')
+ ->never()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3));
+ $smtp->start();
+ $smtp->executeCommand("FOO\r\n", array(250, 251));
+ }
+
+ public function testChainOfCommandAlgorithmWhenNotifyingExtensions()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+ $ext3 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 server.com foo\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-ServerName.tld\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250-AUTH PLAIN LOGIN\r\n");
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn("250 SIZE=123456\r\n");
+ $buf->shouldReceive('write')
+ ->never()
+ ->with("FOO\r\n");
+ $this->_finishBuffer($buf);
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('onCommand')
+ ->once()
+ ->with($smtp, "FOO\r\n", array(250, 251), \Mockery::any(), \Mockery::any())
+ ->andReturnUsing(function ($a, $b, $c, $d, &$e) {
+ $e = true;
+
+ return '250 ok';
+ });
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('SIZE');
+ $ext2->shouldReceive('onCommand')
+ ->never()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $ext3->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $ext3->shouldReceive('onCommand')
+ ->never()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3));
+ $smtp->start();
+ $smtp->executeCommand("FOO\r\n", array(250, 251));
+ }
+
+ public function testExtensionsCanExposeMixinMethods()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandlerMixin')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('exposeMixinMethods')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('setUsername', 'setPassword'));
+ $ext1->shouldReceive('setUsername')
+ ->once()
+ ->with('mick');
+ $ext1->shouldReceive('setPassword')
+ ->once()
+ ->with('pass');
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2));
+ $smtp->setUsername('mick');
+ $smtp->setPassword('pass');
+ }
+
+ public function testMixinMethodsBeginningWithSetAndNullReturnAreFluid()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandlerMixin')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('exposeMixinMethods')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('setUsername', 'setPassword'));
+ $ext1->shouldReceive('setUsername')
+ ->once()
+ ->with('mick')
+ ->andReturn(null);
+ $ext1->shouldReceive('setPassword')
+ ->once()
+ ->with('pass')
+ ->andReturn(null);
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2));
+ $ret = $smtp->setUsername('mick');
+ $this->assertEquals($smtp, $ret);
+ $ret = $smtp->setPassword('pass');
+ $this->assertEquals($smtp, $ret);
+ }
+
+ public function testMixinSetterWhichReturnValuesAreNotFluid()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $ext1 = $this->getMockery('Swift_Transport_EsmtpHandlerMixin')->shouldIgnoreMissing();
+ $ext2 = $this->getMockery('Swift_Transport_EsmtpHandler')->shouldIgnoreMissing();
+
+ $ext1->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('AUTH');
+ $ext1->shouldReceive('exposeMixinMethods')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('setUsername', 'setPassword'));
+ $ext1->shouldReceive('setUsername')
+ ->once()
+ ->with('mick')
+ ->andReturn('x');
+ $ext1->shouldReceive('setPassword')
+ ->once()
+ ->with('pass')
+ ->andReturn('x');
+ $ext2->shouldReceive('getHandledKeyword')
+ ->zeroOrMoreTimes()
+ ->andReturn('STARTTLS');
+ $this->_finishBuffer($buf);
+
+ $smtp->setExtensionHandlers(array($ext1, $ext2));
+ $this->assertEquals('x', $smtp->setUsername('mick'));
+ $this->assertEquals('x', $smtp->setPassword('pass'));
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransportTest.php
new file mode 100644
index 00000000..e6cca15b
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransportTest.php
@@ -0,0 +1,297 @@
+_createEventDispatcher();
+ }
+
+ return new Swift_Transport_EsmtpTransport($buf, array(), $dispatcher);
+ }
+
+ public function testHostCanBeSetAndFetched()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $smtp->setHost('foo');
+ $this->assertEquals('foo', $smtp->getHost(), '%s: Host should be returned');
+ }
+
+ public function testPortCanBeSetAndFetched()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $smtp->setPort(25);
+ $this->assertEquals(25, $smtp->getPort(), '%s: Port should be returned');
+ }
+
+ public function testTimeoutCanBeSetAndFetched()
+ {
+ $buf = $this->_getBuffer();
+ $buf->shouldReceive('setParam')
+ ->once()
+ ->with('timeout', 10);
+
+ $smtp = $this->_getTransport($buf);
+ $smtp->setTimeout(10);
+ $this->assertEquals(10, $smtp->getTimeout(), '%s: Timeout should be returned');
+ }
+
+ public function testEncryptionCanBeSetAndFetched()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $smtp->setEncryption('tls');
+ $this->assertEquals('tls', $smtp->getEncryption(), '%s: Crypto should be returned');
+ }
+
+ public function testStartSendsHeloToInitiate()
+ {
+ //Overridden for EHLO instead
+ }
+
+ public function testStartSendsEhloToInitiate()
+ {
+ /* -- RFC 2821, 3.2.
+
+ 3.2 Client Initiation
+
+ Once the server has sent the welcoming message and the client has
+ received it, the client normally sends the EHLO command to the
+ server, indicating the client's identity. In addition to opening the
+ session, use of EHLO indicates that the client is able to process
+ service extensions and requests that the server provide a list of the
+ extensions it supports. Older SMTP systems which are unable to
+ support service extensions and contemporary clients which do not
+ require service extensions in the mail session being initiated, MAY
+ use HELO instead of EHLO. Servers MUST NOT return the extended
+ EHLO-style response to a HELO command. For a particular connection
+ attempt, if the server returns a "command not recognized" response to
+ EHLO, the client SHOULD be able to fall back and send HELO.
+
+ In the EHLO command the host sending the command identifies itself;
+ the command may be interpreted as saying "Hello, I am " (and,
+ in the case of EHLO, "and I support service extension requests").
+
+ -- RFC 2281, 4.1.1.1.
+
+ ehlo = "EHLO" SP Domain CRLF
+ helo = "HELO" SP Domain CRLF
+
+ -- RFC 2821, 4.3.2.
+
+ EHLO or HELO
+ S: 250
+ E: 504, 550
+
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 ServerName'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ } catch (Exception $e) {
+ $this->fail('Starting Esmtp should send EHLO and accept 250 response');
+ }
+ }
+
+ public function testHeloIsUsedAsFallback()
+ {
+ /* -- RFC 2821, 4.1.4.
+
+ If the EHLO command is not acceptable to the SMTP server, 501, 500,
+ or 502 failure replies MUST be returned as appropriate. The SMTP
+ server MUST stay in the same state after transmitting these replies
+ that it was in before the EHLO was received.
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('501 WTF'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^HELO .+?\r\n$~D')
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 HELO'."\r\n");
+
+ $this->_finishBuffer($buf);
+ try {
+ $smtp->start();
+ } catch (Exception $e) {
+ $this->fail(
+ 'Starting Esmtp should fallback to HELO if needed and accept 250 response'
+ );
+ }
+ }
+
+ public function testInvalidHeloResponseCausesException()
+ {
+ //Overridden to first try EHLO
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('501 WTF'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^HELO .+?\r\n$~D')
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('504 WTF'."\r\n");
+ $this->_finishBuffer($buf);
+
+ try {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started');
+ $smtp->start();
+ $this->fail('Non 250 HELO response should raise Exception');
+ } catch (Exception $e) {
+ $this->assertFalse($smtp->isStarted(), '%s: SMTP start() should have failed');
+ }
+ }
+
+ public function testDomainNameIsPlacedInEhlo()
+ {
+ /* -- RFC 2821, 4.1.4.
+
+ The SMTP client MUST, if possible, ensure that the domain parameter
+ to the EHLO command is a valid principal host name (not a CNAME or MX
+ name) for its host. If this is not possible (e.g., when the client's
+ address is dynamically assigned and the client does not have an
+ obvious name), an address literal SHOULD be substituted for the
+ domain name and supplemental information provided that will assist in
+ identifying the client.
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("EHLO mydomain.com\r\n")
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('250 ServerName'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->setLocalDomain('mydomain.com');
+ $smtp->start();
+ }
+
+ public function testDomainNameIsPlacedInHelo()
+ {
+ //Overridden to include ESMTP
+ /* -- RFC 2821, 4.1.4.
+
+ The SMTP client MUST, if possible, ensure that the domain parameter
+ to the EHLO command is a valid principal host name (not a CNAME or MX
+ name) for its host. If this is not possible (e.g., when the client's
+ address is dynamically assigned and the client does not have an
+ obvious name), an address literal SHOULD be substituted for the
+ domain name and supplemental information provided that will assist in
+ identifying the client.
+ */
+
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(0)
+ ->andReturn("220 some.server.tld bleh\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with('~^EHLO .+?\r\n$~D')
+ ->andReturn(1);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(1)
+ ->andReturn('501 WTF'."\r\n");
+ $buf->shouldReceive('write')
+ ->once()
+ ->with("HELO mydomain.com\r\n")
+ ->andReturn(2);
+ $buf->shouldReceive('readLine')
+ ->once()
+ ->with(2)
+ ->andReturn('250 ServerName'."\r\n");
+
+ $this->_finishBuffer($buf);
+ $smtp->setLocalDomain('mydomain.com');
+ $smtp->start();
+ }
+
+ public function testFluidInterface()
+ {
+ $buf = $this->_getBuffer();
+ $smtp = $this->_getTransport($buf);
+ $buf->shouldReceive('setParam')
+ ->once()
+ ->with('timeout', 30);
+
+ $ref = $smtp
+ ->setHost('foo')
+ ->setPort(25)
+ ->setEncryption('tls')
+ ->setTimeout(30)
+ ;
+ $this->assertEquals($ref, $smtp);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/FailoverTransportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/FailoverTransportTest.php
new file mode 100644
index 00000000..8d80f359
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/FailoverTransportTest.php
@@ -0,0 +1,520 @@
+getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState) {
+ return $connectionState;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState) {
+ if (!$connectionState) {
+ $connectionState = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->twice()
+ ->with(\Mockery::anyOf($message1, $message2), \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState) {
+ if ($connectionState) {
+ return 1;
+ }
+ });
+ $t2->shouldReceive('start')->never();
+ $t2->shouldReceive('send')->never();
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message1));
+ $this->assertEquals(1, $transport->send($message2));
+ }
+
+ public function testMessageCanBeTriedOnNextTransportIfExceptionThrown()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ return 1;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message));
+ }
+
+ public function testZeroIsReturnedIfTransportReturnsZero()
+ {
+ $message = $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ $t1 = $this->getMockery('Swift_Transport')->shouldIgnoreMissing();
+
+ $connectionState = false;
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState) {
+ return $connectionState;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState) {
+ if (!$connectionState) {
+ $connectionState = true;
+ }
+ });
+ $testCase = $this;
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState, $testCase) {
+ if (!$connectionState) {
+ $testCase->fail();
+ }
+
+ return 0;
+ });
+
+ $transport = $this->_getTransport(array($t1));
+ $transport->start();
+ $this->assertEquals(0, $transport->send($message));
+ }
+
+ public function testTransportsWhichThrowExceptionsAreNotRetried()
+ {
+ $e = new Swift_TransportException('maur b0rken');
+
+ $message1 = $this->getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $message3 = $this->getMockery('Swift_Mime_Message');
+ $message4 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message3, \Mockery::any());
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message4, \Mockery::any());
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->times(4)
+ ->with(\Mockery::anyOf($message1, $message2, $message3, $message4), \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ return 1;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message1));
+ $this->assertEquals(1, $transport->send($message2));
+ $this->assertEquals(1, $transport->send($message3));
+ $this->assertEquals(1, $transport->send($message4));
+ }
+
+ public function testExceptionIsThrownIfAllTransportsDie()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ throw $e;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ try {
+ $transport->send($message);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testStoppingTransportStopsAllDelegates()
+ {
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+
+ $connectionState1 = true;
+ $connectionState2 = true;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('stop')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if ($connectionState1) {
+ $connectionState1 = false;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('stop')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if ($connectionState2) {
+ $connectionState2 = false;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $transport->stop();
+ }
+
+ public function testTransportShowsAsNotStartedIfAllDelegatesDead()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ $connectionState1 = false;
+ throw $e;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ $connectionState2 = false;
+ throw $e;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ try {
+ $transport->send($message);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ $this->assertFalse($transport->isStarted());
+ }
+ }
+
+ public function testRestartingTransportRestartsDeadDelegates()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message1 = $this->getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->twice()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ $connectionState1 = false;
+ throw $e;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message2, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if ($connectionState1) {
+ return 10;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ $connectionState2 = false;
+ throw $e;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ try {
+ $transport->send($message1);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ $this->assertFalse($transport->isStarted());
+ }
+ //Restart and re-try
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ $this->assertEquals(10, $transport->send($message2));
+ }
+
+ public function testFailureReferenceIsPassedToDelegates()
+ {
+ $failures = array();
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+
+ $connectionState = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use ($connectionState) {
+ return $connectionState;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use ($connectionState) {
+ if (!$connectionState) {
+ $connectionState = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, $failures)
+ ->andReturnUsing(function () use ($connectionState) {
+ if ($connectionState) {
+ return 1;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1));
+ $transport->start();
+ $transport->send($message, $failures);
+ }
+
+ public function testRegisterPluginDelegatesToLoadedTransports()
+ {
+ $plugin = $this->_createPlugin();
+
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $t1->shouldReceive('registerPlugin')
+ ->once()
+ ->with($plugin);
+ $t2->shouldReceive('registerPlugin')
+ ->once()
+ ->with($plugin);
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->registerPlugin($plugin);
+ }
+
+ // -- Private helpers
+
+ private function _getTransport(array $transports)
+ {
+ $transport = new Swift_Transport_FailoverTransport();
+ $transport->setTransports($transports);
+
+ return $transport;
+ }
+
+ private function _createPlugin()
+ {
+ return $this->getMockery('Swift_Events_EventListener');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/LoadBalancedTransportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/LoadBalancedTransportTest.php
new file mode 100644
index 00000000..cc7297b1
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/LoadBalancedTransportTest.php
@@ -0,0 +1,751 @@
+getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $testCase = $this;
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $testCase) {
+ if ($connectionState1) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message2, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $testCase) {
+ if ($connectionState2) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t2->shouldReceive('send')
+ ->never()
+ ->with($message1, \Mockery::any());
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message1));
+ $this->assertEquals(1, $transport->send($message2));
+ }
+
+ public function testTransportsAreReusedInRotatingFashion()
+ {
+ $message1 = $this->getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $message3 = $this->getMockery('Swift_Mime_Message');
+ $message4 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $testCase = $this;
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $testCase) {
+ if ($connectionState1) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message3, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $testCase) {
+ if ($connectionState1) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message4, \Mockery::any());
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message2, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $testCase) {
+ if ($connectionState2) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t2->shouldReceive('send')
+ ->never()
+ ->with($message1, \Mockery::any());
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message4, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $testCase) {
+ if ($connectionState2) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+ $t2->shouldReceive('send')
+ ->never()
+ ->with($message3, \Mockery::any());
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+
+ $this->assertEquals(1, $transport->send($message1));
+ $this->assertEquals(1, $transport->send($message2));
+ $this->assertEquals(1, $transport->send($message3));
+ $this->assertEquals(1, $transport->send($message4));
+ }
+
+ public function testMessageCanBeTriedOnNextTransportIfExceptionThrown()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $testCase = $this;
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e, $testCase) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ $testCase->fail();
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $testCase) {
+ if ($connectionState2) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message));
+ }
+
+ public function testMessageIsTriedOnNextTransportIfZeroReturned()
+ {
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if ($connectionState1) {
+ return 0;
+ }
+
+ return 1;
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if ($connectionState2) {
+ return 1;
+ }
+
+ return 0;
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message));
+ }
+
+ public function testZeroIsReturnedIfAllTransportsReturnZero()
+ {
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if ($connectionState1) {
+ return 0;
+ }
+
+ return 1;
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if ($connectionState2) {
+ return 0;
+ }
+
+ return 1;
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(0, $transport->send($message));
+ }
+
+ public function testTransportsWhichThrowExceptionsAreNotRetried()
+ {
+ $e = new Swift_TransportException('maur b0rken');
+
+ $message1 = $this->getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $message3 = $this->getMockery('Swift_Mime_Message');
+ $message4 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $testCase = $this;
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e, $testCase) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ $testCase->fail();
+ });
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message3, \Mockery::any());
+ $t1->shouldReceive('send')
+ ->never()
+ ->with($message4, \Mockery::any());
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->times(4)
+ ->with(\Mockery::anyOf($message1, $message3, $message3, $message4), \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $testCase) {
+ if ($connectionState2) {
+ return 1;
+ }
+ $testCase->fail();
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertEquals(1, $transport->send($message1));
+ $this->assertEquals(1, $transport->send($message2));
+ $this->assertEquals(1, $transport->send($message3));
+ $this->assertEquals(1, $transport->send($message4));
+ }
+
+ public function testExceptionIsThrownIfAllTransportsDie()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ throw $e;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ try {
+ $transport->send($message);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ }
+ }
+
+ public function testStoppingTransportStopsAllDelegates()
+ {
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = true;
+ $connectionState2 = true;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('stop')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if ($connectionState1) {
+ $connectionState1 = false;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('stop')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if ($connectionState2) {
+ $connectionState2 = false;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $transport->stop();
+ }
+
+ public function testTransportShowsAsNotStartedIfAllDelegatesDead()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ throw $e;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ throw $e;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ try {
+ $transport->send($message);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ $this->assertFalse($transport->isStarted());
+ }
+ }
+
+ public function testRestartingTransportRestartsDeadDelegates()
+ {
+ $e = new Swift_TransportException('b0rken');
+
+ $message1 = $this->getMockery('Swift_Mime_Message');
+ $message2 = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+ $connectionState1 = false;
+ $connectionState2 = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ return $connectionState1;
+ });
+ $t1->shouldReceive('start')
+ ->twice()
+ ->andReturnUsing(function () use (&$connectionState1) {
+ if (!$connectionState1) {
+ $connectionState1 = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ $connectionState1 = false;
+ throw $e;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message2, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState1, $e) {
+ if ($connectionState1) {
+ return 10;
+ }
+ });
+
+ $t2->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ return $connectionState2;
+ });
+ $t2->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState2) {
+ if (!$connectionState2) {
+ $connectionState2 = true;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->once()
+ ->with($message1, \Mockery::any())
+ ->andReturnUsing(function () use (&$connectionState2, $e) {
+ if ($connectionState2) {
+ throw $e;
+ }
+ });
+ $t2->shouldReceive('send')
+ ->never()
+ ->with($message2, \Mockery::any());
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ try {
+ $transport->send($message1);
+ $this->fail('All transports failed so Exception should be thrown');
+ } catch (Exception $e) {
+ $this->assertFalse($transport->isStarted());
+ }
+ //Restart and re-try
+ $transport->start();
+ $this->assertTrue($transport->isStarted());
+ $this->assertEquals(10, $transport->send($message2));
+ }
+
+ public function testFailureReferenceIsPassedToDelegates()
+ {
+ $failures = array();
+ $testCase = $this;
+
+ $message = $this->getMockery('Swift_Mime_Message');
+ $t1 = $this->getMockery('Swift_Transport');
+ $connectionState = false;
+
+ $t1->shouldReceive('isStarted')
+ ->zeroOrMoreTimes()
+ ->andReturnUsing(function () use (&$connectionState) {
+ return $connectionState;
+ });
+ $t1->shouldReceive('start')
+ ->once()
+ ->andReturnUsing(function () use (&$connectionState) {
+ if (!$connectionState) {
+ $connectionState = true;
+ }
+ });
+ $t1->shouldReceive('send')
+ ->once()
+ ->with($message, \Mockery::on(function (&$var) use (&$failures, $testCase) {
+ return $testCase->varsAreReferences($var, $failures);
+ }))
+ ->andReturnUsing(function () use (&$connectionState) {
+ if ($connectionState) {
+ return 1;
+ }
+ });
+
+ $transport = $this->_getTransport(array($t1));
+ $transport->start();
+ $transport->send($message, $failures);
+ }
+
+ public function testRegisterPluginDelegatesToLoadedTransports()
+ {
+ $plugin = $this->_createPlugin();
+
+ $t1 = $this->getMockery('Swift_Transport');
+ $t2 = $this->getMockery('Swift_Transport');
+
+ $t1->shouldReceive('registerPlugin')
+ ->once()
+ ->with($plugin);
+ $t2->shouldReceive('registerPlugin')
+ ->once()
+ ->with($plugin);
+
+ $transport = $this->_getTransport(array($t1, $t2));
+ $transport->registerPlugin($plugin);
+ }
+
+ /**
+ * Adapted from Yay_Matchers_ReferenceMatcher.
+ */
+ public function varsAreReferences(&$ref1, &$ref2)
+ {
+ if (is_object($ref2)) {
+ return ($ref1 === $ref2);
+ }
+ if ($ref1 !== $ref2) {
+ return false;
+ }
+
+ $copy = $ref2;
+ $randomString = uniqid('yay');
+ $ref2 = $randomString;
+ $isRef = ($ref1 === $ref2);
+ $ref2 = $copy;
+
+ return $isRef;
+ }
+
+ // -- Private helpers
+
+ private function _getTransport(array $transports)
+ {
+ $transport = new Swift_Transport_LoadBalancedTransport();
+ $transport->setTransports($transports);
+
+ return $transport;
+ }
+
+ private function _createPlugin()
+ {
+ return $this->getMockery('Swift_Events_EventListener');
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/MailTransportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/MailTransportTest.php
new file mode 100644
index 00000000..96e9943d
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/MailTransportTest.php
@@ -0,0 +1,535 @@
+_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $invoker->shouldReceive('mail')
+ ->once();
+
+ $transport->send($message);
+ }
+
+ public function testTransportUsesToFieldBodyInSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $to = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'To' => $to,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $to->shouldReceive('getFieldBody')
+ ->zeroOrMoreTimes()
+ ->andReturn('Foo ');
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with('Foo ', \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testTransportUsesSubjectFieldBodyInSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $subj = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'Subject' => $subj,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $subj->shouldReceive('getFieldBody')
+ ->zeroOrMoreTimes()
+ ->andReturn('Thing');
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), 'Thing', \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testTransportUsesBodyOfMessage()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ "To: Foo \r\n".
+ "\r\n".
+ 'This body'
+ );
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), 'This body', \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testTransportSettingUsingReturnPathForExtraParams()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('getReturnPath')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ 'foo@bar'
+ );
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), '-ffoo@bar');
+
+ $transport->send($message);
+ }
+
+ public function testTransportSettingEmptyExtraParams()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('getReturnPath')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $message->shouldReceive('getSender')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), null);
+
+ $transport->send($message);
+ }
+
+ public function testTransportSettingSettingExtraParamsWithF()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+ $transport->setExtraParams('-x\'foo\' -f%s');
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('getReturnPath')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ 'foo@bar'
+ );
+ $message->shouldReceive('getSender')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), '-x\'foo\' -ffoo@bar');
+
+ $transport->send($message);
+ }
+
+ public function testTransportSettingSettingExtraParamsWithoutF()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+ $transport->setExtraParams('-x\'foo\'');
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('getReturnPath')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ 'foo@bar'
+ );
+ $message->shouldReceive('getSender')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), '-x\'foo\'');
+
+ $transport->send($message);
+ }
+
+ public function testTransportSettingInvalidFromEmail()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('getReturnPath')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ '"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php "@email.com'
+ );
+ $message->shouldReceive('getSender')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $message->shouldReceive('getFrom')
+ ->zeroOrMoreTimes()
+ ->andReturn(null);
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), null);
+
+ $transport->send($message);
+ }
+
+ public function testTransportUsesHeadersFromMessage()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $message->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ "Subject: Stuff\r\n".
+ "\r\n".
+ 'This body'
+ );
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), 'Subject: Stuff'.PHP_EOL, \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testTransportReturnsCountOfAllRecipientsIfInvokerReturnsTrue()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessage($headers);
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null, 'zip@button' => null));
+ $message->shouldReceive('getCc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('test@test' => null));
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn(true);
+
+ $this->assertEquals(3, $transport->send($message));
+ }
+
+ public function testTransportReturnsZeroIfInvokerReturnsFalse()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessage($headers);
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => null, 'zip@button' => null));
+ $message->shouldReceive('getCc')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('test@test' => null));
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any())
+ ->andReturn(false);
+
+ $this->assertEquals(0, $transport->send($message));
+ }
+
+ public function testToHeaderIsRemovedFromHeaderSetDuringSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $to = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'To' => $to,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $headers->shouldReceive('remove')
+ ->once()
+ ->with('To');
+ $headers->shouldReceive('remove')
+ ->zeroOrMoreTimes();
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testSubjectHeaderIsRemovedFromHeaderSetDuringSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $subject = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'Subject' => $subject,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $headers->shouldReceive('remove')
+ ->once()
+ ->with('Subject');
+ $headers->shouldReceive('remove')
+ ->zeroOrMoreTimes();
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testToHeaderIsPutBackAfterSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $to = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'To' => $to,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $headers->shouldReceive('set')
+ ->once()
+ ->with($to);
+ $headers->shouldReceive('set')
+ ->zeroOrMoreTimes();
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testSubjectHeaderIsPutBackAfterSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $subject = $this->_createHeader();
+ $headers = $this->_createHeaders(array(
+ 'Subject' => $subject,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+
+ $headers->shouldReceive('set')
+ ->once()
+ ->with($subject);
+ $headers->shouldReceive('set')
+ ->zeroOrMoreTimes();
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any(), \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ public function testMessageHeadersOnlyHavePHPEolsDuringSending()
+ {
+ $invoker = $this->_createInvoker();
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $subject = $this->_createHeader();
+ $subject->shouldReceive('getFieldBody')->andReturn("Foo\r\nBar");
+
+ $headers = $this->_createHeaders(array(
+ 'Subject' => $subject,
+ ));
+ $message = $this->_createMessageWithRecipient($headers);
+ $message->shouldReceive('toString')
+ ->zeroOrMoreTimes()
+ ->andReturn(
+ "From: Foo\r\n\r\n".
+ "\r\n".
+ "This\r\n".
+ 'body'
+ );
+
+ if ("\r\n" != PHP_EOL) {
+ $expectedHeaders = "From: Foo\n\n";
+ $expectedSubject = "Foo\nBar";
+ $expectedBody = "This\nbody";
+ } else {
+ $expectedHeaders = "From: Foo\r\n\r\n";
+ $expectedSubject = "Foo\r\nBar";
+ $expectedBody = "This\r\nbody";
+ }
+
+ $invoker->shouldReceive('mail')
+ ->once()
+ ->with(\Mockery::any(), $expectedSubject, $expectedBody, $expectedHeaders, \Mockery::any());
+
+ $transport->send($message);
+ }
+
+ /**
+ * @expectedException Swift_TransportException
+ * @expectedExceptionMessage Cannot send message without a recipient
+ */
+ public function testExceptionWhenNoRecipients()
+ {
+ $invoker = $this->_createInvoker();
+ $invoker->shouldReceive('mail');
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessage($headers);
+
+ $transport->send($message);
+ }
+
+ public function noExceptionWhenRecipientsExistProvider()
+ {
+ return array(
+ array('To'),
+ array('Cc'),
+ array('Bcc'),
+ );
+ }
+
+ /**
+ * @dataProvider noExceptionWhenRecipientsExistProvider
+ *
+ * @param string $header
+ */
+ public function testNoExceptionWhenRecipientsExist($header)
+ {
+ $invoker = $this->_createInvoker();
+ $invoker->shouldReceive('mail');
+ $dispatcher = $this->_createEventDispatcher();
+ $transport = $this->_createTransport($invoker, $dispatcher);
+
+ $headers = $this->_createHeaders();
+ $message = $this->_createMessage($headers);
+ $message->shouldReceive(sprintf('get%s', $header))->andReturn(array('foo@bar' => 'Foo'));
+
+ $transport->send($message);
+ }
+
+ // -- Creation Methods
+
+ private function _createTransport($invoker, $dispatcher)
+ {
+ return new Swift_Transport_MailTransport($invoker, $dispatcher);
+ }
+
+ private function _createEventDispatcher()
+ {
+ return $this->getMockery('Swift_Events_EventDispatcher')->shouldIgnoreMissing();
+ }
+
+ private function _createInvoker()
+ {
+ return $this->getMockery('Swift_Transport_MailInvoker');
+ }
+
+ private function _createMessage($headers)
+ {
+ $message = $this->getMockery('Swift_Mime_Message')->shouldIgnoreMissing();
+ $message->shouldReceive('getHeaders')
+ ->zeroOrMoreTimes()
+ ->andReturn($headers);
+
+ return $message;
+ }
+
+ private function _createMessageWithRecipient($headers, $recipient = array('foo@bar' => 'Foo'))
+ {
+ $message = $this->_createMessage($headers);
+ $message->shouldReceive('getTo')->andReturn($recipient);
+
+ return $message;
+ }
+
+ private function _createHeaders($headers = array())
+ {
+ $set = $this->getMockery('Swift_Mime_HeaderSet')->shouldIgnoreMissing();
+
+ if (count($headers) > 0) {
+ foreach ($headers as $name => $header) {
+ $set->shouldReceive('get')
+ ->zeroOrMoreTimes()
+ ->with($name)
+ ->andReturn($header);
+ $set->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->with($name)
+ ->andReturn(true);
+ }
+ }
+
+ $header = $this->_createHeader();
+ $set->shouldReceive('get')
+ ->zeroOrMoreTimes()
+ ->andReturn($header);
+ $set->shouldReceive('has')
+ ->zeroOrMoreTimes()
+ ->andReturn(true);
+
+ return $set;
+ }
+
+ private function _createHeader()
+ {
+ return $this->getMockery('Swift_Mime_Header')->shouldIgnoreMissing();
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/SendmailTransportTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/SendmailTransportTest.php
new file mode 100644
index 00000000..9040f9ea
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/SendmailTransportTest.php
@@ -0,0 +1,151 @@
+_createEventDispatcher();
+ }
+ $transport = new Swift_Transport_SendmailTransport($buf, $dispatcher);
+ $transport->setCommand($command);
+
+ return $transport;
+ }
+
+ protected function _getSendmail($buf, $dispatcher = null)
+ {
+ if (!$dispatcher) {
+ $dispatcher = $this->_createEventDispatcher();
+ }
+ $sendmail = new Swift_Transport_SendmailTransport($buf, $dispatcher);
+
+ return $sendmail;
+ }
+
+ public function testCommandCanBeSetAndFetched()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getSendmail($buf);
+
+ $sendmail->setCommand('/usr/sbin/sendmail -bs');
+ $this->assertEquals('/usr/sbin/sendmail -bs', $sendmail->getCommand());
+ $sendmail->setCommand('/usr/sbin/sendmail -oi -t');
+ $this->assertEquals('/usr/sbin/sendmail -oi -t', $sendmail->getCommand());
+ }
+
+ public function testSendingMessageIn_t_ModeUsesSimplePipe()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getSendmail($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => 'Foobar', 'zip@button' => 'Zippy'));
+ $message->shouldReceive('toByteStream')
+ ->once()
+ ->with($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('terminate')
+ ->once();
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array("\r\n" => "\n", "\n." => "\n.."));
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array());
+
+ $sendmail->setCommand('/usr/sbin/sendmail -t');
+ $this->assertEquals(2, $sendmail->send($message));
+ }
+
+ public function testSendingIn_t_ModeWith_i_FlagDoesntEscapeDot()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getSendmail($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => 'Foobar', 'zip@button' => 'Zippy'));
+ $message->shouldReceive('toByteStream')
+ ->once()
+ ->with($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('terminate')
+ ->once();
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array("\r\n" => "\n"));
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array());
+
+ $sendmail->setCommand('/usr/sbin/sendmail -i -t');
+ $this->assertEquals(2, $sendmail->send($message));
+ }
+
+ public function testSendingInTModeWith_oi_FlagDoesntEscapeDot()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getSendmail($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => 'Foobar', 'zip@button' => 'Zippy'));
+ $message->shouldReceive('toByteStream')
+ ->once()
+ ->with($buf);
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('terminate')
+ ->once();
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array("\r\n" => "\n"));
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array());
+
+ $sendmail->setCommand('/usr/sbin/sendmail -oi -t');
+ $this->assertEquals(2, $sendmail->send($message));
+ }
+
+ public function testSendingMessageRegeneratesId()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getSendmail($buf);
+ $message = $this->_createMessage();
+
+ $message->shouldReceive('getTo')
+ ->zeroOrMoreTimes()
+ ->andReturn(array('foo@bar' => 'Foobar', 'zip@button' => 'Zippy'));
+ $message->shouldReceive('generateId');
+ $buf->shouldReceive('initialize')
+ ->once();
+ $buf->shouldReceive('terminate')
+ ->once();
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array("\r\n" => "\n", "\n." => "\n.."));
+ $buf->shouldReceive('setWriteTranslations')
+ ->once()
+ ->with(array());
+
+ $sendmail->setCommand('/usr/sbin/sendmail -t');
+ $this->assertEquals(2, $sendmail->send($message));
+ }
+
+ public function testFluidInterface()
+ {
+ $buf = $this->_getBuffer();
+ $sendmail = $this->_getTransport($buf);
+
+ $ref = $sendmail->setCommand('/foo');
+ $this->assertEquals($ref, $sendmail);
+ }
+}
diff --git a/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/StreamBufferTest.php b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/StreamBufferTest.php
new file mode 100644
index 00000000..6108a954
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/StreamBufferTest.php
@@ -0,0 +1,45 @@
+_createFactory();
+ $factory->expects($this->once())
+ ->method('createFilter')
+ ->with('a', 'b')
+ ->will($this->returnCallback(array($this, '_createFilter')));
+
+ $buffer = $this->_createBuffer($factory);
+ $buffer->setWriteTranslations(array('a' => 'b'));
+ }
+
+ public function testOverridingTranslationsOnlyAddsNeededFilters()
+ {
+ $factory = $this->_createFactory();
+ $factory->expects($this->exactly(2))
+ ->method('createFilter')
+ ->will($this->returnCallback(array($this, '_createFilter')));
+
+ $buffer = $this->_createBuffer($factory);
+ $buffer->setWriteTranslations(array('a' => 'b'));
+ $buffer->setWriteTranslations(array('x' => 'y', 'a' => 'b'));
+ }
+
+ // -- Creation methods
+
+ private function _createBuffer($replacementFactory)
+ {
+ return new Swift_Transport_StreamBuffer($replacementFactory);
+ }
+
+ private function _createFactory()
+ {
+ return $this->getMockBuilder('Swift_ReplacementFilterFactory')->getMock();
+ }
+
+ public function _createFilter()
+ {
+ return $this->getMockBuilder('Swift_StreamFilter')->getMock();
+ }
+}
diff --git a/vendor/symfony/console/.gitignore b/vendor/symfony/console/.gitignore
new file mode 100644
index 00000000..c49a5d8d
--- /dev/null
+++ b/vendor/symfony/console/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php
new file mode 100644
index 00000000..603559f0
--- /dev/null
+++ b/vendor/symfony/console/Application.php
@@ -0,0 +1,1144 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console;
+
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
+use Symfony\Component\Console\Exception\ExceptionInterface;
+use Symfony\Component\Console\Helper\DebugFormatterHelper;
+use Symfony\Component\Console\Helper\ProcessHelper;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputAwareInterface;
+use Symfony\Component\Console\Output\BufferedOutput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Command\HelpCommand;
+use Symfony\Component\Console\Command\ListCommand;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Helper\FormatterHelper;
+use Symfony\Component\Console\Helper\DialogHelper;
+use Symfony\Component\Console\Helper\ProgressHelper;
+use Symfony\Component\Console\Helper\TableHelper;
+use Symfony\Component\Console\Event\ConsoleCommandEvent;
+use Symfony\Component\Console\Event\ConsoleExceptionEvent;
+use Symfony\Component\Console\Event\ConsoleTerminateEvent;
+use Symfony\Component\Console\Exception\CommandNotFoundException;
+use Symfony\Component\Console\Exception\LogicException;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * An Application is the container for a collection of commands.
+ *
+ * It is the main entry point of a Console application.
+ *
+ * This class is optimized for a standard CLI environment.
+ *
+ * Usage:
+ *
+ * $app = new Application('myapp', '1.0 (stable)');
+ * $app->add(new SimpleCommand());
+ * $app->run();
+ *
+ * @author Fabien Potencier
+ */
+class Application
+{
+ private $commands = array();
+ private $wantHelps = false;
+ private $runningCommand;
+ private $name;
+ private $version;
+ private $catchExceptions = true;
+ private $autoExit = true;
+ private $definition;
+ private $helperSet;
+ private $dispatcher;
+ private $terminalDimensions;
+ private $defaultCommand;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of the application
+ * @param string $version The version of the application
+ */
+ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
+ {
+ $this->name = $name;
+ $this->version = $version;
+ $this->defaultCommand = 'list';
+ $this->helperSet = $this->getDefaultHelperSet();
+ $this->definition = $this->getDefaultInputDefinition();
+
+ foreach ($this->getDefaultCommands() as $command) {
+ $this->add($command);
+ }
+ }
+
+ public function setDispatcher(EventDispatcherInterface $dispatcher)
+ {
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * Runs the current application.
+ *
+ * @param InputInterface $input An Input instance
+ * @param OutputInterface $output An Output instance
+ *
+ * @return int 0 if everything went fine, or an error code
+ *
+ * @throws \Exception When doRun returns Exception
+ */
+ public function run(InputInterface $input = null, OutputInterface $output = null)
+ {
+ if (null === $input) {
+ $input = new ArgvInput();
+ }
+
+ if (null === $output) {
+ $output = new ConsoleOutput();
+ }
+
+ $this->configureIO($input, $output);
+
+ try {
+ $exitCode = $this->doRun($input, $output);
+ } catch (\Exception $e) {
+ if (!$this->catchExceptions) {
+ throw $e;
+ }
+
+ if ($output instanceof ConsoleOutputInterface) {
+ $this->renderException($e, $output->getErrorOutput());
+ } else {
+ $this->renderException($e, $output);
+ }
+
+ $exitCode = $e->getCode();
+ if (is_numeric($exitCode)) {
+ $exitCode = (int) $exitCode;
+ if (0 === $exitCode) {
+ $exitCode = 1;
+ }
+ } else {
+ $exitCode = 1;
+ }
+ }
+
+ if ($this->autoExit) {
+ if ($exitCode > 255) {
+ $exitCode = 255;
+ }
+
+ exit($exitCode);
+ }
+
+ return $exitCode;
+ }
+
+ /**
+ * Runs the current application.
+ *
+ * @param InputInterface $input An Input instance
+ * @param OutputInterface $output An Output instance
+ *
+ * @return int 0 if everything went fine, or an error code
+ */
+ public function doRun(InputInterface $input, OutputInterface $output)
+ {
+ if (true === $input->hasParameterOption(array('--version', '-V'))) {
+ $output->writeln($this->getLongVersion());
+
+ return 0;
+ }
+
+ $name = $this->getCommandName($input);
+ if (true === $input->hasParameterOption(array('--help', '-h'))) {
+ if (!$name) {
+ $name = 'help';
+ $input = new ArrayInput(array('command' => 'help'));
+ } else {
+ $this->wantHelps = true;
+ }
+ }
+
+ if (!$name) {
+ $name = $this->defaultCommand;
+ $input = new ArrayInput(array('command' => $this->defaultCommand));
+ }
+
+ // the command name MUST be the first element of the input
+ $command = $this->find($name);
+
+ $this->runningCommand = $command;
+ $exitCode = $this->doRunCommand($command, $input, $output);
+ $this->runningCommand = null;
+
+ return $exitCode;
+ }
+
+ /**
+ * Set a helper set to be used with the command.
+ *
+ * @param HelperSet $helperSet The helper set
+ */
+ public function setHelperSet(HelperSet $helperSet)
+ {
+ $this->helperSet = $helperSet;
+ }
+
+ /**
+ * Get the helper set associated with the command.
+ *
+ * @return HelperSet The HelperSet instance associated with this command
+ */
+ public function getHelperSet()
+ {
+ return $this->helperSet;
+ }
+
+ /**
+ * Set an input definition set to be used with this application.
+ *
+ * @param InputDefinition $definition The input definition
+ */
+ public function setDefinition(InputDefinition $definition)
+ {
+ $this->definition = $definition;
+ }
+
+ /**
+ * Gets the InputDefinition related to this Application.
+ *
+ * @return InputDefinition The InputDefinition instance
+ */
+ public function getDefinition()
+ {
+ return $this->definition;
+ }
+
+ /**
+ * Gets the help message.
+ *
+ * @return string A help message.
+ */
+ public function getHelp()
+ {
+ return $this->getLongVersion();
+ }
+
+ /**
+ * Sets whether to catch exceptions or not during commands execution.
+ *
+ * @param bool $boolean Whether to catch exceptions or not during commands execution
+ */
+ public function setCatchExceptions($boolean)
+ {
+ $this->catchExceptions = (bool) $boolean;
+ }
+
+ /**
+ * Sets whether to automatically exit after a command execution or not.
+ *
+ * @param bool $boolean Whether to automatically exit after a command execution or not
+ */
+ public function setAutoExit($boolean)
+ {
+ $this->autoExit = (bool) $boolean;
+ }
+
+ /**
+ * Gets the name of the application.
+ *
+ * @return string The application name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Sets the application name.
+ *
+ * @param string $name The application name
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Gets the application version.
+ *
+ * @return string The application version
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Sets the application version.
+ *
+ * @param string $version The application version
+ */
+ public function setVersion($version)
+ {
+ $this->version = $version;
+ }
+
+ /**
+ * Returns the long version of the application.
+ *
+ * @return string The long application version
+ */
+ public function getLongVersion()
+ {
+ if ('UNKNOWN' !== $this->getName()) {
+ if ('UNKNOWN' !== $this->getVersion()) {
+ return sprintf('%s version %s', $this->getName(), $this->getVersion());
+ }
+
+ return sprintf('%s', $this->getName());
+ }
+
+ return 'Console Tool';
+ }
+
+ /**
+ * Registers a new command.
+ *
+ * @param string $name The command name
+ *
+ * @return Command The newly created command
+ */
+ public function register($name)
+ {
+ return $this->add(new Command($name));
+ }
+
+ /**
+ * Adds an array of command objects.
+ *
+ * @param Command[] $commands An array of commands
+ */
+ public function addCommands(array $commands)
+ {
+ foreach ($commands as $command) {
+ $this->add($command);
+ }
+ }
+
+ /**
+ * Adds a command object.
+ *
+ * If a command with the same name already exists, it will be overridden.
+ *
+ * @param Command $command A Command object
+ *
+ * @return Command The registered command
+ */
+ public function add(Command $command)
+ {
+ $command->setApplication($this);
+
+ if (!$command->isEnabled()) {
+ $command->setApplication(null);
+
+ return;
+ }
+
+ if (null === $command->getDefinition()) {
+ throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
+ }
+
+ $this->commands[$command->getName()] = $command;
+
+ foreach ($command->getAliases() as $alias) {
+ $this->commands[$alias] = $command;
+ }
+
+ return $command;
+ }
+
+ /**
+ * Returns a registered command by name or alias.
+ *
+ * @param string $name The command name or alias
+ *
+ * @return Command A Command object
+ *
+ * @throws CommandNotFoundException When command name given does not exist
+ */
+ public function get($name)
+ {
+ if (!isset($this->commands[$name])) {
+ throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
+ }
+
+ $command = $this->commands[$name];
+
+ if ($this->wantHelps) {
+ $this->wantHelps = false;
+
+ $helpCommand = $this->get('help');
+ $helpCommand->setCommand($command);
+
+ return $helpCommand;
+ }
+
+ return $command;
+ }
+
+ /**
+ * Returns true if the command exists, false otherwise.
+ *
+ * @param string $name The command name or alias
+ *
+ * @return bool true if the command exists, false otherwise
+ */
+ public function has($name)
+ {
+ return isset($this->commands[$name]);
+ }
+
+ /**
+ * Returns an array of all unique namespaces used by currently registered commands.
+ *
+ * It does not returns the global namespace which always exists.
+ *
+ * @return array An array of namespaces
+ */
+ public function getNamespaces()
+ {
+ $namespaces = array();
+ foreach ($this->all() as $command) {
+ $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
+
+ foreach ($command->getAliases() as $alias) {
+ $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
+ }
+ }
+
+ return array_values(array_unique(array_filter($namespaces)));
+ }
+
+ /**
+ * Finds a registered namespace by a name or an abbreviation.
+ *
+ * @param string $namespace A namespace or abbreviation to search for
+ *
+ * @return string A registered namespace
+ *
+ * @throws CommandNotFoundException When namespace is incorrect or ambiguous
+ */
+ public function findNamespace($namespace)
+ {
+ $allNamespaces = $this->getNamespaces();
+ $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
+ $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
+
+ if (empty($namespaces)) {
+ $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
+
+ if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
+ if (1 == count($alternatives)) {
+ $message .= "\n\nDid you mean this?\n ";
+ } else {
+ $message .= "\n\nDid you mean one of these?\n ";
+ }
+
+ $message .= implode("\n ", $alternatives);
+ }
+
+ throw new CommandNotFoundException($message, $alternatives);
+ }
+
+ $exact = in_array($namespace, $namespaces, true);
+ if (count($namespaces) > 1 && !$exact) {
+ throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
+ }
+
+ return $exact ? $namespace : reset($namespaces);
+ }
+
+ /**
+ * Finds a command by name or alias.
+ *
+ * Contrary to get, this command tries to find the best
+ * match if you give it an abbreviation of a name or alias.
+ *
+ * @param string $name A command name or a command alias
+ *
+ * @return Command A Command instance
+ *
+ * @throws CommandNotFoundException When command name is incorrect or ambiguous
+ */
+ public function find($name)
+ {
+ $allCommands = array_keys($this->commands);
+ $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
+ $commands = preg_grep('{^'.$expr.'}', $allCommands);
+
+ if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
+ if (false !== $pos = strrpos($name, ':')) {
+ // check if a namespace exists and contains commands
+ $this->findNamespace(substr($name, 0, $pos));
+ }
+
+ $message = sprintf('Command "%s" is not defined.', $name);
+
+ if ($alternatives = $this->findAlternatives($name, $allCommands)) {
+ if (1 == count($alternatives)) {
+ $message .= "\n\nDid you mean this?\n ";
+ } else {
+ $message .= "\n\nDid you mean one of these?\n ";
+ }
+ $message .= implode("\n ", $alternatives);
+ }
+
+ throw new CommandNotFoundException($message, $alternatives);
+ }
+
+ // filter out aliases for commands which are already on the list
+ if (count($commands) > 1) {
+ $commandList = $this->commands;
+ $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
+ $commandName = $commandList[$nameOrAlias]->getName();
+
+ return $commandName === $nameOrAlias || !in_array($commandName, $commands);
+ });
+ }
+
+ $exact = in_array($name, $commands, true);
+ if (count($commands) > 1 && !$exact) {
+ $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
+
+ throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
+ }
+
+ return $this->get($exact ? $name : reset($commands));
+ }
+
+ /**
+ * Gets the commands (registered in the given namespace if provided).
+ *
+ * The array keys are the full names and the values the command instances.
+ *
+ * @param string $namespace A namespace name
+ *
+ * @return Command[] An array of Command instances
+ */
+ public function all($namespace = null)
+ {
+ if (null === $namespace) {
+ return $this->commands;
+ }
+
+ $commands = array();
+ foreach ($this->commands as $name => $command) {
+ if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
+ $commands[$name] = $command;
+ }
+ }
+
+ return $commands;
+ }
+
+ /**
+ * Returns an array of possible abbreviations given a set of names.
+ *
+ * @param array $names An array of names
+ *
+ * @return array An array of abbreviations
+ */
+ public static function getAbbreviations($names)
+ {
+ $abbrevs = array();
+ foreach ($names as $name) {
+ for ($len = strlen($name); $len > 0; --$len) {
+ $abbrev = substr($name, 0, $len);
+ $abbrevs[$abbrev][] = $name;
+ }
+ }
+
+ return $abbrevs;
+ }
+
+ /**
+ * Returns a text representation of the Application.
+ *
+ * @param string $namespace An optional namespace name
+ * @param bool $raw Whether to return raw command list
+ *
+ * @return string A string representing the Application
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ */
+ public function asText($namespace = null, $raw = false)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ $descriptor = new TextDescriptor();
+ $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
+ $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
+
+ return $output->fetch();
+ }
+
+ /**
+ * Returns an XML representation of the Application.
+ *
+ * @param string $namespace An optional namespace name
+ * @param bool $asDom Whether to return a DOM or an XML string
+ *
+ * @return string|\DOMDocument An XML string representing the Application
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ */
+ public function asXml($namespace = null, $asDom = false)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ $descriptor = new XmlDescriptor();
+
+ if ($asDom) {
+ return $descriptor->getApplicationDocument($this, $namespace);
+ }
+
+ $output = new BufferedOutput();
+ $descriptor->describe($output, $this, array('namespace' => $namespace));
+
+ return $output->fetch();
+ }
+
+ /**
+ * Renders a caught exception.
+ *
+ * @param \Exception $e An exception instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ public function renderException($e, $output)
+ {
+ $output->writeln('', OutputInterface::VERBOSITY_QUIET);
+
+ do {
+ $title = sprintf(' [%s] ', get_class($e));
+
+ $len = $this->stringWidth($title);
+
+ $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
+ // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
+ if (defined('HHVM_VERSION') && $width > 1 << 31) {
+ $width = 1 << 31;
+ }
+ $formatter = $output->getFormatter();
+ $lines = array();
+ foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
+ foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
+ // pre-format lines to get the right string length
+ $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
+ $lines[] = array($line, $lineLength);
+
+ $len = max($lineLength, $len);
+ }
+ }
+
+ $messages = array();
+ $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len)));
+ $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
+ foreach ($lines as $line) {
+ $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1])));
+ }
+ $messages[] = $emptyLine;
+ $messages[] = '';
+
+ $output->writeln($messages, OutputInterface::OUTPUT_RAW | OutputInterface::VERBOSITY_QUIET);
+
+ if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $output->writeln('Exception trace:', OutputInterface::VERBOSITY_QUIET);
+
+ // exception related properties
+ $trace = $e->getTrace();
+ array_unshift($trace, array(
+ 'function' => '',
+ 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
+ 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
+ 'args' => array(),
+ ));
+
+ for ($i = 0, $count = count($trace); $i < $count; ++$i) {
+ $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
+ $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
+ $function = $trace[$i]['function'];
+ $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
+ $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
+
+ $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
+ }
+
+ $output->writeln('', OutputInterface::VERBOSITY_QUIET);
+ }
+ } while ($e = $e->getPrevious());
+
+ if (null !== $this->runningCommand) {
+ $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
+ $output->writeln('', OutputInterface::VERBOSITY_QUIET);
+ }
+ }
+
+ /**
+ * Tries to figure out the terminal width in which this application runs.
+ *
+ * @return int|null
+ */
+ protected function getTerminalWidth()
+ {
+ $dimensions = $this->getTerminalDimensions();
+
+ return $dimensions[0];
+ }
+
+ /**
+ * Tries to figure out the terminal height in which this application runs.
+ *
+ * @return int|null
+ */
+ protected function getTerminalHeight()
+ {
+ $dimensions = $this->getTerminalDimensions();
+
+ return $dimensions[1];
+ }
+
+ /**
+ * Tries to figure out the terminal dimensions based on the current environment.
+ *
+ * @return array Array containing width and height
+ */
+ public function getTerminalDimensions()
+ {
+ if ($this->terminalDimensions) {
+ return $this->terminalDimensions;
+ }
+
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ // extract [w, H] from "wxh (WxH)"
+ if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
+ return array((int) $matches[1], (int) $matches[2]);
+ }
+ // extract [w, h] from "wxh"
+ if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
+ return array((int) $matches[1], (int) $matches[2]);
+ }
+ }
+
+ if ($sttyString = $this->getSttyColumns()) {
+ // extract [w, h] from "rows h; columns w;"
+ if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
+ return array((int) $matches[2], (int) $matches[1]);
+ }
+ // extract [w, h] from "; h rows; w columns"
+ if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
+ return array((int) $matches[2], (int) $matches[1]);
+ }
+ }
+
+ return array(null, null);
+ }
+
+ /**
+ * Sets terminal dimensions.
+ *
+ * Can be useful to force terminal dimensions for functional tests.
+ *
+ * @param int $width The width
+ * @param int $height The height
+ *
+ * @return Application The current application
+ */
+ public function setTerminalDimensions($width, $height)
+ {
+ $this->terminalDimensions = array($width, $height);
+
+ return $this;
+ }
+
+ /**
+ * Configures the input and output instances based on the user arguments and options.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ protected function configureIO(InputInterface $input, OutputInterface $output)
+ {
+ if (true === $input->hasParameterOption(array('--ansi'))) {
+ $output->setDecorated(true);
+ } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
+ $output->setDecorated(false);
+ }
+
+ if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
+ $input->setInteractive(false);
+ } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
+ $inputStream = $this->getHelperSet()->get('question')->getInputStream();
+ if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
+ $input->setInteractive(false);
+ }
+ }
+
+ if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
+ } else {
+ if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
+ } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
+ } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
+ }
+ }
+ }
+
+ /**
+ * Runs the current command.
+ *
+ * If an event dispatcher has been attached to the application,
+ * events are also dispatched during the life-cycle of the command.
+ *
+ * @param Command $command A Command instance
+ * @param InputInterface $input An Input instance
+ * @param OutputInterface $output An Output instance
+ *
+ * @return int 0 if everything went fine, or an error code
+ *
+ * @throws \Exception when the command being run threw an exception
+ */
+ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
+ {
+ foreach ($command->getHelperSet() as $helper) {
+ if ($helper instanceof InputAwareInterface) {
+ $helper->setInput($input);
+ }
+ }
+
+ if (null === $this->dispatcher) {
+ return $command->run($input, $output);
+ }
+
+ // bind before the console.command event, so the listeners have access to input options/arguments
+ try {
+ $command->mergeApplicationDefinition();
+ $input->bind($command->getDefinition());
+ } catch (ExceptionInterface $e) {
+ // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
+ }
+
+ $event = new ConsoleCommandEvent($command, $input, $output);
+ $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
+
+ if ($event->commandShouldRun()) {
+ try {
+ $exitCode = $command->run($input, $output);
+ } catch (\Exception $e) {
+ $event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
+ $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
+
+ $e = $event->getException();
+
+ $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
+ $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
+
+ throw $e;
+ }
+ } else {
+ $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
+ }
+
+ $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
+ $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
+
+ return $event->getExitCode();
+ }
+
+ /**
+ * Gets the name of the command based on input.
+ *
+ * @param InputInterface $input The input interface
+ *
+ * @return string The command name
+ */
+ protected function getCommandName(InputInterface $input)
+ {
+ return $input->getFirstArgument();
+ }
+
+ /**
+ * Gets the default input definition.
+ *
+ * @return InputDefinition An InputDefinition instance
+ */
+ protected function getDefaultInputDefinition()
+ {
+ return new InputDefinition(array(
+ new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
+
+ new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
+ new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
+ new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
+ new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
+ new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
+ new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
+ new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
+ ));
+ }
+
+ /**
+ * Gets the default commands that should always be available.
+ *
+ * @return Command[] An array of default Command instances
+ */
+ protected function getDefaultCommands()
+ {
+ return array(new HelpCommand(), new ListCommand());
+ }
+
+ /**
+ * Gets the default helper set with the helpers that should always be available.
+ *
+ * @return HelperSet A HelperSet instance
+ */
+ protected function getDefaultHelperSet()
+ {
+ return new HelperSet(array(
+ new FormatterHelper(),
+ new DialogHelper(false),
+ new ProgressHelper(false),
+ new TableHelper(false),
+ new DebugFormatterHelper(),
+ new ProcessHelper(),
+ new QuestionHelper(),
+ ));
+ }
+
+ /**
+ * Runs and parses stty -a if it's available, suppressing any error output.
+ *
+ * @return string
+ */
+ private function getSttyColumns()
+ {
+ if (!function_exists('proc_open')) {
+ return;
+ }
+
+ $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
+ $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
+ if (is_resource($process)) {
+ $info = stream_get_contents($pipes[1]);
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($process);
+
+ return $info;
+ }
+ }
+
+ /**
+ * Runs and parses mode CON if it's available, suppressing any error output.
+ *
+ * @return string x or null if it could not be parsed
+ */
+ private function getConsoleMode()
+ {
+ if (!function_exists('proc_open')) {
+ return;
+ }
+
+ $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
+ $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
+ if (is_resource($process)) {
+ $info = stream_get_contents($pipes[1]);
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($process);
+
+ if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
+ return $matches[2].'x'.$matches[1];
+ }
+ }
+ }
+
+ /**
+ * Returns abbreviated suggestions in string format.
+ *
+ * @param array $abbrevs Abbreviated suggestions to convert
+ *
+ * @return string A formatted string of abbreviated suggestions
+ */
+ private function getAbbreviationSuggestions($abbrevs)
+ {
+ return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
+ }
+
+ /**
+ * Returns the namespace part of the command name.
+ *
+ * This method is not part of public API and should not be used directly.
+ *
+ * @param string $name The full name of the command
+ * @param string $limit The maximum number of parts of the namespace
+ *
+ * @return string The namespace of the command
+ */
+ public function extractNamespace($name, $limit = null)
+ {
+ $parts = explode(':', $name);
+ array_pop($parts);
+
+ return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
+ }
+
+ /**
+ * Finds alternative of $name among $collection,
+ * if nothing is found in $collection, try in $abbrevs.
+ *
+ * @param string $name The string
+ * @param array|\Traversable $collection The collection
+ *
+ * @return array A sorted array of similar string
+ */
+ private function findAlternatives($name, $collection)
+ {
+ $threshold = 1e3;
+ $alternatives = array();
+
+ $collectionParts = array();
+ foreach ($collection as $item) {
+ $collectionParts[$item] = explode(':', $item);
+ }
+
+ foreach (explode(':', $name) as $i => $subname) {
+ foreach ($collectionParts as $collectionName => $parts) {
+ $exists = isset($alternatives[$collectionName]);
+ if (!isset($parts[$i]) && $exists) {
+ $alternatives[$collectionName] += $threshold;
+ continue;
+ } elseif (!isset($parts[$i])) {
+ continue;
+ }
+
+ $lev = levenshtein($subname, $parts[$i]);
+ if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
+ $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
+ } elseif ($exists) {
+ $alternatives[$collectionName] += $threshold;
+ }
+ }
+ }
+
+ foreach ($collection as $item) {
+ $lev = levenshtein($name, $item);
+ if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
+ $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
+ }
+ }
+
+ $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
+ asort($alternatives);
+
+ return array_keys($alternatives);
+ }
+
+ /**
+ * Sets the default Command name.
+ *
+ * @param string $commandName The Command name
+ */
+ public function setDefaultCommand($commandName)
+ {
+ $this->defaultCommand = $commandName;
+ }
+
+ private function stringWidth($string)
+ {
+ if (false === $encoding = mb_detect_encoding($string, null, true)) {
+ return strlen($string);
+ }
+
+ return mb_strwidth($string, $encoding);
+ }
+
+ private function splitStringByWidth($string, $width)
+ {
+ // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
+ // additionally, array_slice() is not enough as some character has doubled width.
+ // we need a function to split string not by character count but by string width
+ if (false === $encoding = mb_detect_encoding($string, null, true)) {
+ return str_split($string, $width);
+ }
+
+ $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
+ $lines = array();
+ $line = '';
+ foreach (preg_split('//u', $utf8String) as $char) {
+ // test if $char could be appended to current line
+ if (mb_strwidth($line.$char, 'utf8') <= $width) {
+ $line .= $char;
+ continue;
+ }
+ // if not, push current line to array and make new line
+ $lines[] = str_pad($line, $width);
+ $line = $char;
+ }
+ if ('' !== $line) {
+ $lines[] = count($lines) ? str_pad($line, $width) : $line;
+ }
+
+ mb_convert_variables($encoding, 'utf8', $lines);
+
+ return $lines;
+ }
+
+ /**
+ * Returns all namespaces of the command name.
+ *
+ * @param string $name The full name of the command
+ *
+ * @return array The namespaces of the command
+ */
+ private function extractAllNamespaces($name)
+ {
+ // -1 as third argument is needed to skip the command short name when exploding
+ $parts = explode(':', $name, -1);
+ $namespaces = array();
+
+ foreach ($parts as $part) {
+ if (count($namespaces)) {
+ $namespaces[] = end($namespaces).':'.$part;
+ } else {
+ $namespaces[] = $part;
+ }
+ }
+
+ return $namespaces;
+ }
+}
diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md
new file mode 100644
index 00000000..8021068e
--- /dev/null
+++ b/vendor/symfony/console/CHANGELOG.md
@@ -0,0 +1,73 @@
+CHANGELOG
+=========
+
+2.8.3
+-----
+
+ * remove readline support from the question helper as it caused issues
+
+2.8.0
+-----
+
+ * use readline for user input in the question helper when available to allow
+ the use of arrow keys
+
+2.6.0
+-----
+
+ * added a Process helper
+ * added a DebugFormatter helper
+
+2.5.0
+-----
+
+ * deprecated the dialog helper (use the question helper instead)
+ * deprecated TableHelper in favor of Table
+ * deprecated ProgressHelper in favor of ProgressBar
+ * added ConsoleLogger
+ * added a question helper
+ * added a way to set the process name of a command
+ * added a way to set a default command instead of `ListCommand`
+
+2.4.0
+-----
+
+ * added a way to force terminal dimensions
+ * added a convenient method to detect verbosity level
+ * [BC BREAK] made descriptors use output instead of returning a string
+
+2.3.0
+-----
+
+ * added multiselect support to the select dialog helper
+ * added Table Helper for tabular data rendering
+ * added support for events in `Application`
+ * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()`
+ * added a way to set the progress bar progress via the `setCurrent` method
+ * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'`
+ * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG
+
+2.2.0
+-----
+
+ * added support for colorization on Windows via ConEmu
+ * add a method to Dialog Helper to ask for a question and hide the response
+ * added support for interactive selections in console (DialogHelper::select())
+ * added support for autocompletion as you type in Dialog Helper
+
+2.1.0
+-----
+
+ * added ConsoleOutputInterface
+ * added the possibility to disable a command (Command::isEnabled())
+ * added suggestions when a command does not exist
+ * added a --raw option to the list command
+ * added support for STDERR in the console output class (errors are now sent
+ to STDERR)
+ * made the defaults (helper set, commands, input definition) in Application
+ more easily customizable
+ * added support for the shell even if readline is not available
+ * added support for process isolation in Symfony shell via
+ `--process-isolation` switch
+ * added support for `--`, which disables options parsing after that point
+ (tokens will be parsed as arguments)
diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php
new file mode 100644
index 00000000..6acbe219
--- /dev/null
+++ b/vendor/symfony/console/Command/Command.php
@@ -0,0 +1,681 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Command;
+
+use Symfony\Component\Console\Descriptor\TextDescriptor;
+use Symfony\Component\Console\Descriptor\XmlDescriptor;
+use Symfony\Component\Console\Exception\ExceptionInterface;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\BufferedOutput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+use Symfony\Component\Console\Exception\LogicException;
+
+/**
+ * Base class for all commands.
+ *
+ * @author Fabien Potencier
+ */
+class Command
+{
+ private $application;
+ private $name;
+ private $processTitle;
+ private $aliases = array();
+ private $definition;
+ private $help;
+ private $description;
+ private $ignoreValidationErrors = false;
+ private $applicationDefinitionMerged = false;
+ private $applicationDefinitionMergedWithArgs = false;
+ private $code;
+ private $synopsis = array();
+ private $usages = array();
+ private $helperSet;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $name The name of the command; passing null means it must be set in configure()
+ *
+ * @throws LogicException When the command name is empty
+ */
+ public function __construct($name = null)
+ {
+ $this->definition = new InputDefinition();
+
+ if (null !== $name) {
+ $this->setName($name);
+ }
+
+ $this->configure();
+
+ if (!$this->name) {
+ throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
+ }
+ }
+
+ /**
+ * Ignores validation errors.
+ *
+ * This is mainly useful for the help command.
+ */
+ public function ignoreValidationErrors()
+ {
+ $this->ignoreValidationErrors = true;
+ }
+
+ /**
+ * Sets the application instance for this command.
+ *
+ * @param Application $application An Application instance
+ */
+ public function setApplication(Application $application = null)
+ {
+ $this->application = $application;
+ if ($application) {
+ $this->setHelperSet($application->getHelperSet());
+ } else {
+ $this->helperSet = null;
+ }
+ }
+
+ /**
+ * Sets the helper set.
+ *
+ * @param HelperSet $helperSet A HelperSet instance
+ */
+ public function setHelperSet(HelperSet $helperSet)
+ {
+ $this->helperSet = $helperSet;
+ }
+
+ /**
+ * Gets the helper set.
+ *
+ * @return HelperSet A HelperSet instance
+ */
+ public function getHelperSet()
+ {
+ return $this->helperSet;
+ }
+
+ /**
+ * Gets the application instance for this command.
+ *
+ * @return Application An Application instance
+ */
+ public function getApplication()
+ {
+ return $this->application;
+ }
+
+ /**
+ * Checks whether the command is enabled or not in the current environment.
+ *
+ * Override this to check for x or y and return false if the command can not
+ * run properly under the current conditions.
+ *
+ * @return bool
+ */
+ public function isEnabled()
+ {
+ return true;
+ }
+
+ /**
+ * Configures the current command.
+ */
+ protected function configure()
+ {
+ }
+
+ /**
+ * Executes the current command.
+ *
+ * This method is not abstract because you can use this class
+ * as a concrete class. In this case, instead of defining the
+ * execute() method, you set the code to execute by passing
+ * a Closure to the setCode() method.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return null|int null or 0 if everything went fine, or an error code
+ *
+ * @throws LogicException When this abstract method is not implemented
+ *
+ * @see setCode()
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ throw new LogicException('You must override the execute() method in the concrete command class.');
+ }
+
+ /**
+ * Interacts with the user.
+ *
+ * This method is executed before the InputDefinition is validated.
+ * This means that this is the only place where the command can
+ * interactively ask for values of missing required arguments.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ protected function interact(InputInterface $input, OutputInterface $output)
+ {
+ }
+
+ /**
+ * Initializes the command just after the input has been validated.
+ *
+ * This is mainly useful when a lot of commands extends one main command
+ * where some things need to be initialized based on the input arguments and options.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ */
+ protected function initialize(InputInterface $input, OutputInterface $output)
+ {
+ }
+
+ /**
+ * Runs the command.
+ *
+ * The code to execute is either defined directly with the
+ * setCode() method or by overriding the execute() method
+ * in a sub-class.
+ *
+ * @param InputInterface $input An InputInterface instance
+ * @param OutputInterface $output An OutputInterface instance
+ *
+ * @return int The command exit code
+ *
+ * @throws \Exception
+ *
+ * @see setCode()
+ * @see execute()
+ */
+ public function run(InputInterface $input, OutputInterface $output)
+ {
+ // force the creation of the synopsis before the merge with the app definition
+ $this->getSynopsis(true);
+ $this->getSynopsis(false);
+
+ // add the application arguments and options
+ $this->mergeApplicationDefinition();
+
+ // bind the input against the command specific arguments/options
+ try {
+ $input->bind($this->definition);
+ } catch (ExceptionInterface $e) {
+ if (!$this->ignoreValidationErrors) {
+ throw $e;
+ }
+ }
+
+ $this->initialize($input, $output);
+
+ if (null !== $this->processTitle) {
+ if (function_exists('cli_set_process_title')) {
+ cli_set_process_title($this->processTitle);
+ } elseif (function_exists('setproctitle')) {
+ setproctitle($this->processTitle);
+ } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
+ $output->writeln('Install the proctitle PECL to be able to change the process title.');
+ }
+ }
+
+ if ($input->isInteractive()) {
+ $this->interact($input, $output);
+ }
+
+ // The command name argument is often omitted when a command is executed directly with its run() method.
+ // It would fail the validation if we didn't make sure the command argument is present,
+ // since it's required by the application.
+ if ($input->hasArgument('command') && null === $input->getArgument('command')) {
+ $input->setArgument('command', $this->getName());
+ }
+
+ $input->validate();
+
+ if ($this->code) {
+ $statusCode = call_user_func($this->code, $input, $output);
+ } else {
+ $statusCode = $this->execute($input, $output);
+ }
+
+ return is_numeric($statusCode) ? (int) $statusCode : 0;
+ }
+
+ /**
+ * Sets the code to execute when running this command.
+ *
+ * If this method is used, it overrides the code defined
+ * in the execute() method.
+ *
+ * @param callable $code A callable(InputInterface $input, OutputInterface $output)
+ *
+ * @return Command The current instance
+ *
+ * @throws InvalidArgumentException
+ *
+ * @see execute()
+ */
+ public function setCode($code)
+ {
+ if (!is_callable($code)) {
+ throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
+ }
+
+ if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
+ $r = new \ReflectionFunction($code);
+ if (null === $r->getClosureThis()) {
+ $code = \Closure::bind($code, $this);
+ }
+ }
+
+ $this->code = $code;
+
+ return $this;
+ }
+
+ /**
+ * Merges the application definition with the command definition.
+ *
+ * This method is not part of public API and should not be used directly.
+ *
+ * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
+ */
+ public function mergeApplicationDefinition($mergeArgs = true)
+ {
+ if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
+ return;
+ }
+
+ $this->definition->addOptions($this->application->getDefinition()->getOptions());
+
+ if ($mergeArgs) {
+ $currentArguments = $this->definition->getArguments();
+ $this->definition->setArguments($this->application->getDefinition()->getArguments());
+ $this->definition->addArguments($currentArguments);
+ }
+
+ $this->applicationDefinitionMerged = true;
+ if ($mergeArgs) {
+ $this->applicationDefinitionMergedWithArgs = true;
+ }
+ }
+
+ /**
+ * Sets an array of argument and option instances.
+ *
+ * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
+ *
+ * @return Command The current instance
+ */
+ public function setDefinition($definition)
+ {
+ if ($definition instanceof InputDefinition) {
+ $this->definition = $definition;
+ } else {
+ $this->definition->setDefinition($definition);
+ }
+
+ $this->applicationDefinitionMerged = false;
+
+ return $this;
+ }
+
+ /**
+ * Gets the InputDefinition attached to this Command.
+ *
+ * @return InputDefinition An InputDefinition instance
+ */
+ public function getDefinition()
+ {
+ return $this->definition;
+ }
+
+ /**
+ * Gets the InputDefinition to be used to create XML and Text representations of this Command.
+ *
+ * Can be overridden to provide the original command representation when it would otherwise
+ * be changed by merging with the application InputDefinition.
+ *
+ * This method is not part of public API and should not be used directly.
+ *
+ * @return InputDefinition An InputDefinition instance
+ */
+ public function getNativeDefinition()
+ {
+ return $this->getDefinition();
+ }
+
+ /**
+ * Adds an argument.
+ *
+ * @param string $name The argument name
+ * @param int $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
+ * @param string $description A description text
+ * @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
+ *
+ * @return Command The current instance
+ */
+ public function addArgument($name, $mode = null, $description = '', $default = null)
+ {
+ $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
+
+ return $this;
+ }
+
+ /**
+ * Adds an option.
+ *
+ * @param string $name The option name
+ * @param string $shortcut The shortcut (can be null)
+ * @param int $mode The option mode: One of the InputOption::VALUE_* constants
+ * @param string $description A description text
+ * @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
+ *
+ * @return Command The current instance
+ */
+ public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
+ {
+ $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
+
+ return $this;
+ }
+
+ /**
+ * Sets the name of the command.
+ *
+ * This method can set both the namespace and the name if
+ * you separate them by a colon (:)
+ *
+ * $command->setName('foo:bar');
+ *
+ * @param string $name The command name
+ *
+ * @return Command The current instance
+ *
+ * @throws InvalidArgumentException When the name is invalid
+ */
+ public function setName($name)
+ {
+ $this->validateName($name);
+
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * Sets the process title of the command.
+ *
+ * This feature should be used only when creating a long process command,
+ * like a daemon.
+ *
+ * PHP 5.5+ or the proctitle PECL library is required
+ *
+ * @param string $title The process title
+ *
+ * @return Command The current instance
+ */
+ public function setProcessTitle($title)
+ {
+ $this->processTitle = $title;
+
+ return $this;
+ }
+
+ /**
+ * Returns the command name.
+ *
+ * @return string The command name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Sets the description for the command.
+ *
+ * @param string $description The description for the command
+ *
+ * @return Command The current instance
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ /**
+ * Returns the description for the command.
+ *
+ * @return string The description for the command
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the help for the command.
+ *
+ * @param string $help The help for the command
+ *
+ * @return Command The current instance
+ */
+ public function setHelp($help)
+ {
+ $this->help = $help;
+
+ return $this;
+ }
+
+ /**
+ * Returns the help for the command.
+ *
+ * @return string The help for the command
+ */
+ public function getHelp()
+ {
+ return $this->help;
+ }
+
+ /**
+ * Returns the processed help for the command replacing the %command.name% and
+ * %command.full_name% patterns with the real values dynamically.
+ *
+ * @return string The processed help for the command
+ */
+ public function getProcessedHelp()
+ {
+ $name = $this->name;
+
+ $placeholders = array(
+ '%command.name%',
+ '%command.full_name%',
+ );
+ $replacements = array(
+ $name,
+ $_SERVER['PHP_SELF'].' '.$name,
+ );
+
+ return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
+ }
+
+ /**
+ * Sets the aliases for the command.
+ *
+ * @param string[] $aliases An array of aliases for the command
+ *
+ * @return Command The current instance
+ *
+ * @throws InvalidArgumentException When an alias is invalid
+ */
+ public function setAliases($aliases)
+ {
+ if (!is_array($aliases) && !$aliases instanceof \Traversable) {
+ throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
+ }
+
+ foreach ($aliases as $alias) {
+ $this->validateName($alias);
+ }
+
+ $this->aliases = $aliases;
+
+ return $this;
+ }
+
+ /**
+ * Returns the aliases for the command.
+ *
+ * @return array An array of aliases for the command
+ */
+ public function getAliases()
+ {
+ return $this->aliases;
+ }
+
+ /**
+ * Returns the synopsis for the command.
+ *
+ * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
+ *
+ * @return string The synopsis
+ */
+ public function getSynopsis($short = false)
+ {
+ $key = $short ? 'short' : 'long';
+
+ if (!isset($this->synopsis[$key])) {
+ $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
+ }
+
+ return $this->synopsis[$key];
+ }
+
+ /**
+ * Add a command usage example.
+ *
+ * @param string $usage The usage, it'll be prefixed with the command name
+ */
+ public function addUsage($usage)
+ {
+ if (0 !== strpos($usage, $this->name)) {
+ $usage = sprintf('%s %s', $this->name, $usage);
+ }
+
+ $this->usages[] = $usage;
+
+ return $this;
+ }
+
+ /**
+ * Returns alternative usages of the command.
+ *
+ * @return array
+ */
+ public function getUsages()
+ {
+ return $this->usages;
+ }
+
+ /**
+ * Gets a helper instance by name.
+ *
+ * @param string $name The helper name
+ *
+ * @return mixed The helper value
+ *
+ * @throws LogicException if no HelperSet is defined
+ * @throws InvalidArgumentException if the helper is not defined
+ */
+ public function getHelper($name)
+ {
+ if (null === $this->helperSet) {
+ throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
+ }
+
+ return $this->helperSet->get($name);
+ }
+
+ /**
+ * Returns a text representation of the command.
+ *
+ * @return string A string representing the command
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ */
+ public function asText()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ $descriptor = new TextDescriptor();
+ $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
+ $descriptor->describe($output, $this, array('raw_output' => true));
+
+ return $output->fetch();
+ }
+
+ /**
+ * Returns an XML representation of the command.
+ *
+ * @param bool $asDom Whether to return a DOM or an XML string
+ *
+ * @return string|\DOMDocument An XML string representing the command
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ */
+ public function asXml($asDom = false)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ $descriptor = new XmlDescriptor();
+
+ if ($asDom) {
+ return $descriptor->getCommandDocument($this);
+ }
+
+ $output = new BufferedOutput();
+ $descriptor->describe($output, $this);
+
+ return $output->fetch();
+ }
+
+ /**
+ * Validates a command name.
+ *
+ * It must be non-empty and parts can optionally be separated by ":".
+ *
+ * @param string $name
+ *
+ * @throws InvalidArgumentException When the name is invalid
+ */
+ private function validateName($name)
+ {
+ if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
+ throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
+ }
+ }
+}
diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php
new file mode 100644
index 00000000..c0e7b388
--- /dev/null
+++ b/vendor/symfony/console/Command/HelpCommand.php
@@ -0,0 +1,93 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Command;
+
+use Symfony\Component\Console\Helper\DescriptorHelper;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * HelpCommand displays the help for a given command.
+ *
+ * @author Fabien Potencier
+ */
+class HelpCommand extends Command
+{
+ private $command;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this->ignoreValidationErrors();
+
+ $this
+ ->setName('help')
+ ->setDefinition(array(
+ new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
+ new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
+ new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
+ ))
+ ->setDescription('Displays help for a command')
+ ->setHelp(<<<'EOF'
+The %command.name% command displays help for a given command:
+
+ php %command.full_name% list
+
+You can also output the help in other formats by using the --format option:
+
+ php %command.full_name% --format=xml list
+
+To display the list of available commands, please use the list command.
+EOF
+ )
+ ;
+ }
+
+ /**
+ * Sets the command.
+ *
+ * @param Command $command The command to set
+ */
+ public function setCommand(Command $command)
+ {
+ $this->command = $command;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if (null === $this->command) {
+ $this->command = $this->getApplication()->find($input->getArgument('command_name'));
+ }
+
+ if ($input->getOption('xml')) {
+ @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED);
+
+ $input->setOption('format', 'xml');
+ }
+
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->command, array(
+ 'format' => $input->getOption('format'),
+ 'raw_text' => $input->getOption('raw'),
+ ));
+
+ $this->command = null;
+ }
+}
diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php
new file mode 100644
index 00000000..5e1b926a
--- /dev/null
+++ b/vendor/symfony/console/Command/ListCommand.php
@@ -0,0 +1,97 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Command;
+
+use Symfony\Component\Console\Helper\DescriptorHelper;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputDefinition;
+
+/**
+ * ListCommand displays the list of all available commands for the application.
+ *
+ * @author Fabien Potencier
+ */
+class ListCommand extends Command
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('list')
+ ->setDefinition($this->createDefinition())
+ ->setDescription('Lists commands')
+ ->setHelp(<<<'EOF'
+The %command.name% command lists all commands:
+
+ php %command.full_name%
+
+You can also display the commands for a specific namespace:
+
+ php %command.full_name% test
+
+You can also output the information in other formats by using the --format option:
+
+ php %command.full_name% --format=xml
+
+It's also possible to get raw list of commands (useful for embedding command runner):
+
+ php %command.full_name% --raw
+EOF
+ )
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNativeDefinition()
+ {
+ return $this->createDefinition();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if ($input->getOption('xml')) {
+ @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED);
+
+ $input->setOption('format', 'xml');
+ }
+
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->getApplication(), array(
+ 'format' => $input->getOption('format'),
+ 'raw_text' => $input->getOption('raw'),
+ 'namespace' => $input->getArgument('namespace'),
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ private function createDefinition()
+ {
+ return new InputDefinition(array(
+ new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
+ new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
+ new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
+ ));
+ }
+}
diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php
new file mode 100644
index 00000000..1ed41b7d
--- /dev/null
+++ b/vendor/symfony/console/ConsoleEvents.php
@@ -0,0 +1,61 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console;
+
+/**
+ * Contains all events dispatched by an Application.
+ *
+ * @author Francesco Levorato
+ */
+final class ConsoleEvents
+{
+ /**
+ * The COMMAND event allows you to attach listeners before any command is
+ * executed by the console. It also allows you to modify the command, input and output
+ * before they are handled to the command.
+ *
+ * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent
+ * instance.
+ *
+ * @Event
+ *
+ * @var string
+ */
+ const COMMAND = 'console.command';
+
+ /**
+ * The TERMINATE event allows you to attach listeners after a command is
+ * executed by the console.
+ *
+ * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent
+ * instance.
+ *
+ * @Event
+ *
+ * @var string
+ */
+ const TERMINATE = 'console.terminate';
+
+ /**
+ * The EXCEPTION event occurs when an uncaught exception appears.
+ *
+ * This event allows you to deal with the exception or
+ * to modify the thrown exception. The event listener method receives
+ * a Symfony\Component\Console\Event\ConsoleExceptionEvent
+ * instance.
+ *
+ * @Event
+ *
+ * @var string
+ */
+ const EXCEPTION = 'console.exception';
+}
diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php
new file mode 100644
index 00000000..89961b9c
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php
@@ -0,0 +1,160 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\CommandNotFoundException;
+
+/**
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class ApplicationDescription
+{
+ const GLOBAL_NAMESPACE = '_global';
+
+ /**
+ * @var Application
+ */
+ private $application;
+
+ /**
+ * @var null|string
+ */
+ private $namespace;
+
+ /**
+ * @var array
+ */
+ private $namespaces;
+
+ /**
+ * @var Command[]
+ */
+ private $commands;
+
+ /**
+ * @var Command[]
+ */
+ private $aliases;
+
+ /**
+ * Constructor.
+ *
+ * @param Application $application
+ * @param string|null $namespace
+ */
+ public function __construct(Application $application, $namespace = null)
+ {
+ $this->application = $application;
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * @return array
+ */
+ public function getNamespaces()
+ {
+ if (null === $this->namespaces) {
+ $this->inspectApplication();
+ }
+
+ return $this->namespaces;
+ }
+
+ /**
+ * @return Command[]
+ */
+ public function getCommands()
+ {
+ if (null === $this->commands) {
+ $this->inspectApplication();
+ }
+
+ return $this->commands;
+ }
+
+ /**
+ * @param string $name
+ *
+ * @return Command
+ *
+ * @throws CommandNotFoundException
+ */
+ public function getCommand($name)
+ {
+ if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
+ throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
+ }
+
+ return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
+ }
+
+ private function inspectApplication()
+ {
+ $this->commands = array();
+ $this->namespaces = array();
+
+ $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
+ foreach ($this->sortCommands($all) as $namespace => $commands) {
+ $names = array();
+
+ /** @var Command $command */
+ foreach ($commands as $name => $command) {
+ if (!$command->getName()) {
+ continue;
+ }
+
+ if ($command->getName() === $name) {
+ $this->commands[$name] = $command;
+ } else {
+ $this->aliases[$name] = $command;
+ }
+
+ $names[] = $name;
+ }
+
+ $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
+ }
+ }
+
+ /**
+ * @param array $commands
+ *
+ * @return array
+ */
+ private function sortCommands(array $commands)
+ {
+ $namespacedCommands = array();
+ $globalCommands = array();
+ foreach ($commands as $name => $command) {
+ $key = $this->application->extractNamespace($name, 1);
+ if (!$key) {
+ $globalCommands['_global'][$name] = $command;
+ } else {
+ $namespacedCommands[$key][$name] = $command;
+ }
+ }
+ ksort($namespacedCommands);
+ $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
+
+ foreach ($namespacedCommands as &$commandsSet) {
+ ksort($commandsSet);
+ }
+ // unset reference to keep scope clear
+ unset($commandsSet);
+
+ return $namespacedCommands;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php
new file mode 100644
index 00000000..43a7a0a1
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/Descriptor.php
@@ -0,0 +1,122 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+abstract class Descriptor implements DescriptorInterface
+{
+ /**
+ * @var OutputInterface
+ */
+ private $output;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function describe(OutputInterface $output, $object, array $options = array())
+ {
+ $this->output = $output;
+
+ switch (true) {
+ case $object instanceof InputArgument:
+ $this->describeInputArgument($object, $options);
+ break;
+ case $object instanceof InputOption:
+ $this->describeInputOption($object, $options);
+ break;
+ case $object instanceof InputDefinition:
+ $this->describeInputDefinition($object, $options);
+ break;
+ case $object instanceof Command:
+ $this->describeCommand($object, $options);
+ break;
+ case $object instanceof Application:
+ $this->describeApplication($object, $options);
+ break;
+ default:
+ throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
+ }
+ }
+
+ /**
+ * Writes content to output.
+ *
+ * @param string $content
+ * @param bool $decorated
+ */
+ protected function write($content, $decorated = false)
+ {
+ $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
+ }
+
+ /**
+ * Describes an InputArgument instance.
+ *
+ * @param InputArgument $argument
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
+
+ /**
+ * Describes an InputOption instance.
+ *
+ * @param InputOption $option
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputOption(InputOption $option, array $options = array());
+
+ /**
+ * Describes an InputDefinition instance.
+ *
+ * @param InputDefinition $definition
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
+
+ /**
+ * Describes a Command instance.
+ *
+ * @param Command $command
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeCommand(Command $command, array $options = array());
+
+ /**
+ * Describes an Application instance.
+ *
+ * @param Application $application
+ * @param array $options
+ *
+ * @return string|mixed
+ */
+ abstract protected function describeApplication(Application $application, array $options = array());
+}
diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php
new file mode 100644
index 00000000..3929b6d9
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Descriptor interface.
+ *
+ * @author Jean-François Simon
+ */
+interface DescriptorInterface
+{
+ /**
+ * Describes an InputArgument instance.
+ *
+ * @param OutputInterface $output
+ * @param object $object
+ * @param array $options
+ */
+ public function describe(OutputInterface $output, $object, array $options = array());
+}
diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php
new file mode 100644
index 00000000..87e38fdb
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php
@@ -0,0 +1,166 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * JSON descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class JsonDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ $this->writeData($this->getInputArgumentData($argument), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ $this->writeData($this->getInputOptionData($option), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $this->writeData($this->getInputDefinitionData($definition), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $this->writeData($this->getCommandData($command), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ $commands = array();
+
+ foreach ($description->getCommands() as $command) {
+ $commands[] = $this->getCommandData($command);
+ }
+
+ $data = $describedNamespace
+ ? array('commands' => $commands, 'namespace' => $describedNamespace)
+ : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
+
+ $this->writeData($data, $options);
+ }
+
+ /**
+ * Writes data as json.
+ *
+ * @param array $data
+ * @param array $options
+ *
+ * @return array|string
+ */
+ private function writeData(array $data, array $options)
+ {
+ $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
+ }
+
+ /**
+ * @param InputArgument $argument
+ *
+ * @return array
+ */
+ private function getInputArgumentData(InputArgument $argument)
+ {
+ return array(
+ 'name' => $argument->getName(),
+ 'is_required' => $argument->isRequired(),
+ 'is_array' => $argument->isArray(),
+ 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
+ 'default' => $argument->getDefault(),
+ );
+ }
+
+ /**
+ * @param InputOption $option
+ *
+ * @return array
+ */
+ private function getInputOptionData(InputOption $option)
+ {
+ return array(
+ 'name' => '--'.$option->getName(),
+ 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
+ 'accept_value' => $option->acceptValue(),
+ 'is_value_required' => $option->isValueRequired(),
+ 'is_multiple' => $option->isArray(),
+ 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
+ 'default' => $option->getDefault(),
+ );
+ }
+
+ /**
+ * @param InputDefinition $definition
+ *
+ * @return array
+ */
+ private function getInputDefinitionData(InputDefinition $definition)
+ {
+ $inputArguments = array();
+ foreach ($definition->getArguments() as $name => $argument) {
+ $inputArguments[$name] = $this->getInputArgumentData($argument);
+ }
+
+ $inputOptions = array();
+ foreach ($definition->getOptions() as $name => $option) {
+ $inputOptions[$name] = $this->getInputOptionData($option);
+ }
+
+ return array('arguments' => $inputArguments, 'options' => $inputOptions);
+ }
+
+ /**
+ * @param Command $command
+ *
+ * @return array
+ */
+ private function getCommandData(Command $command)
+ {
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ return array(
+ 'name' => $command->getName(),
+ 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
+ 'description' => $command->getDescription(),
+ 'help' => $command->getProcessedHelp(),
+ 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
+ );
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php
new file mode 100644
index 00000000..d3d76a42
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php
@@ -0,0 +1,143 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * Markdown descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class MarkdownDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ $this->write(
+ '**'.$argument->getName().':**'."\n\n"
+ .'* Name: '.($argument->getName() ?: '')."\n"
+ .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
+ .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
+ .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $argument->getDescription() ?: '')."\n"
+ .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ $this->write(
+ '**'.$option->getName().':**'."\n\n"
+ .'* Name: `--'.$option->getName().'`'."\n"
+ .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n"
+ .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
+ .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
+ .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
+ .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $option->getDescription() ?: '')."\n"
+ .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ if ($showArguments = count($definition->getArguments()) > 0) {
+ $this->write('### Arguments:');
+ foreach ($definition->getArguments() as $argument) {
+ $this->write("\n\n");
+ $this->write($this->describeInputArgument($argument));
+ }
+ }
+
+ if (count($definition->getOptions()) > 0) {
+ if ($showArguments) {
+ $this->write("\n\n");
+ }
+
+ $this->write('### Options:');
+ foreach ($definition->getOptions() as $option) {
+ $this->write("\n\n");
+ $this->write($this->describeInputOption($option));
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ $this->write(
+ $command->getName()."\n"
+ .str_repeat('-', strlen($command->getName()))."\n\n"
+ .'* Description: '.($command->getDescription() ?: '')."\n"
+ .'* Usage:'."\n\n"
+ .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
+ return $carry .= ' * `'.$usage.'`'."\n";
+ })
+ );
+
+ if ($help = $command->getProcessedHelp()) {
+ $this->write("\n");
+ $this->write($help);
+ }
+
+ if ($command->getNativeDefinition()) {
+ $this->write("\n\n");
+ $this->describeInputDefinition($command->getNativeDefinition());
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+
+ $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));
+
+ foreach ($description->getNamespaces() as $namespace) {
+ if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $this->write("\n\n");
+ $this->write('**'.$namespace['id'].':**');
+ }
+
+ $this->write("\n\n");
+ $this->write(implode("\n", array_map(function ($commandName) {
+ return '* '.$commandName;
+ }, $namespace['commands'])));
+ }
+
+ foreach ($description->getCommands() as $command) {
+ $this->write("\n\n");
+ $this->write($this->describeCommand($command));
+ }
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php
new file mode 100644
index 00000000..64b53971
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/TextDescriptor.php
@@ -0,0 +1,287 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * Text descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class TextDescriptor extends Descriptor
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
+ $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault()));
+ } else {
+ $default = '';
+ }
+
+ $totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
+ $spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
+
+ $this->writeText(sprintf(' %s%s%s%s',
+ $argument->getName(),
+ str_repeat(' ', $spacingWidth),
+ // + 17 = 2 spaces + + + 2 spaces
+ preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()),
+ $default
+ ), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
+ $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault()));
+ } else {
+ $default = '';
+ }
+
+ $value = '';
+ if ($option->acceptValue()) {
+ $value = '='.strtoupper($option->getName());
+
+ if ($option->isValueOptional()) {
+ $value = '['.$value.']';
+ }
+ }
+
+ $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
+ $synopsis = sprintf('%s%s',
+ $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ',
+ sprintf('--%s%s', $option->getName(), $value)
+ );
+
+ $spacingWidth = $totalWidth - strlen($synopsis) + 2;
+
+ $this->writeText(sprintf(' %s%s%s%s%s',
+ $synopsis,
+ str_repeat(' ', $spacingWidth),
+ // + 17 = 2 spaces + + + 2 spaces
+ preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()),
+ $default,
+ $option->isArray() ? ' (multiple values allowed)' : ''
+ ), $options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
+ foreach ($definition->getArguments() as $argument) {
+ $totalWidth = max($totalWidth, strlen($argument->getName()));
+ }
+
+ if ($definition->getArguments()) {
+ $this->writeText('Arguments:', $options);
+ $this->writeText("\n");
+ foreach ($definition->getArguments() as $argument) {
+ $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
+ $this->writeText("\n");
+ }
+ }
+
+ if ($definition->getArguments() && $definition->getOptions()) {
+ $this->writeText("\n");
+ }
+
+ if ($definition->getOptions()) {
+ $laterOptions = array();
+
+ $this->writeText('Options:', $options);
+ foreach ($definition->getOptions() as $option) {
+ if (strlen($option->getShortcut()) > 1) {
+ $laterOptions[] = $option;
+ continue;
+ }
+ $this->writeText("\n");
+ $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
+ }
+ foreach ($laterOptions as $option) {
+ $this->writeText("\n");
+ $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $command->getSynopsis(true);
+ $command->getSynopsis(false);
+ $command->mergeApplicationDefinition(false);
+
+ $this->writeText('Usage:', $options);
+ foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
+ $this->writeText("\n");
+ $this->writeText(' '.$usage, $options);
+ }
+ $this->writeText("\n");
+
+ $definition = $command->getNativeDefinition();
+ if ($definition->getOptions() || $definition->getArguments()) {
+ $this->writeText("\n");
+ $this->describeInputDefinition($definition, $options);
+ $this->writeText("\n");
+ }
+
+ if ($help = $command->getProcessedHelp()) {
+ $this->writeText("\n");
+ $this->writeText('Help:', $options);
+ $this->writeText("\n");
+ $this->writeText(' '.str_replace("\n", "\n ", $help), $options);
+ $this->writeText("\n");
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+
+ if (isset($options['raw_text']) && $options['raw_text']) {
+ $width = $this->getColumnWidth($description->getCommands());
+
+ foreach ($description->getCommands() as $command) {
+ $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
+ $this->writeText("\n");
+ }
+ } else {
+ if ('' != $help = $application->getHelp()) {
+ $this->writeText("$help\n\n", $options);
+ }
+
+ $this->writeText("Usage:\n", $options);
+ $this->writeText(" command [options] [arguments]\n\n", $options);
+
+ $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
+
+ $this->writeText("\n");
+ $this->writeText("\n");
+
+ $width = $this->getColumnWidth($description->getCommands());
+
+ if ($describedNamespace) {
+ $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options);
+ } else {
+ $this->writeText('Available commands:', $options);
+ }
+
+ // add commands by namespace
+ foreach ($description->getNamespaces() as $namespace) {
+ if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $this->writeText("\n");
+ $this->writeText(' '.$namespace['id'].'', $options);
+ }
+
+ foreach ($namespace['commands'] as $name) {
+ $this->writeText("\n");
+ $spacingWidth = $width - strlen($name);
+ $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
+ }
+ }
+
+ $this->writeText("\n");
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ private function writeText($content, array $options = array())
+ {
+ $this->write(
+ isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
+ isset($options['raw_output']) ? !$options['raw_output'] : true
+ );
+ }
+
+ /**
+ * Formats input option/argument default value.
+ *
+ * @param mixed $default
+ *
+ * @return string
+ */
+ private function formatDefaultValue($default)
+ {
+ if (PHP_VERSION_ID < 50400) {
+ return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
+ }
+
+ return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
+ }
+
+ /**
+ * @param Command[] $commands
+ *
+ * @return int
+ */
+ private function getColumnWidth(array $commands)
+ {
+ $widths = array();
+
+ foreach ($commands as $command) {
+ $widths[] = strlen($command->getName());
+ foreach ($command->getAliases() as $alias) {
+ $widths[] = strlen($alias);
+ }
+ }
+
+ return max($widths) + 2;
+ }
+
+ /**
+ * @param InputOption[] $options
+ *
+ * @return int
+ */
+ private function calculateTotalWidthForOptions($options)
+ {
+ $totalWidth = 0;
+ foreach ($options as $option) {
+ // "-" + shortcut + ", --" + name
+ $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName());
+
+ if ($option->acceptValue()) {
+ $valueLength = 1 + strlen($option->getName()); // = + value
+ $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
+
+ $nameLength += $valueLength;
+ }
+ $totalWidth = max($totalWidth, $nameLength);
+ }
+
+ return $totalWidth;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php
new file mode 100644
index 00000000..b5676beb
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php
@@ -0,0 +1,263 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Descriptor;
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * XML descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class XmlDescriptor extends Descriptor
+{
+ /**
+ * @param InputDefinition $definition
+ *
+ * @return \DOMDocument
+ */
+ public function getInputDefinitionDocument(InputDefinition $definition)
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($definitionXML = $dom->createElement('definition'));
+
+ $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
+ foreach ($definition->getArguments() as $argument) {
+ $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
+ }
+
+ $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
+ foreach ($definition->getOptions() as $option) {
+ $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
+ }
+
+ return $dom;
+ }
+
+ /**
+ * @param Command $command
+ *
+ * @return \DOMDocument
+ */
+ public function getCommandDocument(Command $command)
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($commandXML = $dom->createElement('command'));
+
+ $command->getSynopsis();
+ $command->mergeApplicationDefinition(false);
+
+ $commandXML->setAttribute('id', $command->getName());
+ $commandXML->setAttribute('name', $command->getName());
+
+ $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
+
+ foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
+ $usagesXML->appendChild($dom->createElement('usage', $usage));
+ }
+
+ $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
+
+ $commandXML->appendChild($helpXML = $dom->createElement('help'));
+ $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
+
+ $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
+ $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
+
+ return $dom;
+ }
+
+ /**
+ * @param Application $application
+ * @param string|null $namespace
+ *
+ * @return \DOMDocument
+ */
+ public function getApplicationDocument(Application $application, $namespace = null)
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($rootXml = $dom->createElement('symfony'));
+
+ if ($application->getName() !== 'UNKNOWN') {
+ $rootXml->setAttribute('name', $application->getName());
+ if ($application->getVersion() !== 'UNKNOWN') {
+ $rootXml->setAttribute('version', $application->getVersion());
+ }
+ }
+
+ $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
+
+ $description = new ApplicationDescription($application, $namespace);
+
+ if ($namespace) {
+ $commandsXML->setAttribute('namespace', $namespace);
+ }
+
+ foreach ($description->getCommands() as $command) {
+ $this->appendDocument($commandsXML, $this->getCommandDocument($command));
+ }
+
+ if (!$namespace) {
+ $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
+
+ foreach ($description->getNamespaces() as $namespaceDescription) {
+ $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
+ $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
+
+ foreach ($namespaceDescription['commands'] as $name) {
+ $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
+ $commandXML->appendChild($dom->createTextNode($name));
+ }
+ }
+ }
+
+ return $dom;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputArgument(InputArgument $argument, array $options = array())
+ {
+ $this->writeDocument($this->getInputArgumentDocument($argument));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputOption(InputOption $option, array $options = array())
+ {
+ $this->writeDocument($this->getInputOptionDocument($option));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeInputDefinition(InputDefinition $definition, array $options = array())
+ {
+ $this->writeDocument($this->getInputDefinitionDocument($definition));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeCommand(Command $command, array $options = array())
+ {
+ $this->writeDocument($this->getCommandDocument($command));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function describeApplication(Application $application, array $options = array())
+ {
+ $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
+ }
+
+ /**
+ * Appends document children to parent node.
+ *
+ * @param \DOMNode $parentNode
+ * @param \DOMNode $importedParent
+ */
+ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
+ {
+ foreach ($importedParent->childNodes as $childNode) {
+ $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
+ }
+ }
+
+ /**
+ * Writes DOM document.
+ *
+ * @param \DOMDocument $dom
+ *
+ * @return \DOMDocument|string
+ */
+ private function writeDocument(\DOMDocument $dom)
+ {
+ $dom->formatOutput = true;
+ $this->write($dom->saveXML());
+ }
+
+ /**
+ * @param InputArgument $argument
+ *
+ * @return \DOMDocument
+ */
+ private function getInputArgumentDocument(InputArgument $argument)
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+
+ $dom->appendChild($objectXML = $dom->createElement('argument'));
+ $objectXML->setAttribute('name', $argument->getName());
+ $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
+
+ $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+ $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
+ foreach ($defaults as $default) {
+ $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+ $defaultXML->appendChild($dom->createTextNode($default));
+ }
+
+ return $dom;
+ }
+
+ /**
+ * @param InputOption $option
+ *
+ * @return \DOMDocument
+ */
+ private function getInputOptionDocument(InputOption $option)
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+
+ $dom->appendChild($objectXML = $dom->createElement('option'));
+ $objectXML->setAttribute('name', '--'.$option->getName());
+ $pos = strpos($option->getShortcut(), '|');
+ if (false !== $pos) {
+ $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
+ $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
+ } else {
+ $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
+ }
+ $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
+ $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
+
+ if ($option->acceptValue()) {
+ $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
+ $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+
+ if (!empty($defaults)) {
+ foreach ($defaults as $default) {
+ $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+ $defaultXML->appendChild($dom->createTextNode($default));
+ }
+ }
+ }
+
+ return $dom;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php
new file mode 100644
index 00000000..92adf1ef
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php
@@ -0,0 +1,62 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Event;
+
+/**
+ * Allows to do things before the command is executed, like skipping the command or changing the input.
+ *
+ * @author Fabien Potencier
+ */
+class ConsoleCommandEvent extends ConsoleEvent
+{
+ /**
+ * The return code for skipped commands, this will also be passed into the terminate event.
+ */
+ const RETURN_CODE_DISABLED = 113;
+
+ /**
+ * Indicates if the command should be run or skipped.
+ *
+ * @var bool
+ */
+ private $commandShouldRun = true;
+
+ /**
+ * Disables the command, so it won't be run.
+ *
+ * @return bool
+ */
+ public function disableCommand()
+ {
+ return $this->commandShouldRun = false;
+ }
+
+ /**
+ * Enables the command.
+ *
+ * @return bool
+ */
+ public function enableCommand()
+ {
+ return $this->commandShouldRun = true;
+ }
+
+ /**
+ * Returns true if the command is runnable, false otherwise.
+ *
+ * @return bool
+ */
+ public function commandShouldRun()
+ {
+ return $this->commandShouldRun;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php
new file mode 100644
index 00000000..ab620c46
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleEvent.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Event;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Allows to inspect input and output of a command.
+ *
+ * @author Francesco Levorato
+ */
+class ConsoleEvent extends Event
+{
+ protected $command;
+
+ private $input;
+ private $output;
+
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output)
+ {
+ $this->command = $command;
+ $this->input = $input;
+ $this->output = $output;
+ }
+
+ /**
+ * Gets the command that is executed.
+ *
+ * @return Command A Command instance
+ */
+ public function getCommand()
+ {
+ return $this->command;
+ }
+
+ /**
+ * Gets the input instance.
+ *
+ * @return InputInterface An InputInterface instance
+ */
+ public function getInput()
+ {
+ return $this->input;
+ }
+
+ /**
+ * Gets the output instance.
+ *
+ * @return OutputInterface An OutputInterface instance
+ */
+ public function getOutput()
+ {
+ return $this->output;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleExceptionEvent.php b/vendor/symfony/console/Event/ConsoleExceptionEvent.php
new file mode 100644
index 00000000..603b7eed
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleExceptionEvent.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Event;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Allows to handle exception thrown in a command.
+ *
+ * @author Fabien Potencier
+ */
+class ConsoleExceptionEvent extends ConsoleEvent
+{
+ private $exception;
+ private $exitCode;
+
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
+ {
+ parent::__construct($command, $input, $output);
+
+ $this->setException($exception);
+ $this->exitCode = (int) $exitCode;
+ }
+
+ /**
+ * Returns the thrown exception.
+ *
+ * @return \Exception The thrown exception
+ */
+ public function getException()
+ {
+ return $this->exception;
+ }
+
+ /**
+ * Replaces the thrown exception.
+ *
+ * This exception will be thrown if no response is set in the event.
+ *
+ * @param \Exception $exception The thrown exception
+ */
+ public function setException(\Exception $exception)
+ {
+ $this->exception = $exception;
+ }
+
+ /**
+ * Gets the exit code.
+ *
+ * @return int The command exit code
+ */
+ public function getExitCode()
+ {
+ return $this->exitCode;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php
new file mode 100644
index 00000000..b6a5d7c0
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleTerminateEvent.php
@@ -0,0 +1,58 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Event;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Allows to manipulate the exit code of a command after its execution.
+ *
+ * @author Francesco Levorato
+ */
+class ConsoleTerminateEvent extends ConsoleEvent
+{
+ /**
+ * The exit code of the command.
+ *
+ * @var int
+ */
+ private $exitCode;
+
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
+ {
+ parent::__construct($command, $input, $output);
+
+ $this->setExitCode($exitCode);
+ }
+
+ /**
+ * Sets the exit code.
+ *
+ * @param int $exitCode The command exit code
+ */
+ public function setExitCode($exitCode)
+ {
+ $this->exitCode = (int) $exitCode;
+ }
+
+ /**
+ * Gets the exit code.
+ *
+ * @return int The command exit code
+ */
+ public function getExitCode()
+ {
+ return $this->exitCode;
+ }
+}
diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php
new file mode 100644
index 00000000..ce6fefe3
--- /dev/null
+++ b/vendor/symfony/console/Exception/CommandNotFoundException.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * Represents an incorrect command name typed in the console.
+ *
+ * @author Jérôme Tamarelle
+ */
+class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
+{
+ private $alternatives;
+
+ /**
+ * @param string $message Exception message to throw.
+ * @param array $alternatives List of similar defined names.
+ * @param int $code Exception code.
+ * @param Exception $previous previous exception used for the exception chaining.
+ */
+ public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+
+ $this->alternatives = $alternatives;
+ }
+
+ /**
+ * @return array A list of similar defined names.
+ */
+ public function getAlternatives()
+ {
+ return $this->alternatives;
+ }
+}
diff --git a/vendor/symfony/console/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/ExceptionInterface.php
new file mode 100644
index 00000000..491cc4c6
--- /dev/null
+++ b/vendor/symfony/console/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * ExceptionInterface.
+ *
+ * @author Jérôme Tamarelle
+ */
+interface ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/InvalidArgumentException.php b/vendor/symfony/console/Exception/InvalidArgumentException.php
new file mode 100644
index 00000000..07cc0b61
--- /dev/null
+++ b/vendor/symfony/console/Exception/InvalidArgumentException.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/InvalidOptionException.php b/vendor/symfony/console/Exception/InvalidOptionException.php
new file mode 100644
index 00000000..b2eec616
--- /dev/null
+++ b/vendor/symfony/console/Exception/InvalidOptionException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * Represents an incorrect option name typed in the console.
+ *
+ * @author Jérôme Tamarelle
+ */
+class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/LogicException.php b/vendor/symfony/console/Exception/LogicException.php
new file mode 100644
index 00000000..fc37b8d8
--- /dev/null
+++ b/vendor/symfony/console/Exception/LogicException.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/RuntimeException.php b/vendor/symfony/console/Exception/RuntimeException.php
new file mode 100644
index 00000000..51d7d80a
--- /dev/null
+++ b/vendor/symfony/console/Exception/RuntimeException.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php
new file mode 100644
index 00000000..56cd5e56
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatter.php
@@ -0,0 +1,240 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Formatter;
+
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * Formatter class for console output.
+ *
+ * @author Konstantin Kudryashov
+ */
+class OutputFormatter implements OutputFormatterInterface
+{
+ private $decorated;
+ private $styles = array();
+ private $styleStack;
+
+ /**
+ * Escapes "<" special char in given text.
+ *
+ * @param string $text Text to escape
+ *
+ * @return string Escaped text
+ */
+ public static function escape($text)
+ {
+ $text = preg_replace('/([^\\\\]?)', '$1\\<', $text);
+
+ if ('\\' === substr($text, -1)) {
+ $len = strlen($text);
+ $text = rtrim($text, '\\');
+ $text .= str_repeat('<<', $len - strlen($text));
+ }
+
+ return $text;
+ }
+
+ /**
+ * Initializes console output formatter.
+ *
+ * @param bool $decorated Whether this formatter should actually decorate strings
+ * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
+ */
+ public function __construct($decorated = false, array $styles = array())
+ {
+ $this->decorated = (bool) $decorated;
+
+ $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
+ $this->setStyle('info', new OutputFormatterStyle('green'));
+ $this->setStyle('comment', new OutputFormatterStyle('yellow'));
+ $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
+
+ foreach ($styles as $name => $style) {
+ $this->setStyle($name, $style);
+ }
+
+ $this->styleStack = new OutputFormatterStyleStack();
+ }
+
+ /**
+ * Sets the decorated flag.
+ *
+ * @param bool $decorated Whether to decorate the messages or not
+ */
+ public function setDecorated($decorated)
+ {
+ $this->decorated = (bool) $decorated;
+ }
+
+ /**
+ * Gets the decorated flag.
+ *
+ * @return bool true if the output will decorate messages, false otherwise
+ */
+ public function isDecorated()
+ {
+ return $this->decorated;
+ }
+
+ /**
+ * Sets a new style.
+ *
+ * @param string $name The style name
+ * @param OutputFormatterStyleInterface $style The style instance
+ */
+ public function setStyle($name, OutputFormatterStyleInterface $style)
+ {
+ $this->styles[strtolower($name)] = $style;
+ }
+
+ /**
+ * Checks if output formatter has style with specified name.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function hasStyle($name)
+ {
+ return isset($this->styles[strtolower($name)]);
+ }
+
+ /**
+ * Gets style options from style with specified name.
+ *
+ * @param string $name
+ *
+ * @return OutputFormatterStyleInterface
+ *
+ * @throws InvalidArgumentException When style isn't defined
+ */
+ public function getStyle($name)
+ {
+ if (!$this->hasStyle($name)) {
+ throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
+ }
+
+ return $this->styles[strtolower($name)];
+ }
+
+ /**
+ * Formats a message according to the given styles.
+ *
+ * @param string $message The message to style
+ *
+ * @return string The styled message
+ */
+ public function format($message)
+ {
+ $message = (string) $message;
+ $offset = 0;
+ $output = '';
+ $tagRegex = '[a-z][a-z0-9_=;-]*+';
+ preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
+ foreach ($matches[0] as $i => $match) {
+ $pos = $match[1];
+ $text = $match[0];
+
+ if (0 != $pos && '\\' == $message[$pos - 1]) {
+ continue;
+ }
+
+ // add the text up to the next tag
+ $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
+ $offset = $pos + strlen($text);
+
+ // opening tag?
+ if ($open = '/' != $text[1]) {
+ $tag = $matches[1][$i][0];
+ } else {
+ $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
+ }
+
+ if (!$open && !$tag) {
+ // >
+ $this->styleStack->pop();
+ } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
+ $output .= $this->applyCurrentStyle($text);
+ } elseif ($open) {
+ $this->styleStack->push($style);
+ } else {
+ $this->styleStack->pop($style);
+ }
+ }
+
+ $output .= $this->applyCurrentStyle(substr($message, $offset));
+
+ if (false !== strpos($output, '<<')) {
+ return strtr($output, array('\\<' => '<', '<<' => '\\'));
+ }
+
+ return str_replace('\\<', '<', $output);
+ }
+
+ /**
+ * @return OutputFormatterStyleStack
+ */
+ public function getStyleStack()
+ {
+ return $this->styleStack;
+ }
+
+ /**
+ * Tries to create new style instance from string.
+ *
+ * @param string $string
+ *
+ * @return OutputFormatterStyle|bool false if string is not format string
+ */
+ private function createStyleFromString($string)
+ {
+ if (isset($this->styles[$string])) {
+ return $this->styles[$string];
+ }
+
+ if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
+ return false;
+ }
+
+ $style = new OutputFormatterStyle();
+ foreach ($matches as $match) {
+ array_shift($match);
+
+ if ('fg' == $match[0]) {
+ $style->setForeground($match[1]);
+ } elseif ('bg' == $match[0]) {
+ $style->setBackground($match[1]);
+ } else {
+ try {
+ $style->setOption($match[1]);
+ } catch (\InvalidArgumentException $e) {
+ return false;
+ }
+ }
+ }
+
+ return $style;
+ }
+
+ /**
+ * Applies current style from stack to text, if must be applied.
+ *
+ * @param string $text Input text
+ *
+ * @return string Styled text
+ */
+ private function applyCurrentStyle($text)
+ {
+ return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
+ }
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php
new file mode 100644
index 00000000..5a52ba09
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php
@@ -0,0 +1,69 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Formatter;
+
+/**
+ * Formatter interface for console output.
+ *
+ * @author Konstantin Kudryashov
+ */
+interface OutputFormatterInterface
+{
+ /**
+ * Sets the decorated flag.
+ *
+ * @param bool $decorated Whether to decorate the messages or not
+ */
+ public function setDecorated($decorated);
+
+ /**
+ * Gets the decorated flag.
+ *
+ * @return bool true if the output will decorate messages, false otherwise
+ */
+ public function isDecorated();
+
+ /**
+ * Sets a new style.
+ *
+ * @param string $name The style name
+ * @param OutputFormatterStyleInterface $style The style instance
+ */
+ public function setStyle($name, OutputFormatterStyleInterface $style);
+
+ /**
+ * Checks if output formatter has style with specified name.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function hasStyle($name);
+
+ /**
+ * Gets style options from style with specified name.
+ *
+ * @param string $name
+ *
+ * @return OutputFormatterStyleInterface
+ */
+ public function getStyle($name);
+
+ /**
+ * Formats a message according to the given styles.
+ *
+ * @param string $message The message to style
+ *
+ * @return string The styled message
+ */
+ public function format($message);
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
new file mode 100644
index 00000000..c7c6b4a0
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
@@ -0,0 +1,221 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Formatter;
+
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * Formatter style class for defining styles.
+ *
+ * @author Konstantin Kudryashov
+ */
+class OutputFormatterStyle implements OutputFormatterStyleInterface
+{
+ private static $availableForegroundColors = array(
+ 'black' => array('set' => 30, 'unset' => 39),
+ 'red' => array('set' => 31, 'unset' => 39),
+ 'green' => array('set' => 32, 'unset' => 39),
+ 'yellow' => array('set' => 33, 'unset' => 39),
+ 'blue' => array('set' => 34, 'unset' => 39),
+ 'magenta' => array('set' => 35, 'unset' => 39),
+ 'cyan' => array('set' => 36, 'unset' => 39),
+ 'white' => array('set' => 37, 'unset' => 39),
+ 'default' => array('set' => 39, 'unset' => 39),
+ );
+ private static $availableBackgroundColors = array(
+ 'black' => array('set' => 40, 'unset' => 49),
+ 'red' => array('set' => 41, 'unset' => 49),
+ 'green' => array('set' => 42, 'unset' => 49),
+ 'yellow' => array('set' => 43, 'unset' => 49),
+ 'blue' => array('set' => 44, 'unset' => 49),
+ 'magenta' => array('set' => 45, 'unset' => 49),
+ 'cyan' => array('set' => 46, 'unset' => 49),
+ 'white' => array('set' => 47, 'unset' => 49),
+ 'default' => array('set' => 49, 'unset' => 49),
+ );
+ private static $availableOptions = array(
+ 'bold' => array('set' => 1, 'unset' => 22),
+ 'underscore' => array('set' => 4, 'unset' => 24),
+ 'blink' => array('set' => 5, 'unset' => 25),
+ 'reverse' => array('set' => 7, 'unset' => 27),
+ 'conceal' => array('set' => 8, 'unset' => 28),
+ );
+
+ private $foreground;
+ private $background;
+ private $options = array();
+
+ /**
+ * Initializes output formatter style.
+ *
+ * @param string|null $foreground The style foreground color name
+ * @param string|null $background The style background color name
+ * @param array $options The style options
+ */
+ public function __construct($foreground = null, $background = null, array $options = array())
+ {
+ if (null !== $foreground) {
+ $this->setForeground($foreground);
+ }
+ if (null !== $background) {
+ $this->setBackground($background);
+ }
+ if (count($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Sets style foreground color.
+ *
+ * @param string|null $color The color name
+ *
+ * @throws InvalidArgumentException When the color name isn't defined
+ */
+ public function setForeground($color = null)
+ {
+ if (null === $color) {
+ $this->foreground = null;
+
+ return;
+ }
+
+ if (!isset(static::$availableForegroundColors[$color])) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid foreground color specified: "%s". Expected one of (%s)',
+ $color,
+ implode(', ', array_keys(static::$availableForegroundColors))
+ ));
+ }
+
+ $this->foreground = static::$availableForegroundColors[$color];
+ }
+
+ /**
+ * Sets style background color.
+ *
+ * @param string|null $color The color name
+ *
+ * @throws InvalidArgumentException When the color name isn't defined
+ */
+ public function setBackground($color = null)
+ {
+ if (null === $color) {
+ $this->background = null;
+
+ return;
+ }
+
+ if (!isset(static::$availableBackgroundColors[$color])) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid background color specified: "%s". Expected one of (%s)',
+ $color,
+ implode(', ', array_keys(static::$availableBackgroundColors))
+ ));
+ }
+
+ $this->background = static::$availableBackgroundColors[$color];
+ }
+
+ /**
+ * Sets some specific style option.
+ *
+ * @param string $option The option name
+ *
+ * @throws InvalidArgumentException When the option name isn't defined
+ */
+ public function setOption($option)
+ {
+ if (!isset(static::$availableOptions[$option])) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid option specified: "%s". Expected one of (%s)',
+ $option,
+ implode(', ', array_keys(static::$availableOptions))
+ ));
+ }
+
+ if (!in_array(static::$availableOptions[$option], $this->options)) {
+ $this->options[] = static::$availableOptions[$option];
+ }
+ }
+
+ /**
+ * Unsets some specific style option.
+ *
+ * @param string $option The option name
+ *
+ * @throws InvalidArgumentException When the option name isn't defined
+ */
+ public function unsetOption($option)
+ {
+ if (!isset(static::$availableOptions[$option])) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid option specified: "%s". Expected one of (%s)',
+ $option,
+ implode(', ', array_keys(static::$availableOptions))
+ ));
+ }
+
+ $pos = array_search(static::$availableOptions[$option], $this->options);
+ if (false !== $pos) {
+ unset($this->options[$pos]);
+ }
+ }
+
+ /**
+ * Sets multiple style options at once.
+ *
+ * @param array $options
+ */
+ public function setOptions(array $options)
+ {
+ $this->options = array();
+
+ foreach ($options as $option) {
+ $this->setOption($option);
+ }
+ }
+
+ /**
+ * Applies the style to a given text.
+ *
+ * @param string $text The text to style
+ *
+ * @return string
+ */
+ public function apply($text)
+ {
+ $setCodes = array();
+ $unsetCodes = array();
+
+ if (null !== $this->foreground) {
+ $setCodes[] = $this->foreground['set'];
+ $unsetCodes[] = $this->foreground['unset'];
+ }
+ if (null !== $this->background) {
+ $setCodes[] = $this->background['set'];
+ $unsetCodes[] = $this->background['unset'];
+ }
+ if (count($this->options)) {
+ foreach ($this->options as $option) {
+ $setCodes[] = $option['set'];
+ $unsetCodes[] = $option['unset'];
+ }
+ }
+
+ if (0 === count($setCodes)) {
+ return $text;
+ }
+
+ return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
+ }
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
new file mode 100644
index 00000000..c36fda80
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Formatter;
+
+/**
+ * Formatter style interface for defining styles.
+ *
+ * @author Konstantin Kudryashov
+ */
+interface OutputFormatterStyleInterface
+{
+ /**
+ * Sets style foreground color.
+ *
+ * @param string $color The color name
+ */
+ public function setForeground($color = null);
+
+ /**
+ * Sets style background color.
+ *
+ * @param string $color The color name
+ */
+ public function setBackground($color = null);
+
+ /**
+ * Sets some specific style option.
+ *
+ * @param string $option The option name
+ */
+ public function setOption($option);
+
+ /**
+ * Unsets some specific style option.
+ *
+ * @param string $option The option name
+ */
+ public function unsetOption($option);
+
+ /**
+ * Sets multiple style options at once.
+ *
+ * @param array $options
+ */
+ public function setOptions(array $options);
+
+ /**
+ * Applies the style to a given text.
+ *
+ * @param string $text The text to style
+ *
+ * @return string
+ */
+ public function apply($text);
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
new file mode 100644
index 00000000..e5d14ea3
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
@@ -0,0 +1,123 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Formatter;
+
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * @author Jean-François Simon