##// END OF EJS Templates
dummysmtpd: accept additional kwargs from stdlib smtpd...
Augie Fackler -
r39064:78f1899e default
parent child Browse files
Show More
@@ -1,550 +1,551
1 1 test-abort-checkin.t
2 2 test-absorb-filefixupstate.py
3 3 test-absorb-phase.t
4 4 test-absorb-strip.t
5 5 test-add.t
6 6 test-addremove-similar.t
7 7 test-addremove.t
8 8 test-alias.t
9 9 test-amend-subrepo.t
10 10 test-amend.t
11 11 test-ancestor.py
12 12 test-annotate.py
13 13 test-annotate.t
14 14 test-archive-symlinks.t
15 15 test-atomictempfile.py
16 16 test-audit-path.t
17 17 test-audit-subrepo.t
18 18 test-automv.t
19 19 test-backout.t
20 20 test-backwards-remove.t
21 21 test-bad-pull.t
22 22 test-basic.t
23 23 test-bheads.t
24 24 test-bisect.t
25 25 test-bisect2.t
26 26 test-bisect3.t
27 27 test-blackbox.t
28 28 test-bookmarks-current.t
29 29 test-bookmarks-merge.t
30 30 test-bookmarks-pushpull.t
31 31 test-bookmarks-rebase.t
32 32 test-bookmarks-strip.t
33 33 test-bookmarks.t
34 34 test-branch-change.t
35 35 test-branch-option.t
36 36 test-branch-tag-confict.t
37 37 test-branches.t
38 38 test-bundle-phases.t
39 39 test-bundle-r.t
40 40 test-bundle-type.t
41 41 test-bundle-vs-outgoing.t
42 42 test-bundle.t
43 43 test-bundle2-exchange.t
44 44 test-bundle2-format.t
45 45 test-bundle2-multiple-changegroups.t
46 46 test-bundle2-pushback.t
47 47 test-bundle2-remote-changegroup.t
48 48 test-cappedreader.py
49 49 test-casecollision.t
50 50 test-cat.t
51 51 test-cbor.py
52 52 test-censor.t
53 53 test-changelog-exec.t
54 54 test-check-commit.t
55 55 test-check-execute.t
56 56 test-check-interfaces.py
57 57 test-check-module-imports.t
58 58 test-check-pyflakes.t
59 59 test-check-pylint.t
60 60 test-check-shbang.t
61 61 test-children.t
62 62 test-clone-cgi.t
63 63 test-clone-pull-corruption.t
64 64 test-clone-r.t
65 65 test-clone-update-order.t
66 66 test-clonebundles.t
67 67 test-commit-amend.t
68 68 test-commit-interactive.t
69 69 test-commit-multiple.t
70 70 test-commit-unresolved.t
71 71 test-commit.t
72 72 test-committer.t
73 73 test-completion.t
74 74 test-config-env.py
75 75 test-config.t
76 76 test-conflict.t
77 77 test-confused-revert.t
78 78 test-context.py
79 79 test-contrib-check-code.t
80 80 test-contrib-check-commit.t
81 81 test-convert-authormap.t
82 82 test-convert-clonebranches.t
83 83 test-convert-cvs-branch.t
84 84 test-convert-cvs-detectmerge.t
85 85 test-convert-cvs-synthetic.t
86 86 test-convert-cvs.t
87 87 test-convert-cvsnt-mergepoints.t
88 88 test-convert-datesort.t
89 89 test-convert-filemap.t
90 90 test-convert-hg-sink.t
91 91 test-convert-hg-source.t
92 92 test-convert-hg-startrev.t
93 93 test-convert-splicemap.t
94 94 test-convert-tagsbranch-topology.t
95 95 test-copy-move-merge.t
96 96 test-copy.t
97 97 test-copytrace-heuristics.t
98 98 test-debugbuilddag.t
99 99 test-debugbundle.t
100 100 test-debugextensions.t
101 101 test-debugindexdot.t
102 102 test-debugrename.t
103 103 test-default-push.t
104 104 test-diff-antipatience.t
105 105 test-diff-binary-file.t
106 106 test-diff-change.t
107 107 test-diff-copy-depth.t
108 108 test-diff-hashes.t
109 109 test-diff-ignore-whitespace.t
110 110 test-diff-indent-heuristic.t
111 111 test-diff-issue2761.t
112 112 test-diff-newlines.t
113 113 test-diff-reverse.t
114 114 test-diff-subdir.t
115 115 test-diff-unified.t
116 116 test-diff-upgrade.t
117 117 test-diffdir.t
118 118 test-diffstat.t
119 119 test-directaccess.t
120 120 test-dirstate-backup.t
121 121 test-dirstate-nonnormalset.t
122 122 test-dirstate.t
123 123 test-dispatch.py
124 124 test-doctest.py
125 125 test-double-merge.t
126 126 test-drawdag.t
127 127 test-duplicateoptions.py
128 128 test-editor-filename.t
129 129 test-empty-dir.t
130 130 test-empty-file.t
131 131 test-empty-group.t
132 132 test-empty.t
133 133 test-encode.t
134 134 test-encoding-func.py
135 135 test-encoding.t
136 136 test-eol-add.t
137 137 test-eol-clone.t
138 138 test-eol-hook.t
139 139 test-eol-patch.t
140 140 test-eol-tag.t
141 141 test-eol-update.t
142 142 test-eol.t
143 143 test-eolfilename.t
144 144 test-excessive-merge.t
145 145 test-exchange-obsmarkers-case-A1.t
146 146 test-exchange-obsmarkers-case-A2.t
147 147 test-exchange-obsmarkers-case-A3.t
148 148 test-exchange-obsmarkers-case-A4.t
149 149 test-exchange-obsmarkers-case-A5.t
150 150 test-exchange-obsmarkers-case-A6.t
151 151 test-exchange-obsmarkers-case-A7.t
152 152 test-exchange-obsmarkers-case-B1.t
153 153 test-exchange-obsmarkers-case-B2.t
154 154 test-exchange-obsmarkers-case-B3.t
155 155 test-exchange-obsmarkers-case-B4.t
156 156 test-exchange-obsmarkers-case-B5.t
157 157 test-exchange-obsmarkers-case-B6.t
158 158 test-exchange-obsmarkers-case-B7.t
159 159 test-exchange-obsmarkers-case-C1.t
160 160 test-exchange-obsmarkers-case-C2.t
161 161 test-exchange-obsmarkers-case-C3.t
162 162 test-exchange-obsmarkers-case-C4.t
163 163 test-exchange-obsmarkers-case-D1.t
164 164 test-exchange-obsmarkers-case-D2.t
165 165 test-exchange-obsmarkers-case-D3.t
166 166 test-exchange-obsmarkers-case-D4.t
167 167 test-execute-bit.t
168 168 test-export.t
169 169 test-extdata.t
170 170 test-extdiff.t
171 171 test-extensions-afterloaded.t
172 172 test-extensions-wrapfunction.py
173 173 test-extra-filelog-entry.t
174 174 test-fetch.t
175 175 test-filebranch.t
176 176 test-filecache.py
177 177 test-filelog.py
178 178 test-fileset-generated.t
179 179 test-fileset.t
180 180 test-fix-topology.t
181 181 test-flags.t
182 182 test-generaldelta.t
183 183 test-getbundle.t
184 184 test-git-export.t
185 185 test-glog-topological.t
186 186 test-gpg.t
187 187 test-graft.t
188 188 test-hg-parseurl.py
189 189 test-hghave.t
190 190 test-hgignore.t
191 191 test-hgk.t
192 192 test-hgrc.t
193 193 test-hgweb-bundle.t
194 194 test-hgweb-descend-empties.t
195 195 test-hgweb-empty.t
196 196 test-hgweb-removed.t
197 197 test-hgwebdir-paths.py
198 198 test-hgwebdirsym.t
199 199 test-histedit-arguments.t
200 200 test-histedit-base.t
201 201 test-histedit-bookmark-motion.t
202 202 test-histedit-commute.t
203 203 test-histedit-drop.t
204 204 test-histedit-edit.t
205 205 test-histedit-fold-non-commute.t
206 206 test-histedit-fold.t
207 207 test-histedit-no-backup.t
208 208 test-histedit-no-change.t
209 209 test-histedit-non-commute-abort.t
210 210 test-histedit-non-commute.t
211 211 test-histedit-obsolete.t
212 212 test-histedit-outgoing.t
213 213 test-histedit-templates.t
214 214 test-http-branchmap.t
215 215 test-http-bundle1.t
216 216 test-http-clone-r.t
217 217 test-http.t
218 218 test-hybridencode.py
219 219 test-identify.t
220 220 test-impexp-branch.t
221 221 test-import-bypass.t
222 222 test-import-eol.t
223 223 test-import-merge.t
224 224 test-import-unknown.t
225 225 test-import.t
226 226 test-imports-checker.t
227 227 test-incoming-outgoing.t
228 228 test-inherit-mode.t
229 229 test-init.t
230 230 test-issue1089.t
231 231 test-issue1102.t
232 232 test-issue1175.t
233 233 test-issue1306.t
234 234 test-issue1438.t
235 235 test-issue1502.t
236 236 test-issue1802.t
237 237 test-issue1877.t
238 238 test-issue1993.t
239 239 test-issue2137.t
240 240 test-issue3084.t
241 241 test-issue4074.t
242 242 test-issue522.t
243 243 test-issue586.t
244 244 test-issue612.t
245 245 test-issue619.t
246 246 test-issue660.t
247 247 test-issue672.t
248 248 test-issue842.t
249 249 test-journal-exists.t
250 250 test-journal-share.t
251 251 test-journal.t
252 252 test-known.t
253 253 test-largefiles-cache.t
254 254 test-largefiles-misc.t
255 255 test-largefiles-small-disk.t
256 256 test-largefiles-update.t
257 257 test-largefiles.t
258 258 test-lfs-largefiles.t
259 259 test-lfs-pointer.py
260 260 test-linelog.py
261 261 test-linerange.py
262 262 test-locate.t
263 263 test-lock-badness.t
264 264 test-log-linerange.t
265 265 test-log.t
266 266 test-logexchange.t
267 267 test-lrucachedict.py
268 268 test-mactext.t
269 269 test-mailmap.t
270 270 test-manifest-merging.t
271 271 test-manifest.py
272 272 test-manifest.t
273 273 test-match.py
274 274 test-mdiff.py
275 275 test-merge-changedelete.t
276 276 test-merge-closedheads.t
277 277 test-merge-commit.t
278 278 test-merge-criss-cross.t
279 279 test-merge-default.t
280 280 test-merge-force.t
281 281 test-merge-halt.t
282 282 test-merge-internal-tools-pattern.t
283 283 test-merge-local.t
284 284 test-merge-remove.t
285 285 test-merge-revert.t
286 286 test-merge-revert2.t
287 287 test-merge-subrepos.t
288 288 test-merge-symlinks.t
289 289 test-merge-tools.t
290 290 test-merge-types.t
291 291 test-merge1.t
292 292 test-merge10.t
293 293 test-merge2.t
294 294 test-merge4.t
295 295 test-merge5.t
296 296 test-merge6.t
297 297 test-merge7.t
298 298 test-merge8.t
299 299 test-merge9.t
300 300 test-minifileset.py
301 301 test-minirst.py
302 302 test-mq-git.t
303 303 test-mq-header-date.t
304 304 test-mq-header-from.t
305 305 test-mq-merge.t
306 306 test-mq-pull-from-bundle.t
307 307 test-mq-qclone-http.t
308 308 test-mq-qdelete.t
309 309 test-mq-qdiff.t
310 310 test-mq-qfold.t
311 311 test-mq-qgoto.t
312 312 test-mq-qimport-fail-cleanup.t
313 313 test-mq-qnew.t
314 314 test-mq-qpush-exact.t
315 315 test-mq-qqueue.t
316 316 test-mq-qrefresh-interactive.t
317 317 test-mq-qrefresh-replace-log-message.t
318 318 test-mq-qrefresh.t
319 319 test-mq-qrename.t
320 320 test-mq-qsave.t
321 321 test-mq-safety.t
322 322 test-mq-subrepo.t
323 323 test-mq-symlinks.t
324 324 test-mv-cp-st-diff.t
325 325 test-narrow-acl.t
326 326 test-narrow-archive.t
327 327 test-narrow-clone-no-ellipsis.t
328 328 test-narrow-clone-non-narrow-server.t
329 329 test-narrow-clone-nonlinear.t
330 330 test-narrow-clone.t
331 331 test-narrow-commit.t
332 332 test-narrow-copies.t
333 333 test-narrow-debugcommands.t
334 334 test-narrow-debugrebuilddirstate.t
335 335 test-narrow-exchange-merges.t
336 336 test-narrow-exchange.t
337 337 test-narrow-expanddirstate.t
338 338 test-narrow-merge.t
339 339 test-narrow-patch.t
340 340 test-narrow-patterns.t
341 341 test-narrow-pull.t
342 342 test-narrow-rebase.t
343 343 test-narrow-shallow-merges.t
344 344 test-narrow-shallow.t
345 345 test-narrow-strip.t
346 346 test-narrow-update.t
347 347 test-narrow-widen.t
348 348 test-narrow.t
349 349 test-nested-repo.t
350 350 test-newbranch.t
351 351 test-nointerrupt.t
352 352 test-obshistory.t
353 353 test-obsmarker-template.t
354 354 test-obsmarkers-effectflag.t
355 355 test-obsolete-bundle-strip.t
356 356 test-obsolete-changeset-exchange.t
357 357 test-obsolete-checkheads.t
358 358 test-obsolete-distributed.t
359 359 test-obsolete-divergent.t
360 360 test-obsolete-tag-cache.t
361 361 test-pager.t
362 362 test-parents.t
363 363 test-parseindex2.py
364 364 test-patch-offset.t
365 365 test-patch.t
366 test-patchbomb-tls.t
366 367 test-pathconflicts-merge.t
367 368 test-pathconflicts-update.t
368 369 test-pathencode.py
369 370 test-pending.t
370 371 test-permissions.t
371 372 test-phases.t
372 373 test-pull-branch.t
373 374 test-pull-http.t
374 375 test-pull-permission.t
375 376 test-pull-pull-corruption.t
376 377 test-pull-r.t
377 378 test-pull-update.t
378 379 test-pull.t
379 380 test-purge.t
380 381 test-push-checkheads-partial-C1.t
381 382 test-push-checkheads-partial-C2.t
382 383 test-push-checkheads-partial-C3.t
383 384 test-push-checkheads-partial-C4.t
384 385 test-push-checkheads-pruned-B1.t
385 386 test-push-checkheads-pruned-B2.t
386 387 test-push-checkheads-pruned-B3.t
387 388 test-push-checkheads-pruned-B4.t
388 389 test-push-checkheads-pruned-B5.t
389 390 test-push-checkheads-pruned-B6.t
390 391 test-push-checkheads-pruned-B7.t
391 392 test-push-checkheads-pruned-B8.t
392 393 test-push-checkheads-superceed-A1.t
393 394 test-push-checkheads-superceed-A2.t
394 395 test-push-checkheads-superceed-A3.t
395 396 test-push-checkheads-superceed-A4.t
396 397 test-push-checkheads-superceed-A5.t
397 398 test-push-checkheads-superceed-A6.t
398 399 test-push-checkheads-superceed-A7.t
399 400 test-push-checkheads-superceed-A8.t
400 401 test-push-checkheads-unpushed-D1.t
401 402 test-push-checkheads-unpushed-D2.t
402 403 test-push-checkheads-unpushed-D3.t
403 404 test-push-checkheads-unpushed-D4.t
404 405 test-push-checkheads-unpushed-D5.t
405 406 test-push-checkheads-unpushed-D6.t
406 407 test-push-checkheads-unpushed-D7.t
407 408 test-push-http.t
408 409 test-push-warn.t
409 410 test-push.t
410 411 test-pushvars.t
411 412 test-qrecord.t
412 413 test-rebase-abort.t
413 414 test-rebase-backup.t
414 415 test-rebase-base-flag.t
415 416 test-rebase-bookmarks.t
416 417 test-rebase-brute-force.t
417 418 test-rebase-cache.t
418 419 test-rebase-check-restore.t
419 420 test-rebase-collapse.t
420 421 test-rebase-conflicts.t
421 422 test-rebase-dest.t
422 423 test-rebase-detach.t
423 424 test-rebase-emptycommit.t
424 425 test-rebase-inmemory.t
425 426 test-rebase-interruptions.t
426 427 test-rebase-issue-noparam-single-rev.t
427 428 test-rebase-legacy.t
428 429 test-rebase-mq-skip.t
429 430 test-rebase-mq.t
430 431 test-rebase-named-branches.t
431 432 test-rebase-newancestor.t
432 433 test-rebase-obsolete.t
433 434 test-rebase-parameters.t
434 435 test-rebase-partial.t
435 436 test-rebase-pull.t
436 437 test-rebase-rename.t
437 438 test-rebase-scenario-global.t
438 439 test-rebase-templates.t
439 440 test-rebase-transaction.t
440 441 test-rebuildstate.t
441 442 test-record.t
442 443 test-relink.t
443 444 test-remove.t
444 445 test-removeemptydirs.t
445 446 test-rename-after-merge.t
446 447 test-rename-dir-merge.t
447 448 test-rename-merge1.t
448 449 test-rename.t
449 450 test-repair-strip.t
450 451 test-repo-compengines.t
451 452 test-resolve.t
452 453 test-revert-flags.t
453 454 test-revert-interactive.t
454 455 test-revert-unknown.t
455 456 test-revisions.t
456 457 test-revlog-ancestry.py
457 458 test-revlog-group-emptyiter.t
458 459 test-revlog-mmapindex.t
459 460 test-revlog-packentry.t
460 461 test-revlog-raw.py
461 462 test-revlog-v2.t
462 463 test-revset-dirstate-parents.t
463 464 test-revset-legacy-lookup.t
464 465 test-revset-outgoing.t
465 466 test-rollback.t
466 467 test-run-tests.py
467 468 test-run-tests.t
468 469 test-schemes.t
469 470 test-serve.t
470 471 test-setdiscovery.t
471 472 test-share.t
472 473 test-shelve.t
473 474 test-show-stack.t
474 475 test-show-work.t
475 476 test-show.t
476 477 test-simple-update.t
477 478 test-simplekeyvaluefile.py
478 479 test-simplemerge.py
479 480 test-single-head.t
480 481 test-sparse-clear.t
481 482 test-sparse-clone.t
482 483 test-sparse-import.t
483 484 test-sparse-merges.t
484 485 test-sparse-profiles.t
485 486 test-sparse-requirement.t
486 487 test-sparse-verbose-json.t
487 488 test-sparse.t
488 489 test-split.t
489 490 test-ssh-bundle1.t
490 491 test-ssh-clone-r.t
491 492 test-ssh-proto-unbundle.t
492 493 test-ssh-proto.t
493 494 test-ssh.t
494 495 test-sshserver.py
495 496 test-stack.t
496 497 test-status-inprocess.py
497 498 test-status-rev.t
498 499 test-status-terse.t
499 500 test-strict.t
500 501 test-strip-cross.t
501 502 test-strip.t
502 503 test-subrepo-deep-nested-change.t
503 504 test-subrepo-missing.t
504 505 test-subrepo-paths.t
505 506 test-subrepo-recursion.t
506 507 test-subrepo-relative-path.t
507 508 test-subrepo.t
508 509 test-symlink-os-yes-fs-no.py
509 510 test-symlink-placeholder.t
510 511 test-symlinks.t
511 512 test-tag.t
512 513 test-tags.t
513 514 test-template-basic.t
514 515 test-template-functions.t
515 516 test-template-keywords.t
516 517 test-template-map.t
517 518 test-transplant.t
518 519 test-treemanifest.t
519 520 test-ui-color.py
520 521 test-ui-config.py
521 522 test-ui-verbosity.py
522 523 test-unamend.t
523 524 test-unbundlehash.t
524 525 test-uncommit.t
525 526 test-unified-test.t
526 527 test-unionrepo.t
527 528 test-unrelated-pull.t
528 529 test-up-local-change.t
529 530 test-update-branches.t
530 531 test-update-dest.t
531 532 test-update-issue1456.t
532 533 test-update-names.t
533 534 test-update-reverse.t
534 535 test-upgrade-repo.t
535 536 test-url-download.t
536 537 test-url-rev.t
537 538 test-url.py
538 539 test-username-newline.t
539 540 test-util.py
540 541 test-verify.t
541 542 test-walk.t
542 543 test-walkrepo.py
543 544 test-websub.t
544 545 test-win32text.t
545 546 test-wireproto-clientreactor.py
546 547 test-wireproto-framing.py
547 548 test-wireproto-serverreactor.py
548 549 test-wireproto.py
549 550 test-wsgirequest.py
550 551 test-xdg.t
@@ -1,108 +1,108
1 1 #!/usr/bin/env python
2 2
3 3 """dummy SMTP server for use in tests"""
4 4
5 5 from __future__ import absolute_import
6 6
7 7 import asyncore
8 8 import optparse
9 9 import smtpd
10 10 import ssl
11 11 import sys
12 12 import traceback
13 13
14 14 from mercurial import (
15 15 pycompat,
16 16 server,
17 17 sslutil,
18 18 ui as uimod,
19 19 )
20 20
21 21 def log(msg):
22 22 sys.stdout.write(msg)
23 23 sys.stdout.flush()
24 24
25 25 class dummysmtpserver(smtpd.SMTPServer):
26 26 def __init__(self, localaddr):
27 27 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None)
28 28
29 def process_message(self, peer, mailfrom, rcpttos, data):
29 def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
30 30 log('%s from=%s to=%s\n' % (peer[0], mailfrom, ', '.join(rcpttos)))
31 31
32 32 def handle_error(self):
33 33 # On Windows, a bad SSL connection sometimes generates a WSAECONNRESET.
34 34 # The default handler will shutdown this server, and then both the
35 35 # current connection and subsequent ones fail on the client side with
36 36 # "No connection could be made because the target machine actively
37 37 # refused it". If we eat the error, then the client properly aborts in
38 38 # the expected way, and the server is available for subsequent requests.
39 39 traceback.print_exc()
40 40
41 41 class dummysmtpsecureserver(dummysmtpserver):
42 42 def __init__(self, localaddr, certfile):
43 43 dummysmtpserver.__init__(self, localaddr)
44 44 self._certfile = certfile
45 45
46 46 def handle_accept(self):
47 47 pair = self.accept()
48 48 if not pair:
49 49 return
50 50 conn, addr = pair
51 51 ui = uimod.ui.load()
52 52 try:
53 53 # wrap_socket() would block, but we don't care
54 54 conn = sslutil.wrapserversocket(conn, ui, certfile=self._certfile)
55 55 except ssl.SSLError:
56 56 log('%s ssl error\n' % addr[0])
57 57 conn.close()
58 58 return
59 59 smtpd.SMTPChannel(self, conn, addr)
60 60
61 61 def run():
62 62 try:
63 63 asyncore.loop()
64 64 except KeyboardInterrupt:
65 65 pass
66 66
67 67 def _encodestrsonly(v):
68 68 if isinstance(v, type(u'')):
69 69 return v.encode('ascii')
70 70 return v
71 71
72 72 def bytesvars(obj):
73 73 unidict = vars(obj)
74 74 bd = {k.encode('ascii'): _encodestrsonly(v) for k, v in unidict.items()}
75 75 if bd[b'daemon_postexec'] is not None:
76 76 bd[b'daemon_postexec'] = [
77 77 _encodestrsonly(v) for v in bd[b'daemon_postexec']]
78 78 return bd
79 79
80 80 def main():
81 81 op = optparse.OptionParser()
82 82 op.add_option('-d', '--daemon', action='store_true')
83 83 op.add_option('--daemon-postexec', action='append')
84 84 op.add_option('-p', '--port', type=int, default=8025)
85 85 op.add_option('-a', '--address', default='localhost')
86 86 op.add_option('--pid-file', metavar='FILE')
87 87 op.add_option('--tls', choices=['none', 'smtps'], default='none')
88 88 op.add_option('--certificate', metavar='FILE')
89 89
90 90 opts, args = op.parse_args()
91 91 if opts.tls == 'smtps' and not opts.certificate:
92 92 op.error('--certificate must be specified')
93 93
94 94 addr = (opts.address, opts.port)
95 95 def init():
96 96 if opts.tls == 'none':
97 97 dummysmtpserver(addr)
98 98 else:
99 99 dummysmtpsecureserver(addr, opts.certificate)
100 100 log('listening at %s:%d\n' % addr)
101 101
102 102 server.runservice(
103 103 bytesvars(opts), initfn=init, runfn=run,
104 104 runargs=[pycompat.sysexecutable,
105 105 pycompat.fsencode(__file__)] + pycompat.sysargv[1:])
106 106
107 107 if __name__ == '__main__':
108 108 main()
General Comments 0
You need to be logged in to leave comments. Login now