SquirrelMail

Check-in [d293b3aeaf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial snapshot
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:d293b3aeaf889162087ffdec5e673cfa341316c5e2cf280645926165392504bb
User & Date: ajv 2018-04-19 03:11:10
Context
2018-04-19
03:12
Ignore our link to external config check-in: 172df82f66 user: ajv tags: trunk
03:11
Initial snapshot check-in: d293b3aeaf user: ajv tags: trunk
03:09
initial empty check-in check-in: 9a80d3bf37 user: ajv tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added class/deliver/Deliver.class.php.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
<?php

/**
 * Deliver.class.php
 *
 * This contains all the functions needed to send messages through
 * a delivery backend.
 *
 * @author Marc Groot Koerkamp
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Deliver.class.php 14311 2012-04-01 22:09:14Z pdontthink $
 * @package squirrelmail
 */

/**
 * Deliver Class - called to actually deliver the message
 *
 * This class is called by compose.php and other code that needs
 * to send messages.  All delivery functionality should be centralized
 * in this class.
 *
 * Do not place UI code in this class, as UI code should be placed in templates
 * going forward.
 *
 * @author  Marc Groot Koerkamp
 * @package squirrelmail
 */
class Deliver {

    /**
     * function mail - send the message parts to the SMTP stream
     *
     * @param Message  $message      Message object to send
     *                               NOTE that this is passed by
     *                               reference and will be modified
     *                               upon return with updated
     *                               fields such as Message ID, References,
     *                               In-Reply-To and Date headers.
     * @param resource $stream       Handle to the outgoing stream
     *                               (when FALSE, nothing will be
     *                               written to the stream; this can
     *                               be used to determine the actual
     *                               number of bytes that will be 
     *                               written to the stream)
     * @param string   $reply_id     Identifies message being replied to
     *                               (OPTIONAL; caller should ONLY specify
     *                               a value for this when the message
     *                               being sent is a reply)
     * @param string   $reply_ent_id Identifies message being replied to
     *                               in the case it was an embedded/attached
     *                               message inside another (OPTIONAL; caller
     *                               should ONLY specify a value for this 
     *                               when the message being sent is a reply)
     * @param resource $imap_stream  If there is an open IMAP stream in 
     *                               the caller's context, it should be
     *                               passed in here.  This is OPTIONAL,
     *                               as one will be created if not given,
     *                               but as some IMAP servers may baulk
     *                               at opening more than one connection
     *                               at a time, the caller should always
     *                               abide if possible.  Currently, this
     *                               stream is only used when $reply_id
     *                               is also non-zero, but that is subject
     *                               to change.
     * @param mixed    $extra        Any implementation-specific variables
     *                               can be passed in here and used in
     *                               an overloaded version of this method
     *                               if needed.
     *
     * @return integer The number of bytes written (or that would have been
     *                 written) to the output stream.
     *
     */
    function mail(&$message, $stream=false, $reply_id=0, $reply_ent_id=0, 
                  $imap_stream=NULL, $extra=NULL) {

        $rfc822_header = &$message->rfc822_header;

        if (count($message->entities)) {
            $boundary = $this->mimeBoundary();
            $rfc822_header->content_type->properties['boundary']='"'.$boundary.'"';
        } else {
            $boundary='';
        }
        $raw_length = 0;


        // calculate reply header if needed
        //
        if ($reply_id) {
            global $imapConnection, $username, $key, $imapServerAddress, 
                   $imapPort, $mailbox;

            // try our best to use an existing IMAP handle
            //
            $close_imap_stream = FALSE;
            if (is_resource($imap_stream)) {
                $my_imap_stream = $imap_stream;

            } else if (is_resource($imapConnection)) {
                $my_imap_stream = $imapConnection;

            } else {
                $close_imap_stream = TRUE;
                $my_imap_stream = sqimap_login($username, $key,
                                               $imapServerAddress, $imapPort, 0);
            } 

            sqimap_mailbox_select($my_imap_stream, $mailbox);
            $reply_message = sqimap_get_message($my_imap_stream, $reply_id, $mailbox);

            if ($close_imap_stream) {
                sqimap_logout($my_imap_stream);
            }

            if ($reply_ent_id) {
                /* redefine the messsage in case of message/rfc822 */
                $reply_message = $message->getEntity($reply_ent_id);
                /* message is an entity which contains the envelope and type0=message
                 * and type1=rfc822. The actual entities are childs from
                 * $reply_message->entities[0]. That's where the encoding and is located
                 */

                $orig_header = $reply_message->rfc822_header; /* here is the envelope located */

            } else {
                $orig_header = $reply_message->rfc822_header;
            }
            $message->reply_rfc822_header = $orig_header;            
        }


        $reply_rfc822_header = (isset($message->reply_rfc822_header)
                             ? $message->reply_rfc822_header : '');
        $header = $this->prepareRFC822_Header($rfc822_header, $reply_rfc822_header, $raw_length);

        $this->send_mail($message, $header, $boundary, $stream, $raw_length, $extra);

        return $raw_length;
    }

    /**
     * function send_mail - send the message parts to the IMAP stream
     *
     * @param Message  $message      Message object to send
     * @param string   $header       Headers ready to send
     * @param string   $boundary     Message parts boundary
     * @param resource $stream       Handle to the SMTP stream
     *                               (when FALSE, nothing will be
     *                               written to the stream; this can
     *                               be used to determine the actual
     *                               number of bytes that will be
     *                               written to the stream)
     * @param int     &$raw_length   The number of bytes written (or that
     *                               would have been written) to the 
     *                               output stream - NOTE that this is
     *                               passed by reference
     * @param mixed    $extra        Any implementation-specific variables
     *                               can be passed in here and used in
     *                               an overloaded version of this method
     *                               if needed.
     *
     * @return void
     *
     */
    function send_mail($message, $header, $boundary, $stream=false, 
                       &$raw_length, $extra=NULL) {

        if ($stream) {
            $this->preWriteToStream($header);
            $this->writeToStream($stream, $header);
        }
        $this->writeBody($message, $stream, $raw_length, $boundary);
    }

    /**
     * function writeBody - generate and write the mime boundaries around each part to the stream
     *
     * Recursively formats and writes the MIME boundaries of the $message
     * to the output stream.
     *
     * @param Message   $message      Message object to transform
     * @param resource  $stream       SMTP output stream
     *                                (when FALSE, nothing will be
     *                                written to the stream; this can
     *                                be used to determine the actual
     *                                number of bytes that will be 
     *                                written to the stream)
     * @param integer  &$length_raw   raw length of the message (part)
     *                                as returned by mail fn
     * @param string    $boundary     custom boundary to call, usually for subparts
     *
     * @return void
     */
    function writeBody($message, $stream, &$length_raw, $boundary='') {
        // calculate boundary in case of multidimensional mime structures
        if ($boundary && $message->entity_id && count($message->entities)) {
            if (strpos($boundary,'_part_')) {
                $boundary = substr($boundary,0,strpos($boundary,'_part_'));

            // the next four lines use strrev to reverse any nested boundaries
            // because RFC 2046 (5.1.1) says that if a line starts with the outer
            // boundary string (doesn't matter what the line ends with), that
            // can be considered a match for the outer boundary; thus the nested
            // boundary needs to be unique from the outer one
            //
            } else if (strpos($boundary,'_trap_')) {
                $boundary = substr(strrev($boundary),0,strpos(strrev($boundary),'_part_'));
            }
            $boundary_new = strrev($boundary . '_part_'.$message->entity_id);
        } else {
            $boundary_new = $boundary;
        }
        if ($boundary && !$message->rfc822_header) {
            $s = '--'.$boundary."\r\n";
            $s .= $this->prepareMIME_Header($message, $boundary_new);
            $length_raw += strlen($s);
            if ($stream) {
                $this->preWriteToStream($s);
                $this->writeToStream($stream, $s);
            }
        }
        $this->writeBodyPart($message, $stream, $length_raw);

        $last = false;
        for ($i=0, $entCount=count($message->entities);$i<$entCount;$i++) {
            $msg = $this->writeBody($message->entities[$i], $stream, $length_raw, $boundary_new);
            if ($i == $entCount-1) $last = true;
        }
        if ($boundary && $last) {
            $s = "--".$boundary_new."--\r\n\r\n";
            $length_raw += strlen($s);
            if ($stream) {
                $this->preWriteToStream($s);
                $this->writeToStream($stream, $s);
            }
        }
    }

    /**
     * function writeBodyPart - write each individual mimepart
     *
     * Recursively called by WriteBody to write each mime part to the SMTP stream
     *
     * @param Message   $message      Message object to transform
     * @param resource  $stream       SMTP output stream
     *                                (when FALSE, nothing will be
     *                                written to the stream; this can
     *                                be used to determine the actual
     *                                number of bytes that will be 
     *                                written to the stream)
     * @param integer  &$length       length of the message part
     *                                as returned by mail fn
     *
     * @return void
     */
    function writeBodyPart($message, $stream, &$length) {
        if ($message->mime_header) {
            $type0 = $message->mime_header->type0;
        } else {
            $type0 = $message->rfc822_header->content_type->type0;
        }

        $body_part_trailing = $last = '';
        switch ($type0)
        {
        case 'text':
        case 'message':
            if ($message->body_part) {
                $body_part = $message->body_part;
                // remove NUL characters
                $body_part = str_replace("\0",'',$body_part);
                $length += $this->clean_crlf($body_part);
                if ($stream) {
                    $this->preWriteToStream($body_part);
                    $this->writeToStream($stream, $body_part);
                }
                $last = $body_part;
            } elseif ($message->att_local_name) {
                global $username, $attachment_dir;
                $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
                $filename = $message->att_local_name;

                // inspect attached file for lines longer than allowed by RFC,
                // in which case we'll be using base64 encoding (so we can split
                // the lines up without corrupting them) instead of 8bit unencoded...
                // (see RFC 2822/2.1.1)
                //
                // using 990 because someone somewhere is folding lines at
                // 990 instead of 998 and I'm too lazy to find who it is
                //
                $file_has_long_lines = file_has_long_lines($hashed_attachment_dir
                                                           . '/' . $filename, 990);

                $file = fopen ($hashed_attachment_dir . '/' . $filename, 'rb');

                // long lines were found, need to use base64 encoding
                //
                if ($file_has_long_lines) {
                    while ($tmp = fread($file, 570)) {
                        $body_part = chunk_split(base64_encode($tmp));
                        // Up to 4.3.10 chunk_split always appends a newline,
                        // while in 4.3.11 it doesn't if the string to split
                        // is shorter than the chunk length.
                        if( substr($body_part, -1 , 1 ) != "\n" )
                            $body_part .= "\n";
                        $length += $this->clean_crlf($body_part);
                        if ($stream) {
                            $this->writeToStream($stream, $body_part);
                        }
                    }
                }

                // no excessively long lines - normal 8bit
                //
                else {
                    while ($body_part = fgets($file, 4096)) {
                        $length += $this->clean_crlf($body_part);
                        if ($stream) {
                            $this->preWriteToStream($body_part);
                            $this->writeToStream($stream, $body_part);
                        }
                        $last = $body_part;
                    }
                }

                fclose($file);
            }
            break;
        default:
            if ($message->body_part) {
                $body_part = $message->body_part;
                $length += $this->clean_crlf($body_part);
                if ($stream) {
                    $this->writeToStream($stream, $body_part);
                }
            } elseif ($message->att_local_name) {
                global $username, $attachment_dir;
                $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
                $filename = $message->att_local_name;
                $file = fopen ($hashed_attachment_dir . '/' . $filename, 'rb');
                
                while ($tmp = fread($file, 570)) {
                    $body_part = chunk_split(base64_encode($tmp));
                    // Up to 4.3.10 chunk_split always appends a newline,
                    // while in 4.3.11 it doesn't if the string to split
                    // is shorter than the chunk length.
                    if( substr($body_part, -1 , 1 ) != "\n" )
                        $body_part .= "\n";
                    $length += $this->clean_crlf($body_part);
                    if ($stream) {
                        $this->writeToStream($stream, $body_part);
                    }
                }
                fclose($file);
            }
            break;
        }
        $body_part_trailing = '';
        if ($last && substr($last,-1) != "\n") {
            $body_part_trailing = "\r\n";
        }
        if ($body_part_trailing) {
            $length += strlen($body_part_trailing);
            if ($stream) {
                $this->preWriteToStream($body_part_trailing);
                $this->writeToStream($stream, $body_part_trailing);
            }
        }
    }

    /**
     * function clean_crlf - change linefeeds and newlines to legal characters
     *
     * The SMTP format only allows CRLF as line terminators.
     * This function replaces illegal teminators with the correct terminator.
     *
     * @param string &$s string to clean linefeeds on
     *
     * @return void
     */
    function clean_crlf(&$s) {
        $s = str_replace("\r\n", "\n", $s);
        $s = str_replace("\r", "\n", $s);
        $s = str_replace("\n", "\r\n", $s);
        return strlen($s);
    }

    /**
     * function strip_crlf - strip linefeeds and newlines from a string
     *
     * The SMTP format only allows CRLF as line terminators.
     * This function strips all line terminators from the string.
     *
     * @param string &$s string to clean linefeeds on
     *
     * @return void
     */
    function strip_crlf(&$s) {
        $s = str_replace("\r\n ", '', $s);
        $s = str_replace("\r", '', $s);
        $s = str_replace("\n", '', $s);
    }

    /**
     * function preWriteToStream - reserved for extended functionality
     *
     * This function is not yet implemented.
     * Reserved for extended functionality.
     *
     * @param string &$s string to operate on
     *
     * @return void
     */
    function preWriteToStream(&$s) {
    }

    /**
     * function writeToStream - write data to the SMTP stream
     *
     * @param resource $stream  SMTP output stream
     * @param string   $data    string with data to send to the SMTP stream
     *
     * @return void
     */
    function writeToStream($stream, $data) {
        fputs($stream, $data);
    }

    /**
     * function initStream - reserved for extended functionality
     *
     * This function is not yet implemented.
     * Reserved for extended functionality.
     * UPDATE: It is implemented in Deliver_SMTP and Deliver_SendMail classes,
     *         but it remains unimplemented in this base class (and thus not
     *         in Deliver_IMAP or other child classes that don't define it)
     *
     * NOTE: some parameters are specific to the child class
     *       that is implementing this method
     *
     * @param Message $message  Message object
     * @param string  $domain
     * @param integer $length
     * @param string  $host     host name or IP to connect to
     * @param integer $port
     * @param string  $user     username to log into the SMTP server with
     * @param string  $pass     password to log into the SMTP server with
     * @param boolean $authpop  whether or not to use POP-before-SMTP authorization
     * @param string  $pop_host host name or IP to connect to for POP-before-SMTP authorization
     *
     * @return handle $stream file handle resource to SMTP stream
     */
    function initStream($message, $domain, $length=0, $host='', $port='', $user='', $pass='', $authpop=false, $pop_host='') {
        return $stream;
    }

    /**
     * function getBCC - reserved for extended functionality
     *
     * This function is not yet implemented.
     * Reserved for extended functionality.
     *
     */
    function getBCC() {
        return false;
    }

    /**
     * function prepareMIME_Header - creates the mime header
     *
     * @param Message $message  Message object to act on
     * @param string  $boundary mime boundary from fn MimeBoundary
     *
     * @return string $header properly formatted mime header
     */
    function prepareMIME_Header($message, $boundary) {
        $mime_header = $message->mime_header;
        $rn="\r\n";
        $header = array();

        $contenttype = 'Content-Type: '. $mime_header->type0 .'/'.
                        $mime_header->type1;
        if (count($message->entities)) {
            $contenttype .= ';' . 'boundary="'.$boundary.'"';
        }
        if (isset($mime_header->parameters['name'])) {
            $contenttype .= '; name="'.
            encodeHeader($mime_header->parameters['name']). '"';
        }
        if (isset($mime_header->parameters['charset'])) {
            $charset = $mime_header->parameters['charset'];
            $contenttype .= '; charset="'.
            encodeHeader($charset). '"';
        }

        $header[] = $contenttype . $rn;
        if ($mime_header->description) {
            $header[] = 'Content-Description: ' . $mime_header->description . $rn;
        }
        if ($mime_header->encoding) {
            $encoding = $mime_header->encoding;
            $header[] = 'Content-Transfer-Encoding: ' . $mime_header->encoding . $rn;
        } else {

            // inspect attached file for lines longer than allowed by RFC,
            // in which case we'll be using base64 encoding (so we can split
            // the lines up without corrupting them) instead of 8bit unencoded...
            // (see RFC 2822/2.1.1)
            //
            if (!empty($message->att_local_name)) { // is this redundant? I have no idea
                global $username, $attachment_dir;
                $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
                $filename = $hashed_attachment_dir . '/' . $message->att_local_name;

                // using 990 because someone somewhere is folding lines at
                // 990 instead of 998 and I'm too lazy to find who it is
                //
                $file_has_long_lines = file_has_long_lines($filename, 990);
            } else
                $file_has_long_lines = FALSE;

            if ($mime_header->type0 == 'multipart' || $mime_header->type0 == 'alternative') {
                /* no-op; no encoding needed */
            } else if (($mime_header->type0 == 'text' || $mime_header->type0 == 'message')
                    && !$file_has_long_lines) {
                $header[] = 'Content-Transfer-Encoding: 8bit' .  $rn;
            } else {
                $header[] = 'Content-Transfer-Encoding: base64' .  $rn;
            }
        }
        if ($mime_header->id) {
            $header[] = 'Content-ID: ' . $mime_header->id . $rn;
        }
        if ($mime_header->disposition) {
            $disposition = $mime_header->disposition;
            $contentdisp = 'Content-Disposition: ' . $disposition->name;
            if ($disposition->getProperty('filename')) {
                $contentdisp .= '; filename="'.
                encodeHeader($disposition->getProperty('filename')). '"';
            }
            $header[] = $contentdisp . $rn;
        }
        if ($mime_header->md5) {
            $header[] = 'Content-MD5: ' . $mime_header->md5 . $rn;
        }
        if ($mime_header->language) {
            $header[] = 'Content-Language: ' . $mime_header->language . $rn;
        }

        $cnt = count($header);
        $hdr_s = '';
        for ($i = 0 ; $i < $cnt ; $i++)    {
            $hdr_s .= $this->foldLine($header[$i]);
        }
        $header = $hdr_s;
        $header .= $rn; /* One blank line to separate mimeheader and body-entity */
        return $header;
    }

    /**
     * function prepareRFC822_Header - prepares the RFC822 header string from Rfc822Header object(s)
     *
     * This function takes the Rfc822Header object(s) and formats them
     * into the RFC822Header string to send to the SMTP server as part
     * of the SMTP message.
     *
     * @param Rfc822Header  $rfc822_header
     * @param Rfc822Header  $reply_rfc822_header
     * @param integer      &$raw_length length of the message
     *
     * @return string $header
     */
    function prepareRFC822_Header(&$rfc822_header, $reply_rfc822_header, &$raw_length) {
        global $domain, $version, $username, $encode_header_key, $hide_auth_header;

        if (! isset($hide_auth_header)) $hide_auth_header=false;

        /* if server var SERVER_NAME not available, use $domain */
        if(!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) {
            $SERVER_NAME = $domain;
        }

        sqGetGlobalVar('REMOTE_ADDR', $REMOTE_ADDR, SQ_SERVER);
        sqGetGlobalVar('REMOTE_PORT', $REMOTE_PORT, SQ_SERVER);
        sqGetGlobalVar('REMOTE_HOST', $REMOTE_HOST, SQ_SERVER);
        sqGetGlobalVar('HTTP_VIA',    $HTTP_VIA,    SQ_SERVER);
        sqGetGlobalVar('HTTP_X_FORWARDED_FOR', $HTTP_X_FORWARDED_FOR, SQ_SERVER);

        $rn = "\r\n";

        /* This creates an RFC 822 date */
        $date = date('D, j M Y H:i:s ', time()) . $this->timezone();

        /* Create a message-id */
        $message_id = 'MESSAGE ID GENERATION ERROR! PLEASE CONTACT SQUIRRELMAIL DEVELOPERS';
        if (empty($rfc822_header->message_id)) {
            $message_id = '<'
                        . md5(GenerateRandomString(16, '', 7) . uniqid(mt_rand(),true))
                        . '.squirrel@' . $SERVER_NAME .'>';
        }

        /* Make an RFC822 Received: line */
        if (isset($REMOTE_HOST)) {
            $received_from = "$REMOTE_HOST ([$REMOTE_ADDR])";
        } else {
            $received_from = $REMOTE_ADDR;
        }
        if (isset($HTTP_VIA) || isset ($HTTP_X_FORWARDED_FOR)) {
            if (!isset($HTTP_X_FORWARDED_FOR) || $HTTP_X_FORWARDED_FOR == '') {
                $HTTP_X_FORWARDED_FOR = 'unknown';
            }
            $received_from .= " (proxying for $HTTP_X_FORWARDED_FOR)";
        }
        $header = array();

        /**
         * SquirrelMail header
         *
         * This Received: header provides information that allows to track
         * user and machine that was used to send email. Don't remove it
         * unless you understand all possible forging issues or your
         * webmail installation does not prevent changes in user's email address.
         * See SquirrelMail bug tracker #847107 for more details about it.
         *
         * Add hide_squirrelmail_header as a candidate for config_local.php
         * (must be defined as a constant:  define('hide_squirrelmail_header', 1);
         * to allow completely hiding SquirrelMail participation in message
         * processing; This is dangerous, especially if users can modify their
         * account information, as it makes mapping a sent message back to the
         * original sender almost impossible.
         */
        $show_sm_header = ( defined('hide_squirrelmail_header') ? ! hide_squirrelmail_header : 1 );

        // FIXME: The following headers may generate slightly differently between the message sent to the destination and that stored in the Sent folder because this code will be called before both actions.  This is not necessarily a big problem, but other headers such as Message-ID and Date are preserved between both actions
        if ( $show_sm_header ) {
          if (isset($encode_header_key) &&
            trim($encode_header_key)!='') {
            // use encoded headers, if encryption key is set and not empty
            $header[] = 'X-Squirrel-UserHash: '.OneTimePadEncrypt($username,base64_encode($encode_header_key)).$rn;
            $header[] = 'X-Squirrel-FromHash: '.OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR),base64_encode($encode_header_key)).$rn;
            if (isset($HTTP_X_FORWARDED_FOR))
                $header[] = 'X-Squirrel-ProxyHash:'.OneTimePadEncrypt($this->ip2hex($HTTP_X_FORWARDED_FOR),base64_encode($encode_header_key)).$rn;
          } else {
            // use default received headers
            $header[] = "Received: from $received_from" . $rn;
            if (!isset($hide_auth_header) || !$hide_auth_header)
                $header[] = "        (SquirrelMail authenticated user $username)" . $rn;
            $header[] = "        by $SERVER_NAME with HTTP;" . $rn;
            $header[] = "        $date" . $rn;
          }
        }

        /* Insert the rest of the header fields */

        if (!empty($rfc822_header->message_id)) {
            $header[] = 'Message-ID: '. $rfc822_header->message_id . $rn;
        } else {
            $header[] = 'Message-ID: '. $message_id . $rn;
            $rfc822_header->message_id = $message_id;
        }

        if (is_object($reply_rfc822_header) &&
            isset($reply_rfc822_header->message_id) &&
            $reply_rfc822_header->message_id) {
            //if ($reply_rfc822_header->message_id) {
            $rep_message_id = $reply_rfc822_header->message_id;
            $header[] = 'In-Reply-To: '.$rep_message_id . $rn;
            $rfc822_header->in_reply_to = $rep_message_id;
            $references = $this->calculate_references($reply_rfc822_header);
            $header[] = 'References: '.$references . $rn;
            $rfc822_header->references = $references;
        }

        if (!empty($rfc822_header->date) && $rfc822_header->date != -1) {
            $header[] = 'Date: '. $rfc822_header->date . $rn;
        } else {
            $header[] = "Date: $date" . $rn;
            $rfc822_header->date = $date;
        }

        $header[] = 'Subject: '.encodeHeader($rfc822_header->subject) . $rn;

        // folding address list [From|To|Cc|Bcc] happens by using ",$rn<space>"
        // as delimiter
        // Do not use foldLine for that.

        $header[] = 'From: '. $rfc822_header->getAddr_s('from',",$rn ",true) . $rn;

        // RFC2822 if from contains more then 1 address
        if (count($rfc822_header->from) > 1) {
            $header[] = 'Sender: '. $rfc822_header->getAddr_s('sender',',',true) . $rn;
        }
        if (count($rfc822_header->to)) {
            $header[] = 'To: '. $rfc822_header->getAddr_s('to',",$rn ",true) . $rn;
        }
        if (count($rfc822_header->cc)) {
            $header[] = 'Cc: '. $rfc822_header->getAddr_s('cc',",$rn ",true) . $rn;
        }
        if (count($rfc822_header->reply_to)) {
            $header[] = 'Reply-To: '. $rfc822_header->getAddr_s('reply_to',',',true) . $rn;
        }
        /* Sendmail should return true. Default = false */
        $bcc = $this->getBcc();
        if (count($rfc822_header->bcc)) {
            $s = 'Bcc: '. $rfc822_header->getAddr_s('bcc',",$rn ",true) . $rn;
            if (!$bcc) {
                $raw_length += strlen($s);
            } else {
                $header[] = $s;
            }
        }
        /* Identify SquirrelMail */
        $header[] = 'User-Agent: SquirrelMail/' . $version . $rn;
        /* Do the MIME-stuff */
        $header[] = 'MIME-Version: 1.0' . $rn;
        $contenttype = 'Content-Type: '. $rfc822_header->content_type->type0 .'/'.
                                         $rfc822_header->content_type->type1;
        if (count($rfc822_header->content_type->properties)) {
            foreach ($rfc822_header->content_type->properties as $k => $v) {
                if ($k && $v) {
                    $contenttype .= ';' .$k.'='.$v;
                }
            }
        }
        $header[] = $contenttype . $rn;
        if ($encoding = $rfc822_header->encoding) {
            $header[] = 'Content-Transfer-Encoding: ' . $encoding .  $rn;
        }
        if ($rfc822_header->dnt) {
            $dnt = $rfc822_header->getAddr_s('dnt');
            /* Pegasus Mail */
            $header[] = 'X-Confirm-Reading-To: '.$dnt. $rn;
            /* RFC 2298 */
            $header[] = 'Disposition-Notification-To: '.$dnt. $rn;
        }
        if ($rfc822_header->priority) {
            switch($rfc822_header->priority)
            {
            case 1:
                $header[] = 'X-Priority: 1 (Highest)'.$rn;
                $header[] = 'Importance: High'. $rn; break;
            case 3:
                $header[] = 'X-Priority: 3 (Normal)'.$rn;
                $header[] = 'Importance: Normal'. $rn; break;
            case 5:
                $header[] = 'X-Priority: 5 (Lowest)'.$rn;
                $header[] = 'Importance: Low'. $rn; break;
            default: break;
            }
        }
        /* Insert headers from the $more_headers array */
        if(count($rfc822_header->more_headers)) {
            reset($rfc822_header->more_headers);
            foreach ($rfc822_header->more_headers as $k => $v) {
                $header[] = $k.': '.$v .$rn;
            }
        }
        $cnt = count($header);
        $hdr_s = '';

        for ($i = 0 ; $i < $cnt ; $i++) {
            $sKey = substr($header[$i],0,strpos($header[$i],':'));
            switch ($sKey)
            {
            case 'Message-ID':
            case 'In-Reply_To':
                $hdr_s .= $header[$i];
                break;
            case 'References':
                $sRefs = substr($header[$i],12);
                $aRefs = explode(' ',$sRefs);
                $sLine = 'References:';
                foreach ($aRefs as $sReference) {
                    if ( trim($sReference) == '' ) {
                        /* Don't add spaces. */
                    } elseif (strlen($sLine)+strlen($sReference) >76) {
                        $hdr_s .= $sLine;
                        $sLine = $rn . '    ' . $sReference;
                    } else {
                        $sLine .= ' '. $sReference;
                    }
                }
                $hdr_s .= $sLine;
                break;
            case 'To':
            case 'Cc':
            case 'Bcc':
            case 'From':
                $hdr_s .= $header[$i];
                break;
            default: $hdr_s .= $this->foldLine($header[$i]); break;
            }
        }
        $header = $hdr_s;
        $header .= $rn; /* One blank line to separate header and body */
        $raw_length += strlen($header);
        return $header;
    }

    /**
      * Fold header lines per RFC 2822/2.2.3 and RFC 822/3.1.1
      *
      * Herein "soft" folding/wrapping (with whitespace tokens) is
      * what we refer to as the preferred method of wrapping - that
      * which we'd like to do within the $soft_wrap limit, but if
      * not possible, we will try to do as soon as possible after
      * $soft_wrap up to the $hard_wrap limit.  Encoded words don't
      * need to be detected in this phase, since they cannot contain
      * spaces.
      *
      * "Hard" folding/wrapping (with "hard" tokens) is what we refer
      * to as less ideal wrapping that will be done to keep within
      * the $hard_wrap limit.  This adds other syntactical breaking
      * elements such as commas and encoded words.
      *
      * @param string  $header    The header content being folded
      * @param integer $soft_wrap The desirable maximum line length
      *                           (OPTIONAL; default is 78, per RFC)
      * @param string  $indent    Wrapped lines will already have
      *                           whitespace following the CRLF wrap,
      *                           but you can add more indentation (or
      *                           whatever) with this.  The use of this
      *                           parameter is DISCOURAGED, since it
      *                           can corrupt the redisplay (unfolding)
      *                           of headers whose content is space-
      *                           sensitive, like subjects, etc.
      *                           (OPTIONAL; default is an empty string)
      * @param string  $hard_wrap The absolute maximum line length
      *                           (OPTIONAL; default is 998, per RFC)
      *
      * @return string The folded header content, with a trailing CRLF.
      *
      */
    function foldLine($header, $soft_wrap=78, $indent='', $hard_wrap=998) {

        // the "hard" token list can be altered if desired,
        // for example, by adding ":"
        // (in the future, we can take optional arguments
        // for overriding or adding elements to the "hard"
        // token list if we want to get fancy)
        //
        // the order of these is significant - preferred
        // fold points should be listed first
        //
        // it is advised that the "=" always come first
        // since it also finds encoded words, thus if it
        // comes after some other token that happens to
        // fall within the encoded word, the encoded word
        // could be inadvertently broken in half, which
        // is not allowable per RFC
        //
        $hard_break_tokens = array(
            '=',  // includes encoded word detection
            ',',
            ';',
        );

        // the order of these is significant too
        //
        $whitespace = array(
            ' ',
            "\t",
        );

        $CRLF = "\r\n";

        $folded_header = '';

        // if using an indent string, reduce wrap limits by its size
        //
        if (!empty($indent)) {
            $soft_wrap -= strlen($indent);
            $hard_wrap -= strlen($indent);
        }

        while (strlen($header) > $soft_wrap) {

            $soft_wrapped_line = substr($header, 0, $soft_wrap);

            // look for a token as close to the end of the soft wrap limit as possible
            //
            foreach ($whitespace as $token) {

                // note that this if statement also fails when $pos === 0,
                // which is intended, since blank lines are not allowed
                //
                if ($pos = strrpos($soft_wrapped_line, $token))
                {
                    $new_fold = substr($header, 0, $pos);

                    // make sure proposed fold doesn't create a blank line
                    //
                    if (!trim($new_fold)) continue;

                    // with whitespace breaks, we fold BEFORE the token
                    //
                    $folded_header .= $new_fold . $CRLF . $indent;
                    $header = substr($header, $pos);

                    // ready for next while() iteration
                    //
                    continue 2;

                }

            }

            // we were unable to find a wrapping point within the soft
            // wrap limit, so now we'll try to find the first possible
            // soft wrap point within the hard wrap limit
            //
            $hard_wrapped_line = substr($header, 0, $hard_wrap);

            // look for a *SOFT* token as close to the
            // beginning of the hard wrap limit as possible
            //
            foreach ($whitespace as $token) {

                // use while loop instead of if block because it
                // is possible we don't want the first one we find
                //
                $pos = $soft_wrap - 1; // -1 is corrected by +1 on next line
                while ($pos = strpos($hard_wrapped_line, $token, $pos + 1))
                {

                    $new_fold = substr($header, 0, $pos);

                    // make sure proposed fold doesn't create a blank line
                    //
                    if (!trim($new_fold)) continue;

                    // with whitespace breaks, we fold BEFORE the token
                    //
                    $folded_header .= $new_fold . $CRLF . $indent;
                    $header = substr($header, $pos);

                    // ready for next outter while() iteration
                    //
                    continue 3;

                }

            }

            // we were still unable to find a soft wrapping point within
            // both the soft and hard wrap limits, so if the length of
            // what is left is no more than the hard wrap limit, we'll
            // simply take the whole thing
            //
            if (strlen($header) <= strlen($hard_wrapped_line))
                break;

            // otherwise, we can't quit yet - look for a "hard" token
            // as close to the end of the hard wrap limit as possible
            //
            foreach ($hard_break_tokens as $token) {

                // note that this if statement also fails when $pos === 0,
                // which is intended, since blank lines are not allowed
                //
                if ($pos = strrpos($hard_wrapped_line, $token))
                {

                    // if we found a "=" token, we must determine whether,
                    // if it is part of an encoded word, it is the beginning
                    // or middle of one, where we need to readjust $pos a bit
                    //
                    if ($token == '=') {

                        // if we found the beginning of an encoded word,
                        // we want to break BEFORE the token
                        //
                        if (preg_match('/^(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)/i',
                                       substr($header, $pos))) {
                            $pos--;
                        }

                        // check if we found this token in the *middle*
                        // of an encoded word, in which case we have to
                        // ignore it, pushing back to the token that
                        // starts the encoded word instead
                        //
                        // of course, this is only possible if there is
                        // more content after the next hard wrap
                        //
                        // then look for the end of an encoded word in
                        // the next part (past the next hard wrap)
                        //
                        // then see if it is in fact part of a legitimate
                        // encoded word
                        //
                        else if (strlen($header) > $hard_wrap
                         && ($end_pos = strpos(substr($header, $hard_wrap), '?=')) !== FALSE
                         && preg_match('/(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)$/i',
                                       substr($header, 0, $hard_wrap + $end_pos + 2),
                                       $matches)) {

                            $pos = $hard_wrap + $end_pos + 2 - strlen($matches[1]) - 1;

                        }

                    }

                    // $pos could have been changed; make sure it's
                    // not at the beginning of the line, as blank
                    // lines are not allowed
                    //
                    if ($pos === 0) continue;

                    // we are dealing with a simple token break...
                    //
                    // for non-whitespace breaks, we fold AFTER the token
                    // and add a space after the fold if not immediately
                    // followed by a whitespace character in the next part
                    //
                    $folded_header .= substr($header, 0, $pos + 1) . $CRLF;

                    // don't go beyond end of $header, though
                    //
                    if (strlen($header) > $pos + 1) {
                        $header = substr($header, $pos + 1);
                        if (!in_array($header{0}, $whitespace))
                            $header = ' ' . $indent . $header;
                    } else {
                        $header = '';
                    }

                    // ready for next while() iteration
                    //
                    continue 2;

                }

            }

            // finally, we just couldn't find anything to fold on, so we
            // have to just cut it off at the hard limit
            //
            $folded_header .= $hard_wrapped_line . $CRLF;

            // is there more?
            //
            if (strlen($header) > strlen($hard_wrapped_line)) {
                $header = substr($header, strlen($hard_wrapped_line));
                if (!in_array($header{0}, $whitespace))
                    $header = ' ' . $indent . $header;
            } else {
                $header = '';
            }

        }


        // add any left-overs
        //
        $folded_header .= $header;


        // make sure it ends with a CRLF
        //
        if (substr($folded_header, -2) != $CRLF) $folded_header .= $CRLF;


        return $folded_header;
    }

    /**
     * function mimeBoundary - calculates the mime boundary to use
     *
     * This function will generate a random mime boundary base part
     * for the message if the boundary has not already been set.
     *
     * @return string $mimeBoundaryString random mime boundary string
     */
    function mimeBoundary () {
        static $mimeBoundaryString;

        if ( !isset( $mimeBoundaryString ) ||
            $mimeBoundaryString == '') {
            $mimeBoundaryString = '----=_' . date( 'YmdHis' ) . '_' .
            mt_rand( 10000, 99999 );
        }
        return $mimeBoundaryString;
    }

    /**
     * function timezone - Time offset for correct timezone
     *
     * @return string $result with timezone and offset
     */
    function timezone () {
        global $invert_time, $show_timezone_name;

        $diff_second = date('Z');
        if ($invert_time) {
            $diff_second = - $diff_second;
        }
        if ($diff_second > 0) {
            $sign = '+';
        } else {
            $sign = '-';
        }
        $diff_second = abs($diff_second);
        $diff_hour = floor ($diff_second / 3600);
        $diff_minute = floor (($diff_second-3600*$diff_hour) / 60);

        // If an administrator wants to add the timezone name to the
        // end of the date header, they can set $show_timezone_name
        // to boolean TRUE in config/config_local.php, but that is
        // NOT RFC-822 compliant (see section 5.1).  Moreover, some
        // Windows users reported that strftime('%Z') was returning
        // the full zone name (not the abbreviation) which in some
        // cases included 8-bit characters (not allowed as is in headers).
        // The PHP manual actually does NOT promise what %Z will return
        // for strftime!:  "The time zone offset/abbreviation option NOT
        // given by %z (depends on operating system)"
        //
        if ($show_timezone_name) {
            $zonename = '('.strftime('%Z').')';
            $result = sprintf ("%s%02d%02d %s", $sign, $diff_hour, $diff_minute, $zonename);
        } else {
            $result = sprintf ("%s%02d%02d", $sign, $diff_hour, $diff_minute);
        }
        return ($result);
    }

    /**
     * function calculate_references - calculate correct References string
     * Adds the current message ID, and makes sure it doesn't grow forever,
     * to that extent it drops message-ID's in a smart way until the string
     * length is under the recommended value of 1000 ("References: <986>\r\n").
     * It always keeps the first and the last three ID's.
     *
     * @param   Rfc822Header $hdr    message header to calculate from
     *
     * @return  string       $refer  concatenated and trimmed References string
     */
    function calculate_references($hdr) {
        $aReferences = preg_split('/\s+/', $hdr->references);
        $message_id = $hdr->message_id;
        $in_reply_to = $hdr->in_reply_to;
	
        // if References already exists, add the current message ID at the end.
        // no References exists; if we know a IRT, add that aswell
        if (count($aReferences) == 0 && $in_reply_to) {
            $aReferences[] = $in_reply_to;
        }
        $aReferences[] = $message_id;

        // sanitize the array: trim whitespace, remove dupes
        array_walk($aReferences, 'sq_trim_value');
        $aReferences = array_unique($aReferences);

        while ( count($aReferences) > 4 && strlen(implode(' ', $aReferences)) >= 986 ) {
            $aReferences = array_merge(array_slice($aReferences,0,1),array_slice($aReferences,2));
        }
        return implode(' ', $aReferences);
    }

    /**
     * Converts ip address to hexadecimal string
     *
     * Function is used to convert ipv4 and ipv6 addresses to hex strings.
     * It removes all delimiter symbols from ip addresses, converts decimal
     * ipv4 numbers to hex and pads strings in order to present full length
     * address. ipv4 addresses are represented as 8 byte strings, ipv6 addresses
     * are represented as 32 byte string.
     *
     * If function fails to detect address format, it returns unprocessed string.
     * @param string $string ip address string
     * @return string processed ip address string
     * @since 1.5.1 and 1.4.5
     */
    function ip2hex($string) {
        if (preg_match("/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/",$string,$match)) {
            // ipv4 address
            $ret = str_pad(dechex($match[1]),2,'0',STR_PAD_LEFT)
                . str_pad(dechex($match[2]),2,'0',STR_PAD_LEFT)
                . str_pad(dechex($match[3]),2,'0',STR_PAD_LEFT)
                . str_pad(dechex($match[4]),2,'0',STR_PAD_LEFT);
        } elseif (preg_match("/^([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)$/i",$string,$match)) {
            // full ipv6 address
            $ret = str_pad($match[1],4,'0',STR_PAD_LEFT)
                . str_pad($match[2],4,'0',STR_PAD_LEFT)
                . str_pad($match[3],4,'0',STR_PAD_LEFT)
                . str_pad($match[4],4,'0',STR_PAD_LEFT)
                . str_pad($match[5],4,'0',STR_PAD_LEFT)
                . str_pad($match[6],4,'0',STR_PAD_LEFT)
                . str_pad($match[7],4,'0',STR_PAD_LEFT)
                . str_pad($match[8],4,'0',STR_PAD_LEFT);
        } elseif (preg_match("/^\:\:([0-9a-h\:]+)$/i",$string,$match)) {
            // short ipv6 with all starting symbols nulled
            $aAddr=explode(':',$match[1]);
            $ret='';
            foreach ($aAddr as $addr) {
                $ret.=str_pad($addr,4,'0',STR_PAD_LEFT);
            }
            $ret=str_pad($ret,32,'0',STR_PAD_LEFT);
        } elseif (preg_match("/^([0-9a-h\:]+)::([0-9a-h\:]+)$/i",$string,$match)) {
            // short ipv6 with middle part nulled
            $aStart=explode(':',$match[1]);
            $sStart='';
            foreach($aStart as $addr) {
                $sStart.=str_pad($addr,4,'0',STR_PAD_LEFT);
            }
            $aEnd = explode(':',$match[2]);
            $sEnd='';
            foreach($aEnd as $addr) {
                $sEnd.=str_pad($addr,4,'0',STR_PAD_LEFT);
            }
            $ret = $sStart
                . str_pad('',(32 - strlen($sStart . $sEnd)),'0',STR_PAD_LEFT)
                . $sEnd;
        } else {
            // unknown addressing
            $ret = $string;
        }
        return $ret;
    }
}

Added class/deliver/Deliver_IMAP.class.php.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?php

/**
 * Deliver_IMAP.class.php
 *
 * Delivery backend for the Deliver class.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Deliver_IMAP.class.php 14310 2012-04-01 21:28:13Z pdontthink $
 * @package squirrelmail
 */

/** This of course depends upon Deliver.. */

require_once(SM_PATH . 'class/deliver/Deliver.class.php');

/**
 * This class is incomplete and entirely undocumented.
 * @package squirrelmail
 */
class Deliver_IMAP extends Deliver {

    function getBcc() {
       return true;
    }

    /**
     * function send_mail - send the message parts to the IMAP stream
     *
     * Overridden from parent class so that we can insert some 
     * IMAP APPEND commands before and after the message is 
     * sent on the IMAP stream.
     *
     * @param Message  $message      Message object to send
     * @param string   $header       Headers ready to send
     * @param string   $boundary     Message parts boundary
     * @param resource $stream       Handle to the SMTP stream
     *                               (when FALSE, nothing will be
     *                               written to the stream; this can
     *                               be used to determine the actual
     *                               number of bytes that will be
     *                               written to the stream)
     * @param int     &$raw_length   The number of bytes written (or that
     *                               would have been written) to the 
     *                               output stream - NOTE that this is
     *                               passed by reference
     * @param string   $folder       The IMAP folder to which the 
     *                               message is being sent
     *
     * @return void
     *
     */
    function send_mail($message, $header, $boundary, $stream=false, 
                       &$raw_length, $folder=NULL) {

        if (is_null($folder))
            die('Internal error. Cannot pass NULL folder name to Deliver_IMAP::send_mail()');

        // write the body without providing a stream so we
        // can calculate the final length - after this call,
        // $final_length will be our correct final length value
        //
        $final_length = $raw_length;
        $this->writeBody($message, 0, $final_length, $boundary);


        // now if we have a real live stream, send the message
        //
        if ($stream) {
            sqimap_append ($stream, $folder, $final_length);

            $this->preWriteToStream($header);
            $this->writeToStream($stream, $header);
            $this->writeBody($message, $stream, $raw_length, $boundary);

            sqimap_append_done ($stream, $folder);
        }

    }


    /* to do: finishing the imap-class so the initStream function can call the
       imap-class */
}

Added class/deliver/Deliver_SMTP.class.php.

















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
<?php

/**
 * Deliver_SMTP.class.php
 *
 * SMTP delivery backend for the Deliver class.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Deliver_SMTP.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

/** This of course depends upon Deliver */
require_once(SM_PATH . 'class/deliver/Deliver.class.php');

/**
 * Deliver messages using SMTP
 * @package squirrelmail
 */
class Deliver_SMTP extends Deliver {

    function preWriteToStream(&$s) {
        if ($s) {
            if ($s{0} == '.')   $s = '.' . $s;
            $s = str_replace("\n.","\n..",$s);
        }
    }

    function initStream($message, $domain, $length=0, $host='', $port='', $user='', $pass='', $authpop=false, $pop_host='') {
        global $use_smtp_tls, $smtp_auth_mech;

        if ($authpop) {
            $this->authPop($pop_host, '', $user, $pass);
        }

        $rfc822_header = $message->rfc822_header;

        $from = $rfc822_header->from[0];
        $to =   $rfc822_header->to;
        $cc =   $rfc822_header->cc;
        $bcc =  $rfc822_header->bcc;
        $content_type  = $rfc822_header->content_type;

        // MAIL FROM: <from address> MUST be empty in cae of MDN (RFC2298)
        if ($content_type->type0 == 'multipart' &&
            $content_type->type1 == 'report' &&
            isset($content_type->properties['report-type']) &&
            $content_type->properties['report-type']=='disposition-notification') {
            // reinitialize the from object because otherwise the from header somehow
            // is affected. This $from var is used for smtp command MAIL FROM which
            // is not the same as what we put in the rfc822 header.
            $from = new AddressStructure();
            $from->host = '';
            $from->mailbox = '';
        }

        if (($use_smtp_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
            $stream = @fsockopen('tls://' . $host, $port, $errorNumber, $errorString);
        } else {
            $stream = @fsockopen($host, $port, $errorNumber, $errorString);
        }

        if (!$stream) {
            $this->dlv_msg = $errorString;
            $this->dlv_ret_nr = $errorNumber;
            $this->dlv_server_msg = _("Can't open SMTP stream.");
            return(0);
        }
        $tmp = fgets($stream, 1024);
        if ($this->errorCheck($tmp, $stream)) {
            return(0);
        }

        /*
         * If $_SERVER['HTTP_HOST'] is set, use that in our HELO to the SMTP
         * server.  This should fix the DNS issues some people have had
         */
        if (sqgetGlobalVar('HTTP_HOST', $HTTP_HOST, SQ_SERVER)) { // HTTP_HOST is set
            // optionally trim off port number
            if($p = strrpos($HTTP_HOST, ':')) {
                $HTTP_HOST = substr($HTTP_HOST, 0, $p);
            }
            $helohost = $HTTP_HOST;
        } else { // For some reason, HTTP_HOST is not set - revert to old behavior
            $helohost = $domain;
        }

        // if the host is an IPv4 address, enclose it in brackets
        //
        if (preg_match('/^\d+\.\d+\.\d+\.\d+$/', $helohost))
            $helohost = '[' . $helohost . ']';

        /* Lets introduce ourselves */
        fputs($stream, "EHLO $helohost\r\n");
        $tmp = fgets($stream,1024);
        if ($this->errorCheck($tmp,$stream)) {
            // fall back to HELO if EHLO is not supported (error 5xx)
            if ($this->dlv_ret_nr{0} == '5') {
                fputs($stream, "HELO $helohost\r\n");
                $tmp = fgets($stream,1024);
                if ($this->errorCheck($tmp,$stream)) {
                    return(0);
                }
            } else {
                return(0);
            }
        }

        // Try authentication by a plugin
        //
        // NOTE: there is another hook in functions/auth.php called "smtp_auth"
        // that allows a plugin to specify a different set of login credentials
        // (so is slightly mis-named, but is too old to change), so be careful
        // that you do not confuse your hook names.
        //
        $smtp_auth_args = array(
            'auth_mech' => $smtp_auth_mech,
            'user' => $user,
            'pass' => $pass,
            'host' => $host,
            'port' => $port,
            'stream' => $stream,
        );
        if (boolean_hook_function('smtp_authenticate', $smtp_auth_args, 1)) {
            // authentication succeeded
        } else if (( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) {
            // Doing some form of non-plain auth
            if ($smtp_auth_mech == 'cram-md5') {
                fputs($stream, "AUTH CRAM-MD5\r\n");
            } elseif ($smtp_auth_mech == 'digest-md5') {
                fputs($stream, "AUTH DIGEST-MD5\r\n");
            }

            $tmp = fgets($stream,1024);

            if ($this->errorCheck($tmp,$stream)) {
                return(0);
            }

            // At this point, $tmp should hold "334 <challenge string>"
            $chall = substr($tmp,4);
            // Depending on mechanism, generate response string
            if ($smtp_auth_mech == 'cram-md5') {
                $response = cram_md5_response($user,$pass,$chall);
            } elseif ($smtp_auth_mech == 'digest-md5') {
                $response = digest_md5_response($user,$pass,$chall,'smtp',$host);
            }
            fputs($stream, $response);

            // Let's see what the server had to say about that
            $tmp = fgets($stream,1024);
            if ($this->errorCheck($tmp,$stream)) {
                return(0);
            }

            // CRAM-MD5 is done at this point.  If DIGEST-MD5, there's a bit more to go
            if ($smtp_auth_mech == 'digest-md5') {
                // $tmp contains rspauth, but I don't store that yet. (No need yet)
                fputs($stream,"\r\n");
                $tmp = fgets($stream,1024);

                if ($this->errorCheck($tmp,$stream)) {
                return(0);
                }
            }
        // CRAM-MD5 and DIGEST-MD5 code ends here
        } elseif ($smtp_auth_mech == 'none') {
        // No auth at all, just send helo and then send the mail
        // We already said hi earlier, nothing more is needed.
        } elseif ($smtp_auth_mech == 'login') {
            // The LOGIN method
            fputs($stream, "AUTH LOGIN\r\n");
            $tmp = fgets($stream, 1024);

            if ($this->errorCheck($tmp, $stream)) {
                return(0);
            }
            fputs($stream, base64_encode ($user) . "\r\n");
            $tmp = fgets($stream, 1024);
            if ($this->errorCheck($tmp, $stream)) {
                return(0);
            }

            fputs($stream, base64_encode($pass) . "\r\n");
            $tmp = fgets($stream, 1024);
            if ($this->errorCheck($tmp, $stream)) {
                return(0);
            }
        } elseif ($smtp_auth_mech == "plain") {
            /* SASL Plain */
            $auth = base64_encode("$user\0$user\0$pass");

            $query = "AUTH PLAIN\r\n";
            fputs($stream, $query);
            $read=fgets($stream, 1024);

            if (substr($read,0,3) == '334') { // OK so far..
                fputs($stream, "$auth\r\n");
                $read = fgets($stream, 1024);
            }

            $results=explode(" ",$read,3);
            $response=$results[1];
            $message=$results[2];
        } else {
            /* Right here, they've reached an unsupported auth mechanism.
            This is the ugliest hack I've ever done, but it'll do till I can fix
            things up better tomorrow.  So tired... */
            if ($this->errorCheck("535 Unable to use this auth type",$stream)) {
                return(0);
            }
        }

        /* Ok, who is sending the message? */
        $fromaddress = (strlen($from->mailbox) && $from->host) ?
            $from->mailbox.'@'.$from->host : '';
        fputs($stream, 'MAIL FROM:<'.$fromaddress.">\r\n");
        $tmp = fgets($stream, 1024);
        if ($this->errorCheck($tmp, $stream)) {
            return(0);
        }

        /* send who the recipients are */
        for ($i = 0, $cnt = count($to); $i < $cnt; $i++) {
            if (!$to[$i]->host) $to[$i]->host = $domain;
            if (strlen($to[$i]->mailbox)) {
                fputs($stream, 'RCPT TO:<'.$to[$i]->mailbox.'@'.$to[$i]->host.">\r\n");
                $tmp = fgets($stream, 1024);
                if ($this->errorCheck($tmp, $stream)) {
                    return(0);
                }
            }
        }

        for ($i = 0, $cnt = count($cc); $i < $cnt; $i++) {
            if (!$cc[$i]->host) $cc[$i]->host = $domain;
            if (strlen($cc[$i]->mailbox)) {
                fputs($stream, 'RCPT TO:<'.$cc[$i]->mailbox.'@'.$cc[$i]->host.">\r\n");
                $tmp = fgets($stream, 1024);
                if ($this->errorCheck($tmp, $stream)) {
                    return(0);
                }
            }
        }

        for ($i = 0, $cnt = count($bcc); $i < $cnt; $i++) {
            if (!$bcc[$i]->host) $bcc[$i]->host = $domain;
            if (strlen($bcc[$i]->mailbox)) {
                fputs($stream, 'RCPT TO:<'.$bcc[$i]->mailbox.'@'.$bcc[$i]->host.">\r\n");
                $tmp = fgets($stream, 1024);
                if ($this->errorCheck($tmp, $stream)) {
                    return(0);
                }
            }
        }
        /* Lets start sending the actual message */
        fputs($stream, "DATA\r\n");
        $tmp = fgets($stream, 1024);
        if ($this->errorCheck($tmp, $stream)) {
                return(0);
        }
        return $stream;
    }

    function finalizeStream($stream) {
        fputs($stream, "\r\n.\r\n"); /* end the DATA part */
        $tmp = fgets($stream, 1024);
        $this->errorCheck($tmp, $stream);
        if ($this->dlv_ret_nr != 250) {
                return(0);
        }
        fputs($stream, "QUIT\r\n"); /* log off */
        fclose($stream);
        return true;
    }

    /* check if an SMTP reply is an error and set an error message) */
    function errorCheck($line, $smtpConnection) {

        $err_num = substr($line, 0, 3);
        $this->dlv_ret_nr = $err_num;
        $server_msg = substr($line, 4);

        while(substr($line, 0, 4) == ($err_num.'-')) {
            $line = fgets($smtpConnection, 1024);
            $server_msg .= substr($line, 4);
        }

        if ( ((int) $err_num{0}) < 4) {
            return false;
        }

        switch ($err_num) {
        case '421': $message = _("Service not available, closing channel");
            break;
        case '432': $message = _("A password transition is needed");
            break;
        case '450': $message = _("Requested mail action not taken: mailbox unavailable");
            break;
        case '451': $message = _("Requested action aborted: error in processing");
            break;
        case '452': $message = _("Requested action not taken: insufficient system storage");
            break;
        case '454': $message = _("Temporary authentication failure");
            break;
        case '500': $message = _("Syntax error; command not recognized");
            break;
        case '501': $message = _("Syntax error in parameters or arguments");
            break;
        case '502': $message = _("Command not implemented");
            break;
        case '503': $message = _("Bad sequence of commands");
            break;
        case '504': $message = _("Command parameter not implemented");
            break;
        case '530': $message = _("Authentication required");
            break;
        case '534': $message = _("Authentication mechanism is too weak");
            break;
        case '535': $message = _("Authentication failed");
            break;
        case '538': $message = _("Encryption required for requested authentication mechanism");
            break;
        case '550': $message = _("Requested action not taken: mailbox unavailable");
            break;
        case '551': $message = _("User not local; please try forwarding");
            break;
        case '552': $message = _("Requested mail action aborted: exceeding storage allocation");
            break;
        case '553': $message = _("Requested action not taken: mailbox name not allowed");
            break;
        case '554': $message = _("Transaction failed");
            break;
        default:    $message = _("Unknown response");
            break;
        }

        $this->dlv_msg = $message;
        $this->dlv_server_msg = nl2br(sm_encode_html_special_chars($server_msg));

        return true;
    }

    function authPop($pop_server='', $pop_port='', $user, $pass) {
        if (!$pop_port) {
            $pop_port = 110;
        }
        if (!$pop_server) {
            $pop_server = 'localhost';
        }
        $popConnection = @fsockopen($pop_server, $pop_port, $err_no, $err_str);
        if (!$popConnection) {
            error_log("Error connecting to POP Server ($pop_server:$pop_port)"
                . " $err_no : $err_str");
        } else {
            $tmp = fgets($popConnection, 1024); /* banner */
            if (substr($tmp, 0, 3) != '+OK') {
                return(0);
            }
            fputs($popConnection, "USER $user\r\n");
            $tmp = fgets($popConnection, 1024);
            if (substr($tmp, 0, 3) != '+OK') {
                return(0);
            }
            fputs($popConnection, 'PASS ' . $pass . "\r\n");
            $tmp = fgets($popConnection, 1024);
            if (substr($tmp, 0, 3) != '+OK') {
                return(0);
            }
            fputs($popConnection, "QUIT\r\n"); /* log off */
            fclose($popConnection);
        }
    }
}

Added class/deliver/Deliver_SendMail.class.php.

































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<?php

/**
 * Deliver_SendMail.class.php
 *
 * Delivery backend for the Deliver class.
 *
 * @author Marc Groot Koerkamp
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Deliver_SendMail.class.php 14311 2012-04-01 22:09:14Z pdontthink $
 * @package squirrelmail
 */


/** This of course depends upon Deliver */
require_once(SM_PATH . 'class/deliver/Deliver.class.php');

/**
 * Delivers messages using the sendmail binary
 * @package squirrelmail
 */
class Deliver_SendMail extends Deliver {
    /**
     * Extra sendmail arguments
     *
     * Parameter can be set in class constructor function.
     *
     * WARNING: Introduction of this parameter broke backwards compatibility 
     * with workarounds specific to qmail-inject.
     *
     * If parameter needs some security modifications, it should be set to 
     * private in PHP 5+ in order to prevent uncontrolled access.
     * @var string
     * @since 1.5.1 and 1.4.8
     */
    var $sendmail_args = '-i -t';

    /**
     * Stores used sendmail command
     * Private variable that is used to inform about used sendmail command.
     * @var string
     * @since 1.5.1 and 1.4.8
     */
    var $sendmail_command = '';

    /**
     * Constructor function
     * @param array configuration options. array key = option name, 
     * array value = option value.
     * @return void
     * @since 1.5.1 and 1.4.8
     */
    function Deliver_SendMail($params=array()) {
        if (!empty($params) && is_array($params)) {
            // set extra sendmail arguments
            if (isset($params['sendmail_args'])) {
                $this->sendmail_args = $params['sendmail_args'];
            }
        }
    }

   /**
    * function preWriteToStream
    *
    * Sendmail needs LF's as line endings instead of CRLF.
    * This function translates the line endings to LF and should be called
    * before each line is written to the stream.
    *
    * @param string $s Line to process
    * @return void
    * @access private
    */
    function preWriteToStream(&$s) {
       if ($s) {
           $s = str_replace("\r\n", "\n", $s);
       }
    }

   /**
    * function initStream
    *
    * Initialise the sendmail connection.
    *
    * @param Message $message Message object containing the from address
    * @param string $sendmail_path Location of sendmail binary
    * @param mixed $ignore Seven extra arguments that the parent class
    *                      requires which are not used here
    * @return void
    * @access public
    */
    function initStream($message, $sendmail_path, $ignore=0, $ignore='', $ignore='', $ignore='', $ignore='', $ignore=false, $ignore='') {
        $rfc822_header = $message->rfc822_header;
        $from = $rfc822_header->from[0];
        $envelopefrom = trim($from->mailbox.'@'.$from->host);
        $envelopefrom = str_replace(array("\0","\n"),array('',''),$envelopefrom);
        // save executed command for future reference
        $this->sendmail_command = escapeshellcmd("$sendmail_path $this->sendmail_args -f") . escapeshellarg($envelopefrom);
        // open process handle for writing
        $stream = popen($this->sendmail_command, "w");
        return $stream;
    }

   /**
    * function finalizeStream
    *
    * Close the stream.
    *
    * @param resource $stream
    * @return boolean
    * @access public
    */
    function finalizeStream($stream) {
        $ret = true;
        $status = pclose($stream);
        // check pclose() status.
        if ($status!=0) {
            $ret = false;
            $this->dlv_msg=_("Email delivery error");
            $this->dlv_ret_nr=$status;
            // we can get better error messsage only if we switch to php 4.3+ and proc_open().
            $this->dlv_server_msg=sprintf(_("Can't execute command '%s'."),$this->sendmail_command);
        }
        return $ret;
    }

   /**
    * function getBcc
    *
    * In case of sendmail, the rfc822header must contain the bcc header.
    *
    * @return boolean true if rfc822header should include the bcc header.
    * @access private
    */
    function getBcc() {
        return true;
    }

   /**
    * function clean_crlf
    *
    * Cleans each line to only end in a LF
    * Returns the length of the line including a CR,
    * so that length is correct when the message is saved to imap
    * Implemented to fix sendmail->postfix rejection of messages with
    * attachments because of stray LF's
    *
    * @param string $s string to strip of CR's
    * @return integer length of string including a CR for each LF
    * @access private
    */
    function clean_crlf(&$s) {
        $s = str_replace("\r\n", "\n", $s);
        $s = str_replace("\r", "\n", $s);
        $s2 = str_replace("\n", "\r\n", $s);
        return strlen($s2);
    }


}

Added class/deliver/index.php.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

/**
 * index.php
 *
 * This file simply takes any attempt to view source files and sends those
 * people to the login screen. At this point no attempt is made to see if the
 * person is logged in or not.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: index.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

header('Location: ../index.php');

Added class/helper/VCard.class.php.























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
<?php

/**
 * vCard.class
 *
 * This (will) contain functions needed to vCards.
 *
 * http://www.imc.org/pdi/vcard-21.txt
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: VCard.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @since 1.3.2
 */

/**
 * Unimplemented class that should handle vcards
 * Don't use it unless it is marked as implemented.
 * @package squirrelmail
 */
class VCard {
    /**
     * Create vcard from information stored in array
     * @todo implement vcard creation from array
     * @param array $value_array
     * @return string
     */
    function create_vcard ($value_array) {
        return $vcard;
    }

    /**
     * Read vcard and convert it to array
     * @todo implement vcard parsing
     * @param string $vcard
     * @return array
     */
    function parse_vcard ($vcard) {
        return $array;
    }
}

Added class/helper/index.php.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

/**
 * index.php
 *
 * This file simply takes any attempt to view source files and sends those
 * people to the login screen. At this point no attempt is made to see if the
 * person is logged in or not.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: index.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

header('Location: ../index.php');

Added class/html.class.php.



























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<?php

/**
 * html.class.php
 *
 * This contains functions needed to generate html output.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: html.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

/**
 * Undocumented class
 * @package squirrelmail
 */
class html {
    var $tag, $text, $style, $class,  
        $id, $html_el = array(), $javascript, $xtr_prop;

    function html($tag='', $text='', $style ='', $class='', $id='',
            $xtr_prop = '', $javascript = '') {
        $this->tag = $tag;
        $this->text = $text;
        $this->style = $style;
        $this->class = $class;
        $this->id = $id;
        $this->xtr_prop = $xtr_prop;
        $this->javascript = $javascript;
    }

    function htmlAdd($el, $last=true) {
        if ($last) {
            $this->html_el[] = $el;
        } else {
            $new_html_el = array();
            $new_html_el[] = $el;
            foreach ($this->html_el as $html_el) {
                $new_html_el[] = $html_el;
            }
            $this->html_el = $new_html_el;
        }
    }

    function AddChild($tag='', $text='', $style ='', $class='', $id='',
            $xtr_prop = '', $javascript = '') {
        $el = new html ($tag, $text, $style, $class, $id, $xtr_prop, $javascript);
        $this->htmlAdd($el);
    }

    function FindId($id) {
        $cnt = count($this->html_el);
        $el = false;
        if ($cnt) {
            for ($i = 0 ; $i < $cnt; $i++) {
                if ($this->html_el[$i]->id == $id) {
                    $ret = $this->html_el[$i];
                    return $ret;
                } else if (count($this->html_el[$i]->html_el)) {
                    $el = $this->html_el[$i]->FindId($id);
                }
                if ($el) return $el;
            }
        }
        return $el;
    }     

    function InsToId( $el, $id, $last=true) {
        $html_el = &$this->FindId($id);
        if ($html_el) {
            $html_el->htmlAdd($el, $last);
        }
    }     

    function scriptAdd($script) {
        $s = "\n".'<!--'."\n".
            $script .
            "\n".'// -->'."\n";
        $el = new html ('script',$s,'','','',array('language' => 'JavaScript',
                    'type' => 'text/javascript'));
        $this->htmlAdd($el);
    }

    function echoHtml( $usecss=false, $indent='x') {
        if ($indent == 'x') {
            $indent = ''; $indentmore = '';
        } else {
            $indentmore = $indent . '  ';
        }
        $tag = $this->tag;
        $text = $this->text;
        $class = $this->class;
        $id = $this->id;
        $style = $this->style;
        $javascript = $this->javascript;
        $xtr_prop = $this->xtr_prop;
        if ($xtr_prop) {
            $prop = '';
            foreach ($xtr_prop as $k => $v) {
                if (is_string($k)) {
                    $prop.=' '.$k.'="'.$v.'"';
                } else {
                    $prop.=' '.$v;
                }
            }
        }   
        if ($javascript) {
            $js = '';
            foreach ($javascript as $k => $v) { /* here we put the onclick, onmouseover etc entries */
                $js.=' '.$k.'="'.$v.'";';
            }
        }
        if ($tag) {   	  
            echo $indent . '<' . $tag;
        } else {
            echo $indent;
        }
        if ($class) {
            echo ' class="'.$class.'"';
        }  
        if ($id) {
            echo ' id="'.$id.'"';
        }
        if ($xtr_prop) {
            echo ' '.$prop;
        }
        if ($style && !$usecss && !is_array($style)) {
            /* last premisse is to prevent 'style="Array"' in the output */
            echo ' style="'.$style.'"';  
        }
        if ($javascript) {
            echo ' '.$js;
        }
        if ($tag) echo '>';

        $openstyles = '';
        $closestyles = '';
        if ($style && !$usecss) {
            foreach ($style as $k => $v) {
                $openstyles .= '<'.$k.'>';
            }
            foreach ($style as $k => $v) {
                /* if value of key value = true close the tag */
                if ($v) {
                    $closestyles .= '</'.$k.'>';
                }   
            }
        }
        echo $openstyles;

        if ($text) {
            echo $text;
        }

        $cnt = count($this->html_el);
        if ($cnt) {
            echo "\n";
            for($i = 0;$i<$cnt;$i++) {
                $el = $this->html_el[$i];
                $el->echoHtml($usecss,$indentmore);
            }
            echo $indent;
        }
        echo $closestyles;
        if ($tag) {
            echo '</'.$tag.'>'."\n";
        } else {
            echo "\n";
        }
    }
}

Added class/index.php.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

/**
 * index.php
 *
 * This file simply takes any attempt to view source files and sends those
 * people to the login screen. At this point no attempt is made to see if the
 * person is logged in or not.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: index.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

header('Location: ../index.php');

Added class/mime.class.php.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/**
 * mime.class
 *
 * This file loads classes needed to handle mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: mime.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 */

/** @ignore */
if (! defined('SM_PATH')) define('SM_PATH','../');

/** Load in the entire MIME system */
require_once(SM_PATH . 'class/mime/Rfc822Header.class.php');
require_once(SM_PATH . 'class/mime/MessageHeader.class.php');
require_once(SM_PATH . 'class/mime/AddressStructure.class.php');
require_once(SM_PATH . 'class/mime/Message.class.php');
require_once(SM_PATH . 'class/mime/SMimeMessage.class.php');
require_once(SM_PATH . 'class/mime/Disposition.class.php');
require_once(SM_PATH . 'class/mime/Language.class.php');
require_once(SM_PATH . 'class/mime/ContentType.class.php');

Added class/mime/AddressStructure.class.php.



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php

/**
 * AddressStructure.class.php
 *
 * This file contains functions needed to extract email address headers from
 * mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: AddressStructure.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Class used to work with email address headers
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */
class AddressStructure {
    /**
     * Personal information
     * @var string
     */
    var $personal = '';
    /**
     * @todo check use of this variable. var is not used in class.
     * @var string
     */
    var $adl      = '';
    /**
     * Mailbox name.
     * @var string
     */
    var $mailbox  = '';
    /**
     * Server address.
     * @var string
     */
    var $host     = '';
    /**
     * @todo check use of this variable. var is not used in class.
     * @var string
     */
    var $group    = '';

    /**
     * Return address information from mime headers.
     * @param boolean $full return full address (true) or only personal if it exists, otherwise email (false)
     * @param boolean $encoded (since 1.4.0) return rfc2047 encoded address (true) or plain text (false).
     * @param boolean $unconditionally_quote (since 1.4.21/1.5.2) when TRUE, always quote the personal part, whether or not it is encoded, otherwise quoting is only added if the personal part is not encoded
     * @return string
     */
    function getAddress($full = true, $encoded = false, $unconditionally_quote = FALSE) {
        $result = '';
        if (is_object($this)) {
            $email = ($this->host ? $this->mailbox.'@'.$this->host
                                  : $this->mailbox);
            $personal = trim($this->personal);
            $is_encoded = false;
            // FIXME: I don't think the U modifier below does anything at all
            if (preg_match('/(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)(.*)/Ui',$personal,$reg)) {
                $is_encoded = true;
            }
            if ($personal) {
                if ($encoded && !$is_encoded) {
                    $personal_encoded = encodeHeader('"' . $personal . '"');
                    if ($personal !== $personal_encoded) {
                        $personal = $personal_encoded;
                    } else {
                        //FIXME: this probably adds quotes around an encoded string which itself is already quoted
                        $personal = '"'.$this->personal.'"';
                    }
                } else {
                    if (!$is_encoded || $unconditionally_quote) {
                        $personal = '"'.$this->personal.'"';
                    }
                }
                $addr = ($email ? $personal . ' <' .$email.'>'
                        : $this->personal);
                $best_dpl = $this->personal;
            } else {
                $addr = $email;
                $best_dpl = $email;
            }
            $result = ($full ? $addr : $best_dpl);
        }
        return $result;
    }

    /**
     * Shorter version of getAddress() function
     * Returns full encoded address.
     * @param boolean $unconditionally_quote (since 1.4.21) when TRUE, always quote the personal part, whether or not it is encoded, otherwise quoting is only added if the personal part is not encoded
     * @return string
     * @since 1.4.0
     */
    function getEncodedAddress($unconditionally_quote=FALSE) {
        return $this->getAddress(true, true, $unconditionally_quote);
    }
}

Added class/mime/ContentType.class.php.

























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php

/**
 * ContentType.class.php
 *
 * This file contains functions needed to handle content type headers 
 * (rfc2045) in mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: ContentType.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Class that handles content-type headers
 * Class was named content_type in 1.3.0 and 1.3.1. It is used internally
 * by rfc822header class.
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */
class ContentType {
    /**
     * Media type
     * @var string
     */
    var $type0 = 'text';
    /**
     * Media subtype
     * @var string
     */
    var $type1 = 'plain';
    /**
     * Auxiliary header information
     * prepared with parseContentType() function in rfc822header class.
     * @var array
     */
    var $properties = '';

    /**
     * Constructor function.
     * Prepared type0 and type1 properties
     * @param string $type content type string without auxiliary information
     */
    function ContentType($type) {
        $type = strtolower($type);
        $pos = strpos($type, '/');
        if ($pos > 0) {
            $this->type0 = substr($type, 0, $pos);
            $this->type1 = substr($type, $pos+1);
        } else {
            $this->type0 = $type;
        }
        $this->properties = array();
    }
}

Added class/mime/Disposition.class.php.

































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php

/**
 * Disposition.class.php
 *
 * This file contains functions needed to handle content disposition headers 
 * in mime messages. See RFC 2183.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Disposition.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Class that handles content disposition header
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.0
 * @todo FIXME: do we have to declare vars ($name and $properties)?
 */
class Disposition {
    /**
     * Constructor function
     * @param string $name
     */
    function Disposition($name) {
       $this->name = $name;
       $this->properties = array();
    }

    /**
     * Returns value of content disposition property
     * @param string $par content disposition property name
     * @return string
     * @since 1.3.1
     */
    function getProperty($par) {
        $value = strtolower($par);
        if (isset($this->properties[$par])) {
            return $this->properties[$par];
        }
        return '';
    }
}

Added class/mime/Language.class.php.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
<?php

/**
 * Language.class.php
 *
 * This file should contain class needed to handle Language properties in 
 * mime messages. I suspect that it is RFC2231
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Language.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Class that can be used to handle language properties in MIME headers.
 *
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.0
 */
class Language {
    /**
     * Class constructor
     * @param mixed $name
     */
    function Language($name) {
        /** @var mixed */
        $this->name = $name;
        /**
         * Language properties
         * @var array 
         */
        $this->properties = array();
    }
}

Added class/mime/Message.class.php.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
<?php

/**
 * Message.class.php
 *
 * This file contains functions needed to handle mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Message.class.php 14300 2012-04-01 17:56:49Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * The object that contains a message.
 *
 * message is the object that contains messages. It is a recursive object in
 * that through the $entities variable, it can contain more objects of type
 * message. See documentation in mime.txt for a better description of how this
 * works.
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.0
 */
class Message {
    /**
     * rfc822header object
     * @var object
     */
    var $rfc822_header = '';
    /**
     * Headers from original email in reply
     * @var string 
     */
    var $reply_rfc822_header = '';
    /**
     * MessageHeader object
     * @var object
     */
    var $mime_header = '';
    /**
     * @var mixed
     */
    var $flags = '';
    /**
     * Media type
     * @var string
     */
    var $type0='';
    /**
     * Media subtype
     * @var string
     */
    var $type1='';
    /**
     * Nested mime parts
     * @var array
     */
    var $entities = array();
    /**
     * Message part id
     * @var string
     */
    var $entity_id = '';
    /**
     * Parent message part id
     * @var string
     */
    var $parent_ent;
    /**
     * @var mixed
     */
    var $entity;
    /**
     * @var mixed
     */
    var $parent = '';
    /**
     * @var string
     */
    var $decoded_body='';
    /**
     * Message \seen status
     * @var boolean
     */
    var $is_seen = 0;
    /**
     * Message \answered status
     * @var boolean
     */
    var $is_answered = 0;
    /**
     * Message \deleted status
     * @var boolean
     */
    var $is_deleted = 0;
    /**
     * Message \flagged status
     * @var boolean
     */
    var $is_flagged = 0;
    /**
     * Message mdn status
     * @var boolean
     */
    var $is_mdnsent = 0;
    /**
     * Message text body
     * @var string
     */
    var $body_part = '';
    /**
     * Message part offset
     * for fetching body parts out of raw messages
     * @var integer
     */
    var $offset = 0;
    /**
     * Message part length
     * for fetching body parts out of raw messages
     * @var integer
     */
    var $length = 0;
    /**
     * Local attachment filename location where the tempory attachment is
     * stored. For use in delivery class.
     * @var string
     */
    var $att_local_name = '';

    /**
     * @param string $ent entity id
     */
    function setEnt($ent) {
        $this->entity_id= $ent;
    }

    /**
     * Add nested message part
     * @param object $msg
     */
    function addEntity ($msg) {
        $this->entities[] = $msg;
    }

    /**
     * Get file name used for mime part
     * @return string file name
     * @since 1.3.2
     */
    function getFilename() {
         $filename = '';
         $header = $this->header;
         if (is_object($header->disposition)) {
              $filename = $header->disposition->getProperty('filename');
              if (trim($filename) == '') {
                  $name = decodeHeader($header->disposition->getProperty('name'));
                  if (!trim($name)) {
                      $name = $header->getParameter('name');
                      if(!trim($name)) {
                          if (!trim( $header->id )) {
                              $filename = 'untitled-[' . $this->entity_id . ']' . '.' . strtolower($header->type1);
                          } else {
                              $filename = 'cid: ' . $header->id . '.' . strtolower($header->type1);
                          }
                      } else {
                          $filename = $name;
                      }
                  } else {
                      $filename = $name;
                  }
              }
         } else {
              $filename = $header->getParameter('filename');
              if (!trim($filename)) {
                  $filename = $header->getParameter('name');
                  if (!trim($filename)) {
                      if (!trim( $header->id )) {
                          $filename = 'untitled-[' . $this->entity_id . ']' . '.' . strtolower($header->type1);
                      } else {
                          $filename = 'cid: ' . $header->id . '.' . strtolower($header->type1);
                      }
                  }
              }
         }
         return $filename;
    }

    /**
     * Add header object to message object.
     * WARNING: Unfinished code. Don't expect it to work in older sm versions.
     * @param mixed $read array or string with message headers
     * @todo FIXME: rfc822header->parseHeader() does not return rfc822header object
     */
    function addRFC822Header($read) {
        $header = new Rfc822Header();
        $this->rfc822_header = $header->parseHeader($read);
    }

    /**
     * @param string $ent
     * @return mixed (object or string?)
     */
    function getEntity($ent) {
        $cur_ent = $this->entity_id;
        $msg = $this;
        if (($cur_ent == '') || ($cur_ent == '0')) {
            $cur_ent_a = array();
        } else {
            $cur_ent_a = explode('.', $this->entity_id);
        }
        $ent_a = explode('.', $ent);

        for ($i = 0,$entCount = count($ent_a) - 1; $i < $entCount; ++$i) {
            if (isset($cur_ent_a[$i]) && ($cur_ent_a[$i] != $ent_a[$i])) {
                $msg = $msg->parent;
                $cur_ent_a = explode('.', $msg->entity_id);
                --$i;
            } else if (!isset($cur_ent_a[$i])) {
                if (isset($msg->entities[($ent_a[$i]-1)])) {
                    $msg = $msg->entities[($ent_a[$i]-1)];
                } else {
                    $msg = $msg->entities[0];
                }
            }
            if (($msg->type0 == 'message') && ($msg->type1 == 'rfc822')) {
                /*this is a header for a message/rfc822 entity */
                $msg = $msg->entities[0];
            }
        }

        if (($msg->type0 == 'message') && ($msg->type1 == 'rfc822')) {
            /*this is a header for a message/rfc822 entity */
            $msg = $msg->entities[0];
        }

        if (isset($msg->entities[($ent_a[$entCount])-1])) {
            if (is_object($msg->entities[($ent_a[$entCount])-1])) {
                $msg = $msg->entities[($ent_a[$entCount]-1)];
            }
        }

        return $msg;
    }

    /**
     * Set message body
     * @param string $s message body
     */
    function setBody($s) {
        $this->body_part = $s;
    }

    /**
     * Clean message object
     */
    function clean_up() {
        $msg = $this;
        $msg->body_part = '';

        foreach ($msg->entities as $m) {
            $m->clean_up();
        }
    }

    /**
     * @return string
     */
    function getMailbox() {
        $msg = $this;
        while (is_object($msg->parent)) {
            $msg = $msg->parent;
        }
        return $msg->mailbox;
    }

    /*
     * Bodystructure parser, a recursive function for generating the
     * entity-tree with all the mime-parts.
     *
     * It follows RFC2060 and stores all the described fields in the
     * message object.
     *
     * Question/Bugs:
     *
     * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net)
     * @param string $read
     * @param integer $i
     * @param mixed $sub_msg
     * @return object Message object
     * @todo define argument and return types
     */
    function parseStructure($read, &$i, $sub_msg = '') {
        $msg = Message::parseBodyStructure($read, $i, $sub_msg);
        if($msg) $msg->setEntIds($msg,false,0);
        return $msg;
    }

    /**
     * @param object $msg
     * @param mixed $init
     * @param integer $i
     * @todo document me
     * @since 1.4.0
     */
    function setEntIds(&$msg,$init=false,$i=0) {
        $iCnt = count($msg->entities);
        if ($init !==false) {
            $iEntSub = $i+1;
            if ($msg->parent->type0 == 'message' &&
                $msg->parent->type1 == 'rfc822' &&
                $msg->type0 == 'multipart') {
                $iEntSub = '0';
            }
            if ($init) {
                $msg->entity_id = "$init.$iEntSub";
            } else {
                $msg->entity_id = $iEntSub;
            }
        } else if ($iCnt) {
            $msg->entity_id='0';
        } else {
            $msg->entity_id='1';
        }
        for ($i=0;$i<$iCnt;++$i) {
            $msg->entities[$i]->parent =& $msg;
            if (strrchr($msg->entity_id, '.') != '.0') {
                $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->entity_id,$i);
            } else {
                $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->parent->entity_id,$i);
            }
        }
    }

    /**
     * @param string $read
     * @param integer $i
     * @param mixed $sub_msg
     * @return object Message object
     * @todo document me
     * @since 1.4.0 (code was part of parseStructure() in 1.3.x)
     */
    function parseBodyStructure($read, &$i, $sub_msg = '') {
        $arg_no = 0;
        $arg_a  = array();
        if ($sub_msg) {
            $message = $sub_msg;
        } else {
            $message = new Message();
        }

        for ($cnt = strlen($read); $i < $cnt; ++$i) {
            $char = strtoupper($read{$i});
            switch ($char) {
                case '(':
                    switch($arg_no) {
                        case 0:
                            if (!isset($msg)) {
                                $msg = new Message();
                                $hdr = new MessageHeader();
                                $hdr->type0 = 'text';
                                $hdr->type1 = 'plain';
                                $hdr->encoding = '7bit';
                                $msg->header = $hdr;
                            } else {
                                $msg->header->type0 = 'multipart';
                                $msg->type0 = 'multipart';
                                while ($read{$i} == '(') {
                                    $msg->addEntity($msg->parseBodyStructure($read, $i, $msg));
                                }
                            }
                            break;
                        case 1:
                            /* multipart properties */
                            ++$i;
                            $arg_a[] = $msg->parseProperties($read, $i);
                            ++$arg_no;
                            break;
                        case 2:
                            if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
                                ++$i;
                                $arg_a[] = $msg->parseDisposition($read, $i);
                            } else { /* properties */
                                $arg_a[] = $msg->parseProperties($read, $i);
                            }
                            ++$arg_no;
                            break;
                        case 3:
                            if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
                                ++$i;
                                $arg_a[]= $msg->parseLanguage($read, $i);
                            }
                        case 7:
                            if (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822')) {
                                $msg->header->type0 = $arg_a[0];
                                $msg->header->type1 = $arg_a[1];
                                $msg->type0 = $arg_a[0];
                                $msg->type1 = $arg_a[1];
                                $rfc822_hdr = new Rfc822Header();
                                $msg->rfc822_header = $msg->parseEnvelope($read, $i, $rfc822_hdr);
                                while (($i < $cnt) && ($read{$i} != '(')) {
                                    ++$i;
                                }
                                $msg->addEntity($msg->parseBodyStructure($read, $i,$msg));
                            }
                            break;
                        case 8:
                            ++$i;
                            $arg_a[] = $msg->parseDisposition($read, $i);
                            ++$arg_no;
                            break;
                        case 9:
                            ++$i;
                            if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
                                $arg_a[] = $msg->parseDisposition($read, $i);
                            } else {
                                $arg_a[] = $msg->parseLanguage($read, $i);
                            }
                            ++$arg_no;
                            break;
                       case 10:
                           if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
                               ++$i;
                               $arg_a[] = $msg->parseLanguage($read, $i);
                           } else {
                               $i = $msg->parseParenthesis($read, $i);
                               $arg_a[] = ''; /* not yet described in rfc2060 */
                           }
                           ++$arg_no;
                           break;
                       default:
                           /* unknown argument, skip this part */
                           $i = $msg->parseParenthesis($read, $i);
                           $arg_a[] = '';
                           ++$arg_no;
                           break;
                   } /* switch */
                   break;
                case '"':
                    /* inside an entity -> start processing */
                    $arg_s = $msg->parseQuote($read, $i);
                    ++$arg_no;
                    if ($arg_no < 3) {
                        $arg_s = strtolower($arg_s); /* type0 and type1 */
                    }
                    $arg_a[] = $arg_s;
                    break;
                case 'n':
                case 'N':
                    /* probably NIL argument */
                    $tmpnil = strtoupper(substr($read, $i, 4));
                    if ($tmpnil == 'NIL ' || $tmpnil == 'NIL)') {
                        $arg_a[] = '';
                        ++$arg_no;
                        $i += 2;
                    }
                    break;
                case '{':
                    /* process the literal value */
                    $arg_a[] = $msg->parseLiteral($read, $i);
                    ++$arg_no;
                    break;
                case '0':
                case is_numeric($read{$i}):
                    /* process integers */
                    if ($read{$i} == ' ') { break; }
                    ++$arg_no;
                    if (preg_match('/^([0-9]+).*/',substr($read,$i), $regs)) {
                        $i += strlen($regs[1])-1;
                        $arg_a[] = $regs[1];
                    } else {
                        $arg_a[] = 0;
                    }
                    break;
                case ')':
                    $multipart = (isset($msg->type0) && ($msg->type0 == 'multipart'));
                    if (!$multipart) {
                        $shifted_args = (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822')));
                        $hdr->type0 = $arg_a[0];
                        $hdr->type1 = $arg_a[1];

                        $msg->type0 = $arg_a[0];
                        $msg->type1 = $arg_a[1];
                        $arr = $arg_a[2];
                        if (is_array($arr)) {
                            $hdr->parameters = $arg_a[2];
                        }
                        $hdr->id = str_replace('<', '', str_replace('>', '', $arg_a[3]));
                        $hdr->description = $arg_a[4];
                        $hdr->encoding = strtolower($arg_a[5]);
                        $hdr->entity_id = $msg->entity_id;
                        $hdr->size = $arg_a[6];
                        if ($shifted_args) {
                            $hdr->lines = $arg_a[7];
                            $s = 1;
                        } else {
                            $s = 0;
                        }
                        $hdr->md5 = (isset($arg_a[7+$s]) ? $arg_a[7+$s] : $hdr->md5);
                        $hdr->disposition = (isset($arg_a[8+$s]) ? $arg_a[8+$s] : $hdr->disposition);
                        $hdr->language = (isset($arg_a[9+$s]) ? $arg_a[9+$s] : $hdr->language);
                        $msg->header = $hdr;
                    } else {
                        $hdr->type0 = 'multipart';
                        $hdr->type1 = $arg_a[0];
                        $msg->type0 = 'multipart';
                        $msg->type1 = $arg_a[0];
                        $hdr->parameters = (isset($arg_a[1]) ? $arg_a[1] : $hdr->parameters);
                        $hdr->disposition = (isset($arg_a[2]) ? $arg_a[2] : $hdr->disposition);
                        $hdr->language = (isset($arg_a[3]) ? $arg_a[3] : $hdr->language);
                        $msg->header = $hdr;
                    }
                    return $msg;
                default: break;
            } /* switch */
        } /* for */
    } /* parsestructure */

    /**
     * @param string $read
     * @param integer $i
     * @return array
     */
    function parseProperties($read, &$i) {
        $properties = array();
        $prop_name = '';

        for (; $read{$i} != ')'; ++$i) {
            $arg_s = '';
            if ($read{$i} == '"') {
                $arg_s = $this->parseQuote($read, $i);
            } else if ($read{$i} == '{') {
                $arg_s = $this->parseLiteral($read, $i);
            }

            if ($arg_s != '') {
                if ($prop_name == '') {
                    $prop_name = strtolower($arg_s);
                    $properties[$prop_name] = '';
                } else if ($prop_name != '') {
                    $properties[$prop_name] = $arg_s;
                    $prop_name = '';
                }
            }
        }
        return $properties;
    }

    /**
     * @param string $read
     * @param integer $i
     * @param object $hdr MessageHeader object
     * @return object MessageHeader object
     */
    function parseEnvelope($read, &$i, $hdr) {
        $arg_no = 0;
        $arg_a = array();
        ++$i;
        for ($cnt = strlen($read); ($i < $cnt) && ($read{$i} != ')'); ++$i) {
            $char = strtoupper($read{$i});
            switch ($char) {
                case '"':
                    $arg_a[] = $this->parseQuote($read, $i);
                    ++$arg_no;
                    break;
                case '{':
                    $arg_a[] = $this->parseLiteral($read, $i);
            /* temp bugfix (SM 1.5 will have a working clean version)
               too much work to implement that version right now */
//            --$i;
                    ++$arg_no;
                    break;
                case 'N':
                    /* probably NIL argument */
                    if (strtoupper(substr($read, $i, 3)) == 'NIL') {
                        $arg_a[] = '';
                        ++$arg_no;
                        $i += 2;
                    }
                    break;
                case '(':
                    /* Address structure (with group support)
                     * Note: Group support is useless on SMTP connections
                     *       because the protocol doesn't support it
                     */
                    $addr_a = array();
                    $group = '';
                    $a=0;
                    for (; $i < $cnt && $read{$i} != ')'; ++$i) {
                        if ($read{$i} == '(') {
                            $addr = $this->parseAddress($read, $i);
                            if (($addr->host == '') && ($addr->mailbox != '')) {
                                /* start of group */
                                $group = $addr->mailbox;
                                $group_addr = $addr;
                                $j = $a;
                            } else if ($group && ($addr->host == '') && ($addr->mailbox == '')) {
                               /* end group */
                                if ($a == ($j+1)) { /* no group members */
                                    $group_addr->group = $group;
                                    $group_addr->mailbox = '';
                                    $group_addr->personal = "$group: Undisclosed recipients;";
                                    $addr_a[] = $group_addr;
                                    $group ='';
                                }
                            } else {
                                $addr->group = $group;
                                $addr_a[] = $addr;
                            }
                            ++$a;
                        }
                    }
                    $arg_a[] = $addr_a;
                    break;
                default: break;
            }
        }

        if (count($arg_a) > 9) {
            $d = strtr($arg_a[0], array('  ' => ' '));
            $d_parts = explode(' ', $d);
            if (!$arg_a[1]) $arg_a[1] = _("(no subject)");

            $hdr->date = getTimeStamp($d_parts); /* argument 1: date */
            $hdr->date_unparsed = strtr($d,'<>','  '); /* original date */
            $hdr->subject = $arg_a[1];     /* argument 2: subject */
            $hdr->from = is_array($arg_a[2]) ? $arg_a[2][0] : '';     /* argument 3: from        */
            $hdr->sender = is_array($arg_a[3]) ? $arg_a[3][0] : '';   /* argument 4: sender      */
            $hdr->reply_to = is_array($arg_a[4]) ? $arg_a[4][0] : '';  /* argument 5: reply-to    */
            $hdr->to = $arg_a[5];          /* argument 6: to          */
            $hdr->cc = $arg_a[6];          /* argument 7: cc          */
            $hdr->bcc = $arg_a[7];         /* argument 8: bcc         */
            $hdr->in_reply_to = $arg_a[8];   /* argument 9: in-reply-to */
            $hdr->message_id = $arg_a[9];  /* argument 10: message-id */
        }
        return $hdr;
    }

    /**
     * @param string $read
     * @param integer $i
     * @return string
     * @todo document me
     */
    function parseLiteral($read, &$i) {
        $lit_cnt = '';
        ++$i;
        $iPos = strpos($read,'}',$i);
        if ($iPos) {
            $lit_cnt = substr($read, $i, $iPos - $i);
            $i += strlen($lit_cnt) + 3; /* skip } + \r + \n */
            /* Now read the literal */
            $s = ($lit_cnt ? substr($read,$i,$lit_cnt): '');
            $i += $lit_cnt;
            /* temp bugfix (SM 1.5 will have a working clean version)
               too much work to implement that version right now */
            --$i;
        } else { /* should never happen */
            $i += 3; /* } + \r + \n */
            $s = '';
        }
        return $s;
    }

    /**
     * function parseQuote
     *
     * This extract the string value from a quoted string. After the end-quote
     * character is found it returns the string. The offset $i when calling
     * this function points to the first double quote. At the end it points to
     * The ending quote. This function takes care of escaped double quotes.
     * "some \"string\""
     * ^               ^
     * initial $i      end position $i
     *
     * @param string $read
     * @param integer $i offset in $read
     * @return string string inbetween the double quotes
     * @author Marc Groot Koerkamp
     */
    function parseQuote($read, &$i) {
        $s = '';
        $iPos = ++$i;
        $iPosStart = $iPos;
        while (true) {
            $iPos = strpos($read,'"',$iPos);
            if (!$iPos) break;
            if ($iPos && $read{$iPos -1} != '\\') {
                $s = substr($read,$i,($iPos-$i));
                $i = $iPos;
                break;
            } else if ($iPos > 1 && $read{$iPos -1} == '\\' && $read{$iPos-2} == '\\') {
                // This is an unique situation where the fast detection of the string
                // fails. If the quote string ends with \\ then we need to iterate
                // through the entire string to make sure we detect the unexcaped
                // double quotes correctly.
                $s = '';
                $bEscaped = false;
                $k = 0;
                 for ($j=$iPosStart,$iCnt=strlen($read);$j<$iCnt;++$j) {
                    $cChar = $read{$j};
                    switch ($cChar) {
                        case '\\':
                           $bEscaped = !$bEscaped;
                            $s .= $cChar;
                            break;
                         case '"':
                            if ($bEscaped) {
                                $s .= $cChar;
                                $bEscaped = false;
                            } else {
                                $i = $j;
                                break 3;
                            }
                            break;
                         default:
                            if ($bEscaped) {
                               $bEscaped = false;
                            }
                            $s .= $cChar;
                            break;
                    }
                }
            }
            ++$iPos;
            if ($iPos > strlen($read)) {
                break;
            }
        }
        return $s;
    }

    /**
     * @param string $read
     * @param integer $i
     * @return object AddressStructure object
     */
    function parseAddress($read, &$i) {
        $arg_a = array();
        for (; $read{$i} != ')'; ++$i) {
            $char = strtoupper($read{$i});
            switch ($char) {
                case '"': $arg_a[] = $this->parseQuote($read, $i); break;
                case '{': $arg_a[] = $this->parseLiteral($read, $i); break;
                case 'n':
                case 'N':
                    if (strtoupper(substr($read, $i, 3)) == 'NIL') {
                        $arg_a[] = '';
                        $i += 2;
                    }
                    break;
                default: break;
            }
        }

        if (count($arg_a) == 4) {
            $adr = new AddressStructure();
            $adr->personal = $arg_a[0];
            $adr->adl = $arg_a[1];
            $adr->mailbox = $arg_a[2];
            $adr->host = $arg_a[3];
        } else {
            $adr = '';
        }
        return $adr;
    }

    /**
     * @param string $read
     * @param integer $i
     * @param object Disposition object or empty string
     */
    function parseDisposition($read, &$i) {
        $arg_a = array();
        for (; $read{$i} != ')'; ++$i) {
            switch ($read{$i}) {
                case '"': $arg_a[] = $this->parseQuote($read, $i); break;
                case '{': $arg_a[] = $this->parseLiteral($read, $i); break;
                case '(': $arg_a[] = $this->parseProperties($read, $i); break;
                default: break;
            }
        }

        if (isset($arg_a[0])) {
            $disp = new Disposition($arg_a[0]);
            if (isset($arg_a[1])) {
                $disp->properties = $arg_a[1];
            }
        }
        return (is_object($disp) ? $disp : '');
    }

    /**
     * @param string $read
     * @param integer $i
     * @return object Language object or empty string
     */
    function parseLanguage($read, &$i) {
        /* no idea how to process this one without examples */
        $arg_a = array();

        for (; $read{$i} != ')'; ++$i) {
            switch ($read{$i}) {
                case '"': $arg_a[] = $this->parseQuote($read, $i); break;
                case '{': $arg_a[] = $this->parseLiteral($read, $i); break;
                case '(': $arg_a[] = $this->parseProperties($read, $i); break;
                default: break;
            }
        }

        if (isset($arg_a[0])) {
            $lang = new Language($arg_a[0]);
            if (isset($arg_a[1])) {
                $lang->properties = $arg_a[1];
            }
        }
        return (is_object($lang) ? $lang : '');
    }

    /**
     * Parse message text enclosed in parenthesis
     * @param string $read
     * @param integer $i
     * @return integer
     */
    function parseParenthesis($read, $i) {
        for ($i++; $read{$i} != ')'; ++$i) {
            switch ($read{$i}) {
                case '"': $this->parseQuote($read, $i); break;
                case '{': $this->parseLiteral($read, $i); break;
                case '(': $this->parseProperties($read, $i); break;
                default: break;
            }
        }
        return $i;
    }

    /**
     * Function to fill the message structure in case the
     * bodystructure is not available
     * NOT FINISHED YET
     * @param string $read
     * @param string $type0 message part type
     * @param string $type1 message part subtype
     * @return string (only when type0 is not message or multipart)
     */
    function parseMessage($read, $type0, $type1) {
        switch ($type0) {
            case 'message':
                $rfc822_header = true;
                $mime_header = false;
                break;
            case 'multipart':
                $rfc822_header = false;
                $mime_header = true;
                break;
            default: return $read;
        }

        for ($i = 1; $i < $count; ++$i) {
            $line = trim($body[$i]);
            if (($mime_header || $rfc822_header) &&
                (preg_match("/^.*boundary=\"?(.+(?=\")|.+).*/i", $line, $reg))) {
                $bnd = $reg[1];
                $bndreg = $bnd;
                $bndreg = str_replace("\\", "\\\\", $bndreg);
                $bndreg = str_replace("?", "\\?", $bndreg);
                $bndreg = str_replace("+", "\\+", $bndreg);
                $bndreg = str_replace(".", "\\.", $bndreg);
                $bndreg = str_replace("/", "\\/", $bndreg);
                $bndreg = str_replace("-", "\\-", $bndreg);
                $bndreg = str_replace("(", "\\(", $bndreg);
                $bndreg = str_replace(")", "\\)", $bndreg);
            } else if ($rfc822_header && $line == '') {
                $rfc822_header = false;
                if ($msg->type0 == 'multipart') {
                    $mime_header = true;
                }
            }

            if ((($line{0} == '-') || $rfc822_header)  && isset($boundaries[0])) {
                $cnt = count($boundaries)-1;
                $bnd = $boundaries[$cnt]['bnd'];
                $bndreg = $boundaries[$cnt]['bndreg'];

                $regstr = '/^--'."($bndreg)".".*".'/';
                if (preg_match($regstr, $line, $reg)) {
                    $bndlen = strlen($reg[1]);
                    $bndend = false;
                    if (strlen($line) > ($bndlen + 3)) {
                        if (($line{$bndlen+2} == '-') && ($line{$bndlen+3} == '-')) {
                            $bndend = true;
                        }
                    }
                    if ($bndend) {
                        /* calc offset and return $msg */
                        //$entStr = CalcEntity("$entStr", -1);
                        array_pop($boundaries);
                        $mime_header = true;
                        $bnd_end = true;
                    } else {
                        $mime_header = true;
                         $bnd_end = false;
                        //$entStr = CalcEntity("$entStr", 0);
                        ++$content_indx;
                    }
                } else {
                    if ($header) { }
                }
            }
        }
    }

    /**
     * @param array $entity
     * @param array $alt_order
     * @param boolean $strict
     * @return array
     */
    function findDisplayEntity($entity = array(), $alt_order = array('text/plain', 'text/html'), $strict=false) {
        $found = false;
        if ($this->type0 == 'multipart') {
            if($this->type1 == 'alternative') {
                $msg = $this->findAlternativeEntity($alt_order);
                if ( ! is_null($msg) ) {
                    if (count($msg->entities) == 0) {
                        $entity[] = $msg->entity_id;
                    } else {
                        $entity = $msg->findDisplayEntity($entity, $alt_order, $strict);
                    }
                    $found = true;
                }
            } else if ($this->type1 == 'related') { /* RFC 2387 */
                $msgs = $this->findRelatedEntity();
                foreach ($msgs as $msg) {
                    if (count($msg->entities) == 0) {
                        $entity[] = $msg->entity_id;
                    } else {
                        $entity = $msg->findDisplayEntity($entity, $alt_order, $strict);
                    }
                }
                if (count($msgs) > 0) {
                    $found = true;
                }
            } else { /* Treat as multipart/mixed */
                foreach ($this->entities as $ent) {
                    if(!(is_object($ent->header->disposition) && strtolower($ent->header->disposition->name) == 'attachment') &&
                            (!isset($ent->header->parameters['filename'])) &&
                            (!isset($ent->header->parameters['name'])) &&
                            (($ent->type0 != 'message') && ($ent->type1 != 'rfc822'))) {
                        $entity = $ent->findDisplayEntity($entity, $alt_order, $strict);
                        $found = true;
                    }
                }
            }
        } else { /* If not multipart, then just compare with each entry from $alt_order */
            $type = $this->type0.'/'.$this->type1;
//        $alt_order[] = "message/rfc822";
            foreach ($alt_order as $alt) {
                if( ($alt == $type) && isset($this->entity_id) ) {
                    if ((count($this->entities) == 0) &&
                            (!isset($this->header->parameters['filename'])) &&
                            (!isset($this->header->parameters['name'])) &&
                            (isset($this->header->disposition) && is_object($this->header->disposition) &&
                             strtolower($this->header->disposition->name) != 'attachment')) {
                        $entity[] = $this->entity_id;
                        $found = true;
                    }
                }
            }
        }
        if(!$found) {
            foreach ($this->entities as $ent) {
                if(!(is_object($ent->header->disposition) && strtolower($ent->header->disposition->name) == 'attachment') &&
                   (($ent->type0 != 'message') && ($ent->type1 != 'rfc822'))) {
                    $entity = $ent->findDisplayEntity($entity, $alt_order, $strict);
                    $found = true;
                }
            }
        }
        if(!$strict && !$found) {
            if (($this->type0 == 'text') &&
                in_array($this->type1, array('plain', 'html', 'message')) &&
                isset($this->entity_id)) {
                if (count($this->entities) == 0) {
                    if (!is_object($this->header->disposition) || strtolower($this->header->disposition->name) != 'attachment') {
                        $entity[] = $this->entity_id;
                    }
                }
            }
        }
        return $entity;
    }

    /**
     * @param array $alt_order
     * @return entity
     */
    function findAlternativeEntity($alt_order) {
        /* If we are dealing with alternative parts then we  */
        /* choose the best viewable message supported by SM. */
        $best_view = 0;
        $entity = null;
        foreach($this->entities as $ent) {
            $type = $ent->header->type0 . '/' . $ent->header->type1;
            if ($type == 'multipart/related') {
                $type = $ent->header->getParameter('type');
                // Mozilla bug. Mozilla does not provide the parameter type.
                if (!$type) $type = 'text/html';
            }
            $altCount = count($alt_order);
            for ($j = $best_view; $j < $altCount; ++$j) {
                if (($alt_order[$j] == $type) && ($j >= $best_view)) {
                    $best_view = $j;
                    $entity = $ent;
                }
            }
        }
        return $entity;
    }

    /**
     * @return array
     */
    function findRelatedEntity() {
        $msgs = array();
        $related_type = $this->header->getParameter('type');
        // Mozilla bug. Mozilla does not provide the parameter type.
        if (!$related_type) $related_type = 'text/html';
        $entCount = count($this->entities);
        for ($i = 0; $i < $entCount; ++$i) {
            $type = $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1;
            if ($related_type == $type) {
                $msgs[] = $this->entities[$i];
            }
        }
        return $msgs;
    }

    /**
     * @param array $exclude_id
     * @param array $result
     * @return array
     */
    function getAttachments($exclude_id=array(), $result = array()) {
/*
        if (($this->type0 == 'message') &&
        ($this->type1 == 'rfc822') &&
        ($this->entity_id) ) {
            $this = $this->entities[0];
        }
*/
        if (count($this->entities)) {
            foreach ($this->entities as $entity) {
                $exclude = false;
                foreach ($exclude_id as $excl) {
                    if ($entity->entity_id === $excl) {
                        $exclude = true;
                    }
                }

                if (!$exclude) {
                    if ($entity->type0 == 'multipart') {
                        $result = $entity->getAttachments($exclude_id, $result);
                    } else if ($entity->type0 != 'multipart') {
                        $result[] = $entity;
                    }
                }
            }
        } else {
            $exclude = false;
            foreach ($exclude_id as $excl) {
                $exclude = $exclude || ($this->entity_id == $excl);
            }

            if (!$exclude) {
                $result[] = $this;
            }
        }
        return $result;
    }

    /**
     * Add attachment to message object
     * @param string $type attachment type
     * @param string $name attachment name
     * @param string $location path to attachment
     */
    function initAttachment($type, $name, $location) {
        $attachment = new Message();
        $mime_header = new MessageHeader();
        $mime_header->setParameter('name', $name);
        $pos = strpos($type, '/');
        if ($pos > 0) {
            $mime_header->type0 = substr($type, 0, $pos);
            $mime_header->type1 = substr($type, $pos+1);
        } else {
            $mime_header->type0 = $type;
        }
        $attachment->att_local_name = $location;
        $disposition = new Disposition('attachment');
        $disposition->properties['filename'] = $name;
        $mime_header->disposition = $disposition;
        $attachment->mime_header = $mime_header;
        $this->entities[]=$attachment;
    }

    /**
     * Delete all attachments from this object from disk.
     * @since 1.4.6
     */
    function purgeAttachments() {
        if ($this->att_local_name) {
            global $username, $attachment_dir;
            $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
            if ( file_exists($hashed_attachment_dir . '/' . $this->att_local_name) ) {
                unlink($hashed_attachment_dir . '/' . $this->att_local_name);
            }
        }
        // recursively delete attachments from entities contained in this object
        for ($i=0, $entCount=count($this->entities);$i< $entCount; ++$i) {
            $this->entities[$i]->purgeAttachments();
        }
    }
}

Added class/mime/MessageHeader.class.php.







































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php

/**
 * MessageHeader.class.php
 *
 * This file contains functions needed to handle headers in mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: MessageHeader.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Message header class
 * Class contains all variables available in a bodystructure
 * entity like described in rfc2060
 * It was called msg_header in 1.3.0 and 1.3.1.
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */
class MessageHeader {
    /**
     * Media type
     * @var string
     */
    var $type0 = '';
    /**
     * Media subtype
     * @var string
     */
    var $type1 = '';
    /**
     * Content type parameters
     * @var array
     */
    var $parameters = array();
    /**
     * @var mixed
     */
    var $id = 0;
    /**
     * @var string
     */
    var $description = '';
    /**
     * @var string
     */
    var $encoding='';
    /**
     * Message size
     * @var integer
     */
    var $size = 0;
    /**
     * @var string
     */
    var $md5='';
    /**
     * @var mixed
     */
    var $disposition = '';
    /**
     * @var mixed
     */
    var $language='';

    /**
     * Sets header variable
     * @param string $var
     * @param mixed $value
     */
    function setVar($var, $value) {
        $this->{$var} = $value;
    }

    /**
     * Gets parameter value from $parameters array
     * @param string $p
     * @return mixed
     */
    function getParameter($p) {
        $value = strtolower($p);
        return (isset($this->parameters[$p]) ? $this->parameters[$p] : '');
    }

    /**
     * Sets parameter value in $parameters array
     * @param string $parameter
     * @param mixed $value
     */
    function setParameter($parameter, $value) {
        $this->parameters[strtolower($parameter)] = $value;
    }
}

Added class/mime/Rfc822Header.class.php.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
<?php

/**
 * Rfc822Header.class.php
 *
 * This file contains functions needed to handle headers in mime messages.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: Rfc822Header.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * MIME header class
 * input: header_string or array
 * You must call parseHeader() function after creating object in order to fill object's
 * parameters.
 * @todo FIXME: there is no constructor function and class should ignore all input args.
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.0
 */
class Rfc822Header {
    /**
     * Date header
     * @var mixed
     */
    var $date = -1;
    /**
     * Original date header as fallback for unparsable dates
     * @var mixed
     */
    var $date_unparsed = '';
    /**
     * Subject header
     * @var string
     */
    var $subject = '';
    /**
     * From header
     * @var array
     */
    var $from = array();
    /**
     * @var mixed
     */
    var $sender = '';
    /**
     * Reply-To header
     * @var array
     */
    var $reply_to = array();
    /**
     * Mail-Followup-To header
     * @var array
     */
    var $mail_followup_to = array();
    /**
     * To header
     * @var array
     */
    var $to = array();
    /**
     * Cc header
     * @var array
     */
    var $cc = array();
    /**
     * Bcc header
     * @var array
     */
    var $bcc = array();
    /**
     * In-reply-to header
     * @var string
     */
    var $in_reply_to = '';
    /**
     * Message-ID header
     * @var string
     */
    var $message_id = '';
    /**
     * References header
     * @var string
     */
    var $references = '';
    /**
     * @var mixed
     */
    var $mime = false;
    /**
     * @var mixed
     */
    var $content_type = '';
    /**
     * @var mixed
     */
    var $disposition = '';
    /**
     * X-Mailer header
     * @var string
     */
    var $xmailer = '';
    /**
     * Priority header
     * @var integer
     */
    var $priority = 3;
    /**
     * @var mixed
     */
    var $dnt = '';
    /**
     * @var mixed
     */
    var $encoding = '';
    /**
     * @var mixed
     */
    var $mlist = array();
    /**
     * SpamAssassin 'x-spam-status' header
     * @var mixed
     */
    var $x_spam_status = array();
    /**
     * Extra header
     * only needed for constructing headers in delivery class
     * @var array
     */
    var $more_headers = array();

    /**
     * @param mixed $hdr string or array with message headers
     */
    function parseHeader($hdr) {
        if (is_array($hdr)) {
            $hdr = implode('', $hdr);
        }
        /* First we replace \r\n by \n and unfold the header */
        /* FIXME: unfolding header with multiple spaces "\n( +)" */
        $hdr = trim(str_replace(array("\r\n", "\n\t", "\n "),array("\n", ' ', ' '), $hdr));

        /* Now we can make a new header array with */
        /* each element representing a headerline  */
        $hdr = explode("\n" , $hdr);
        foreach ($hdr as $line) {
            $pos = strpos($line, ':');
            if ($pos > 0) {
                $field = substr($line, 0, $pos);
                if (!strstr($field,' ')) { /* valid field */
                        $value = trim(substr($line, $pos+1));
                        $this->parseField($field, $value);
                }
            }
        }
        if (!is_object($this->content_type)) {
            $this->parseContentType('text/plain; charset=us-ascii');
        }
    }

    /**
     * @param string $value
     * @return string
     */
    function stripComments($value) {
        $result = '';
        $cnt = strlen($value);
        for ($i = 0; $i < $cnt; ++$i) {
            switch ($value{$i}) {
                case '"':
                    $result .= '"';
                    while ((++$i < $cnt) && ($value{$i} != '"')) {
                        if ($value{$i} == '\\') {
                            $result .= '\\';
                            ++$i;
                        }
                        $result .= $value{$i};
                    }
                    $result .= $value{$i};
                    break;
                case '(':
                    $depth = 1;
                    while (($depth > 0) && (++$i < $cnt)) {
                        switch($value{$i}) {
                            case '\\':
                                ++$i;
                                break;
                            case '(':
                                ++$depth;
                                break;
                            case ')':
                                --$depth;
                                break;
                            default:
                                break;
                        }
                    }
                    break;
                default:
                    $result .= $value{$i};
                    break;
            }
        }
        return $result;
    }

    /**
     * Parse header field according to field type
     * @param string $field field name
     * @param string $value field value
     */
    function parseField($field, $value) {
        $field = strtolower($field);
        switch($field) {
            case 'date':
                $value = $this->stripComments($value);
                $d = strtr($value, array('  ' => ' '));
                $d = explode(' ', $d);
                $this->date = getTimeStamp($d);
                $this->date_unparsed = strtr($value,'<>','  ');
                break;
            case 'subject':
                $this->subject = $value;
                break;
            case 'from':
                $this->from = $this->parseAddress($value,true);
                break;
            case 'sender':
                $this->sender = $this->parseAddress($value);
                break;
            case 'reply-to':
                $this->reply_to = $this->parseAddress($value, true);
                break;
            case 'mail-followup-to':
                $this->mail_followup_to = $this->parseAddress($value, true);
                break;
            case 'to':
                $this->to = $this->parseAddress($value, true);
                break;
            case 'cc':
                $this->cc = $this->parseAddress($value, true);
                break;
            case 'bcc':
                $this->bcc = $this->parseAddress($value, true);
                break;
            case 'in-reply-to':
                $this->in_reply_to = $value;
                break;
            case 'message-id':
                $value = $this->stripComments($value);
                $this->message_id = $value;
                break;
            case 'references':
                $value = $this->stripComments($value);
                $this->references = $value;
                break;
            case 'x-confirm-reading-to':
            case 'return-receipt-to':
            case 'disposition-notification-to':
                $value = $this->stripComments($value);
                $this->dnt = $this->parseAddress($value);
                break;
            case 'mime-version':
                $value = $this->stripComments($value);
                $value = str_replace(' ', '', $value);
                $this->mime = ($value == '1.0' ? true : $this->mime);
                break;
            case 'content-type':
                $value = $this->stripComments($value);
                $this->parseContentType($value);
                break;
            case 'content-disposition':
                $value = $this->stripComments($value);
                $this->parseDisposition($value);
                break;
            case 'user-agent':
            case 'x-mailer':
                $this->xmailer = $value;
                break;
            case 'x-priority':
            case 'importance':
            case 'priority':
                $this->priority = $this->parsePriority($value);
                break;
            case 'list-post':
                $value = $this->stripComments($value);
                $this->mlist('post', $value);
                break;
            case 'list-reply':
                $value = $this->stripComments($value);
                $this->mlist('reply', $value);
                break;
            case 'list-subscribe':
                $value = $this->stripComments($value);
                $this->mlist('subscribe', $value);
                break;
            case 'list-unsubscribe':
                $value = $this->stripComments($value);
                $this->mlist('unsubscribe', $value);
                break;
            case 'list-archive':
                $value = $this->stripComments($value);
                $this->mlist('archive', $value);
                break;
            case 'list-owner':
                $value = $this->stripComments($value);
                $this->mlist('owner', $value);
                break;
            case 'list-help':
                $value = $this->stripComments($value);
                $this->mlist('help', $value);
                break;
            case 'list-id':
                $value = $this->stripComments($value);
                $this->mlist('id', $value);
                break;
            case 'x-spam-status':
                $this->x_spam_status = $this->parseSpamStatus($value);
                break;
            default:
                break;
        }
    }

    /**
     * @param string $address
     * @return array
     */
    function getAddressTokens($address) {
        $aTokens = array();
        $aAddress = array();
        $aSpecials = array('(' ,'<' ,',' ,';' ,':');
        $aReplace =  array(' (',' <',' ,',' ;',' :');
        $address = str_replace($aSpecials,$aReplace,$address);
        $iCnt = strlen($address);
        $i = 0;
        while ($i < $iCnt) {
            $cChar = $address{$i};
            switch($cChar)
            {
            case '<':
                $iEnd = strpos($address,'>',$i+1);
                if (!$iEnd) {
                   $sToken = substr($address,$i);
                   $i = $iCnt;
                } else {
                   $sToken = substr($address,$i,$iEnd - $i +1);
                   $i = $iEnd;
                }
                $sToken = str_replace($aReplace, $aSpecials,$sToken);
                if ($sToken) $aTokens[] = $sToken;
                break;
            case '"':
                $iEnd = strpos($address,$cChar,$i+1);
                if ($iEnd) {
                   // skip escaped quotes
                   $prev_char = $address{$iEnd-1};
                   while ($prev_char === '\\' && substr($address,$iEnd-2,2) !== '\\\\') {
                       $iEnd = strpos($address,$cChar,$iEnd+1);
                       if ($iEnd) {
                          $prev_char = $address{$iEnd-1};
                       } else {
                          $prev_char = false;
                       }
                   }
                }
                if (!$iEnd) {
                    $sToken = substr($address,$i);
                    $i = $iCnt;
                } else {
                    // also remove the surrounding quotes
                    $sToken = substr($address,$i+1,$iEnd - $i -1);
                    $i = $iEnd;
                }
                $sToken = str_replace($aReplace, $aSpecials,$sToken);
                if ($sToken) $aTokens[] = $sToken;
                break;
            case '(':
                array_pop($aTokens); //remove inserted space
                $iEnd = strpos($address,')',$i);
                if (!$iEnd) {
                    $sToken = substr($address,$i);
                    $i = $iCnt;
                } else {
                    $iDepth = 1;
                    $iComment = $i;
                    while (($iDepth > 0) && (++$iComment < $iCnt)) {
                        $cCharComment = $address{$iComment};
                        switch($cCharComment) {
                            case '\\':
                                ++$iComment;
                                break;
                            case '(':
                                ++$iDepth;
                                break;
                            case ')':
                                --$iDepth;
                                break;
                            default:
                                break;
                        }
                    }
                    if ($iDepth == 0) {
                        $sToken = substr($address,$i,$iComment - $i +1);
                        $i = $iComment;
                    } else {
                        $sToken = substr($address,$i,$iEnd - $i + 1);
                        $i = $iEnd;
                    }
                }
                // check the next token in case comments appear in the middle of email addresses
                $prevToken = end($aTokens);
                if (!in_array($prevToken,$aSpecials,true)) {
                    if ($i+1<strlen($address) && !in_array($address{$i+1},$aSpecials,true)) {
                        $iEnd = strpos($address,' ',$i+1);
                        if ($iEnd) {
                            $sNextToken = trim(substr($address,$i+1,$iEnd - $i -1));
                            $i = $iEnd-1;
                        } else {
                            $sNextToken = trim(substr($address,$i+1));
                            $i = $iCnt;
                        }
                        // remove the token
                        array_pop($aTokens);
                        // create token and add it again
                        $sNewToken = $prevToken . $sNextToken;
                        if($sNewToken) $aTokens[] = $sNewToken;
                    }
                }
                $sToken = str_replace($aReplace, $aSpecials,$sToken);
                if ($sToken) $aTokens[] = $sToken;
                break;
            case ',':
            case ':':
            case ';':
            case ' ':
                $aTokens[] = $cChar;
                break;
            default:
                $iEnd = strpos($address,' ',$i+1);
                if ($iEnd) {
                    $sToken = trim(substr($address,$i,$iEnd - $i));
                    $i = $iEnd-1;
                } else {
                    $sToken = trim(substr($address,$i));
                    $i = $iCnt;
                }
                if ($sToken) $aTokens[] = $sToken;
            }
            ++$i;
        }
        return $aTokens;
    }

    /**
     * @param array $aStack
     * @param array $aComment
     * @param string $sEmail
     * @param string $sGroup
     * @return object AddressStructure object
     */
    function createAddressObject(&$aStack,&$aComment,&$sEmail,$sGroup='') {
        //$aStack=explode(' ',implode('',$aStack));
        if (!$sEmail) {
            while (count($aStack) && !$sEmail) {
                $sEmail = trim(array_pop($aStack));
            }
        }
        if (count($aStack)) {
            $sPersonal = trim(implode('',$aStack));
        } else {
            $sPersonal = '';
        }
        if (!$sPersonal && count($aComment)) {
            $sComment = trim(implode(' ',$aComment));
            $sPersonal .= $sComment;
        }
        $oAddr = new AddressStructure();
        if ($sPersonal && substr($sPersonal,0,2) == '=?') {
            $oAddr->personal = encodeHeader($sPersonal);
        } else {
            $oAddr->personal = $sPersonal;
        }
 //       $oAddr->group = $sGroup;
        $iPosAt = strpos($sEmail,'@');
        if ($iPosAt) {
           $oAddr->mailbox = substr($sEmail, 0, $iPosAt);
           $oAddr->host = substr($sEmail, $iPosAt+1);
        } else {
           $oAddr->mailbox = $sEmail;
           $oAddr->host = false;
        }
        $sEmail = '';
        $aStack = $aComment = array();
        return $oAddr;
    }

    /**
     * recursive function for parsing address strings and storing them in an address stucture object.
     *  personal name: encoded: =?charset?Q|B?string?=
     *                 quoted:  "string"
     *                 normal:  string
     *  email        : <mailbox@host>
     *               : mailbox@host
     *  This function is also used for validating addresses returned from compose
     *  That's also the reason that the function became a little bit huge
     * @param string $address
     * @param boolean $ar return array instead of only the first element
     * @param array $addr_ar (obsolete) array with parsed addresses
     * @param string $group (obsolete)
     * @param string $host default domainname in case of addresses without a domainname
     * @param string $lookup (since) callback function for lookup of address strings which are probably nicks (without @)
     * @return mixed array with AddressStructure objects or only one address_structure object.
     */
    function parseAddress($address,$ar=false,$aAddress=array(),$sGroup='',$sHost='',$lookup=false) {
        $aTokens = $this->getAddressTokens($address);
        $sPersonal = $sEmail = $sComment = $sGroup = '';
        $aStack = $aComment = array();
        foreach ($aTokens as $sToken) {
            $cChar = $sToken{0};
            switch ($cChar)
            {
            case '=':
            case '"':
            case ' ':
                $aStack[] = $sToken;
                break;
            case '(':
                $aComment[] = substr($sToken,1,-1);
                break;
            case ';':
                if ($sGroup) {
                    $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
                    $oAddr = end($aAddress);
                    if(!$oAddr || ((isset($oAddr)) && !strlen($oAddr->mailbox) && !$oAddr->personal)) {
                        $sEmail = $sGroup . ':;';
                    }
                    $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
                    $sGroup = '';
                    $aStack = $aComment = array();
                    break;
                }
            case ',':
                $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
                break;
            case ':':
                $sGroup = trim(implode(' ',$aStack));
                $sGroup = preg_replace('/\s+/',' ',$sGroup);
                $aStack = array();
                break;
            case '<':
               $sEmail = trim(substr($sToken,1,-1));
               break;
            case '>':
               /* skip */
               break;
            default: $aStack[] = $sToken; break;
            }
        }
        /* now do the action again for the last address */
        $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail);
        /* try to lookup the addresses in case of invalid email addresses */
        $aProcessedAddress = array();
        foreach ($aAddress as $oAddr) {
          $aAddrBookAddress = array();
          if (!$oAddr->host) {
            $grouplookup = false;
            if ($lookup) {
                 $aAddr = call_user_func_array($lookup,array($oAddr->mailbox));
                 if (isset($aAddr['email'])) {
                     if (strpos($aAddr['email'],',')) {
                         $grouplookup = true;
                         $aAddrBookAddress = $this->parseAddress($aAddr['email'],true);
                     } else {
                         $iPosAt = strpos($aAddr['email'], '@');
                         if ($iPosAt === FALSE) {
                             $oAddr->mailbox = $aAddr['email'];
                             $oAddr->host = FALSE;
                         } else {
                             $oAddr->mailbox = substr($aAddr['email'], 0, $iPosAt);
                             $oAddr->host = substr($aAddr['email'], $iPosAt+1);
                         }
                         if (isset($aAddr['name'])) {
                             $oAddr->personal = $aAddr['name'];
                         } else {
                             $oAddr->personal = encodeHeader($sPersonal);
                         }
                     }
                 }
            }
            if (!$grouplookup && !strlen($oAddr->mailbox)) {
                $oAddr->mailbox = trim($sEmail);
                if ($sHost && strlen($oAddr->mailbox)) {
                    $oAddr->host = $sHost;
                }
            } else if (!$grouplookup && !$oAddr->host) {
                if ($sHost && strlen($oAddr->mailbox)) {
                    $oAddr->host = $sHost;
                }
            }
          }
          if (!$aAddrBookAddress && strlen($oAddr->mailbox)) {
              $aProcessedAddress[] = $oAddr;
          } else {
              $aProcessedAddress = array_merge($aProcessedAddress,$aAddrBookAddress);
          }
        }
        if ($ar) {
            return $aProcessedAddress;
        } else {
            if (isset($aProcessedAddress[0]))
                return $aProcessedAddress[0];
            else
                return '';
        }
    }

    /**
     * Normalise the different Priority headers into a uniform value,
     * namely that of the X-Priority header (1, 3, 5). Supports:
     * Priority, X-Priority, Importance.
     * X-MS-Mail-Priority is not parsed because it always coincides
     * with one of the other headers.
     *
     * NOTE: this is actually a duplicate from the function in
     * functions/imap_messages. I'm not sure if it's ok here to call
     * that function?
     * @param string $sValue literal priority name
     * @return integer
     */
    function parsePriority($sValue) {
        // don't use function call inside array_shift.
        $aValue = preg_split('/\s/',trim($sValue));
        $value = strtolower(array_shift($aValue));

        if ( is_numeric($value) ) {
            return $value;
        }
        if ( $value == 'urgent' || $value == 'high' ) {
            return 1;
        } elseif ( $value == 'non-urgent' || $value == 'low' ) {
            return 5;
        }
        // default is normal priority
        return 3;
    }

    /**
     * @param string $value content type header
     */
    function parseContentType($value) {
        $pos = strpos($value, ';');
        $props = '';
        if ($pos > 0) {
           $type = trim(substr($value, 0, $pos));
           $props = trim(substr($value, $pos+1));
        } else {
           $type = $value;
        }
        $content_type = new ContentType($type);
        if ($props) {
            $properties = $this->parseProperties($props);
            if (!isset($properties['charset'])) {
                $properties['charset'] = 'us-ascii';
            }
            $content_type->properties = $this->parseProperties($props);
        }
        $this->content_type = $content_type;
    }

    /**
     * RFC2184
     * @param array $aParameters
     * @return array
     */
    function processParameters($aParameters) {
        $aResults = array();
        $aCharset = array();
        // handle multiline parameters
        foreach($aParameters as $key => $value) {
            if ($iPos = strpos($key,'*')) {
                $sKey = substr($key,0,$iPos);
                if (!isset($aResults[$sKey])) {
                    $aResults[$sKey] = $value;
                    if (substr($key,-1) == '*') { // parameter contains language/charset info
                        $aCharset[] = $sKey;
                    }
                } else {
                    $aResults[$sKey] .= $value;
                }
            } else {
                $aResults[$key] = $value;
            }
        }
        foreach ($aCharset as $key) {
            $value = $aResults[$key];
            // extract the charset & language
            $charset = substr($value,0,strpos($value,"'"));
            $value = substr($value,strlen($charset)+1);
            $language = substr($value,0,strpos($value,"'"));
            $value = substr($value,strlen($charset)+1);
            /* FIXME: What's the status of charset decode with language information ????
             * Maybe language information contains only ascii text and charset_decode() 
             * only runs sm_encode_html_special_chars() on it. If it contains 8bit information, you 
             * get html encoded text in charset used by selected translation.
             */
            $value = charset_decode($charset,$value);
            $aResults[$key] = $value;
        }
        return $aResults;
    }

    /**
     * @param string $value
     * @return array
     */
    function parseProperties($value) {
        $propArray = explode(';', $value);
        $propResultArray = array();
        foreach ($propArray as $prop) {
            $prop = trim($prop);
            $pos = strpos($prop, '=');
            if ($pos > 0)  {
                $key = trim(substr($prop, 0, $pos));
                $val = trim(substr($prop, $pos+1));
                if (strlen($val) > 0 && $val{0} == '"') {
                    $val = substr($val, 1, -1);
                }
                $propResultArray[$key] = $val;
            }
        }
        return $this->processParameters($propResultArray);
    }

    /**
     * Fills disposition object in rfc822Header object
     * @param string $value
     */
    function parseDisposition($value) {
        $pos = strpos($value, ';');
        $props = '';
        if ($pos > 0) {
            $name = trim(substr($value, 0, $pos));
            $props = trim(substr($value, $pos+1));
        } else {
            $name = $value;
        }
        $props_a = $this->parseProperties($props);
        $disp = new Disposition($name);
        $disp->properties = $props_a;
        $this->disposition = $disp;
    }

    /**
     * Fills mlist array keys in rfc822Header object 
     * @param string $field
     * @param string $value
     */
    function mlist($field, $value) {
        $res_a = array();
        $value_a = explode(',', $value);
        foreach ($value_a as $val) {
            $val = trim($val);
            if ($val{0} == '<') {
                $val = substr($val, 1, -1);
            }
            if (substr($val, 0, 7) == 'mailto:') {
                $res_a['mailto'] = substr($val, 7);
            } else {
                $res_a['href'] = $val;
            }
        }
        $this->mlist[$field] = $res_a;
    }

    /**
     * Parses the X-Spam-Status header
     * @param string $value
     */
    function parseSpamStatus($value) {
        // Header value looks like this:
        // No, score=1.5 required=5.0 tests=MSGID_FROM_MTA_ID,NO_REAL_NAME,UPPERCASE_25_50 autolearn=disabled version=3.1.0-gr0

        $spam_status = array();

        if (preg_match ('/^(No|Yes),\s+score=(-?\d+\.\d+)\s+required=(-?\d+\.\d+)\s+tests=(.*?)\s+autolearn=(.*?)\s+version=(.+?)$/', $value, $matches)) {
            // full header
            $spam_status['bad_format'] = 0;
            $spam_status['value'] = $matches[0];
            // is_spam
            if (isset($matches[1])
                && strtolower($matches[1]) == 'yes') {
                $spam_status['is_spam'] = true;
            } else {
                $spam_status['is_spam'] = false;
            }

            // score
            $spam_status['score'] = $matches[2];

            // required
            $spam_status['required'] = $matches[3];

            // tests
            $tests = array();
            $tests = explode(',', $matches[4]);
            foreach ($tests as $test) {
                $spam_status['tests'][] = trim($test);
            }

            // autolearn
            $spam_status['autolearn'] = $matches[5];

            // version
            $spam_status['version'] = $matches[6];
        } else {
            $spam_status['bad_format'] = 1;
            $spam_status['value'] = $value;
        }
        return $spam_status;
    }

    /**
     * function to get the address strings out of the header.
     * example1: header->getAddr_s('to').
     * example2: header->getAddr_s(array('to', 'cc', 'bcc'))
     * @param mixed $arr string or array of strings
     * @param string $separator
     * @param boolean $encoded (since 1.4.0) return encoded or plain text addresses
     * @param boolean $unconditionally_quote (since 1.4.21/1.5.2) When TRUE, always
     *                                                      quote the personal part,
     *                                                      whether or not it is
     *                                                      encoded, otherwise quoting
     *                                                      is only added if the
     *                                                      personal part is not encoded
     * @return string
     */
    function getAddr_s($arr, $separator = ',',$encoded=false,$unconditionally_quote=FALSE) {
        $s = '';

        if (is_array($arr)) {
            foreach($arr as $arg) {
                if ($this->getAddr_s($arg, $separator, $encoded, $unconditionally_quote)) {
                    $s .= $separator;
                }
            }
            $s = ($s ? substr($s, 2) : $s);
        } else {
            $addr = $this->{$arr};
            if (is_array($addr)) {
                foreach ($addr as $addr_o) {
                    if (is_object($addr_o)) {
                        if ($encoded) {
                            $s .= $addr_o->getEncodedAddress($unconditionally_quote) . $separator;
                        } else {
                            $s .= $addr_o->getAddress(TRUE, FALSE, $unconditionally_quote) . $separator;
                        }
                    }
                }
                $s = substr($s, 0, -strlen($separator));
            } else {
                if (is_object($addr)) {
                    if ($encoded) {
                        $s .= $addr->getEncodedAddress($unconditionally_quote);
                    } else {
                        $s .= $addr->getAddress(TRUE, FALSE, $unconditionally_quote);
                    }
                }
            }
        }
        return $s;
    }

    /**
     * function to get the array of addresses out of the header.
     * @param mixed $arg string or array of strings
     * @param array $excl_arr array of excluded email addresses
     * @param array $arr array of added email addresses
     * @return array
     */
    function getAddr_a($arg, $excl_arr = array(), $arr = array()) {
        if (is_array($arg)) {
            foreach($arg as $argument) {
                $arr = $this->getAddr_a($argument, $excl_arr, $arr);
            }
        } else {
            $addr = $this->{$arg};
            if (is_array($addr)) {
                foreach ($addr as $next_addr) {
                    if (is_object($next_addr)) {
                        if (isset($next_addr->host) && ($next_addr->host != '')) {
                            $email = $next_addr->mailbox . '@' . $next_addr->host;
                        } else {
                            $email = $next_addr->mailbox;
                        }
                        $email = strtolower($email);
                        if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) {
                            $arr[$email] = $next_addr->personal;
                        }
                    }
                }
            } else {
                if (is_object($addr)) {
                    $email  = $addr->mailbox;
                    $email .= (isset($addr->host) ? '@' . $addr->host : '');
                    $email  = strtolower($email);
                    if ($email && !isset($arr[$email]) && !isset($excl_arr[$email])) {
                        $arr[$email] = $addr->personal;
                    }
                }
            }
        }
        return $arr;
    }

    /**
//FIXME: This needs some documentation (inside the function too)!  Don't code w/out comments!
     * @param mixed $address array or string
     * @param boolean $recurs
     * @return mixed array, boolean
     * @since 1.3.2
     */
    function findAddress($address, $recurs = false) {
        $result = false;
        if (is_array($address)) {
            $i=0;
            foreach($address as $argument) {
                $match = $this->findAddress($argument, true);
                $last = end($match);
                if ($match[1]) {
                    return $i;
                } else {
                    if (count($match[0]) && !$result) {
                        $result = $i;
                    }
                }
                ++$i;
            }
        } else {
            if (!is_array($this->cc)) $this->cc = array();
            if (!is_array($this->to)) $this->to = array();
            $srch_addr = $this->parseAddress($address);
            $results = array();
            foreach ($this->to as $to) {
                if (strtolower($to->host) == strtolower($srch_addr->host)) {
                    if (strtolower($to->mailbox) == strtolower($srch_addr->mailbox)) {
                        $results[] = $srch_addr;
                        if (strtolower($to->personal) == strtolower($srch_addr->personal)) {
                            if ($recurs) {
                                return array($results, true);
                            } else {
                                return true;
                            }
                        }
                    }
                }
            }
            foreach ($this->cc as $cc) {
                if (strtolower($cc->host) == strtolower($srch_addr->host)) {
                    if (strtolower($cc->mailbox) == strtolower($srch_addr->mailbox)) {
                        $results[] = $srch_addr;
                        if (strtolower($cc->personal) == strtolower($srch_addr->personal)) {
                            if ($recurs) {
                                return array($results, true);
                            } else {
                                return true;
                            }
                        }
                    }
                }
            }
            if ($recurs) {
                return array($results, false);
            } elseif (count($result)) {
                return true;
            } else {
                return false;
            }
        }
        //exit;
        return $result;
    }

    /**
     * @param string $type0 media type
     * @param string $type1 media subtype
     * @return array media properties
     * @todo check use of media type arguments
     */
    function getContentType($type0, $type1) {
        $type0 = $this->content_type->type0;
        $type1 = $this->content_type->type1;
        return $this->content_type->properties;
    }
}

Added class/mime/SMimeMessage.class.php.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/**
 * SMimeMessage.class.php
 *
 * This file contains class needed to handle SMIME mime messages.
 *
 * @link http://www.ietf.org/html.charters/smime-charter.html
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: SMimeMessage.class.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 * @since 1.3.2
 */

/**
 * Unimplemented class.
 * @package squirrelmail
 * @subpackage mime
 * @todo implement smime parsing
 */
class SMimeMessage {

}

Added class/mime/index.php.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

/**
 * index.php
 *
 * This file simply takes any attempt to view source files and sends those
 * people to the login screen. At this point no attempt is made to see if the
 * person is logged in or not.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: index.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage mime
 */

header('Location: ../index.php');

Added functions/abook_database.php.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
<?php

/**
 * abook_database.php
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: abook_database.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage addressbook
 */

/** Needs the DB functions */
if (!include_once('DB.php')) {
    // same error also in db_prefs.php
    require_once(SM_PATH . 'functions/display_messages.php');
    $error  = _("Could not include PEAR database functions required for the database backend.") . "<br />\n";
    $error .= sprintf(_("Is PEAR installed, and is the include path set correctly to find %s?"),
                        '<tt>DB.php</tt>') . "<br />\n";
    $error .= _("Please contact your system administrator and report this error.");
    error_box($error, $color);
    exit;
}

/**
 * Address book in a database backend
 *
 * Backend for personal/shared address book stored in a database,
 * accessed using the DB-classes in PEAR.
 *
 * IMPORTANT:  The PEAR modules must be in the include path
 * for this class to work.
 *
 * An array with the following elements must be passed to
 * the class constructor (elements marked ? are optional):
 * <pre>
 *   dsn       => database DNS (see PEAR for syntax)
 *   table     => table to store addresses in (must exist)
 *   owner     => current user (owner of address data)
 * ? name      => name of address book
 * ? writeable => set writeable flag (true/false)
 * ? listing   => enable/disable listing
 * </pre>
 * The table used should have the following columns:
 * owner, nickname, firstname, lastname, email, label
 * The pair (owner,nickname) should be unique (primary key).
 *
 *  NOTE. This class should not be used directly. Use the
 *        "AddressBook" class instead.
 * @package squirrelmail
 * @subpackage addressbook
 */
class abook_database extends addressbook_backend {
    /**
     * Backend type
     * @var string
     */
    var $btype = 'local';
    /**
     * Backend name
     * @var string
     */
    var $bname = 'database';

    /**
     * Data Source Name (connection description)
     * @var string
     */
    var $dsn       = '';
    /**
     * Table that stores addresses
     * @var string
     */
    var $table     = '';
    /**
     * Owner name
     *
     * Limits list of database entries visible to end user
     * @var string
     */
    var $owner     = '';
    /**
     * Database Handle
     * @var resource
     */
    var $dbh       = false;
    /**
     * Enable/disable writing into address book
     * @var bool
     */
    var $writeable = true;
    /**
     * Enable/disable address book listing
     * @var bool
     */
    var $listing = true;

    /* ========================== Private ======================= */

    /**
     * Constructor
     * @param array $param address book backend options
     */
    function abook_database($param) {
        $this->sname = _("Personal address book");

        if (is_array($param)) {
            if (empty($param['dsn']) ||
                empty($param['table']) ||
                empty($param['owner'])) {
                return $this->set_error('Invalid parameters');
            }

            $this->dsn   = $param['dsn'];
            $this->table = $param['table'];
            $this->owner = $param['owner'];

            if (!empty($param['name'])) {
               $this->sname = $param['name'];
            }

            if (isset($param['writeable'])) {
               $this->writeable = $param['writeable'];
            }

            if (isset($param['listing'])) {
               $this->listing = $param['listing'];
            }

            $this->open(true);
        }
        else {
            return $this->set_error('Invalid argument to constructor');
        }
    }


    /**
     * Open the database.
     * @param bool $new new connection if it is true
     * @return bool
     */
    function open($new = false) {
        $this->error = '';

        /* Return true is file is open and $new is unset */
        if ($this->dbh && !$new) {
            return true;
        }

        /* Close old file, if any */
        if ($this->dbh) {
            $this->close();
        }

        $dbh = DB::connect($this->dsn, true);

        if (DB::isError($dbh)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($dbh)));
        }

        $this->dbh = $dbh;

        /**
         * field names are lowercased.
         * We use unquoted identifiers and they use upper case in Oracle
         */
        $this->dbh->setOption('portability', DB_PORTABILITY_LOWERCASE);

        return true;
    }

    /**
     * Close the file and forget the filehandle
     */
    function close() {
        $this->dbh->disconnect();
        $this->dbh = false;
    }

    /**
     * Determine internal database field name given one of
     * the SquirrelMail SM_ABOOK_FIELD_* constants
     *
     * @param integer $field The SM_ABOOK_FIELD_* contant to look up
     *
     * @return string The desired field name, or the string "ERROR"
     *                if the $field is not understood (the caller
     *                is responsible for handing errors)
     *
     */
    function get_field_name($field) {
        switch ($field) {
            case SM_ABOOK_FIELD_NICKNAME:
                return 'nickname';
            case SM_ABOOK_FIELD_FIRSTNAME:
                return 'firstname';
            case SM_ABOOK_FIELD_LASTNAME:
                return 'lastname';
            case SM_ABOOK_FIELD_EMAIL:
                return 'email';
            case SM_ABOOK_FIELD_LABEL:
                return 'label';
            default:
                return 'ERROR';
        }
    }

    /* ========================== Public ======================== */

    /**
     * Search the database
     * @param string $expr search expression
     * @return array search results
     */
    function search($expr) {
        $ret = array();
        if(!$this->open()) {
            return false;
        }

        /* To be replaced by advanded search expression parsing */
        if (is_array($expr)) {
            return;
        }

        // don't allow wide search when listing is disabled.
        if ($expr=='*' && ! $this->listing) {
            return array();
        }

        /* lowercase expression in order to make it case insensitive */
        $expr = strtolower($expr);

        /* escape SQL wildcards */
        $expr = str_replace('_', '\\_', $expr);
        $expr = str_replace('%', '\\%', $expr);

        /* Convert wildcards to SQL syntax  */
        $expr = str_replace('?', '_', $expr);
        $expr = str_replace('*', '%', $expr);
        $expr = $this->dbh->quoteString($expr);
        $expr = "%$expr%";

        /* create escape expression */
        $escape = 'ESCAPE \'' . $this->dbh->quoteString('\\') . '\'';

        $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND " .
                         "(LOWER(firstname) LIKE '%s' %s " .
                         "OR LOWER(lastname) LIKE '%s' %s " .
                         "OR LOWER(email) LIKE '%s' %s " .
                         "OR LOWER(nickname) LIKE '%s' %s)",
                         $this->table, $this->owner, $expr, $escape, $expr, $escape,
                                                     $expr, $escape, $expr, $escape);
        $res = $this->dbh->query($query);

        if (DB::isError($res)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($res)));
        }

        while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            array_push($ret, array('nickname'  => $row['nickname'],
                                   'name'      => "$row[firstname] $row[lastname]",
                                   'firstname' => $row['firstname'],
                                   'lastname'  => $row['lastname'],
                                   'email'     => $row['email'],
                                   'label'     => $row['label'],
                                   'backend'   => $this->bnum,
                                   'source'    => &$this->sname));
        }
        return $ret;
    }

    /**
     * Lookup by the indicated field
     *
     * @param string  $value Value to look up
     * @param integer $field The field to look in, should be one
     *                       of the SM_ABOOK_FIELD_* constants
     *                       defined in functions/constants.php
     *                       (OPTIONAL; defaults to nickname field)
     *                       NOTE: uniqueness is only guaranteed
     *                       when the nickname field is used here;
     *                       otherwise, the first matching address
     *                       is returned.
     *
     * @return array search results
     *
     */
    function lookup($value, $field=SM_ABOOK_FIELD_NICKNAME) {
        if (empty($value)) {
            return array();
        }

        $value = strtolower($value);

        if (!$this->open()) {
            return false;
        }

        $query = sprintf("SELECT * FROM %s WHERE owner = '%s' AND LOWER(%s) = '%s'",
                         $this->table, $this->owner, $this->get_field_name($field), 
                         $this->dbh->quoteString($value));

        $res = $this->dbh->query($query);

        if (DB::isError($res)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($res)));
        }

        if ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            return array('nickname'  => $row['nickname'],
                         'name'      => "$row[firstname] $row[lastname]",
                         'firstname' => $row['firstname'],
                         'lastname'  => $row['lastname'],
                         'email'     => $row['email'],
                         'label'     => $row['label'],
                         'backend'   => $this->bnum,
                         'source'    => &$this->sname);
        }
        return array();
    }

    /**
     * List all addresses
     * @return array search results
     */
    function list_addr() {
        $ret = array();
        if (!$this->open()) {
            return false;
        }

        if(isset($this->listing) && !$this->listing) {
            return array();
        }


        $query = sprintf("SELECT * FROM %s WHERE owner='%s'",
                         $this->table, $this->owner);

        $res = $this->dbh->query($query);

        if (DB::isError($res)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($res)));
        }

        while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            array_push($ret, array('nickname'  => $row['nickname'],
                                   'name'      => "$row[firstname] $row[lastname]",
                                   'firstname' => $row['firstname'],
                                   'lastname'  => $row['lastname'],
                                   'email'     => $row['email'],
                                   'label'     => $row['label'],
                                   'backend'   => $this->bnum,
                                   'source'    => &$this->sname));
        }
        return $ret;
    }

    /**
     * Add address
     * @param array $userdata added data
     * @return bool
     */
    function add($userdata) {
        if (!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        if (!$this->open()) {
            return false;
        }

        /* See if user exist already */
        $ret = $this->lookup($userdata['nickname']);
        if (!empty($ret)) {
            return $this->set_error(sprintf(_("User \"%s\" already exists"), $ret['nickname']));
        }

        /* Create query */
        $query = sprintf("INSERT INTO %s (owner, nickname, firstname, " .
                         "lastname, email, label) VALUES('%s','%s','%s'," .
                         "'%s','%s','%s')",
                         $this->table, $this->owner,
                         $this->dbh->quoteString($userdata['nickname']),
                         $this->dbh->quoteString($userdata['firstname']),
                         $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
                         $this->dbh->quoteString($userdata['email']),
                         $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')) );

         /* Do the insert */
         $r = $this->dbh->simpleQuery($query);

         /* Check for errors */
         if (DB::isError($r)) {
             return $this->set_error(sprintf(_("Database error: %s"),
                                             DB::errorMessage($r)));
         }

         return true;
    }

    /**
     * Delete address
     * @param string $alias alias that has to be deleted
     * @return bool
     */
    function remove($alias) {
        if (!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        if (!$this->open()) {
            return false;
        }

        /* Create query */
        $query = sprintf("DELETE FROM %s WHERE owner='%s' AND (",
                         $this->table, $this->owner);

        $sepstr = '';
        while (list($undef, $nickname) = each($alias)) {
            $query .= sprintf("%s nickname='%s' ", $sepstr,
                              $this->dbh->quoteString($nickname));
            $sepstr = 'OR';
        }
        $query .= ')';

        /* Delete entry */
        $r = $this->dbh->simpleQuery($query);

        /* Check for errors */
        if (DB::isError($r)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($r)));
        }
        return true;
    }

    /**
     * Modify address
     * @param string $alias modified alias
     * @param array $userdata new data
     * @return bool
     */
    function modify($alias, $userdata) {
        if (!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        if (!$this->open()) {
            return false;
        }

         /* See if user exist */
        $ret = $this->lookup($alias);
        if (empty($ret)) {
            return $this->set_error(sprintf(_("User \"%s\" does not exist"), $alias));
        }

        /* make sure that new nickname is not used */
        if (strtolower($alias) != strtolower($userdata['nickname'])) {
            /* same check as in add() */
            $ret = $this->lookup($userdata['nickname']);
            if (!empty($ret)) {
                $error = sprintf(_("User '%s' already exist."), $ret['nickname']);
                return $this->set_error($error);
            }
        }

        /* Create query */
        $query = sprintf("UPDATE %s SET nickname='%s', firstname='%s', ".
                         "lastname='%s', email='%s', label='%s' ".
                         "WHERE owner='%s' AND nickname='%s'",
                         $this->table,
                         $this->dbh->quoteString($userdata['nickname']),
                         $this->dbh->quoteString($userdata['firstname']),
                         $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
                         $this->dbh->quoteString($userdata['email']),
                         $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')),
                         $this->owner,
                         $this->dbh->quoteString($alias) );

        /* Do the insert */
        $r = $this->dbh->simpleQuery($query);

        /* Check for errors */
        if (DB::isError($r)) {
            return $this->set_error(sprintf(_("Database error: %s"),
                                            DB::errorMessage($r)));
        }
        return true;
    }
} /* End of class abook_database */

// vim: et ts=4

Added functions/abook_ldap_server.php.















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
<?php

/**
 * abook_ldap_server.php
 *
 * Address book backend for LDAP server
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: abook_ldap_server.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage addressbook
 */

/**
 * Address book backend for LDAP server
 *
 * An array with the following elements must be passed to
 * the class constructor (elements marked ? are optional):
 * <pre>
 *    host      => LDAP server hostname/IP-address
 *    base      => LDAP server root (base dn). Empty string allowed.
 *  ? port      => LDAP server TCP port number (default: 389)
 *  ? charset   => LDAP server charset (default: utf-8)
 *  ? name      => Name for LDAP server (default "LDAP: hostname")
 *                 Used to tag the result data
 *  ? maxrows   => Maximum # of rows in search result
 *  ? timeout   => Timeout for LDAP operations (in seconds, default: 30)
 *                 Might not work for all LDAP libraries or servers.
 *  ? binddn    => LDAP Bind DN.
 *  ? bindpw    => LDAP Bind Password.
 *  ? protocol  => LDAP Bind protocol.
 * </pre>
 * NOTE. This class should not be used directly. Use the
 *       "AddressBook" class instead.
 * @package squirrelmail
 * @subpackage addressbook
 */
class abook_ldap_server extends addressbook_backend {
    /**
     * @var string backend type
     */
    var $btype = 'remote';
    /**
     * @var string backend name
     */
    var $bname = 'ldap_server';

    /* Parameters changed by class */
    /**
     * @var string displayed name
     */
    var $sname   = 'LDAP';       /* Service name */
    /**
     * @var string LDAP server name or address or url
     */
    var $server  = '';
    /**
     * @var integer LDAP server port
     */
    var $port    = 389;
    /**
     * @var string LDAP base DN
     */
    var $basedn  = '';
    /**
     * @var string charset used for entries in LDAP server
     */
    var $charset = 'utf-8';
    /**
     * @var object PHP LDAP link ID
     */
    var $linkid  = false;
    /**
     * @var bool True if LDAP server is bound
     */
    var $bound   = false;
    /**
     * @var integer max rows in result
     */
    var $maxrows = 250;
    /**
     * @var integer timeout of LDAP operations (in seconds)
     */
    var $timeout = 30;
    /**
     * @var string DN to bind to (non-anonymous bind)
     * @since 1.5.0 and 1.4.3
     */
    var $binddn = '';
    /**
     * @var string  password to bind with (non-anonymous bind)
     * @since 1.5.0 and 1.4.3
     */
    var $bindpw = '';
    /**
     * @var integer protocol used to connect to ldap server
     * @since 1.5.0 and 1.4.3
     */
    var $protocol = '';

    /**
     * Constructor. Connects to database
     * @param array connection options
     */
    function abook_ldap_server($param) {
        if(!function_exists('ldap_connect')) {
            $this->set_error('LDAP support missing from PHP');
            return;
        }
        if(is_array($param)) {
            $this->server = $param['host'];
            $this->basedn = $param['base'];
            if(!empty($param['port'])) {
                $this->port = $param['port'];
            }
            if(!empty($param['charset'])) {
                $this->charset = strtolower($param['charset']);
            }
            if(isset($param['maxrows'])) {
                $this->maxrows = $param['maxrows'];
            }
            if(isset($param['timeout'])) {
                $this->timeout = $param['timeout'];
            }
            if(isset($param['binddn'])) {
                $this->binddn = $param['binddn'];
            }
            if(isset($param['bindpw'])) {
                $this->bindpw = $param['bindpw'];
            }
            if(isset($param['protocol'])) {
                $this->protocol = $param['protocol'];
            }
            if(empty($param['name'])) {
                $this->sname = 'LDAP: ' . $param['host'];
            }
            else {
                $this->sname = $param['name'];
            }

            $this->open(true);
        } else {
            $this->set_error('Invalid argument to constructor');
        }
    }


    /**
     * Open the LDAP server.
     * @param bool $new is it a new connection
     * @return bool
     */
    function open($new = false) {
        $this->error = '';

        /* Connection is already open */
        if($this->linkid != false && !$new) {
            return true;
        }

        $this->linkid = @ldap_connect($this->server, $this->port);
        if(!$this->linkid) {
            if(function_exists('ldap_error')) {
                return $this->set_error(ldap_error($this->linkid));
            } else {
                return $this->set_error('ldap_connect failed');
            }
        }

        if(!empty($this->protocol)) {
            if(!@ldap_set_option($this->linkid, LDAP_OPT_PROTOCOL_VERSION, $this->protocol)) {
                if(function_exists('ldap_error')) {
                    return $this->set_error(ldap_error($this->linkid));
                } else {
                    return $this->set_error('ldap_set_option failed');
                }
            }
        }

        if(!empty($this->binddn)) {
            if(!@ldap_bind($this->linkid, $this->binddn, $this->bindpw)) {
                if(function_exists('ldap_error')) {
                    return $this->set_error(ldap_error($this->linkid));
                } else {
                    return $this->set_error('authenticated ldap_bind failed');
                }
              }
        } else {
            if(!@ldap_bind($this->linkid)) {
                if(function_exists('ldap_error')) {
                    return $this->set_error(ldap_error($this->linkid));
                } else {
                    return $this->set_error('anonymous ldap_bind failed');
                }
            }
        }

        $this->bound = true;

        return true;
    }

    /**
     * Converts string to the charset used by LDAP server
     * @param string string that has to be converted
     * @return string converted string
     */
    function charset_encode($str) {
        global $default_charset;
        if($this->charset != $default_charset) {
            return charset_convert($default_charset,$str,$this->charset,false);
        } else {
            return $str;
        }
    }

    /**
     * Convert from charset used by LDAP server to charset used by translation
     *
     * Output must be sanitized.
     * @param string string that has to be converted
     * @return string converted string
     */
    function charset_decode($str) {
        global $default_charset;
        if ($this->charset != $default_charset) {
            return charset_convert($this->charset,$str,$default_charset,false);
        } else {
            return $str;
        }
    }

    /**
     * Sanitizes ldap search strings.
     * See rfc2254
     * @link http://www.faqs.org/rfcs/rfc2254.html
     * @since 1.5.1 and 1.4.5
     * @param string $string
     * @return string sanitized string
     */
    function ldapspecialchars($string) {
        $sanitized=array('\\' => '\5c',
                         '*' => '\2a',
                         '(' => '\28',
                         ')' => '\29',
                         "\x00" => '\00');

        return str_replace(array_keys($sanitized),array_values($sanitized),$string);
    }

    /* ========================== Public ======================== */

    /**
     * Search the LDAP server
     * @param string $expr search expression
     * @return array search results
     */
    function search($expr) {
        /* To be replaced by advanded search expression parsing */
        if(is_array($expr)) return false;

        /* Encode the expression */
        $expr = $this->charset_encode($expr);

        /*
         * allow use of one asterisk in search. 
         * Don't allow any ldap special chars if search is different
         */
        if($expr!='*') {
            $expr = '*' . $this->ldapspecialchars($expr) . '*';
            /* Undo sanitizing of * symbol */
            $expr = str_replace('\2a','*',$expr);
        }
        $expr = preg_replace('/\*+/', '*', $expr); // LDAP chokes on more than one *
        $expression = "(|(cn=$expr)(sn=$expr)(givenname=$expr)(mail=$expr))";

        /* Make sure connection is there */
        if(!$this->open()) {
            return false;
        }

        $sret = @ldap_search($this->linkid, $this->basedn, $expression,
            array('dn', 'o', 'ou', 'sn', 'givenname', 'cn', 'mail'),
            0, $this->maxrows, $this->timeout);

        /* Should get error from server using the ldap_error() function,
         * but it only exist in the PHP LDAP documentation. */
        if(!$sret) {
            if(function_exists('ldap_error')) {
                return $this->set_error(ldap_error($this->linkid));
            } else {
                return $this->set_error('ldap_search failed');
            }
        }

        if(@ldap_count_entries($this->linkid, $sret) <= 0) {
            return array();
        }

        /* Get results */
        $ret = array();
        $returned_rows = 0;
        $res = @ldap_get_entries($this->linkid, $sret);
        for($i = 0 ; $i < $res['count'] ; $i++) {
            $row = $res[$i];

            /* Extract data common for all e-mail addresses
             * of an object. Use only the first name */
            $nickname = $this->charset_decode($row['dn']);
            $fullname = $this->charset_decode($row['cn'][0]);

            if(!empty($row['ou'][0])) {
                $label = $this->charset_decode($row['ou'][0]);
            }
            else if(!empty($row['o'][0])) {
                $label = $this->charset_decode($row['o'][0]);
            } else {
                $label = '';
            }

            if(empty($row['givenname'][0])) {
                $firstname = '';
            } else {
                $firstname = $this->charset_decode($row['givenname'][0]);
            }

            if(empty($row['sn'][0])) {
                $surname = '';
            } else {
                $surname = $this->charset_decode($row['sn'][0]);
            }

            /* Add one row to result for each e-mail address */
            if(isset($row['mail']['count'])) {
                for($j = 0 ; $j < $row['mail']['count'] ; $j++) {
                    array_push($ret, array('nickname'  => $nickname,
                   'name'      => $fullname,
                   'firstname' => $firstname,
                   'lastname'  => $surname,
                   'email'     => $row['mail'][$j],
                   'label'     => $label,
                   'backend'   => $this->bnum,
                   'source'    => &$this->sname));

                    // Limit number of hits
                    $returned_rows++;
                    if(($returned_rows >= $this->maxrows) &&
                       ($this->maxrows > 0) ) {
                        ldap_free_result($sret);
                        return $ret;
                    }

                } // for($j ...)

            } // isset($row['mail']['count'])

        }

        ldap_free_result($sret);
        return $ret;
    } /* end search() */


    /**
     * List all entries present in LDAP server
     *
     * If you run a small-sized LDAP server and you want the "List all"
     * button (found on the address book search screen that is accessed
     * via the "Addresses" button on the compose screen) to show all
     * addresses in the directory, add the following to config/config_local.php
     *
     *    $ldap_abook_allow_listing = TRUE;
     *
     * Remember that the "maxrows" configuration setting for the LDAP
     * server backend might limit list of returned entries.
     *
     * NOTE: You should exercise caution enabling the listing of large
     *       or public LDAP address book backends.
     *
     * @return array all entries in ldap server
     *
     */
     function list_addr() {
         global $ldap_abook_allow_listing;
         if ($ldap_abook_allow_listing)
            return $this->search('*');
         else
            return array();
     }
}

Added functions/abook_local_file.php.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
<?php

/**
 * abook_local_file.php
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: abook_local_file.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage addressbook
 */

/**
 * Backend for address book as a pipe separated file
 *
 * Stores the address book in a local file
 *
 * An array with the following elements must be passed to
 * the class constructor (elements marked ? are optional):
 *<pre>
 *   filename  => path to addressbook file
 * ? create    => if true: file is created if it does not exist.
 * ? umask     => umask set before opening file.
 * ? name      => name of address book.
 * ? detect_writeable => detect address book access permissions by
 *                checking file permissions.
 * ? writeable => allow writing into address book. Used only when
 *                detect_writeable is set to false.
 * ? listing   => enable/disable listing
 * ? line_length => allowed address book record size
 *</pre>
 * NOTE. This class should not be used directly. Use the
 *       "AddressBook" class instead.
 * @package squirrelmail
 */
class abook_local_file extends addressbook_backend {
    /**
     * Backend type
     * @var string
     */
    var $btype = 'local';
    /**
     * Backend name
     * @var string
     */
    var $bname = 'local_file';

    /**
     * File used to store data
     * @var string
     */
    var $filename = '';
    /**
     * File handle
     * @var object
     */
    var $filehandle = 0;
    /**
     * Create file, if it not present
     * @var bool
     */
    var $create = false;
    /**
     * Detect, if address book is writeable by checking file permisions
     * @var bool
     */
    var $detect_writeable   = true;
    /**
     * Control write access to address book
     *
     * Option does not have any effect, if 'detect_writeable' is 'true'
     * @var bool
     */
    var $writeable = false;
    /**
     * controls listing of address book
     * @var bool
     * @since 1.5.1 and 1.4.9
     */
    var $listing = true;
    /**
     * Umask of the file
     * @var string
     */
    var $umask;
    /**
     * Sets max entry size (number of bytes used for all address book fields
     * (including escapes) + 4 delimiters + 1 linefeed)
     * @var integer
     * @since 1.5.2 and 1.4.9
     */
    var $line_length = 2048;

    /* ========================== Private ======================= */

    /**
     * Constructor
     * @param array $param backend options
     * @return bool
     */
    function abook_local_file($param) {
        $this->sname = _("Personal address book");
        $this->umask = Umask();

        if(is_array($param)) {
            if(empty($param['filename'])) {
                return $this->set_error('Invalid parameters');
            }
            if(!is_string($param['filename'])) {
                return $this->set_error($param['filename'] . ': '.
                     _("Not a file name"));
            }

            $this->filename = $param['filename'];

            if(isset($param['create'])) {
                $this->create = $param['create'];
            }
            if(isset($param['umask'])) {
                $this->umask = $param['umask'];
            }
            if(isset($param['name'])) {
                $this->sname = $param['name'];
            }
            if(isset($param['detect_writeable'])) {
                $this->detect_writeable = $param['detect_writeable'];
            }
            if(!empty($param['writeable'])) {
                $this->writeable = $param['writeable'];
            }
            if(isset($param['listing'])) {
                $this->listing = $param['listing'];
            }
            if(isset($param['line_length']) && ! empty($param['line_length'])) {
                $this->line_length = (int) $param['line_length'];
            }

            $this->open(true);
        } else {
            $this->set_error('Invalid argument to constructor');
        }
    }

    /**
     * Open the addressbook file and store the file pointer.
     * Use $file as the file to open, or the class' own
     * filename property. If $param is empty and file is
     * open, do nothing.
     * @param bool $new is file already opened
     * @return bool
     */
    function open($new = false) {
        $this->error = '';
        $file   = $this->filename;
        $create = $this->create;
        $fopenmode = (($this->writeable && is_writable($file)) ? 'a+' : 'r');

        /* Return true is file is open and $new is unset */
        if($this->filehandle && !$new) {
            return true;
        }

        /* Check that new file exitsts */
        if((!(file_exists($file) && is_readable($file))) && !$create) {
            return $this->set_error("$file: " . _("No such file or directory"));
        }

        /* Close old file, if any */
        if($this->filehandle) { $this->close(); }

        umask($this->umask);
        if (! $this->detect_writeable) {
            $fh = @fopen($file,$fopenmode);
            if ($fh) {
                $this->filehandle = &$fh;
                $this->filename = $file;
            } else {
                return $this->set_error("$file: " . _("Open failed"));
            }
        } else {
            /* Open file. First try to open for reading and writing,
             * but fall back to read only. */
            $fh = @fopen($file, 'a+');
            if($fh) {
                $this->filehandle = &$fh;
                $this->filename   = $file;
                $this->writeable  = true;
            } else {
                $fh = @fopen($file, 'r');
                if($fh) {
                    $this->filehandle = &$fh;
                    $this->filename   = $file;
                    $this->writeable  = false;
                } else {
                    return $this->set_error("$file: " . _("Open failed"));
                }
            }
        }
        return true;
    }

    /** Close the file and forget the filehandle */
    function close() {
        @fclose($this->filehandle);
        $this->filehandle = 0;
        $this->filename   = '';
        $this->writable   = false;
    }

    /** Lock the datafile - try 20 times in 5 seconds */
    function lock() {
        for($i = 0 ; $i < 20 ; $i++) {
            if(flock($this->filehandle, 2 + 4))
                return true;
            else
                usleep(250000);
        }
        return false;
    }

    /** Unlock the datafile */
    function unlock() {
        return flock($this->filehandle, 3);
    }

    /**
     * Overwrite the file with data from $rows
     * NOTE! Previous locks are broken by this function
     * @param array $rows new data
     * @return bool
     */
    function overwrite(&$rows) {
        $this->unlock();
        $newfh = @fopen($this->filename.'.tmp', 'w');

        if(!$newfh) {
            return $this->set_error($this->filename. '.tmp:' . _("Open failed"));
        }

        for($i = 0, $cnt=sizeof($rows) ; $i < $cnt ; $i++) {
            if(is_array($rows[$i])) {
                for($j = 0, $cnt_part=count($rows[$i]) ; $j < $cnt_part ; $j++) {
                    $rows[$i][$j] = $this->quotevalue($rows[$i][$j]);
                }
                $tmpwrite = sq_fwrite($newfh, join('|', $rows[$i]) . "\n");
                if ($tmpwrite === FALSE) {
                    return $this->set_error($this->filename . '.tmp:' . _("Write failed"));
                }
            }
        }

        fclose($newfh);
        if (!@copy($this->filename . '.tmp' , $this->filename)) {
          return $this->set_error($this->filename . ':' . _("Unable to update"));
        }
        @unlink($this->filename . '.tmp');
        @chmod($this->filename, 0600);
        $this->unlock();
        $this->open(true);
        return true;
    }

    /* ========================== Public ======================== */

    /**
     * Search the file
     * @param string $expr search expression
     * @return array search results
     */
    function search($expr) {

        /* To be replaced by advanded search expression parsing */
        if(is_array($expr)) { return; }

        // don't allow wide search when listing is disabled.
        if ($expr=='*' && ! $this->listing)
            return array();

        // Make regexp from glob'ed expression
        $expr = preg_quote($expr);
        $expr = str_replace(array('\\?', '\\*'), array('.', '.*'), $expr);

        $res = array();
        if(!$this->open()) {
            return false;
        }
        @rewind($this->filehandle);

        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
            if (count($row)<5) {
                /** address book is corrupted. */
                global $color;
                error_box(_("Address book is corrupted. Required fields are missing."),$color);
                die('</body></html>');
            } else {
                // errors on preg_match call are suppressed in order to prevent display of regexp compilation errors
                if (@preg_match('/' . $expr . '/i', $row[0])    // nickname
                 || @preg_match('/' . $expr . '/i', $row[1])    // firstname
                 || @preg_match('/' . $expr . '/i', $row[2])    // lastname
                 || @preg_match('/' . $expr . '/i', $row[3])) { // email
                    array_push($res, array('nickname'  => $row[0],
                                           'name'      => $row[1] . ' ' . $row[2],
                                           'firstname' => $row[1],
                                           'lastname'  => $row[2],
                                           'email'     => $row[3],
                                           'label'     => $row[4],
                                           'backend'   => $this->bnum,
                                           'source'    => &$this->sname));
                }
            }
        }
        return $res;
    }

    /**
     * Lookup by the indicated field
     *
     * @param string  $value Value to look up
     * @param integer $field The field to look in, should be one
     *                       of the SM_ABOOK_FIELD_* constants
     *                       defined in functions/constants.php
     *                       (OPTIONAL; defaults to nickname field)
     *                       NOTE: uniqueness is only guaranteed
     *                       when the nickname field is used here;
     *                       otherwise, the first matching address
     *                       is returned.
     *
     * @return array search results
     *
     */
    function lookup($value, $field=SM_ABOOK_FIELD_NICKNAME) {
        if(empty($value)) {
            return array();
        }

        $value = strtolower($value);

        $this->open();
        @rewind($this->filehandle);

        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
            if (count($row)<5) {
                /** address book is corrupted. */
                global $color;
                error_box(_("Address book is corrupted. Required fields are missing."),$color);
                die('</body></html>');
            } else {
                if(strtolower($row[$field]) == $value) {
                    return array('nickname'  => $row[0],
                                 'name'      => $row[1] . ' ' . $row[2],
                                 'firstname' => $row[1],
                                 'lastname'  => $row[2],
                                 'email'     => $row[3],
                                 'label'     => $row[4],
                                 'backend'   => $this->bnum,
                                 'source'    => &$this->sname);
                }
            }
        }

        return array();
    }

    /**
     * List all addresses
     * @return array list of all addresses
     */
    function list_addr() {
        // check if listing is not disabled
        if(isset($this->listing) && !$this->listing) {
            return array();
        }

        $res = array();
        $this->open();
        @rewind($this->filehandle);

        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
            if (count($row)<5) {
                /** address book is corrupted. */
                global $color;
                error_box(_("Address book is corrupted. Required fields are missing."),$color);
                die('</body></html>');
            } else {
                array_push($res, array('nickname'  => $row[0],
                                       'name'      => $row[1] . ' ' . $row[2],
                                       'firstname' => $row[1],
                                       'lastname'  => $row[2],
                                       'email'     => $row[3],
                                       'label'     => $row[4],
                                       'backend'   => $this->bnum,
                                       'source'    => &$this->sname));
            }
        }
        return $res;
    }

    /**
     * Add address
     * @param array $userdata new data
     * @return bool
     */
    function add($userdata) {
        if(!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }
        /* See if user exists already */
        $ret = $this->lookup($userdata['nickname']);
        if(!empty($ret)) {
            // i18n: don't use html formating in translation
            return $this->set_error(sprintf(_("User \"%s\" already exists"), $ret['nickname']));
        }

        /* Here is the data to write */
        $data = $this->quotevalue($userdata['nickname']) . '|' .
                $this->quotevalue($userdata['firstname']) . '|' .
                $this->quotevalue((!empty($userdata['lastname'])?$userdata['lastname']:'')) . '|' .
                $this->quotevalue($userdata['email']) . '|' .
                $this->quotevalue((!empty($userdata['label'])?$userdata['label']:''));

        /* Strip linefeeds */
		$nl_str = array("\r","\n");
		$data = str_replace($nl_str, ' ', $data);

        /**
         * Make sure that entry fits into allocated record space.
         * One byte is reserved for linefeed
         */
        if (strlen($data) >= $this->line_length) {
            return $this->set_error(_("Address book entry is too big"));
        }

        /* Add linefeed at end */
        $data = $data . "\n";

        /* Reopen file, just to be sure */
        $this->open(true);
        if(!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        /* Lock the file */
        if(!$this->lock()) {
            return $this->set_error(_("Could not lock datafile"));
        }

        /* Write */
        $r = sq_fwrite($this->filehandle, $data);

        /* Unlock file */
        $this->unlock();

        /* Test write result */
        if($r === FALSE) {
            /* Fail */
            $this->set_error(_("Write to address book failed"));
            return FALSE;
        }

        return TRUE;
    }

    /**
     * Delete address
     * @param string $alias alias that has to be deleted
     * @return bool
     */
    function remove($alias) {
        if(!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        /* Lock the file to make sure we're the only process working
         * on it. */
        if(!$this->lock()) {
            return $this->set_error(_("Could not lock datafile"));
        }

        /* Read file into memory, ignoring nicknames to delete */
        @rewind($this->filehandle);
        $i = 0;
        $rows = array();
        while($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
            if(!in_array($row[0], $alias)) {
                $rows[$i++] = $row;
            }
        }

        /* Write data back */
        if(!$this->overwrite($rows)) {
            $this->unlock();
            return false;
        }

        $this->unlock();
        return true;
    }

    /**
     * Modify address
     * @param string $alias modified alias
     * @param array $userdata new data
     * @return bool true, if operation successful
     */
    function modify($alias, $userdata) {
        if(!$this->writeable) {
            return $this->set_error(_("Address book is read-only"));
        }

        /* See if user exists */
        $ret = $this->lookup($alias);
        if(empty($ret)) {
            // i18n: don't use html formating in translation
            return $this->set_error(sprintf(_("User \"%s\" does not exist"), $alias));
        }

        /* If the alias changed, see if the new alias exists */
        if (strtolower($alias) != strtolower($userdata['nickname'])) {
            $ret = $this->lookup($userdata['nickname']);
            if (!empty($ret)) {
                return $this->set_error(sprintf(_("User \"%s\" already exists"), $userdata['nickname']));
            }
        }

        /* calculate userdata size */
        $data = $this->quotevalue($userdata['nickname']) . '|'
            . $this->quotevalue($userdata['firstname']) . '|'
            . $this->quotevalue((!empty($userdata['lastname'])?$userdata['lastname']:'')) . '|'
            . $this->quotevalue($userdata['email']) . '|'
            . $this->quotevalue((!empty($userdata['label'])?$userdata['label']:''));
        /* make sure that it fits into allocated space */
        if (strlen($data) >= $this->line_length) {
            return $this->set_error(_("Address book entry is too big"));
        }

        /* Lock the file to make sure we're the only process working
         * on it. */
        if(!$this->lock()) {
            return $this->set_error(_("Could not lock datafile"));
        }

        /* Read file into memory, modifying the data for the
         * user identified by $alias */
        $this->open(true);
        @rewind($this->filehandle);
        $i = 0;
        $rows = array();
        while($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
            if(strtolower($row[0]) != strtolower($alias)) {
                $rows[$i++] = $row;
            } else {
                $rows[$i++] = array(0 => $userdata['nickname'],
                                    1 => $userdata['firstname'],
                                    2 => (!empty($userdata['lastname'])?$userdata['lastname']:''),
                                    3 => $userdata['email'],
                                    4 => (!empty($userdata['label'])?$userdata['label']:''));
            }
        }

        /* Write data back */
        if(!$this->overwrite($rows)) {
            $this->unlock();
            return false;
        }

        $this->unlock();
        return true;
    }

    /**
     * Function for quoting values before saving
     * @param string $value string that has to be quoted
     * @param string quoted string
     */
    function quotevalue($value) {
        /* Quote the field if it contains | or ". Double quotes need to
         * be replaced with "" */
        if(stristr($value, '"') || stristr($value, '|')) {
            $value = '"' . str_replace('"', '""', $value) . '"';
        }
        return $value;
    }

} /* End of class abook_local_file */

Added functions/addressbook.php.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
<?php

/**
 * functions/addressbook.php - Functions and classes for the addressbook system
 *
 * Functions require SM_PATH and support of forms.php functions
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: addressbook.php 14307 2012-04-01 21:13:57Z pdontthink $
 * @package squirrelmail
 * @subpackage addressbook
 */

/**
 * If SM_PATH isn't defined, define it.  Required to include files.
 * @ignore
 */
if (!defined('SM_PATH'))  {
    define('SM_PATH','../');
}

/* make sure that display_messages.php is loaded */
include_once(SM_PATH . 'functions/display_messages.php');

global $addrbook_dsn, $addrbook_global_dsn;

/**
   Create and initialize an addressbook object.
   Returns the created object
*/
function addressbook_init($showerr = true, $onlylocal = false) {
    global $data_dir, $username, $color, $ldap_server, $address_book_global_filename;
    global $addrbook_dsn, $addrbook_table;
    // Shared file based address book globals
    global $abook_global_file, $abook_global_file_writeable, $abook_global_file_listing;
    // Shared DB based address book globals
    global $addrbook_global_dsn, $addrbook_global_table, $addrbook_global_writeable, $addrbook_global_listing;
    // Record size restriction in file based address books
    global $abook_file_line_length;

    /* Create a new addressbook object */
    $abook = new AddressBook;

    /* Create empty error message */
    $abook_init_error='';

    /*
        Always add a local backend. We use *either* file-based *or* a
        database addressbook. If $addrbook_dsn is set, the database
        backend is used. If not, addressbooks are stores in files.
    */
    if (isset($addrbook_dsn) && !empty($addrbook_dsn)) {
        /* Database */
        if (!isset($addrbook_table) || empty($addrbook_table)) {
            $addrbook_table = 'address';
        }
        $r = $abook->add_backend('database', Array('dsn' => $addrbook_dsn,
                            'owner' => $username,
                            'table' => $addrbook_table));
        if (!$r && $showerr) {
            $abook_init_error.=_("Error initializing address book database.") .' '. $abook->error;
        }
    } else {
        /* File */
        $filename = getHashedFile($username, $data_dir, "$username.abook");
        $r = $abook->add_backend('local_file', Array('filename' => $filename,
                                                     'umask' => 0077,
                                                     'line_length' => $abook_file_line_length,
                                                     'create'   => true));
        if(!$r && $showerr) {
            $abook_init_error.=sprintf( _("Error opening file %s"), $filename );
        }
    }

    /* This would be for the global addressbook */
    if (isset($abook_global_file) && isset($abook_global_file_writeable)
        && trim($abook_global_file)!=''){
        // Detect place of address book
        if (! preg_match("/[\/\\\]/",$abook_global_file)) {
            /* no path chars, address book stored in data directory
             * make sure that there is a slash between data directory
             * and address book file name
             */
            $abook_global_filename=$data_dir
                . ((substr($data_dir, -1) != '/') ? '/' : '')
                . $abook_global_file;
        } elseif (preg_match("/^\/|\w:/",$abook_global_file)) {
            // full path is set in options (starts with slash or x:)
            $abook_global_filename=$abook_global_file;
        } else {
            $abook_global_filename=SM_PATH . $abook_global_file;
        }
        $r = $abook->add_backend('local_file',array('filename'=>$abook_global_filename,
                                                    'name' => _("Global address book"),
                                                    'detect_writeable' => false,
                                                    'line_length' => $abook_file_line_length,
                                                    'writeable'=> $abook_global_file_writeable,
                                                    'listing' => $abook_global_file_listing));
        if (!$r && $showerr) {
            if ($abook_init_error!='') $abook_init_error.="\n";
            $abook_init_error.=_("Error initializing global address book.") . "\n" . $abook->error;
        }
    }

    /* Load global addressbook from SQL if configured */
    if (isset($addrbook_global_dsn) && !empty($addrbook_global_dsn)) {
        /* Database configured */
        if (!isset($addrbook_global_table) || empty($addrbook_global_table)) {
            $addrbook_global_table = 'global_abook';
        }
        $r = $abook->add_backend('database',
                                 Array('dsn' => $addrbook_global_dsn,
                                       'owner' => 'global',
                                       'name' => _("Global address book"),
                                       'writeable' => $addrbook_global_writeable,
                                       'listing' => $addrbook_global_listing,
                                       'table' => $addrbook_global_table));
        if (!$r && $showerr) {
            if ($abook_init_error!='') $abook_init_error.="\n";
            $abook_init_error.=_("Error initializing global address book.") . "\n" . $abook->error;
    }
    }

    /*
     * hook allows to include different address book backends.
     * plugins should extract $abook and $r from arguments
     * and use same add_backend commands as above functions.
     * @since 1.5.1 and 1.4.5
     */
    $hookReturn = do_hook('abook_init', $abook, $r);
    $abook = $hookReturn[1];
    $r = $hookReturn[2];

    if (! $onlylocal) {
    /* Load configured LDAP servers (if PHP has LDAP support) */
    if (isset($ldap_server) && is_array($ldap_server) && function_exists('ldap_connect')) {
        reset($ldap_server);
        while (list($undef,$param) = each($ldap_server)) {
            if (is_array($param)) {
                $r = $abook->add_backend('ldap_server', $param);
                if (!$r && $showerr) {
                        if ($abook_init_error!='') $abook_init_error.="\n";
                        $abook_init_error.=sprintf(_("Error initializing LDAP server %s:") .
                            "\n", $param['host']);
                        $abook_init_error.= $abook->error;
                    }
                }
            }
        }
    } // end of remote abook backends init

    /**
     * display address book init errors.
     */
    if ($abook_init_error!='' && $showerr) {
        $abook_init_error = sm_encode_html_special_chars($abook_init_error);
        error_box($abook_init_error,$color);
    }

    /* Return the initialized object */
    return $abook;
}


/*
 *   Had to move this function outside of the Addressbook Class
 *   PHP 4.0.4 Seemed to be having problems with inline functions.
 */
function addressbook_cmp($a,$b) {

    if($a['backend'] > $b['backend']) {
        return 1;
    } else if($a['backend'] < $b['backend']) {
        return -1;
    }

    return (strtolower($a['name']) > strtolower($b['name'])) ? 1 : -1;

}

/**
 * Sort array by the key "name"
 */
function alistcmp($a,$b) {
    $abook_sort_order=get_abook_sort();

    switch ($abook_sort_order) {
    case 0:
    case 1:
      $abook_sort='nickname';
      break;
    case 4:
    case 5:
      $abook_sort='email';
      break;
    case 6:
    case 7:
      $abook_sort='label';
      break;
    case 2:
    case 3:
    case 8:
    default:
      $abook_sort='name';
    }

    if ($a['backend'] > $b['backend']) {
        return 1;
    } else {
        if ($a['backend'] < $b['backend']) {
            return -1;
        }
    }

    if( (($abook_sort_order+2) % 2) == 1) {
      return (strtolower($a[$abook_sort]) < strtolower($b[$abook_sort])) ? 1 : -1;
    } else {
      return (strtolower($a[$abook_sort]) > strtolower($b[$abook_sort])) ? 1 : -1;
    }
}

/**
 * Address book sorting options
 *
 * returns address book sorting order
 * @return integer book sorting options order
 */
function get_abook_sort() {
    global $data_dir, $username;

    /* get sorting order */
    if(sqgetGlobalVar('abook_sort_order', $temp, SQ_GET)) {
      $abook_sort_order = (int) $temp;

      if ($abook_sort_order < 0 or $abook_sort_order > 8)
        $abook_sort_order=8;

      setPref($data_dir, $username, 'abook_sort_order', $abook_sort_order);
    } else {
      /* get previous sorting options. default to unsorted */
      $abook_sort_order = getPref($data_dir, $username, 'abook_sort_order', 8);
    }

    return $abook_sort_order;
}

/**
 * This function shows the address book sort button.
 *
 * @param integer $abook_sort_order current sort value
 * @param string $alt_tag alt tag value (string visible to text only browsers)
 * @param integer $Down sort value when list is sorted ascending
 * @param integer $Up sort value when list is sorted descending
 * @return string html code with sorting images and urls
 * @since 1.5.1 and 1.4.6
 */
function show_abook_sort_button($abook_sort_order, $alt_tag, $Down, $Up ) {
    global $form_url;

     /* Figure out which image we want to use. */
    if ($abook_sort_order != $Up && $abook_sort_order != $Down) {
        $img = 'sort_none.png';
        $which = $Up;
    } elseif ($abook_sort_order == $Up) {
        $img = 'up_pointer.png';
        $which = $Down;
    } else {
        $img = 'down_pointer.png';
        $which = 8;
    }

      /* Now that we have everything figured out, show the actual button. */
    return ' <a href="' . $form_url .'?abook_sort_order=' . $which
         . '"><img src="../images/' . $img
         . '" border="0" width="12" height="10" alt="' . $alt_tag . '" title="'
         . _("Click here to change the sorting of the address list") .'" /></a>';
}


/**
 * This is the main address book class that connect all the
 * backends and provide services to the functions above.
 * @package squirrelmail
 */

class AddressBook {

    var $backends    = array();
    var $numbackends = 0;
    var $error       = '';
    var $localbackend = 0;
    var $localbackendname = '';
    var $add_extra_field = false;

      // Constructor function.
    function AddressBook() {
        $this->localbackendname = _("Personal address book");
    }

    /*
     * Return an array of backends of a given type,
     * or all backends if no type is specified.
     */
    function get_backend_list($type = '') {
        $ret = array();
        for ($i = 1 ; $i <= $this->numbackends ; $i++) {
            if (empty($type) || $type == $this->backends[$i]->btype) {
                $ret[] = &$this->backends[$i];
            }
        }
        return $ret;
    }


    /*
       ========================== Public ========================

        Add a new backend. $backend is the name of a backend
        (without the abook_ prefix), and $param is an optional
        mixed variable that is passed to the backend constructor.
        See each of the backend classes for valid parameters.
     */
    function add_backend($backend, $param = '') {
        $backend_name = 'abook_' . $backend;
        eval('$newback = new ' . $backend_name . '($param);');
        if(!empty($newback->error)) {
            $this->error = $newback->error;
            return false;
        }

        $this->numbackends++;

        $newback->bnum = $this->numbackends;
        $this->backends[$this->numbackends] = $newback;

        /* Store ID of first local backend added */
        if ($this->localbackend == 0 && $newback->btype == 'local') {
            $this->localbackend = $this->numbackends;
            $this->localbackendname = $newback->sname;
        }

        return $this->numbackends;
    }


    /*
     * This function takes a $row array as returned by the addressbook
     * search and returns an e-mail address with the full name or
     * nickname optionally prepended.
     */

    function full_address($row) {
        global $data_dir, $username;
        $addrsrch_fullname = getPref($data_dir, $username, 'addrsrch_fullname', 'fullname');

        // allow multiple addresses in one row (poor person's grouping - bah)
        // (separate with commas)
        //
        $return = '';
        $addresses = explode(',', $row['email']);
        foreach ($addresses as $address) {

            if (!empty($return)) $return .= ', ';

            if ($addrsrch_fullname == 'fullname')
                $return .= '"' . $row['name'] . '" <' . trim($address) . '>';
            else if ($addrsrch_fullname == 'nickname')
                $return .= '"' . $row['nickname'] . '" <' . trim($address) . '>';
            else // "noprefix"
                $return .= trim($address);

        }

        return $return;
    }

    /*
        Return a list of addresses matching expression in
        all backends of a given type.
    */
    function search($expression, $bnum = -1) {
        $ret = array();
        $this->error = '';

        /* Search all backends */
        if ($bnum == -1) {
            $sel = $this->get_backend_list('');
            $failed = 0;
            for ($i = 0 ; $i < sizeof($sel) ; $i++) {
                $backend = &$sel[$i];
                $backend->error = '';
                $res = $backend->search($expression);
                if (is_array($res)) {
                    $ret = array_merge($ret, $res);
                } else {
                    $this->error .= "\n" . $backend->error;
                    $failed++;
                }
            }

            /* Only fail if all backends failed */
            if( $failed >= sizeof( $sel ) ) {
                $ret = FALSE;
            }

        }  else {

            /* Search only one backend */

            $ret = $this->backends[$bnum]->search($expression);
            if (!is_array($ret)) {
                $this->error .= "\n" . $this->backends[$bnum]->error;
                $ret = FALSE;
            }
        }

        return( $ret );
    }


    /* Return a sorted search */
    function s_search($expression, $bnum = -1) {

        $ret = $this->search($expression, $bnum);
        if ( is_array( $ret ) ) {
            usort($ret, 'addressbook_cmp');
        }
        return $ret;
    }


    /*
     *  Lookup an address by the indicated field. Only
     *  possible in local backends.
     */
    function lookup($value, $bnum = -1, $field = SM_ABOOK_FIELD_NICKNAME) {

        $ret = array();

        if ($bnum > -1) {
            $res = $this->backends[$bnum]->lookup($value, $field);
            if (is_array($res)) {
               return $res;
            } else {
               $this->error = $this->backends[$bnum]->error;
               return false;
            }
        }

        $sel = $this->get_backend_list('local');
        for ($i = 0 ; $i < sizeof($sel) ; $i++) {
            $backend = &$sel[$i];
            $backend->error = '';
            $res = $backend->lookup($value, $field);

            // return an address if one is found
            // (empty array means lookup concluded
            // but no result found - in this case,
            // proceed to next backend)
            //
            if (is_array($res)) {
                if (!empty($res)) return $res;
            } else {
                $this->error = $backend->error;
                return false;
            }
        }

        return $ret;
    }


    /* Return all addresses */
    function list_addr($bnum = -1) {
        $ret = array();

        if ($bnum == -1) {
            $sel = $this->get_backend_list('');
        } else {
            $sel = array(0 => &$this->backends[$bnum]);
        }

        for ($i = 0 ; $i < sizeof($sel) ; $i++) {
            $backend = &$sel[$i];
            $backend->error = '';
            $res = $backend->list_addr();
            if (is_array($res)) {
               $ret = array_merge($ret, $res);
            } else {
               $this->error = $backend->error;
               return false;
            }
        }

        return $ret;
    }

    /*
     * Create a new address from $userdata, in backend $bnum.
     * Return the backend number that the/ address was added
     * to, or false if it failed.
     */
    function add($userdata, $bnum) {

        /* Validate data */
        if (!is_array($userdata)) {
            $this->error = _("Invalid input data");
            return false;
        }
        if (empty($userdata['firstname']) && empty($userdata['lastname'])) {
            $this->error = _("Name is missing");
            return false;
        }
        if (empty($userdata['email'])) {
            $this->error = _("E-mail address is missing");
            return false;
        }
        if (empty($userdata['nickname'])) {
            $userdata['nickname'] = $userdata['email'];
        }

        if (preg_match('/[ :|#"!]/', $userdata['nickname'])) {
            $this->error = _("Nickname contains illegal characters");
            return false;
        }

        /* Check that specified backend accept new entries */
        if (!$this->backends[$bnum]->writeable) {
            $this->error = _("Address book is read-only");
            return false;
        }

        /* Add address to backend */
        $res = $this->backends[$bnum]->add($userdata);
        if ($res) {
            return $bnum;
        } else {
            $this->error = $this->backends[$bnum]->error;
            return false;
        }

        return false;  // Not reached
    } /* end of add() */


    /*
     * Remove the user identified by $alias from backend $bnum
     * If $alias is an array, all users in the array are removed.
     */
    function remove($alias, $bnum) {

        /* Check input */
        if (empty($alias)) {
            return true;
        }

        /* Convert string to single element array */
        if (!is_array($alias)) {
            $alias = array(0 => $alias);
        }

        /* Check that specified backend is writable */
        if (!$this->backends[$bnum]->writeable) {
            $this->error = _("Address book is read-only");
            return false;
        }

        /* Remove user from backend */
        $res = $this->backends[$bnum]->remove($alias);
        if ($res) {
            return $bnum;
        } else {
            $this->error = $this->backends[$bnum]->error;
            return false;
        }

        return FALSE;  /* Not reached */
    } /* end of remove() */


    /*
     * Remove the user identified by $alias from backend $bnum
     * If $alias is an array, all users in the array are removed.
     */
    function modify($alias, $userdata, $bnum) {

        /* Check input */
        if (empty($alias) || !is_string($alias)) {
            return true;
        }

        /* Validate data */
        if(!is_array($userdata)) {
            $this->error = _("Invalid input data");
            return false;
        }
        if (empty($userdata['firstname']) && empty($userdata['lastname'])) {
            $this->error = _("Name is missing");
            return false;
        }
        if (empty($userdata['email'])) {
            $this->error = _("E-mail address is missing");
            return false;
        }

        if (preg_match('/[: |#"!]/', $userdata['nickname'])) {
            $this->error = _("Nickname contains illegal characters");
            return false;
        }

        if (empty($userdata['nickname'])) {
            $userdata['nickname'] = $userdata['email'];
        }

        /* Check that specified backend is writable */
        if (!$this->backends[$bnum]->writeable) {
            $this->error = _("Address book is read-only");;
            return false;
        }

        /* Modify user in backend */
        $res = $this->backends[$bnum]->modify($alias, $userdata);
        if ($res) {
            return $bnum;
        } else {
            $this->error = $this->backends[$bnum]->error;
            return false;
        }

        return FALSE;  /* Not reached */
    } /* end of modify() */


} /* End of class Addressbook */

/**
 * Generic backend that all other backends extend
 * @package squirrelmail
 */
class addressbook_backend {

    /* Variables that all backends must provide. */
    var $btype      = 'dummy';
    var $bname      = 'dummy';
    var $sname      = 'Dummy backend';

    /*
     * Variables common for all backends, but that
     * should not be changed by the backends.
     */
    var $bnum       = -1;
    var $error      = '';
    var $writeable  = false;

    function set_error($string) {
        $this->error = '[' . $this->sname . '] ' . $string;
        return false;
    }


    /* ========================== Public ======================== */

    function search($expression) {
        $this->set_error('search not implemented');
        return false;
    }

    function lookup($value, $field=SM_ABOOK_FIELD_NICKNAME) {
        $this->set_error('lookup not implemented');
        return false;
    }

    function list_addr() {
        $this->set_error('list_addr not implemented');
        return false;
    }

    function add($userdata) {
        $this->set_error('add not implemented');
        return false;
    }

    function remove($alias) {
        $this->set_error('delete not implemented');
        return false;
    }

    function modify($alias, $newuserdata) {
        $this->set_error('modify not implemented');
        return false;
    }

}

/*
  PHP 5 requires that the class be made first, which seems rather
  logical, and should have been the way it was generated the first time.
*/

require_once(SM_PATH . 'functions/abook_local_file.php');
require_once(SM_PATH . 'functions/abook_ldap_server.php');

/* Only load database backend if database is configured */
if((isset($addrbook_dsn) && !empty($addrbook_dsn)) ||
 (isset($addrbook_global_dsn) && !empty($addrbook_global_dsn))) {
  include_once(SM_PATH . 'functions/abook_database.php');
}

/*
 * hook allows adding different address book classes.
 * class must follow address book class coding standards.
 *
 * see addressbook_backend class and functions/abook_*.php files.
 * @since 1.5.1 and 1.4.5
 */
do_hook('abook_add_class');

Added functions/attachment_common.php.

















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
<?php

/**
 * attachment_common.php
 *
 * This file provides the handling of often-used attachment types.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: attachment_common.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

/**
 * FIXME Needs phpDocumentator style documentation
 */
require_once(SM_PATH . 'functions/global.php');

global $attachment_common_show_images_list;
$attachment_common_show_images_list = array();

global $FileExtensionToMimeType, $attachment_common_types;
$FileExtensionToMimeType = array('bmp'  => 'image/x-bitmap',
                                 'gif'  => 'image/gif',
                                 'htm'  => 'text/html',
                                 'html' => 'text/html',
                                 'jpg'  => 'image/jpeg',
                                 'jpeg' => 'image/jpeg',
                                 'php'  => 'text/plain',
                                 'png'  => 'image/png',
                                 'rtf'  => 'text/richtext',
                                 'txt'  => 'text/plain',
                                 'patch'=> 'text/plain',
                                 'vcf'  => 'text/x-vcard');

/* Register browser-supported image types */
sqgetGlobalVar('attachment_common_types', $attachment_common_types);
if (isset($attachment_common_types)) {
    // var is used to detect activation of jpeg image types
    unset($jpeg_done);
    /* Don't run this before being logged in. That may happen
       when plugins include mime.php */
    foreach ($attachment_common_types as $val => $v) {
        if ($val == 'image/gif')
            register_attachment_common('image/gif',       'link_image');
        elseif (($val == 'image/jpeg' || $val == 'image/pjpeg') and
                (!isset($jpeg_done))) {
            $jpeg_done = 1;
            register_attachment_common('image/jpeg',      'link_image');
            register_attachment_common('image/pjpeg',     'link_image');
        }
        elseif ($val == 'image/png')
            register_attachment_common('image/png',       'link_image');
        elseif ($val == 'image/x-xbitmap')
            register_attachment_common('image/x-xbitmap', 'link_image');
        elseif ($val == '*/*' || $val == 'image/*') {
            /**
             * browser (Firefox) declared that anything is acceptable. 
             * Lets register some common image types.
             */
            if (! isset($jpeg_done)) {
                $jpeg_done = 1;
                register_attachment_common('image/jpeg',  'link_image');
                register_attachment_common('image/pjpeg', 'link_image');
            }
            register_attachment_common('image/gif',       'link_image');
            register_attachment_common('image/png',       'link_image');
            register_attachment_common('image/x-xbitmap', 'link_image');
        }
    }
    unset($jpeg_done);
}

/* Register text-type attachments */
register_attachment_common('message/rfc822', 'link_message');
register_attachment_common('text/plain',     'link_text');
register_attachment_common('text/richtext',  'link_text');

/* Register HTML */
register_attachment_common('text/html',      'link_html');


/* Register vcards */
register_attachment_common('text/x-vcard',   'link_vcard');
register_attachment_common('text/directory', 'link_vcard');

/* Register rules for general types.
 * These will be used if there isn't a more specific rule available. */
register_attachment_common('text/*',  'link_text');
register_attachment_common('message/*',  'link_text');

/* Register "unknown" attachments */
register_attachment_common('application/octet-stream', 'octet_stream');


/* Function which optimizes readability of the above code */

function register_attachment_common($type, $func) {
    global $squirrelmail_plugin_hooks;
    $squirrelmail_plugin_hooks['attachment ' . $type]['attachment_common'] =
                      'attachment_common_' . $func;
}


function attachment_common_link_text(&$Args) {

    global $squirrelmail_attachments_finished_handling;
    if (!empty($squirrelmail_attachments_finished_handling[$Args[7]])) return;
    $squirrelmail_attachments_finished_handling[$Args[7]] = TRUE;

    /* If there is a text attachment, we would like to create a "View" button
       that links to the text attachment viewer.

       $Args[1] = the array of actions

       Use the name of this file for adding an action
       $Args[1]['attachment_common'] = Array for href and text

       $Args[1]['attachment_common']['text'] = What is displayed
       $Args[1]['attachment_common']['href'] = Where it links to */
    sqgetGlobalVar('QUERY_STRING', $QUERY_STRING, SQ_SERVER);

    $Args[1]['attachment_common']['href'] = SM_PATH . 'src/view_text.php?'. $QUERY_STRING;
    $Args[1]['attachment_common']['href'] =
          set_url_var($Args[1]['attachment_common']['href'],
          'ent_id',$Args[5]);

    /* The link that we created needs a name. */
    $Args[1]['attachment_common']['text'] = _("View");

    /* Each attachment has a filename on the left, which is a link.
       Where that link points to can be changed.  Just in case the link above
       for viewing text attachments is not the same as the default link for
       this file, we'll change it.

       This is a lot better in the image links, since the defaultLink will just
       download the image, but the one that we set it to will format the page
       to have an image tag in the center (looking a lot like this text viewer) */
    $Args[6] = $Args[1]['attachment_common']['href'];
}

function attachment_common_link_message(&$Args) {

    global $squirrelmail_attachments_finished_handling;
    if (!empty($squirrelmail_attachments_finished_handling[$Args[7]])) return;
    $squirrelmail_attachments_finished_handling[$Args[7]] = TRUE;

    $Args[1]['attachment_common']['href'] = SM_PATH . 'src/read_body.php?startMessage=' .
        $Args[2] . '&amp;passed_id=' . $Args[3] . '&amp;mailbox=' . $Args[4] .
        '&amp;passed_ent_id=' . $Args[5] . '&amp;override_type0=message&amp;override_type1=rfc822';

    $Args[1]['attachment_common']['text'] = _("View");

    $Args[6] = $Args[1]['attachment_common']['href'];
}


function attachment_common_link_html(&$Args) {

    global $squirrelmail_attachments_finished_handling;
    if (!empty($squirrelmail_attachments_finished_handling[$Args[7]])) return;
    $squirrelmail_attachments_finished_handling[$Args[7]] = TRUE;

    sqgetGlobalVar('QUERY_STRING', $QUERY_STRING, SQ_SERVER);

    $Args[1]['attachment_common']['href'] = SM_PATH . 'src/view_text.php?'. $QUERY_STRING.
       /* why use the overridetype? can this be removed */
       '&amp;override_type0=text&amp;override_type1=html';
    $Args[1]['attachment_common']['href'] =
          set_url_var($Args[1]['attachment_common']['href'],
          'ent_id',$Args[5]);

    $Args[1]['attachment_common']['text'] = _("View");

    $Args[6] = $Args[1]['attachment_common']['href'];
}

function attachment_common_link_image(&$Args) {

    global $squirrelmail_attachments_finished_handling;
    if (!empty($squirrelmail_attachments_finished_handling[$Args[7]])) return;
    $squirrelmail_attachments_finished_handling[$Args[7]] = TRUE;

    global $attachment_common_show_images, $attachment_common_show_images_list;

    sqgetGlobalVar('QUERY_STRING', $QUERY_STRING, SQ_SERVER);

    $info['passed_id'] = $Args[3];
    $info['mailbox'] = $Args[4];
    $info['ent_id'] = $Args[5];

    $attachment_common_show_images_list[] = $info;

    $Args[1]['attachment_common']['href'] = SM_PATH . 'src/image.php?'. $QUERY_STRING;
    $Args[1]['attachment_common']['href'] =
          set_url_var($Args[1]['attachment_common']['href'],
          'ent_id',$Args[5]);

    $Args[1]['attachment_common']['text'] = _("View");

    $Args[6] = $Args[1]['attachment_common']['href'];
}


function attachment_common_link_vcard(&$Args) {

    global $squirrelmail_attachments_finished_handling;
    if (!empty($squirrelmail_attachments_finished_handling[$Args[7]])) return;
    $squirrelmail_attachments_finished_handling[$Args[7]] = TRUE;

    sqgetGlobalVar('QUERY_STRING', $QUERY_STRING, SQ_SERVER);

    $Args[1]['attachment_common']['href'] = SM_PATH . 'src/vcard.php?'. $QUERY_STRING;
    $Args[1]['attachment_common']['href'] =
          set_url_var($Args[1]['attachment_common']['href'],
          'ent_id',$Args[5]);

    $Args[1]['attachment_common']['text'] = _("View Business Card");

    $Args[6] = $Args[1]['attachment_common']['href'];
}


function attachment_common_octet_stream(&$Args) {
    global $FileExtensionToMimeType;

    do_hook('attachment_common-load_mime_types');

    preg_match('/\.([^.]+)$/', $Args[7], $Regs);

    $Ext = '';
    if (is_array($Regs) && isset($Regs[1])) {
        $Ext = $Regs[1];
        $Ext = strtolower($Regs[1]);
    }

    if ($Ext == '' || ! isset($FileExtensionToMimeType[$Ext]))
        return;

    $Ret = do_hook('attachment ' . $FileExtensionToMimeType[$Ext],
        $Args[1], $Args[2], $Args[3], $Args[4], $Args[5], $Args[6],
        $Args[7], $Args[8], $Args[9]);

    foreach ($Ret as $a => $b) {
        $Args[$a] = $b;
    }
}

Added functions/auth.php.







































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<?php

/**
 * auth.php
 *
 * Contains functions used to do authentication.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: auth.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

/** Put in a safety net here, in case a naughty admin didn't run conf.pl when they upgraded */

if (! isset($smtp_auth_mech)) {
    $smtp_auth_mech = 'none';
}

if (! isset($imap_auth_mech)) {
    $imap_auth_mech = 'login';
}

if (! isset($use_imap_tls)) {
    $use_imap_tls = false;
}

if (! isset($use_smtp_tls)) {
    $use_smtp_tls = false;
}

/**
 * Check if user has previously logged in to the SquirrelMail session.  If user
 * has not logged in, execution will stop inside this function.
 *
 * This function optionally checks the referrer of this page request.  If the
 * administrator wants to impose a check that the referrer of this page request
 * is another page on the same domain (otherwise, the page request is likely
 * the result of a XSS or phishing attack), then they need to specify the
 * acceptable referrer domain in a variable named $check_referrer in
 * config/config.php (or the configuration tool) for which the value is
 * usually the same as the $domain setting (for example:
 *    $check_referrer = 'example.com';
 * However, in some cases (where proxy servers are in use, etc.), the
 * acceptable referrer might be different.  If $check_referrer is set to
 * "###DOMAIN###", then the current value of $domain is used (useful in
 * situations where $domain might change at runtime (when using the Login
 * Manager plugin to host multiple domains with one SquirrelMail installation,
 * for example)):
 *    $check_referrer = '###DOMAIN###';
 * NOTE HOWEVER, that referrer checks are not foolproof - they can be spoofed
 * by browsers, and some browsers intentionally don't send them, in which
 * case SquirrelMail silently ignores referrer checks.
 *
 * @return void This function returns ONLY if user has previously logged in
 * successfully (otherwise, execution terminates herein).
 */
function is_logged_in() {

    // check for user login as well as referrer if needed
    //
    global $check_referrer, $domain;
    if ($check_referrer == '###DOMAIN###') $check_referrer = $domain;
    if (!empty($check_referrer)) {
        $ssl_check_referrer = 'https://' . $check_referrer;
        $plain_check_referrer = 'http://' . $check_referrer;
    }
    if (!sqgetGlobalVar('HTTP_REFERER', $referrer, SQ_SERVER)) $referrer = '';
    if (sqsession_is_registered('user_is_logged_in') 
     && (!$check_referrer || empty($referrer)
      || ($check_referrer && !empty($referrer)
       && (strpos(strtolower($referrer), strtolower($plain_check_referrer)) === 0
        || strpos(strtolower($referrer), strtolower($ssl_check_referrer)) === 0)))) {
        return;
    } else {

        global $session_expired_post,
               $session_expired_location, $squirrelmail_language;

        // use $message to indicate what logout text the user
        // will see... if 0, typical "You must be logged in"
        // if 1, information that the user session was saved
        // and will be resumed after (re)login, if 2, there
        // seems to have been a XSS or phishing attack (bad
        // referrer)
        //
        $message = 0;

        //  First we store some information in the new session to prevent
        //  information-loss.
        $session_expired_post = $_POST;
        if (defined('PAGE_NAME')) {
            $session_expired_location = PAGE_NAME;
        }
        
        if (!sqsession_is_registered('session_expired_post')) {
            sqsession_register($session_expired_post,'session_expired_post');
        }
        if (!sqsession_is_registered('session_expired_location')) {
            sqsession_register($session_expired_location,'session_expired_location');
            if ($session_expired_location == 'compose')
                $message = 1;
        }

        // was bad referrer the reason we were rejected?
        //
        if (sqsession_is_registered('user_is_logged_in') 
         && $check_referrer && !empty($referrer))
            $message = 2;
      
        session_write_close();

        // signout page will deal with users who aren't logged 
        // in on its own; don't show error here
        if (defined('PAGE_NAME') && PAGE_NAME == 'signout') {
           return;
        }

        include_once( SM_PATH . 'functions/display_messages.php' );
        set_up_language($squirrelmail_language, true);
        if (!$message)
            logout_error( _("You must be logged in to access this page.") );
        else if ($message == 1)
            logout_error( _("Your session has expired, but will be resumed after logging in again.") );
        else if ($message == 2)
            logout_error( _("The current page request appears to have originated from an unrecognized source.") );
        exit;
    }
}

/**
 * Given the challenge from the server, supply the response using cram-md5 (See
 * RFC 2195 for details)
 *
 * @param string $username User ID
 * @param string $password User password supplied by User
 * @param string $challenge The challenge supplied by the server
 * @return string The response to be sent to the IMAP server
 *
 */
function cram_md5_response ($username,$password,$challenge) {
    $challenge=base64_decode($challenge);
    $hash=bin2hex(hmac_md5($challenge,$password));
    $response=base64_encode($username . " " . $hash) . "\r\n";
    return $response;
}

/**
 * Return Digest-MD5 response.
 * Given the challenge from the server, calculate and return the
 * response-string for digest-md5 authentication.  (See RFC 2831 for more
 * details)
 *
 * @param string $username User ID
 * @param string $password User password supplied by User
 * @param string $challenge The challenge supplied by the server
 * @param string $service The service name, usually 'imap'; it is used to
 *   define the digest-uri.
 * @param string $host The host name, usually the server's FQDN; it is used to
 *   define the digest-uri.
 * @param string $authz Authorization ID (since 1.4.23)
 * @return string The response to be sent to the IMAP server
 * @since 1.4.0
 */
function digest_md5_response ($username,$password,$challenge,$service,$host,$authz='') {
    $result=digest_md5_parse_challenge($challenge);
    //FIXME we should check that $result contains the expected values that we use below

    // verify server supports qop=auth
    // $qop = explode(",",$result['qop']);
    //if (!in_array("auth",$qop)) {
    // rfc2831: client MUST fail if no qop methods supported
    // return false;
    //}
    $cnonce = base64_encode(bin2hex(hmac_md5(microtime())));
    $ncount = "00000001";

    /* This can be auth (authentication only), auth-int (integrity protection), or
       auth-conf (confidentiality protection).  Right now only auth is supported.
       DO NOT CHANGE THIS VALUE */
    $qop_value = "auth";

    $digest_uri_value = $service . '/' . $host;

    // build the $response_value
    //FIXME This will probably break badly if a server sends more than one realm
    $string_a1 = utf8_encode($username).":";
    $string_a1 .= utf8_encode($result['realm']).":";
    $string_a1 .= utf8_encode($password);
    $string_a1 = hmac_md5($string_a1);
    $A1 = $string_a1 . ":" . $result['nonce'] . ":" . $cnonce;
    if(!empty($authz)) {
        $A1 .= ":" . utf8_encode($authz);
    }
    $A1 = bin2hex(hmac_md5($A1));
    $A2 = "AUTHENTICATE:$digest_uri_value";
    // If qop is auth-int or auth-conf, A2 gets a little extra
    if ($qop_value != 'auth') {
        $A2 .= ':00000000000000000000000000000000';
    }
    $A2 = bin2hex(hmac_md5($A2));

    $string_response = $result['nonce'] . ':' . $ncount . ':' . $cnonce . ':' . $qop_value;
    $response_value = bin2hex(hmac_md5($A1.":".$string_response.":".$A2));

    $reply = 'charset=utf-8,username="' . $username . '",realm="' . $result["realm"] . '",';
    $reply .= 'nonce="' . $result['nonce'] . '",nc=' . $ncount . ',cnonce="' . $cnonce . '",';
    $reply .= "digest-uri=\"$digest_uri_value\",response=$response_value";
    $reply .= ',qop=' . $qop_value;
    if(!empty($authz)) {
        $reply .= ',authzid=' . $authz;
    }
    $reply = base64_encode($reply);
    return $reply . "\r\n";

}

/**
 * Parse Digest-MD5 challenge.
 * This function parses the challenge sent during DIGEST-MD5 authentication and
 * returns an array. See the RFC for details on what's in the challenge string.
 *
 * @param string $challenge Digest-MD5 Challenge
 * @return array Digest-MD5 challenge decoded data
 */
function digest_md5_parse_challenge($challenge) {
    $challenge=base64_decode($challenge);
    $parsed = array();
    while (!empty($challenge)) {
        if ($challenge{0} == ',') { // First char is a comma, must not be 1st time through loop
            $challenge=substr($challenge,1);
        }
        $key=explode('=',$challenge,2);
        $challenge=$key[1];
        $key=$key[0];
        if ($challenge{0} == '"') {
            // We're in a quoted value
            // Drop the first quote, since we don't care about it
            $challenge=substr($challenge,1);
            // Now explode() to the next quote, which is the end of our value
            $val=explode('"',$challenge,2);
            $challenge=$val[1]; // The rest of the challenge, work on it in next iteration of loop
            $value=explode(',',$val[0]);
            // Now, for those quoted values that are only 1 piece..
            if (sizeof($value) == 1) {
                $value=$value[0];  // Convert to non-array
            }
        } else {
            // We're in a "simple" value - explode to next comma
            $val=explode(',',$challenge,2);
            if (isset($val[1])) {
                $challenge=$val[1];
            } else {
                unset($challenge);
            }
            $value=$val[0];
        }
        $parsed["$key"]=$value;
    } // End of while loop
    return $parsed;
}

/**
 * Creates a HMAC digest that can be used for auth purposes
 * See RFCs 2104, 2617, 2831
 * Uses mhash() extension if available
 *
 * @param string $data Data to apply hash function to.
 * @param string $key Optional key, which, if supplied, will be used to
 * calculate data's HMAC.
 * @return string HMAC Digest string
 */
function hmac_md5($data, $key='') {
    if (extension_loaded('mhash')) {
        if ($key== '') {
            $mhash=mhash(MHASH_MD5,$data);
        } else {
            $mhash=mhash(MHASH_MD5,$data,$key);
        }
        return $mhash;
    }
    if (!$key) {
        return pack('H*',md5($data));
    }
    $key = str_pad($key,64,chr(0x00));
    if (strlen($key) > 64) {
        $key = pack("H*",md5($key));
    }
    $k_ipad =  $key ^ str_repeat(chr(0x36), 64) ;
    $k_opad =  $key ^ str_repeat(chr(0x5c), 64) ;
    /* Heh, let's get recursive. */
    $hmac=hmac_md5($k_opad . pack("H*",md5($k_ipad . $data)) );
    return $hmac;
}

/**
 * Reads and decodes stored user password information
 *
 * Direct access to password information is deprecated.
 * @return string password in plain text
 * @since 1.4.11
 */
function sqauth_read_password() {
    global $is_login_verified_hook;
    if ($is_login_verified_hook) global $key;

    sqgetGlobalVar('key',         $key,       SQ_COOKIE);
    sqgetGlobalVar('onetimepad',  $onetimepad,SQ_SESSION);

    return OneTimePadDecrypt($key, $onetimepad);
}

/**
 * Saves or updates user password information
 *
 * This function is used to update the password information that
 * SquirrelMail stores in the existing PHP session. It does NOT
 * modify the password stored in the authentication system used
 * by the IMAP server.
 *
 * This function must be called before any html output is started.
 * Direct access to password information is deprecated. The saved
 * password information is available only to the SquirrelMail script
 * that is called/executed AFTER the current one. If your script
 * needs access to the saved password after a sqauth_save_password()
 * call, use the returned OTP encrypted key.
 *
 * @param string $pass password
 *
 * @return string Password encrypted with OTP. In case the script
 *                wants to access the password information before
 *                the end of its execution.
 *
 * @since 1.4.16
 *
 */
function sqauth_save_password($pass) {
    sqgetGlobalVar('base_uri',    $base_uri,   SQ_SESSION);

    $onetimepad = OneTimePadCreate(strlen($pass));
    sqsession_register($onetimepad,'onetimepad');
    $key = OneTimePadEncrypt($pass, $onetimepad);
    sqsetcookie('key', $key, false, $base_uri);
    return $key;
}

/**
 * Fillin user and password based on SMTP auth settings.
 *
 * @param string $user Reference to SMTP username
 * @param string $pass Reference to SMTP password (unencrypted)
 * @since 1.4.11
 */
function get_smtp_user(&$user, &$pass) {
    global $username, $smtp_auth_mech,
           $smtp_sitewide_user, $smtp_sitewide_pass;

    if ($smtp_auth_mech == 'none') {
        $user = '';
        $pass = '';
    } elseif ( isset($smtp_sitewide_user) && isset($smtp_sitewide_pass) &&
               !empty($smtp_sitewide_user)) {
        $user = $smtp_sitewide_user;
        $pass = $smtp_sitewide_pass;
    } else {
        $user = $username;
        $pass = sqauth_read_password();
    }

    // plugin authors note: override $user or $pass by
    // returning an array where the new username is the
    // first array value and the new password is the 
    // second array value e.g., return array($myuser, $mypass);
    //
    // NOTE: there is another hook in class/deliver/Deliver_SMTP.class.php
    // called "smtp_authenticate" that allows a plugin to run its own
    // custom authentication routine - this hook here is thus slightly
    // mis-named but is too old to change.  Be careful that you do not
    // confuse your hook names.
    //
    $ret = do_hook_function('smtp_auth', array($user, $pass));
    if (!empty($ret[0]))
        $user = $ret[0];
    if (!empty($ret[1]))
        $pass = $ret[1];
}

Added functions/constants.php.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php

/**
 * constants.php
 *
 * Loads constants used by the rest of the SquirrelMail source.
 * This file is include by src/login.php, src/redirect.php and
 * src/load_prefs.php.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: constants.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @since 1.2.0
 */

/** Need to enable plugin functions for a hook */
require_once(SM_PATH . 'functions/plugin.php');  /* Required for the hook */

/**************************************************************/
/* Set values for constants used by Squirrelmail preferences. */
/**************************************************************/

/* Define basic, general purpose preference constants. */
define('SMPREF_NO', 0);
define('SMPREF_OFF', 0);
define('SMPREF_YES', 1);
define('SMPREF_ON', 1);
define('SMPREF_NONE', 'none');

/* Define constants for location based preferences. */
define('SMPREF_LOC_TOP', 'top');
define('SMPREF_LOC_BETWEEN', 'between');
define('SMPREF_LOC_BOTTOM', 'bottom');
define('SMPREF_LOC_LEFT', '');
define('SMPREF_LOC_RIGHT', 'right');

/* Define preferences for folder settings. */
define('SMPREF_UNSEEN_NONE', 1);
define('SMPREF_UNSEEN_INBOX', 2);
define('SMPREF_UNSEEN_ALL', 3);
define('SMPREF_UNSEEN_SPECIAL', 4); // Only special folders
define('SMPREF_UNSEEN_NORMAL', 5);  // Only normal folders
define('SMPREF_UNSEEN_ONLY', 1);
define('SMPREF_UNSEEN_TOTAL', 2);

/* Define constants for time/date display preferences. */
define('SMPREF_TIME_24HR', 1);
define('SMPREF_TIME_12HR', 2);

/* Define constants for javascript preferences. */
define('SMPREF_JS_OFF', 0);
define('SMPREF_JS_ON', 1);
define('SMPREF_JS_AUTODETECT', 2);

/* Define constants for address book functionalities. */
define('SM_ABOOK_FIELD_NICKNAME', 0);
define('SM_ABOOK_FIELD_FIRSTNAME', 1);
define('SM_ABOOK_FIELD_LASTNAME', 2);
define('SM_ABOOK_FIELD_EMAIL', 3);
define('SM_ABOOK_FIELD_LABEL', 4);

do_hook('loading_constants');

Added functions/date.php.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
<?php

/**
 * date.php
 *
 * Takes a date and parses it into a usable format.  The form that a
 * date SHOULD arrive in is:
 *       <Tue,> 29 Jun 1999 09:52:11 -0500 (EDT)
 * (as specified in RFC 822) -- 'Tue' is optional
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: date.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage date
 */

/** Load up some useful constants */
require_once(SM_PATH . 'functions/constants.php');

/**
 * Corrects a time stamp to be the local time.
 *
 * @param int stamp the timestamp to adjust
 * @param string tzc the timezone correction
 * @return int the corrected timestamp
 */
function getGMTSeconds($stamp, $tzc) {
    /* date couldn't be parsed */
    if ($stamp == -1) {
        return -1;
    }
    /* timezone correction, expressed as `shhmm' */
    switch($tzc)
    {
        case 'Pacific':
        case 'PST':
            $tzc = '-0800';
            break;
        case 'Mountain':
        case 'MST':
        case 'PDT':
            $tzc = '-0700';
            break;
        case 'Central':
        case 'CST':
        case 'MDT':
            $tzc = '-0600';
            break;
        case 'Eastern':
        case 'EST':
        case 'CDT':
            $tzc = '-0500';
            break;
        case 'EDT':
            $tzc = '-0400';
            break;
        case 'GMT':
            $tzc = '+0000';
            break;
        case 'BST':
        case 'MET':
        case 'CET':
            $tzc = '+0100';
            break;
        case 'EET':
        case 'IST':
        case 'MET DST':
        case 'METDST':
	case 'CEST':
	case 'MEST':
            $tzc = '+0200';
            break;
        case 'HKT':
            $tzc = '+0800';
            break;
        case 'JST':
        case 'KST':
            $tzc = '+0900';
            break;
    }
    $neg = false;
    if (substr($tzc, 0, 1) == '-') {
        $neg = true;
    } else if (substr($tzc, 0, 1) != '+') {
        $tzc = '+'.$tzc;
    }
    $hh = substr($tzc,1,2);
    $mm = substr($tzc,3,2);
    $iTzc = ($hh * 60 + $mm) * 60;
    if ($neg) $iTzc = -1 * (int) $iTzc;
    /* stamp in gmt */
    $stamp -= $iTzc;
    /** now find what the server is at **/
    $current = date('Z', time());
    /* stamp in local timezone */
    $stamp += $current;

    return $stamp;
}

/**
 * Returns the (localized) string for a given day number.
 * Switch system has been intentionaly chosen for the
 * internationalization of month and day names. The reason
 * is to make sure that _("") strings will go into the
 * main po.
 *
 * @param int day_number the day number
 * @return string the day in human readable form
 */
function getDayName( $day_number ) {

    switch( $day_number ) {
    case 0:
        $ret = _("Sunday");
        break;
    case 1:
        $ret = _("Monday");
        break;
    case 2:
        $ret = _("Tuesday");
        break;
    case 3:
        $ret = _("Wednesday");
        break;
    case 4:
        $ret = _("Thursday");
        break;
    case 5:
        $ret = _("Friday");
        break;
    case 6:
        $ret = _("Saturday");
        break;
    default:
        $ret = '';
    }
    return( $ret );
}

/**
 * Like getDayName, but returns the short form
 * @param int day_number the day number
 * @return string the day in short human readable form
 */
function getDayAbrv( $day_number ) {

    switch( $day_number ) {
    case 0:
        $ret = _("Sun");
        break;
    case 1:
        $ret = _("Mon");
        break;
    case 2:
        $ret = _("Tue");
        break;
    case 3:
        $ret = _("Wed");
        break;
    case 4:
        $ret = _("Thu");
        break;
    case 5:
        $ret = _("Fri");
        break;
    case 6:
        $ret = _("Sat");
        break;
    default:
        $ret = '';
    }
    return( $ret );
}


/**
 * Returns the (localized) string for a given month number.
 *
 * @param string month_number the month number (01..12)
 * @return string the month name in human readable form
 */
function getMonthName( $month_number ) {
    switch( $month_number ) {
     case '01':
        $ret = _("January");
        break;
     case '02':
        $ret = _("February");
        break;
     case '03':
        $ret = _("March");
        break;
     case '04':
        $ret = _("April");
        break;
     case '05':
        $ret = _("May");
        break;
     case '06':
        $ret = _("June");
        break;
     case '07':
        $ret = _("July");
        break;
     case '08':
        $ret = _("August");
        break;
     case '09':
        $ret = _("September");
        break;
     case '10':
        $ret = _("October");
        break;
     case '11':
        $ret = _("November");
        break;
     case '12':
        $ret = _("December");
        break;
     default:
        $ret = '';
    }
    return( $ret );
}

/**
 * Returns the (localized) string for a given month number,
 * short representation.
 *
 * @param string month_number the month number (01..12)
 * @return string the shortened month in human readable form
 */
function getMonthAbrv( $month_number ) {
    switch( $month_number ) {
     case '01':
        $ret = _("Jan");
        break;
     case '02':
        $ret = _("Feb");
        break;
     case '03':
        $ret = _("Mar");
        break;
     case '04':
        $ret = _("Apr");
        break;
     case '05':
        $ret = _("Ma&#121;");
        break;
     case '06':
        $ret = _("Jun");
        break;
     case '07':
        $ret = _("Jul");
        break;
     case '08':
        $ret = _("Aug");
        break;
     case '09':
        $ret = _("Sep");
        break;
     case '10':
        $ret = _("Oct");
        break;
     case '11':
        $ret = _("Nov");
        break;
     case '12':
        $ret = _("Dec");
        break;
     default:
        $ret = '';
    }
    return( $ret );
}

/**
 * Returns the localized representation of the date/time.
 *
 * @param string date_format The format for the date, like the input for the PHP date() function.
 * @param int stamp the timestamp to convert
 * @return string a full date representation
 */
function date_intl( $date_format, $stamp ) {
    $ret = str_replace( array('D','F','l','M'), array('$1','$2','$3','$4'), $date_format );
    // to reduce the date calls we retrieve m and w in the same call
    $ret = date('w#m#'. $ret, $stamp );
    // extract day and month in order to replace later by intl day and month
    $aParts = explode('#',$ret);
    $ret = str_replace(array('$1','$4','$2','$3',), array(getDayAbrv($aParts[0]),
                                                          getMonthAbrv($aParts[1]),
                   				          getMonthName($aParts[1]),
						          getDayName($aParts[0])),
						          $aParts[2]);
    return( $ret );
}

/**
 * This returns a date of the format "Wed, Oct 29, 2003 9:52 am",
 * or the same in 24H format (depending on the user's settings),
 * and taking localization into accout.
 *
 * @param int stamp the timestamp
 * @param string fallback string to use when stamp not valid
 * @return string the long date string
 */
function getLongDateString( $stamp, $fallback = '' ) {

    global $hour_format;

    if ($stamp == -1) {
        return $fallback;
    }

    if ( $hour_format == SMPREF_TIME_12HR ) {
        $date_format = _("D, F j, Y g:i a");
    } else {
        $date_format = _("D, F j, Y H:i");
    }

    return( date_intl( $date_format, $stamp ) );

}

/**
 * Returns a short representation of the date,
 * taking timezones and localization into account.
 * Depending on user's settings, this string can be
 * of the form: "14:23" or "Jun 14, 2003" depending
 * on whether the stamp is "today" or not.
 *
 * @param int stamp the timestamp
 * @return string the date string
 */
function getDateString( $stamp ) {

    global $invert_time, $hour_format, $show_full_date;

    if ( $stamp == -1 ) {
       return '';
    }

    $now = time();

    $dateZ = date('Z', $now );

    // FIXME: isn't this obsolete and introduced as a terrible workaround
    // for bugs at other places which are fixed a long time ago?
    if ($invert_time) {
        $dateZ = - $dateZ;
    }

    // calculate when it was midnight and when it will be,
    // in order to display dates differently if they're 'today'
    $midnight = $now - ($now % 86400) - $dateZ;
    // this is to correct if after calculations midnight is more than
    // one whole day away.
    if ($now - $midnight > 86400) {
        $midnight += 86400;
    }
    $nextmid = $midnight + 86400;

    if (($show_full_date == 1) || ($nextmid < $stamp)) {
        $date_format = _("M j, Y");
    } else if ($midnight < $stamp) {
        /* Today */
        if ( $hour_format == SMPREF_TIME_12HR ) {
            $date_format = _("g:i a");
        } else {
            $date_format = _("H:i");
        }
    } else if ($midnight - 518400 < $stamp) {
        /* This week */
        if ( $hour_format == SMPREF_TIME_12HR ) {
            $date_format = _("D, g:i a");
        } else {
            $date_format = _("D, H:i");
        }
    } else {
        /* before this week */
        $date_format = _("M j, Y");
    }

    return( date_intl( $date_format, $stamp ) );
}

/**
 * Decodes a RFC 822 Date-header into a timestamp
 *
 * @param array dateParts the Date-header split by whitespace
 * @return int the timestamp calculated from the header
 */
function getTimeStamp($dateParts) {
    /** $dateParts[0] == <day of week>   Mon, Tue, Wed
    ** $dateParts[1] == <day of month>  23
    ** $dateParts[2] == <month>         Jan, Feb, Mar
    ** $dateParts[3] == <year>          1999
    ** $dateParts[4] == <time>          18:54:23 (HH:MM:SS)
    ** $dateParts[5] == <from GMT>      +0100
    ** $dateParts[6] == <zone>          (EDT)
    **
    ** NOTE:  In RFC 822, it states that <day of week> is optional.
    **        In that case, dateParts[0] would be the <day of month>
    **        and everything would be bumped up one.
    **/
    if (count($dateParts) <2) {
        return -1;
    } else if (count($dateParts) ==3) {
        if (substr_count($dateParts[0],'-') == 2 &&
            substr_count($dateParts[1],':') == 2) {
            //  dd-Month-yyyy 23:19:05 +0200
            //  redefine the date
            $aDate = explode('-',$dateParts[0]);
            $newDate = array($aDate[0],$aDate[1],$aDate[2],$dateParts[1],$dateParts[2]);
            $dateParts = $newDate;
        }
    }

    /*
     * Simply check to see if the first element in the dateParts
     * array is an integer or not.
     * Since the day of week is optional, this check is needed.
     */
    if (!is_numeric(trim($dateParts[0]))) {
        /* cope with broken mailers that send "Tue,23" without space */
        if ( preg_match ('/^\w+,(\d{1,2})$/', $dateParts[0], $match) ) {
            /* replace Tue,23 with 23 */
            $dateParts[0] = $match[1];
        } else {
            /* just drop the day of the week */
            array_shift($dateParts);
        }
    }
    /* calculate timestamp separated from the zone and obs-zone */
    $stamp = strtotime(implode (' ', array_splice ($dateParts,0,4)));
    if (!isset($dateParts[0])) {
        $dateParts[0] = '+0000';
    }

    if (!preg_match('/^[+-]{1}[0-9]{4}$/',$dateParts[0])) {
        /* zone in obs-zone format */
        if (preg_match('/\((.+)\)/',$dateParts[0],$regs)) {
            $obs_zone = $regs[1];
        } else {
            $obs_zone = $dateParts[0];
        }
        return getGMTSeconds($stamp, $obs_zone);
    } else {
        return getGMTSeconds($stamp, $dateParts[0]);
    }
}

/* I use this function for profiling. Should never be called in
   actual versions of squirrelmail released to public. */
/*
   function getmicrotime() {
      $mtime = microtime();
      $mtime = explode(' ',$mtime);
      $mtime = $mtime[1] + $mtime[0];
      return ($mtime);
   }
*/

Added functions/db_prefs.php.































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
<?php

/**
 * db_prefs.php
 *
 * This contains functions for manipulating user preferences
 * stored in a database, accessed though the Pear DB layer.
 *
 * Database:
 *
 * The preferences table should have three columns:
 *    user       char  \  primary
 *    prefkey    char  /  key
 *    prefval    blob
 *
 *   CREATE TABLE userprefs (user CHAR(128) NOT NULL DEFAULT '',
 *                           prefkey CHAR(64) NOT NULL DEFAULT '',
 *                           prefval BLOB NOT NULL DEFAULT '',
 *                           primary key (user,prefkey));
 *
 * Configuration of databasename, username and password is done
 * by using conf.pl or the administrator plugin
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: db_prefs.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage prefs
 * @since 1.1.3
 */

/** Unknown database */
define('SMDB_UNKNOWN', 0);
/** MySQL */
define('SMDB_MYSQL', 1);
/** PostgreSQL */
define('SMDB_PGSQL', 2);

if (!include_once('DB.php')) {
    // same error also in abook_database.php
    require_once(SM_PATH . 'functions/display_messages.php');
    $error  = _("Could not include PEAR database functions required for the database backend.") . "<br />\n";
    $error .= sprintf(_("Is PEAR installed, and is the include path set correctly to find %s?"),
                        '<tt>DB.php</tt>') . "<br />\n";
    $error .= _("Please contact your system administrator and report this error.");
    error_box($error, $color);
    exit;
}

global $prefs_are_cached, $prefs_cache;

/**
 * @ignore
 */
function cachePrefValues($username) {
    global $prefs_are_cached, $prefs_cache;

    sqgetGlobalVar('prefs_are_cached', $prefs_are_cached, SQ_SESSION );
    if ($prefs_are_cached) {
        sqgetGlobalVar('prefs_cache', $prefs_cache, SQ_SESSION );
        return;
    }

    sqsession_unregister('prefs_cache');
    sqsession_unregister('prefs_are_cached');

    $db = new dbPrefs;
    if(isset($db->error)) {
        printf( _("Preference database error (%s). Exiting abnormally"),
              $db->error);
        exit;
    }

    $db->fillPrefsCache($username);
    if (isset($db->error)) {
        printf( _("Preference database error (%s). Exiting abnormally"),
              $db->error);
        exit;
    }

    $prefs_are_cached = true;

    sqsession_register($prefs_cache, 'prefs_cache');
    sqsession_register($prefs_are_cached, 'prefs_are_cached');
}

/**
 * Completely undocumented class - someone document it!
 * @package squirrelmail
 */
class dbPrefs {
    var $table = 'userprefs';
    var $user_field = 'user';
    var $key_field = 'prefkey';
    var $val_field = 'prefval';

    var $dbh   = NULL;
    var $error = NULL;
    var $db_type = SMDB_UNKNOWN;

    var $default = Array('theme_default' => 0,
                         'show_html_default' => '0');

    function open() {
        global $prefs_dsn, $prefs_table;
        global $prefs_user_field, $prefs_key_field, $prefs_val_field;

        if(isset($this->dbh)) {
            return true;
        }

        if (preg_match('/^mysql/', $prefs_dsn)) {
            $this->db_type = SMDB_MYSQL;
        } elseif (preg_match('/^pgsql/', $prefs_dsn)) {
            $this->db_type = SMDB_PGSQL;
        }

        if (!empty($prefs_table)) {
            $this->table = $prefs_table;
        }
        if (!empty($prefs_user_field)) {
            $this->user_field = $prefs_user_field;
        }

        // the default user field is "user", which in PostgreSQL
        // is an identifier and causes errors if not escaped
        //
        if ($this->db_type == SMDB_PGSQL) {
           $this->user_field = '"' . $this->user_field . '"';
        }

        if (!empty($prefs_key_field)) {
            $this->key_field = $prefs_key_field;
        }
        if (!empty($prefs_val_field)) {
            $this->val_field = $prefs_val_field;
        }
        $dbh = DB::connect($prefs_dsn, true);

        if(DB::isError($dbh)) {
            $this->error = DB::errorMessage($dbh);
            return false;
        }

        $this->dbh = $dbh;
        return true;
    }

    function failQuery($res = NULL) {
        if($res == NULL) {
            printf(_("Preference database error (%s). Exiting abnormally"),
                  $this->error);
        } else {
            printf(_("Preference database error (%s). Exiting abnormally"),
                  DB::errorMessage($res));
        }
        exit;
    }


    function getKey($user, $key, $default = '') {
        global $prefs_cache;

        $result = do_hook_function('get_pref_override', array($user, $key));
//FIXME: testing below for !$result means that a plugin cannot fetch its own pref value of 0, '0', '', FALSE, or anything else that evaluates to boolean FALSE.
        if (!$result) {
            cachePrefValues($user);

            if (isset($prefs_cache[$key])) {
                $result = $prefs_cache[$key];
            } else {
//FIXME: is there justification for having these TWO hooks so close together?  who uses these?
                $result = do_hook_function('get_pref', array($user, $key));
//FIXME: testing below for !$result means that a plugin cannot fetch its own pref value of 0, '0', '', FALSE, or anything else that evaluates to boolean FALSE.
                if (!$result) {
                    if (isset($this->default[$key])) {
                        $result = $this->default[$key];
                    } else {
                        $result = $default;
                    }
                }
            }
        }
        return $result;
    }

    function deleteKey($user, $key) {
        global $prefs_cache;

        if (!$this->open()) {
            return false;
        }
        $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
                         $this->table,
                         $this->user_field,
                         $this->dbh->quoteString($user),
                         $this->key_field,
                         $this->dbh->quoteString($key));

        $res = $this->dbh->simpleQuery($query);
        if(DB::isError($res)) {
            $this->failQuery($res);
        }

        unset($prefs_cache[$key]);

        return true;
    }

    function setKey($user, $key, $value) {
        if (!$this->open()) {
            return false;
        }
        if ($this->db_type == SMDB_MYSQL) {
            $query = sprintf("REPLACE INTO %s (%s, %s, %s) ".
                             "VALUES('%s','%s','%s')",
                             $this->table,
                             $this->user_field,
                             $this->key_field,
                             $this->val_field,
                             $this->dbh->quoteString($user),
                             $this->dbh->quoteString($key),
                             $this->dbh->quoteString($value));

            $res = $this->dbh->simpleQuery($query);
            if(DB::isError($res)) {
                $this->failQuery($res);
            }
        } elseif ($this->db_type == SMDB_PGSQL) {
            $this->dbh->simpleQuery("BEGIN TRANSACTION");
            $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
                             $this->table,
                             $this->user_field,
                             $this->dbh->quoteString($user),
                             $this->key_field,
                             $this->dbh->quoteString($key));
            $res = $this->dbh->simpleQuery($query);
            if (DB::isError($res)) {
                $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
                $this->failQuery($res);
            }
            $query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
                             $this->table,
                             $this->user_field,
                             $this->key_field,
                             $this->val_field,
                             $this->dbh->quoteString($user),
                             $this->dbh->quoteString($key),
                             $this->dbh->quoteString($value));
            $res = $this->dbh->simpleQuery($query);
            if (DB::isError($res)) {
                $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
                $this->failQuery($res);
            }
            $this->dbh->simpleQuery("COMMIT TRANSACTION");
        } else {
            $query = sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
                             $this->table,
                             $this->user_field,
                             $this->dbh->quoteString($user),
                             $this->key_field,
                             $this->dbh->quoteString($key));
            $res = $this->dbh->simpleQuery($query);
            if (DB::isError($res)) {
                $this->failQuery($res);
            }
            $query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
                             $this->table,
                             $this->user_field,
                             $this->key_field,
                             $this->val_field,
                             $this->dbh->quoteString($user),
                             $this->dbh->quoteString($key),
                             $this->dbh->quoteString($value));
            $res = $this->dbh->simpleQuery($query);
            if (DB::isError($res)) {
                $this->failQuery($res);
            }
        }

        return true;
    }

    function fillPrefsCache($user) {
        global $prefs_cache;

        if (!$this->open()) {
            return;
        }

        $prefs_cache = array();
        $query = sprintf("SELECT %s as prefkey, %s as prefval FROM %s ".
                         "WHERE %s = '%s'",
                         $this->key_field,
                         $this->val_field,
                         $this->table,
                         $this->user_field,
                         $this->dbh->quoteString($user));
        $res = $this->dbh->query($query);
        if (DB::isError($res)) {
            $this->failQuery($res);
        }

        while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $prefs_cache[$row['prefkey']] = $row['prefval'];
        }
    }

} /* end class dbPrefs */


/**
 * returns the value for the pref $string
 * @ignore
 */
function getPref($data_dir, $username, $string, $default = '') {
    $db = new dbPrefs;
    if(isset($db->error)) {
        printf( _("Preference database error (%s). Exiting abnormally"),
              $db->error);
        exit;
    }

    return $db->getKey($username, $string, $default);
}

/**
 * Remove the pref $string
 * @ignore
 */
function removePref($data_dir, $username, $string) {
    global $prefs_cache;
    $db = new dbPrefs;
    if(isset($db->error)) {
        $db->failQuery();
    }

    $db->deleteKey($username, $string);

    if (isset($prefs_cache[$string])) {
        unset($prefs_cache[$string]);
    }

    sqsession_register($prefs_cache , 'prefs_cache');
    return;
}

/**
 * sets the pref, $string, to $set_to
 * @ignore
 */
function setPref($data_dir, $username, $string, $set_to) {
    global $prefs_cache;

    if (isset($prefs_cache[$string]) && ($prefs_cache[$string] == $set_to)) {
        return;
    }

    if ($set_to === '') {
        removePref($data_dir, $username, $string);
        return;
    }

    $db = new dbPrefs;
    if(isset($db->error)) {
        $db->failQuery();
    }

    $db->setKey($username, $string, $set_to);
    $prefs_cache[$string] = $set_to;
    assert_options(ASSERT_ACTIVE, 1);
    assert_options(ASSERT_BAIL, 1);
    assert ('$set_to == $prefs_cache[$string]');
    sqsession_register($prefs_cache , 'prefs_cache');
    return;
}

/**
 * This checks if the prefs are available
 * @ignore
 */
function checkForPrefs($data_dir, $username) {
    $db = new dbPrefs;
    if(isset($db->error)) {
        $db->failQuery();
    }
}

/**
 * Writes the Signature
 * @ignore
 */
function setSig($data_dir, $username, $number, $string) {
    if ($number == "g") {
        $key = '___signature___';
    } else {
        $key = sprintf('___sig%s___', $number);
    }
    setPref($data_dir, $username, $key, $string);
    return;
}

/**
 * Gets the signature
 * @ignore
 */
function getSig($data_dir, $username, $number) {
    if ($number == "g") {
        $key = '___signature___';
    } else {
        $key = sprintf('___sig%d___', $number);
    }
    return getPref($data_dir, $username, $key);
}

Added functions/decode/cp1250.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1250.php
 *
 * This file contains cp1250 decoding function that is needed to read
 * cp1250 encoded mails in non-cp1250 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT
 *
 *  Name:     cp1250 to Unicode table
 *  Unicode version: 2.0
 *  Table version: 2.01
 *  Table format:  Format A
 *  Date:          04/15/98
 *  Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1250.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode a cp1250 string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1250 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1250'))
        return $string;

    $cp1250 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#65533;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#65533;',
        "\x89" => '&#8240;',
        "\x8A" => '&#352;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#346;',
        "\x8D" => '&#356;',
        "\x8E" => '&#381;',
        "\x8F" => '&#377;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#65533;',
        "\x99" => '&#8482;',
        "\x9A" => '&#353;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#347;',
        "\x9D" => '&#357;',
        "\x9E" => '&#382;',
        "\x9F" => '&#378;',
        "\xA0" => '&#160;',
        "\xA1" => '&#711;',
        "\xA2" => '&#728;',
        "\xA3" => '&#321;',
        "\xA4" => '&#164;',
        "\xA5" => '&#260;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#350;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#379;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#731;',
        "\xB3" => '&#322;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#261;',
        "\xBA" => '&#351;',
        "\xBB" => '&#187;',
        "\xBC" => '&#317;',
        "\xBD" => '&#733;',
        "\xBE" => '&#318;',
        "\xBF" => '&#380;',
        "\xC0" => '&#340;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#258;',
        "\xC4" => '&#196;',
        "\xC5" => '&#313;',
        "\xC6" => '&#262;',
        "\xC7" => '&#199;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#280;',
        "\xCB" => '&#203;',
        "\xCC" => '&#282;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#270;',
        "\xD0" => '&#272;',
        "\xD1" => '&#323;',
        "\xD2" => '&#327;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#336;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#344;',
        "\xD9" => '&#366;',
        "\xDA" => '&#218;',
        "\xDB" => '&#368;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#354;',
        "\xDF" => '&#223;',
        "\xE0" => '&#341;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#259;',
        "\xE4" => '&#228;',
        "\xE5" => '&#314;',
        "\xE6" => '&#263;',
        "\xE7" => '&#231;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#281;',
        "\xEB" => '&#235;',
        "\xEC" => '&#283;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#271;',
        "\xF0" => '&#273;',
        "\xF1" => '&#324;',
        "\xF2" => '&#328;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#337;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#345;',
        "\xF9" => '&#367;',
        "\xFA" => '&#250;',
        "\xFB" => '&#369;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#355;',
        "\xFF" => '&#729;'
    );

    $string = str_replace(array_keys($cp1250), array_values($cp1250), $string);

    return $string;
}

Added functions/decode/cp1251.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1251.php
 *
 * This file contains cp1251 decoding function that is needed to read
 * cp1251 encoded mails in non-cp1251 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT
 *
 *   Name:     cp1251 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          04/15/98
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1251.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1251-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1251 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1251'))
        return $string;

    $cp1251 = array(
        "\x80" => '&#1026;',
        "\x81" => '&#1027;',
        "\x82" => '&#8218;',
        "\x83" => '&#1107;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#8364;',
        "\x89" => '&#8240;',
        "\x8A" => '&#1033;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#1034;',
        "\x8D" => '&#1036;',
        "\x8E" => '&#1035;',
        "\x8F" => '&#1039;',
        "\x90" => '&#1106;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#65533;',
        "\x99" => '&#8482;',
        "\x9A" => '&#1113;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#1114;',
        "\x9D" => '&#1116;',
        "\x9E" => '&#1115;',
        "\x9F" => '&#1119;',
        "\xA0" => '&#160;',
        "\xA1" => '&#1038;',
        "\xA2" => '&#1118;',
        "\xA3" => '&#1032;',
        "\xA4" => '&#164;',
        "\xA5" => '&#1168;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#1025;',
        "\xA9" => '&#169;',
        "\xAA" => '&#1028;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#1031;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#1030;',
        "\xB3" => '&#1110;',
        "\xB4" => '&#1169;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#1105;',
        "\xB9" => '&#8470;',
        "\xBA" => '&#1108;',
        "\xBB" => '&#187;',
        "\xBC" => '&#1112;',
        "\xBD" => '&#1029;',
        "\xBE" => '&#1109;',
        "\xBF" => '&#1111;',
        "\xC0" => '&#1040;',
        "\xC1" => '&#1041;',
        "\xC2" => '&#1042;',
        "\xC3" => '&#1043;',
        "\xC4" => '&#1044;',
        "\xC5" => '&#1045;',
        "\xC6" => '&#1046;',
        "\xC7" => '&#1047;',
        "\xC8" => '&#1048;',
        "\xC9" => '&#1049;',
        "\xCA" => '&#1050;',
        "\xCB" => '&#1051;',
        "\xCC" => '&#1052;',
        "\xCD" => '&#1053;',
        "\xCE" => '&#1054;',
        "\xCF" => '&#1055;',
        "\xD0" => '&#1056;',
        "\xD1" => '&#1057;',
        "\xD2" => '&#1058;',
        "\xD3" => '&#1059;',
        "\xD4" => '&#1060;',
        "\xD5" => '&#1061;',
        "\xD6" => '&#1062;',
        "\xD7" => '&#1063;',
        "\xD8" => '&#1064;',
        "\xD9" => '&#1065;',
        "\xDA" => '&#1066;',
        "\xDB" => '&#1067;',
        "\xDC" => '&#1068;',
        "\xDD" => '&#1069;',
        "\xDE" => '&#1070;',
        "\xDF" => '&#1071;',
        "\xE0" => '&#1072;',
        "\xE1" => '&#1073;',
        "\xE2" => '&#1074;',
        "\xE3" => '&#1075;',
        "\xE4" => '&#1076;',
        "\xE5" => '&#1077;',
        "\xE6" => '&#1078;',
        "\xE7" => '&#1079;',
        "\xE8" => '&#1080;',
        "\xE9" => '&#1081;',
        "\xEA" => '&#1082;',
        "\xEB" => '&#1083;',
        "\xEC" => '&#1084;',
        "\xED" => '&#1085;',
        "\xEE" => '&#1086;',
        "\xEF" => '&#1087;',
        "\xF0" => '&#1088;',
        "\xF1" => '&#1089;',
        "\xF2" => '&#1090;',
        "\xF3" => '&#1091;',
        "\xF4" => '&#1092;',
        "\xF5" => '&#1093;',
        "\xF6" => '&#1094;',
        "\xF7" => '&#1095;',
        "\xF8" => '&#1096;',
        "\xF9" => '&#1097;',
        "\xFA" => '&#1098;',
        "\xFB" => '&#1099;',
        "\xFC" => '&#1100;',
        "\xFD" => '&#1101;',
        "\xFE" => '&#1102;',
        "\xFF" => '&#1103;'
    );

    $string = str_replace(array_keys($cp1251), array_values($cp1251), $string);

    return $string;
}

Added functions/decode/cp1252.php.

























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?php

/**
 * decode/cp1252.php
 *
 * This file contains cp1252 decoding function that is needed to read
 * cp1252 encoded mails in non-cp1252 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
 *
 *   Name:     cp1252 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          04/15/98
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1252.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1252-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */

function charset_decode_cp1252 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1252'))
        return $string;

    $cp1252 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#710;',
        "\x89" => '&#8240;',
        "\x8A" => '&#352;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#338;',
        "\x8D" => '&#65533;',
        "\x8E" => '&#381;',
        "\x8F" => '&#65533;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#732;',
        "\x99" => '&#8482;',
        "\x9A" => '&#353;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#339;',
        "\x9D" => '&#65533;',
        "\x9E" => '&#382;',
        "\x9F" => '&#376;',
        "\xA0" => '&#160;',
        "\xA1" => '&#161;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#170;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#186;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#191;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#208;',
        "\xD1" => '&#209;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#216;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#222;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#240;',
        "\xF1" => '&#241;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#248;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#254;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($cp1252), array_values($cp1252), $string);

    return $string;
}

Added functions/decode/cp1253.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1253.php
 *
 * This file contains cp1253 decoding function that is needed to read
 * cp1253 encoded mails in non-cp1253 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT
 *
 *   Name:     cp1253 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          04/15/98
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1253.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1253-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1253 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1253'))
        return $string;

    $cp1253 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#65533;',
        "\x89" => '&#8240;',
        "\x8A" => '&#65533;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#65533;',
        "\x8D" => '&#65533;',
        "\x8E" => '&#65533;',
        "\x8F" => '&#65533;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#65533;',
        "\x99" => '&#8482;',
        "\x9A" => '&#65533;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#65533;',
        "\x9D" => '&#65533;',
        "\x9E" => '&#65533;',
        "\x9F" => '&#65533;',
        "\xA0" => '&#160;',
        "\xA1" => '&#901;',
        "\xA2" => '&#902;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#65533;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#8213;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#900;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#904;',
        "\xB9" => '&#905;',
        "\xBA" => '&#906;',
        "\xBB" => '&#187;',
        "\xBC" => '&#908;',
        "\xBD" => '&#189;',
        "\xBE" => '&#910;',
        "\xBF" => '&#911;',
        "\xC0" => '&#912;',
        "\xC1" => '&#913;',
        "\xC2" => '&#914;',
        "\xC3" => '&#915;',
        "\xC4" => '&#916;',
        "\xC5" => '&#917;',
        "\xC6" => '&#918;',
        "\xC7" => '&#919;',
        "\xC8" => '&#920;',
        "\xC9" => '&#921;',
        "\xCA" => '&#922;',
        "\xCB" => '&#923;',
        "\xCC" => '&#924;',
        "\xCD" => '&#925;',
        "\xCE" => '&#926;',
        "\xCF" => '&#927;',
        "\xD0" => '&#928;',
        "\xD1" => '&#929;',
        "\xD2" => '&#65533;',
        "\xD3" => '&#931;',
        "\xD4" => '&#932;',
        "\xD5" => '&#933;',
        "\xD6" => '&#934;',
        "\xD7" => '&#935;',
        "\xD8" => '&#936;',
        "\xD9" => '&#937;',
        "\xDA" => '&#938;',
        "\xDB" => '&#939;',
        "\xDC" => '&#940;',
        "\xDD" => '&#941;',
        "\xDE" => '&#942;',
        "\xDF" => '&#943;',
        "\xE0" => '&#944;',
        "\xE1" => '&#945;',
        "\xE2" => '&#946;',
        "\xE3" => '&#947;',
        "\xE4" => '&#948;',
        "\xE5" => '&#949;',
        "\xE6" => '&#950;',
        "\xE7" => '&#951;',
        "\xE8" => '&#952;',
        "\xE9" => '&#953;',
        "\xEA" => '&#954;',
        "\xEB" => '&#955;',
        "\xEC" => '&#956;',
        "\xED" => '&#957;',
        "\xEE" => '&#958;',
        "\xEF" => '&#959;',
        "\xF0" => '&#960;',
        "\xF1" => '&#961;',
        "\xF2" => '&#962;',
        "\xF3" => '&#963;',
        "\xF4" => '&#964;',
        "\xF5" => '&#965;',
        "\xF6" => '&#966;',
        "\xF7" => '&#967;',
        "\xF8" => '&#968;',
        "\xF9" => '&#969;',
        "\xFA" => '&#970;',
        "\xFB" => '&#971;',
        "\xFC" => '&#972;',
        "\xFD" => '&#973;',
        "\xFE" => '&#974;',
        "\xFF" => '&#65533;'
    );

    $string = str_replace(array_keys($cp1253), array_values($cp1253), $string);

    return $string;
}

Added functions/decode/cp1254.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1254.php
 *
 * This file contains cp1254 decoding function that is needed to read
 * cp1254 encoded mails in non-cp1254 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT
 *
 *   Name:     cp1254 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          04/15/98
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1254.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1254-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1254 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1254'))
        return $string;

    $cp1254 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#710;',
        "\x89" => '&#8240;',
        "\x8A" => '&#352;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#338;',
        "\x8D" => '&#65533;',
        "\x8E" => '&#65533;',
        "\x8F" => '&#65533;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#732;',
        "\x99" => '&#8482;',
        "\x9A" => '&#353;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#339;',
        "\x9D" => '&#65533;',
        "\x9E" => '&#65533;',
        "\x9F" => '&#376;',
        "\xA0" => '&#160;',
        "\xA1" => '&#161;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#170;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#186;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#191;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#286;',
        "\xD1" => '&#209;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#216;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#304;',
        "\xDE" => '&#350;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#287;',
        "\xF1" => '&#241;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#248;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#305;',
        "\xFE" => '&#351;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($cp1254), array_values($cp1254), $string);

    return $string;
}

Added functions/decode/cp1255.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1255.php
 *
 * This file contains cp1255 decoding function that is needed to read
 * cp1255 encoded mails in non-cp1255 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT
 *
 *   Name:     cp1255 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          1/7/2000
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1255.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1255-encoded string
 * @param string $string Encoded string
 * @return string $string decoded string
 */
function charset_decode_cp1255 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1255'))
        return $string;

    $cp1255 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#710;',
        "\x89" => '&#8240;',
        "\x8A" => '&#65533;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#65533;',
        "\x8D" => '&#65533;',
        "\x8E" => '&#65533;',
        "\x8F" => '&#65533;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#732;',
        "\x99" => '&#8482;',
        "\x9A" => '&#65533;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#65533;',
        "\x9D" => '&#65533;',
        "\x9E" => '&#65533;',
        "\x9F" => '&#65533;',
        "\xA0" => '&#160;',
        "\xA1" => '&#161;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#8362;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#215;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#247;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#191;',
        "\xC0" => '&#1456;',
        "\xC1" => '&#1457;',
        "\xC2" => '&#1458;',
        "\xC3" => '&#1459;',
        "\xC4" => '&#1460;',
        "\xC5" => '&#1461;',
        "\xC6" => '&#1462;',
        "\xC7" => '&#1463;',
        "\xC8" => '&#1464;',
        "\xC9" => '&#1465;',
        "\xCA" => '&#65533;',
        "\xCB" => '&#1467;',
        "\xCC" => '&#1468;',
        "\xCD" => '&#1469;',
        "\xCE" => '&#1470;',
        "\xCF" => '&#1471;',
        "\xD0" => '&#1472;',
        "\xD1" => '&#1473;',
        "\xD2" => '&#1474;',
        "\xD3" => '&#1475;',
        "\xD4" => '&#1520;',
        "\xD5" => '&#1521;',
        "\xD6" => '&#1522;',
        "\xD7" => '&#1523;',
        "\xD8" => '&#1524;',
        "\xD9" => '&#65533;',
        "\xDA" => '&#65533;',
        "\xDB" => '&#65533;',
        "\xDC" => '&#65533;',
        "\xDD" => '&#65533;',
        "\xDE" => '&#65533;',
        "\xDF" => '&#65533;',
        "\xE0" => '&#1488;',
        "\xE1" => '&#1489;',
        "\xE2" => '&#1490;',
        "\xE3" => '&#1491;',
        "\xE4" => '&#1492;',
        "\xE5" => '&#1493;',
        "\xE6" => '&#1494;',
        "\xE7" => '&#1495;',
        "\xE8" => '&#1496;',
        "\xE9" => '&#1497;',
        "\xEA" => '&#1498;',
        "\xEB" => '&#1499;',
        "\xEC" => '&#1500;',
        "\xED" => '&#1501;',
        "\xEE" => '&#1502;',
        "\xEF" => '&#1503;',
        "\xF0" => '&#1504;',
        "\xF1" => '&#1505;',
        "\xF2" => '&#1506;',
        "\xF3" => '&#1507;',
        "\xF4" => '&#1508;',
        "\xF5" => '&#1509;',
        "\xF6" => '&#1510;',
        "\xF7" => '&#1511;',
        "\xF8" => '&#1512;',
        "\xF9" => '&#1513;',
        "\xFA" => '&#1514;',
        "\xFB" => '&#65533;',
        "\xFC" => '&#65533;',
        "\xFD" => '&#8206;',
        "\xFE" => '&#8207;',
        "\xFF" => '&#65533;'
    );

    $string = str_replace(array_keys($cp1255), array_values($cp1255), $string);

    return $string;
}

Added functions/decode/cp1256.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1256.php
 *
 * This file contains cp1256 decoding function that is needed to read
 * cp1256 encoded mails in non-cp1256 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT
 *
 *   Name:     cp1256 to Unicode table
 *   Unicode version: 2.1
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          01/5/99
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1256.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * decode cp1256-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1256 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1256'))
        return $string;

    $cp1256 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#1662;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#710;',
        "\x89" => '&#8240;',
        "\x8A" => '&#1657;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#338;',
        "\x8D" => '&#1670;',
        "\x8E" => '&#1688;',
        "\x8F" => '&#1672;',
        "\x90" => '&#1711;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#1705;',
        "\x99" => '&#8482;',
        "\x9A" => '&#1681;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#339;',
        "\x9D" => '&#8204;',
        "\x9E" => '&#8205;',
        "\x9F" => '&#1722;',
        "\xA0" => '&#160;',
        "\xA1" => '&#1548;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#1726;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#1563;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#1567;',
        "\xC0" => '&#1729;',
        "\xC1" => '&#1569;',
        "\xC2" => '&#1570;',
        "\xC3" => '&#1571;',
        "\xC4" => '&#1572;',
        "\xC5" => '&#1573;',
        "\xC6" => '&#1574;',
        "\xC7" => '&#1575;',
        "\xC8" => '&#1576;',
        "\xC9" => '&#1577;',
        "\xCA" => '&#1578;',
        "\xCB" => '&#1579;',
        "\xCC" => '&#1580;',
        "\xCD" => '&#1581;',
        "\xCE" => '&#1582;',
        "\xCF" => '&#1583;',
        "\xD0" => '&#1584;',
        "\xD1" => '&#1585;',
        "\xD2" => '&#1586;',
        "\xD3" => '&#1587;',
        "\xD4" => '&#1588;',
        "\xD5" => '&#1589;',
        "\xD6" => '&#1590;',
        "\xD7" => '&#215;',
        "\xD8" => '&#1591;',
        "\xD9" => '&#1592;',
        "\xDA" => '&#1593;',
        "\xDB" => '&#1594;',
        "\xDC" => '&#1600;',
        "\xDD" => '&#1601;',
        "\xDE" => '&#1602;',
        "\xDF" => '&#1603;',
        "\xE0" => '&#224;',
        "\xE1" => '&#1604;',
        "\xE2" => '&#226;',
        "\xE3" => '&#1605;',
        "\xE4" => '&#1606;',
        "\xE5" => '&#1607;',
        "\xE6" => '&#1608;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#1609;',
        "\xED" => '&#1610;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#1611;',
        "\xF1" => '&#1612;',
        "\xF2" => '&#1613;',
        "\xF3" => '&#1614;',
        "\xF4" => '&#244;',
        "\xF5" => '&#1615;',
        "\xF6" => '&#1616;',
        "\xF7" => '&#247;',
        "\xF8" => '&#1617;',
        "\xF9" => '&#249;',
        "\xFA" => '&#1618;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#8206;',
        "\xFE" => '&#8207;',
        "\xFF" => '&#1746;'
    );

    $string = str_replace(array_keys($cp1256), array_values($cp1256), $string);

    return $string;
}

Added functions/decode/cp1257.php.































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php

/**
 * decode/cp1257.php
 *
 * This file contains cp1257 decoding function that is needed to read
 * cp1257 encoded mails in non-cp1257 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT
 *
 *  Name:     cp1257 to Unicode table
 *  Unicode version: 2.0
 *  Table version: 2.01
 *  Table format:  Format A
 *  Date:          04/15/98
 *  Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1257.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode cp1257-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1257 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1257'))
        return $string;

    $cp1257 = array(
        "\x80" => '&#8364;',
        "\x82" => '&#8218;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x89" => '&#8240;',
        "\x8B" => '&#8249;',
        "\x8D" => '&#168;',
        "\x8E" => '&#711;',
        "\x8F" => '&#184;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x99" => '&#8482;',
        "\x9B" => '&#8250;',
        "\x9D" => '&#175;',
        "\x9E" => '&#731;',
        "\xA0" => '&#160;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#216;',
        "\xA9" => '&#169;',
        "\xAA" => '&#342;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#198;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#248;',
        "\xB9" => '&#185;',
        "\xBA" => '&#343;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#230;',
        "\xC0" => '&#260;',
        "\xC1" => '&#302;',
        "\xC2" => '&#256;',
        "\xC3" => '&#262;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#280;',
        "\xC7" => '&#274;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#377;',
        "\xCB" => '&#278;',
        "\xCC" => '&#290;',
        "\xCD" => '&#310;',
        "\xCE" => '&#298;',
        "\xCF" => '&#315;',
        "\xD0" => '&#352;',
        "\xD1" => '&#323;',
        "\xD2" => '&#325;',
        "\xD3" => '&#211;',
        "\xD4" => '&#332;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#370;',
        "\xD9" => '&#321;',
        "\xDA" => '&#346;',
        "\xDB" => '&#362;',
        "\xDC" => '&#220;',
        "\xDD" => '&#379;',
        "\xDE" => '&#381;',
        "\xDF" => '&#223;',
        "\xE0" => '&#261;',
        "\xE1" => '&#303;',
        "\xE2" => '&#257;',
        "\xE3" => '&#263;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#281;',
        "\xE7" => '&#275;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#378;',
        "\xEB" => '&#279;',
        "\xEC" => '&#291;',
        "\xED" => '&#311;',
        "\xEE" => '&#299;',
        "\xEF" => '&#316;',
        "\xF0" => '&#353;',
        "\xF1" => '&#324;',
        "\xF2" => '&#326;',
        "\xF3" => '&#243;',
        "\xF4" => '&#333;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#371;',
        "\xF9" => '&#322;',
        "\xFA" => '&#347;',
        "\xFB" => '&#363;',
        "\xFC" => '&#252;',
        "\xFD" => '&#380;',
        "\xFE" => '&#382;',
        "\xFF" => '&#729;'
    );

    $string = str_replace(array_keys($cp1257), array_values($cp1257), $string);

    return $string;
}

Added functions/decode/cp1258.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp1258.php
 *
 * This file contains cp1258 decoding function that is needed to read
 * cp1258 encoded mails in non-cp1258 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT
 *
 *   Name:     cp1258 to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.01
 *   Table format:  Format A
 *   Date:          04/15/98
 *   Contact:       cpxlate@microsoft.com
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1258.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decde a cp1258-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp1258 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'windows-1258'))
        return $string;

    $cp1258 = array(
        "\x80" => '&#8364;',
        "\x81" => '&#65533;',
        "\x82" => '&#8218;',
        "\x83" => '&#402;',
        "\x84" => '&#8222;',
        "\x85" => '&#8230;',
        "\x86" => '&#8224;',
        "\x87" => '&#8225;',
        "\x88" => '&#710;',
        "\x89" => '&#8240;',
        "\x8A" => '&#65533;',
        "\x8B" => '&#8249;',
        "\x8C" => '&#338;',
        "\x8D" => '&#65533;',
        "\x8E" => '&#65533;',
        "\x8F" => '&#65533;',
        "\x90" => '&#65533;',
        "\x91" => '&#8216;',
        "\x92" => '&#8217;',
        "\x93" => '&#8220;',
        "\x94" => '&#8221;',
        "\x95" => '&#8226;',
        "\x96" => '&#8211;',
        "\x97" => '&#8212;',
        "\x98" => '&#732;',
        "\x99" => '&#8482;',
        "\x9A" => '&#65533;',
        "\x9B" => '&#8250;',
        "\x9C" => '&#339;',
        "\x9D" => '&#65533;',
        "\x9E" => '&#65533;',
        "\x9F" => '&#376;',
        "\xA0" => '&#160;',
        "\xA1" => '&#161;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#170;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#186;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#191;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#258;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#768;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#272;',
        "\xD1" => '&#209;',
        "\xD2" => '&#777;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#416;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#216;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#431;',
        "\xDE" => '&#771;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#259;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#769;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#273;',
        "\xF1" => '&#241;',
        "\xF2" => '&#803;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#417;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#248;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#432;',
        "\xFE" => '&#8363;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($cp1258), array_values($cp1258), $string);

    return $string;
}

Added functions/decode/cp855.php.























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

/**
 * decode/cp855.php
 *
 * This file contains cp855 decoding function that is needed to read
 * cp855 encoded mails in non-cp855 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP855.TXT
 *   Name:     cp855_DOSCyrillic to Unicode table
 *   Unicode version: 2.0
 *   Table version: 2.00
 *   Table format:  Format A
 *   Date:          04/24/96
 *   Authors:       Lori Brownell <loribr@microsoft.com>
 *                  K.D. Chang    <a-kchang@microsoft.com>
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp855.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode a cp855-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp855 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'ibm855'))
        return $string;

    $cp855 = array(
        "\x80" => '&#1106;',
        "\x81" => '&#1026;',
        "\x82" => '&#1107;',
        "\x83" => '&#1027;',
        "\x84" => '&#1105;',
        "\x85" => '&#1025;',
        "\x86" => '&#1108;',
        "\x87" => '&#1028;',
        "\x88" => '&#1109;',
        "\x89" => '&#1029;',
        "\x8a" => '&#1110;',
        "\x8b" => '&#1030;',
        "\x8c" => '&#1111;',
        "\x8d" => '&#1031;',
        "\x8e" => '&#1112;',
        "\x8f" => '&#1032;',
        "\x90" => '&#1113;',
        "\x91" => '&#1033;',
        "\x92" => '&#1114;',
        "\x93" => '&#1034;',
        "\x94" => '&#1115;',
        "\x95" => '&#1035;',
        "\x96" => '&#1116;',
        "\x97" => '&#1036;',
        "\x98" => '&#1118;',
        "\x99" => '&#1038;',
        "\x9a" => '&#1119;',
        "\x9b" => '&#1039;',
        "\x9c" => '&#1102;',
        "\x9d" => '&#1070;',
        "\x9e" => '&#1098;',
        "\x9f" => '&#1066;',
        "\xa0" => '&#1072;',
        "\xa1" => '&#1040;',
        "\xa2" => '&#1073;',
        "\xa3" => '&#1041;',
        "\xa4" => '&#1094;',
        "\xa5" => '&#1062;',
        "\xa6" => '&#1076;',
        "\xa7" => '&#1044;',
        "\xa8" => '&#1077;',
        "\xa9" => '&#1045;',
        "\xaa" => '&#1092;',
        "\xab" => '&#1060;',
        "\xac" => '&#1075;',
        "\xad" => '&#1043;',
        "\xae" => '&#171;',
        "\xaf" => '&#187;',
        "\xb0" => '&#9617;',
        "\xb1" => '&#9618;',
        "\xb2" => '&#9619;',
        "\xb3" => '&#9474;',
        "\xb4" => '&#9508;',
        "\xb5" => '&#1093;',
        "\xb6" => '&#1061;',
        "\xb7" => '&#1080;',
        "\xb8" => '&#1048;',
        "\xb9" => '&#9571;',
        "\xba" => '&#9553;',
        "\xbb" => '&#9559;',
        "\xbc" => '&#9565;',
        "\xbd" => '&#1081;',
        "\xbe" => '&#1049;',
        "\xbf" => '&#9488;',
        "\xc0" => '&#9492;',
        "\xc1" => '&#9524;',
        "\xc2" => '&#9516;',
        "\xc3" => '&#9500;',
        "\xc4" => '&#9472;',
        "\xc5" => '&#9532;',
        "\xc6" => '&#1082;',
        "\xc7" => '&#1050;',
        "\xc8" => '&#9562;',
        "\xc9" => '&#9556;',
        "\xca" => '&#9577;',
        "\xcb" => '&#9574;',
        "\xcc" => '&#9568;',
        "\xcd" => '&#9552;',
        "\xce" => '&#9580;',
        "\xcf" => '&#164;',
        "\xd0" => '&#1083;',
        "\xd1" => '&#1051;',
        "\xd2" => '&#1084;',
        "\xd3" => '&#1052;',
        "\xd4" => '&#1085;',
        "\xd5" => '&#1053;',
        "\xd6" => '&#1086;',
        "\xd7" => '&#1054;',
        "\xd8" => '&#1087;',
        "\xd9" => '&#9496;',
        "\xda" => '&#9484;',
        "\xdb" => '&#9608;',
        "\xdc" => '&#9604;',
        "\xdd" => '&#1055;',
        "\xde" => '&#1103;',
        "\xdf" => '&#9600;',
        "\xe0" => '&#1071;',
        "\xe1" => '&#1088;',
        "\xe2" => '&#1056;',
        "\xe3" => '&#1089;',
        "\xe4" => '&#1057;',
        "\xe5" => '&#1090;',
        "\xe6" => '&#1058;',
        "\xe7" => '&#1091;',
        "\xe8" => '&#1059;',
        "\xe9" => '&#1078;',
        "\xea" => '&#1046;',
        "\xeb" => '&#1074;',
        "\xec" => '&#1042;',
        "\xed" => '&#1100;',
        "\xee" => '&#1068;',
        "\xef" => '&#8470;',
        "\xf0" => '&#173;',
        "\xf1" => '&#1099;',
        "\xf2" => '&#1067;',
        "\xf3" => '&#1079;',
        "\xf4" => '&#1047;',
        "\xf5" => '&#1096;',
        "\xf6" => '&#1064;',
        "\xf7" => '&#1101;',
        "\xf8" => '&#1069;',
        "\xf9" => '&#1097;',
        "\xfa" => '&#1065;',
        "\xfb" => '&#1095;',
        "\xfc" => '&#1063;',
        "\xfd" => '&#167;',
        "\xfe" => '&#9632;',
        "\xff" => '&#160;'
    );

    $string = str_replace(array_keys($cp855), array_values($cp855), $string);

    return $string;
}

Added functions/decode/cp866.php.

























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?php

/**
 * decode/cp866.php
 *
 * This file contains cp866 decoding function that is needed to read
 * cp866 encoded mails in non-cp866 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/

    Name:     cp866_DOSCyrillicRussian to Unicode table
    Unicode version: 2.0
    Table version: 2.00
    Table format:  Format A
    Date:          04/24/96
    Authors:       Lori Brownell <loribr@microsoft.com>
                   K.D. Chang    <a-kchang@microsoft.com>
    The entries are in cp866_DOSCyrillicRussian order
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp866.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
*/

/**
 * Decode a cp866-encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_cp866 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'ibm866'))
        return $string;

    $cp866 = array(
        "\x80" => '&#1040;',
        "\x81" => '&#1041;',
        "\x82" => '&#1042;',
        "\x83" => '&#1043;',
        "\x84" => '&#1044;',
        "\x85" => '&#1045;',
        "\x86" => '&#1046;',
        "\x87" => '&#1047;',
        "\x88" => '&#1048;',
        "\x89" => '&#1049;',
        "\x8a" => '&#1050;',
        "\x8b" => '&#1051;',
        "\x8c" => '&#1052;',
        "\x8d" => '&#1053;',
        "\x8e" => '&#1054;',
        "\x8f" => '&#1055;',
        "\x90" => '&#1056;',
        "\x91" => '&#1057;',
        "\x92" => '&#1058;',
        "\x93" => '&#1059;',
        "\x94" => '&#1060;',
        "\x95" => '&#1061;',
        "\x96" => '&#1062;',
        "\x97" => '&#1063;',
        "\x98" => '&#1064;',
        "\x99" => '&#1065;',
        "\x9a" => '&#1066;',
        "\x9b" => '&#1067;',
        "\x9c" => '&#1068;',
        "\x9d" => '&#1069;',
        "\x9e" => '&#1070;',
        "\x9f" => '&#1071;',
        "\xa0" => '&#1072;',
        "\xa1" => '&#1073;',
        "\xa2" => '&#1074;',
        "\xa3" => '&#1075;',
        "\xa4" => '&#1076;',
        "\xa5" => '&#1077;',
        "\xa6" => '&#1078;',
        "\xa7" => '&#1079;',
        "\xa8" => '&#1080;',
        "\xa9" => '&#1081;',
        "\xaa" => '&#1082;',
        "\xab" => '&#1083;',
        "\xac" => '&#1084;',
        "\xad" => '&#1085;',
        "\xae" => '&#1086;',
        "\xaf" => '&#1087;',
        "\xb0" => '&#9617;',
        "\xb1" => '&#9618;',
        "\xb2" => '&#9619;',
        "\xb3" => '&#9474;',
        "\xb4" => '&#9508;',
        "\xb5" => '&#9569;',
        "\xb6" => '&#9570;',
        "\xb7" => '&#9558;',
        "\xb8" => '&#9557;',
        "\xb9" => '&#9571;',
        "\xba" => '&#9553;',
        "\xbb" => '&#9559;',
        "\xbc" => '&#9565;',
        "\xbd" => '&#9564;',
        "\xbe" => '&#9563;',
        "\xbf" => '&#9488;',
        "\xc0" => '&#9492;',
        "\xc1" => '&#9524;',
        "\xc2" => '&#9516;',
        "\xc3" => '&#9500;',
        "\xc4" => '&#9472;',
        "\xc5" => '&#9532;',
        "\xc6" => '&#9566;',
        "\xc7" => '&#9567;',
        "\xc8" => '&#9562;',
        "\xc9" => '&#9556;',
        "\xca" => '&#9577;',
        "\xcb" => '&#9574;',
        "\xcc" => '&#9568;',
        "\xcd" => '&#9552;',
        "\xce" => '&#9580;',
        "\xcf" => '&#9575;',
        "\xd0" => '&#9576;',
        "\xd1" => '&#9572;',
        "\xd2" => '&#9573;',
        "\xd3" => '&#9561;',
        "\xd4" => '&#9560;',
        "\xd5" => '&#9554;',
        "\xd6" => '&#9555;',
        "\xd7" => '&#9579;',
        "\xd8" => '&#9578;',
        "\xd9" => '&#9496;',
        "\xda" => '&#9484;',
        "\xdb" => '&#9608;',
        "\xdc" => '&#9604;',
        "\xdd" => '&#9612;',
        "\xde" => '&#9616;',
        "\xdf" => '&#9600;',
        "\xe0" => '&#1088;',
        "\xe1" => '&#1089;',
        "\xe2" => '&#1090;',
        "\xe3" => '&#1091;',
        "\xe4" => '&#1092;',
        "\xe5" => '&#1093;',
        "\xe6" => '&#1094;',
        "\xe7" => '&#1095;',
        "\xe8" => '&#1096;',
        "\xe9" => '&#1097;',
        "\xea" => '&#1098;',
        "\xeb" => '&#1099;',
        "\xec" => '&#1100;',
        "\xed" => '&#1101;',
        "\xee" => '&#1102;',
        "\xef" => '&#1103;',
        "\xf0" => '&#1025;',
        "\xf1" => '&#1105;',
        "\xf2" => '&#1028;',
        "\xf3" => '&#1108;',
        "\xf4" => '&#1031;',
        "\xf5" => '&#1111;',
        "\xf6" => '&#1038;',
        "\xf7" => '&#1118;',
        "\xf8" => '&#176;',
        "\xf9" => '&#8729;',
        "\xfa" => '&#183;',
        "\xfb" => '&#8730;',
        "\xfc" => '&#8470;',
        "\xfd" => '&#164;',
        "\xfe" => '&#9632;',
        "\xff" => '&#160;'
    );

    $string = str_replace(array_keys($cp866), array_values($cp866), $string);

    return $string;
}

Added functions/decode/index.php.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

/**
 * index.php
 *
 * This file simply takes any attempt to view source files and sends those
 * people to the login screen. At this point no attempt is made to see if the
 * person is logged in or not.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: index.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

header('Location: ../index.php');

Added functions/decode/iso_8859_1.php.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
<?php

/**
 * decode/iso8859-1.php
 *
 * This file contains iso-8859-1 decoding function that is needed to read
 * iso-8859-1 encoded mails in non-iso-8859-1 locale.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_1.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-1 string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_1 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-1'))
        return $string;

    $string = preg_replace("/([\201-\237])/e","'&#' . ord('\\1') . ';'",$string);

    /* I don't want to use 0xA0 (\240) in any ranges. RH73 may dislike it */
    $string = str_replace("\240", '&#160;', $string);

    $string = preg_replace("/([\241-\377])/e","'&#' . ord('\\1') . ';'",$string);
    return $string;
}

Added functions/decode/iso_8859_10.php.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php

/**
 * decode/iso8859-10.php
 *
 * This file contains iso-8859-10 decoding function that is needed to read
 * iso-8859-10 encoded mails in non-iso-8859-10 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT
 *
 *   Name:             ISO/IEC 8859-10:1998 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.1
 *   Table format:     Format A
 *   Date:             1999 October 11
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_10.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso-8859-10 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_10 ($string) {
     // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-10'))
        return $string;

    $iso8859_10 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#260;',
        "\xA2" => '&#274;',
        "\xA3" => '&#290;',
        "\xA4" => '&#298;',
        "\xA5" => '&#296;',
        "\xA6" => '&#310;',
        "\xA7" => '&#167;',
        "\xA8" => '&#315;',
        "\xA9" => '&#272;',
        "\xAA" => '&#352;',
        "\xAB" => '&#358;',
        "\xAC" => '&#381;',
        "\xAD" => '&#173;',
        "\xAE" => '&#362;',
        "\xAF" => '&#330;',
        "\xB0" => '&#176;',
        "\xB1" => '&#261;',
        "\xB2" => '&#275;',
        "\xB3" => '&#291;',
        "\xB4" => '&#299;',
        "\xB5" => '&#297;',
        "\xB6" => '&#311;',
        "\xB7" => '&#183;',
        "\xB8" => '&#316;',
        "\xB9" => '&#273;',
        "\xBA" => '&#353;',
        "\xBB" => '&#359;',
        "\xBC" => '&#382;',
        "\xBD" => '&#8213;',
        "\xBE" => '&#363;',
        "\xBF" => '&#331;',
        "\xC0" => '&#256;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#302;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#280;',
        "\xCB" => '&#203;',
        "\xCC" => '&#278;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#208;',
        "\xD1" => '&#325;',
        "\xD2" => '&#332;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#360;',
        "\xD8" => '&#216;',
        "\xD9" => '&#370;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#222;',
        "\xDF" => '&#223;',
        "\xE0" => '&#257;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#303;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#281;',
        "\xEB" => '&#235;',
        "\xEC" => '&#279;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#240;',
        "\xF1" => '&#326;',
        "\xF2" => '&#333;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#361;',
        "\xF8" => '&#248;',
        "\xF9" => '&#371;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#254;',
        "\xFF" => '&#312;'
    );

    $string = str_replace(array_keys($iso8859_10), array_values($iso8859_10), $string);

    return $string;
}

Added functions/decode/iso_8859_11.php.









































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php

/**
 * decode/iso8859-11.php
 *
 * This file contains iso-8859-11 decoding function that is needed to read
 * iso-8859-11 encoded mails in non-iso-8859-11 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-11.TXT
 *
 *        Name:             ISO/IEC 8859-11:2001 to Unicode
 *        Unicode version:  3.2
 *        Table version:    1.0
 *        Table format:     Format A
 *        Date:             2002 October 7
 *        Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *        Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *        This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *        No claims are made as to fitness for any particular purpose.  No
 *        warranties of any kind are expressed or implied.  The recipient
 *        agrees to determine applicability of information provided.  If this
 *        file has been provided on optical media by Unicode, Inc., the sole
 *        remedy for any claim will be exchange of defective media within 90
 *        days of receipt.
 *
 *        Unicode, Inc. hereby grants the right to freely use the information
 *        supplied in this file in the creation of products supporting the
 *        Unicode Standard, and to make copies of this file in any form for
 *        internal or external distribution as long as this notice remains
 *        attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_11.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-11 string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_11 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-11'))
        return $string;

    $iso8859_11 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#3585;',
        "\xA2" => '&#3586;',
        "\xA3" => '&#3587;',
        "\xA4" => '&#3588;',
        "\xA5" => '&#3589;',
        "\xA6" => '&#3590;',
        "\xA7" => '&#3591;',
        "\xA8" => '&#3592;',
        "\xA9" => '&#3593;',
        "\xAA" => '&#3594;',
        "\xAB" => '&#3595;',
        "\xAC" => '&#3596;',
        "\xAD" => '&#3597;',
        "\xAE" => '&#3598;',
        "\xAF" => '&#3599;',
        "\xB0" => '&#3600;',
        "\xB1" => '&#3601;',
        "\xB2" => '&#3602;',
        "\xB3" => '&#3603;',
        "\xB4" => '&#3604;',
        "\xB5" => '&#3605;',
        "\xB6" => '&#3606;',
        "\xB7" => '&#3607;',
        "\xB8" => '&#3608;',
        "\xB9" => '&#3609;',
        "\xBA" => '&#3610;',
        "\xBB" => '&#3611;',
        "\xBC" => '&#3612;',
        "\xBD" => '&#3613;',
        "\xBE" => '&#3614;',
        "\xBF" => '&#3615;',
        "\xC0" => '&#3616;',
        "\xC1" => '&#3617;',
        "\xC2" => '&#3618;',
        "\xC3" => '&#3619;',
        "\xC4" => '&#3620;',
        "\xC5" => '&#3621;',
        "\xC6" => '&#3622;',
        "\xC7" => '&#3623;',
        "\xC8" => '&#3624;',
        "\xC9" => '&#3625;',
        "\xCA" => '&#3626;',
        "\xCB" => '&#3627;',
        "\xCC" => '&#3628;',
        "\xCD" => '&#3629;',
        "\xCE" => '&#3630;',
        "\xCF" => '&#3631;',
        "\xD0" => '&#3632;',
        "\xD1" => '&#3633;',
        "\xD2" => '&#3634;',
        "\xD3" => '&#3635;',
        "\xD4" => '&#3636;',
        "\xD5" => '&#3637;',
        "\xD6" => '&#3638;',
        "\xD7" => '&#3639;',
        "\xD8" => '&#3640;',
        "\xD9" => '&#3641;',
        "\xDA" => '&#3642;',
        "\xDF" => '&#3647;',
        "\xE0" => '&#3648;',
        "\xE1" => '&#3649;',
        "\xE2" => '&#3650;',
        "\xE3" => '&#3651;',
        "\xE4" => '&#3652;',
        "\xE5" => '&#3653;',
        "\xE6" => '&#3654;',
        "\xE7" => '&#3655;',
        "\xE8" => '&#3656;',
        "\xE9" => '&#3657;',
        "\xEA" => '&#3658;',
        "\xEB" => '&#3659;',
        "\xEC" => '&#3660;',
        "\xED" => '&#3661;',
        "\xEE" => '&#3662;',
        "\xEF" => '&#3663;',
        "\xF0" => '&#3664;',
        "\xF1" => '&#3665;',
        "\xF2" => '&#3666;',
        "\xF3" => '&#3667;',
        "\xF4" => '&#3668;',
        "\xF5" => '&#3669;',
        "\xF6" => '&#3670;',
        "\xF7" => '&#3671;',
        "\xF8" => '&#3672;',
        "\xF9" => '&#3673;',
        "\xFA" => '&#3674;',
        "\xFB" => '&#3675;'
    );

    $string = str_replace(array_keys($iso8859_11), array_values($iso8859_11), $string);

    return $string;
}

Added functions/decode/iso_8859_13.php.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php

/**
 * decode/iso8859-13.php
 *
 * This file contains iso-8859-13 decoding function that is needed to read
 * iso-8859-13 encoded mails in non-iso-8859-13 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT
 *
 *   Name:             ISO/IEC 8859-13:1998  to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_13.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-13
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_13 ($string) {
     // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-13'))
        return $string;

    $iso8859_13 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#8221;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#8222;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#216;',
        "\xA9" => '&#169;',
        "\xAA" => '&#342;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#198;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#8220;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#248;',
        "\xB9" => '&#185;',
        "\xBA" => '&#343;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xBF" => '&#230;',
        "\xC0" => '&#260;',
        "\xC1" => '&#302;',
        "\xC2" => '&#256;',
        "\xC3" => '&#262;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#280;',
        "\xC7" => '&#274;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#377;',
        "\xCB" => '&#278;',
        "\xCC" => '&#290;',
        "\xCD" => '&#310;',
        "\xCE" => '&#298;',
        "\xCF" => '&#315;',
        "\xD0" => '&#352;',
        "\xD1" => '&#323;',
        "\xD2" => '&#325;',
        "\xD3" => '&#211;',
        "\xD4" => '&#332;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#370;',
        "\xD9" => '&#321;',
        "\xDA" => '&#346;',
        "\xDB" => '&#362;',
        "\xDC" => '&#220;',
        "\xDD" => '&#379;',
        "\xDE" => '&#381;',
        "\xDF" => '&#223;',
        "\xE0" => '&#261;',
        "\xE1" => '&#303;',
        "\xE2" => '&#257;',
        "\xE3" => '&#263;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#281;',
        "\xE7" => '&#275;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#378;',
        "\xEB" => '&#279;',
        "\xEC" => '&#291;',
        "\xED" => '&#311;',
        "\xEE" => '&#299;',
        "\xEF" => '&#316;',
        "\xF0" => '&#353;',
        "\xF1" => '&#324;',
        "\xF2" => '&#326;',
        "\xF3" => '&#243;',
        "\xF4" => '&#333;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#371;',
        "\xF9" => '&#322;',
        "\xFA" => '&#347;',
        "\xFB" => '&#363;',
        "\xFC" => '&#252;',
        "\xFD" => '&#380;',
        "\xFE" => '&#382;',
        "\xFF" => '&#8217;'
    );

    $string = str_replace(array_keys($iso8859_13), array_values($iso8859_13), $string);

    return $string;
}

Added functions/decode/iso_8859_14.php.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php

/**
 * decode/iso8859-14.php
 *
 * This file contains iso-8859-14 decoding function that is needed to read
 * iso-8859-14 encoded mails in non-iso-8859-14 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT
 *
 *   Name:             ISO/IEC 8859-14:1998 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Markus Kuhn <mkuhn@acm.org>
 *                     Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_14.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-14 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_14 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-14'))
        return $string;

    $iso8859_14 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#7682;',
        "\xA2" => '&#7683;',
        "\xA3" => '&#163;',
        "\xA4" => '&#266;',
        "\xA5" => '&#267;',
        "\xA6" => '&#7690;',
        "\xA7" => '&#167;',
        "\xA8" => '&#7808;',
        "\xA9" => '&#169;',
        "\xAA" => '&#7810;',
        "\xAB" => '&#7691;',
        "\xAC" => '&#7922;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#376;',
        "\xB0" => '&#7710;',
        "\xB1" => '&#7711;',
        "\xB2" => '&#288;',
        "\xB3" => '&#289;',
        "\xB4" => '&#7744;',
        "\xB5" => '&#7745;',
        "\xB6" => '&#182;',
        "\xB7" => '&#7766;',
        "\xB8" => '&#7809;',
        "\xB9" => '&#7767;',
        "\xBA" => '&#7811;',
        "\xBB" => '&#7776;',
        "\xBC" => '&#7923;',
        "\xBD" => '&#7812;',
        "\xBE" => '&#7813;',
        "\xBF" => '&#7777;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#372;',
        "\xD1" => '&#209;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#7786;',
        "\xD8" => '&#216;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#374;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#373;',
        "\xF1" => '&#241;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#7787;',
        "\xF8" => '&#248;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#375;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($iso8859_14), array_values($iso8859_14), $string);

    return $string;
}

Added functions/decode/iso_8859_15.php.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php

/**
 * decode/iso8859-15.php
 *
 * This file contains iso-8859-15 decoding function that is needed to read
 * iso-8859-15 encoded mails in non-iso-8859-15 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT
 *
 *   Name:             ISO/IEC 8859-15:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Markus Kuhn <mkuhn@acm.org>
 *                     Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_15.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-15 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_15 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-15'))
        return $string;

    $iso8859_15 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#161;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#8364;',
        "\xA5" => '&#165;',
        "\xA6" => '&#352;',
        "\xA7" => '&#167;',
        "\xA8" => '&#353;',
        "\xA9" => '&#169;',
        "\xAA" => '&#170;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#381;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#382;',
        "\xB9" => '&#185;',
        "\xBA" => '&#186;',
        "\xBB" => '&#187;',
        "\xBC" => '&#338;',
        "\xBD" => '&#339;',
        "\xBE" => '&#376;',
        "\xBF" => '&#191;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#208;',
        "\xD1" => '&#209;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#216;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#222;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#240;',
        "\xF1" => '&#241;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#248;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#254;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($iso8859_15), array_values($iso8859_15), $string);

    return $string;
}

Added functions/decode/iso_8859_16.php.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php

/**
 * decode/iso8859-16.php
 *
 * This file contains iso-8859-16 decoding function that is needed to read
 * iso-8859-16 encoded mails in non-iso-8859-16 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-16.TXT
 *
 *   Name:             ISO/IEC 8859-16:2001 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             2001 July 26
 *   Authors:          Markus Kuhn <mkuhn@acm.org>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_16.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-16 string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_16 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-16'))
        return $string;

    $iso8859_16 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#260;',
        "\xA2" => '&#261;',
        "\xA3" => '&#321;',
        "\xA4" => '&#8364;',
        "\xA5" => '&#8222;',
        "\xA6" => '&#352;',
        "\xA7" => '&#167;',
        "\xA8" => '&#353;',
        "\xA9" => '&#169;',
        "\xAA" => '&#536;',
        "\xAB" => '&#171;',
        "\xAC" => '&#377;',
        "\xAD" => '&#173;',
        "\xAE" => '&#378;',
        "\xAF" => '&#379;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#268;',
        "\xB3" => '&#322;',
        "\xB4" => '&#381;',
        "\xB5" => '&#8221;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#382;',
        "\xB9" => '&#269;',
        "\xBA" => '&#537;',
        "\xBB" => '&#187;',
        "\xBC" => '&#338;',
        "\xBD" => '&#339;',
        "\xBE" => '&#376;',
        "\xBF" => '&#380;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#258;',
        "\xC4" => '&#196;',
        "\xC5" => '&#262;',
        "\xC6" => '&#198;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD0" => '&#272;',
        "\xD1" => '&#323;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#336;',
        "\xD6" => '&#214;',
        "\xD7" => '&#346;',
        "\xD8" => '&#368;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#280;',
        "\xDE" => '&#538;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#259;',
        "\xE4" => '&#228;',
        "\xE5" => '&#263;',
        "\xE6" => '&#230;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF0" => '&#273;',
        "\xF1" => '&#324;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#337;',
        "\xF6" => '&#246;',
        "\xF7" => '&#347;',
        "\xF8" => '&#369;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#281;',
        "\xFE" => '&#539;',
        "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($iso8859_16), array_values($iso8859_16), $string);

    return $string;
}

Added functions/decode/iso_8859_2.php.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php

/**
 * decode/iso8859-2.php
 *
 * This file contains iso-8859-2 decoding function that is needed to read
 * iso-8859-2 encoded mails in non-iso-8859-2 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT
 *
 *   Name:             ISO 8859-2:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_2.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-2 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_2 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-2'))
        return $string;

    $iso8859_2 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#260;',
        "\xA2" => '&#728;',
        "\xA3" => '&#321;',
        "\xA4" => '&#164;',
        "\xA5" => '&#317;',
        "\xA6" => '&#346;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#352;',
        "\xAA" => '&#350;',
        "\xAB" => '&#356;',
        "\xAC" => '&#377;',
        "\xAD" => '&#173;',
        "\xAE" => '&#381;',
        "\xAF" => '&#379;',
        "\xB0" => '&#176;',
        "\xB1" => '&#261;',
        "\xB2" => '&#731;',
        "\xB3" => '&#322;',
        "\xB4" => '&#180;',
        "\xB5" => '&#318;',
        "\xB6" => '&#347;',
        "\xB7" => '&#711;',
        "\xB8" => '&#184;',
        "\xB9" => '&#353;',
        "\xBA" => '&#351;',
        "\xBB" => '&#357;',
        "\xBC" => '&#378;',
        "\xBD" => '&#733;',
        "\xBE" => '&#382;',
        "\xBF" => '&#380;',
        "\xC0" => '&#340;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#258;',
        "\xC4" => '&#196;',
        "\xC5" => '&#313;',
        "\xC6" => '&#262;',
        "\xC7" => '&#199;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#280;',
        "\xCB" => '&#203;',
        "\xCC" => '&#282;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#270;',
        "\xD0" => '&#272;',
        "\xD1" => '&#323;',
        "\xD2" => '&#327;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#336;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#344;',
        "\xD9" => '&#366;',
        "\xDA" => '&#218;',
        "\xDB" => '&#368;',
        "\xDC" => '&#220;',
        "\xDD" => '&#221;',
        "\xDE" => '&#354;',
        "\xDF" => '&#223;',
        "\xE0" => '&#341;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#259;',
        "\xE4" => '&#228;',
        "\xE5" => '&#314;',
        "\xE6" => '&#263;',
        "\xE7" => '&#231;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#281;',
        "\xEB" => '&#235;',
        "\xEC" => '&#283;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#271;',
        "\xF0" => '&#273;',
        "\xF1" => '&#324;',
        "\xF2" => '&#328;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#337;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#345;',
        "\xF9" => '&#367;',
        "\xFA" => '&#250;',
        "\xFB" => '&#369;',
        "\xFC" => '&#252;',
        "\xFD" => '&#253;',
        "\xFE" => '&#355;',
        "\xFF" => '&#729;'
    );

    $string = str_replace(array_keys($iso8859_2), array_values($iso8859_2), $string);

    return $string;
}

Added functions/decode/iso_8859_3.php.









































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php

/**
 * decode/iso8859-3.php
 *
 * This file contains iso-8859-3 decoding function that is needed to read
 * iso-8859-3 encoded mails in non-iso-8859-3 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT
 *
 *   Name:             ISO/IEC 8859-3:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_3.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-3 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_3 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-3'))
        return $string;

    $iso8859_3 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#294;',
        "\xA2" => '&#728;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA6" => '&#292;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#304;',
        "\xAA" => '&#350;',
        "\xAB" => '&#286;',
        "\xAC" => '&#308;',
        "\xAD" => '&#173;',
        "\xAF" => '&#379;',
        "\xB0" => '&#176;',
        "\xB1" => '&#295;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#293;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#305;',
        "\xBA" => '&#351;',
        "\xBB" => '&#287;',
        "\xBC" => '&#309;',
        "\xBD" => '&#189;',
        "\xBF" => '&#380;',
        "\xC0" => '&#192;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC4" => '&#196;',
        "\xC5" => '&#266;',
        "\xC6" => '&#264;',
        "\xC7" => '&#199;',
        "\xC8" => '&#200;',
        "\xC9" => '&#201;',
        "\xCA" => '&#202;',
        "\xCB" => '&#203;',
        "\xCC" => '&#204;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#207;',
        "\xD1" => '&#209;',
        "\xD2" => '&#210;',
        "\xD3" => '&#211;',
        "\xD4" => '&#212;',
        "\xD5" => '&#288;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#284;',
        "\xD9" => '&#217;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#364;',
        "\xDE" => '&#348;',
        "\xDF" => '&#223;',
        "\xE0" => '&#224;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE4" => '&#228;',
        "\xE5" => '&#267;',
        "\xE6" => '&#265;',
        "\xE7" => '&#231;',
        "\xE8" => '&#232;',
        "\xE9" => '&#233;',
        "\xEA" => '&#234;',
        "\xEB" => '&#235;',
        "\xEC" => '&#236;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#239;',
        "\xF1" => '&#241;',
        "\xF2" => '&#242;',
        "\xF3" => '&#243;',
        "\xF4" => '&#244;',
        "\xF5" => '&#289;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#285;',
        "\xF9" => '&#249;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#365;',
        "\xFE" => '&#349;',
        "\xFF" => '&#729;'
    );

    $string = str_replace(array_keys($iso8859_3), array_values($iso8859_3), $string);

    return $string;
}

Added functions/decode/iso_8859_4.php.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php

/**
 * decode/iso8859-4.php
 *
 * This file contains iso-8859-4 decoding function that is needed to read
 * iso-8859-4 encoded mails in non-iso-8859-4 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT
 *
 *   Name:             ISO/IEC 8859-4:1998 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_4.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-4 string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_4 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-4'))
        return $string;

    $iso8859_4 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#260;',
        "\xA2" => '&#312;',
        "\xA3" => '&#342;',
        "\xA4" => '&#164;',
        "\xA5" => '&#296;',
        "\xA6" => '&#315;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#352;',
        "\xAA" => '&#274;',
        "\xAB" => '&#290;',
        "\xAC" => '&#358;',
        "\xAD" => '&#173;',
        "\xAE" => '&#381;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#261;',
        "\xB2" => '&#731;',
        "\xB3" => '&#343;',
        "\xB4" => '&#180;',
        "\xB5" => '&#297;',
        "\xB6" => '&#316;',
        "\xB7" => '&#711;',
        "\xB8" => '&#184;',
        "\xB9" => '&#353;',
        "\xBA" => '&#275;',
        "\xBB" => '&#291;',
        "\xBC" => '&#359;',
        "\xBD" => '&#330;',
        "\xBE" => '&#382;',
        "\xBF" => '&#331;',
        "\xC0" => '&#256;',
        "\xC1" => '&#193;',
        "\xC2" => '&#194;',
        "\xC3" => '&#195;',
        "\xC4" => '&#196;',
        "\xC5" => '&#197;',
        "\xC6" => '&#198;',
        "\xC7" => '&#302;',
        "\xC8" => '&#268;',
        "\xC9" => '&#201;',
        "\xCA" => '&#280;',
        "\xCB" => '&#203;',
        "\xCC" => '&#278;',
        "\xCD" => '&#205;',
        "\xCE" => '&#206;',
        "\xCF" => '&#298;',
        "\xD0" => '&#272;',
        "\xD1" => '&#325;',
        "\xD2" => '&#332;',
        "\xD3" => '&#310;',
        "\xD4" => '&#212;',
        "\xD5" => '&#213;',
        "\xD6" => '&#214;',
        "\xD7" => '&#215;',
        "\xD8" => '&#216;',
        "\xD9" => '&#370;',
        "\xDA" => '&#218;',
        "\xDB" => '&#219;',
        "\xDC" => '&#220;',
        "\xDD" => '&#360;',
        "\xDE" => '&#362;',
        "\xDF" => '&#223;',
        "\xE0" => '&#257;',
        "\xE1" => '&#225;',
        "\xE2" => '&#226;',
        "\xE3" => '&#227;',
        "\xE4" => '&#228;',
        "\xE5" => '&#229;',
        "\xE6" => '&#230;',
        "\xE7" => '&#303;',
        "\xE8" => '&#269;',
        "\xE9" => '&#233;',
        "\xEA" => '&#281;',
        "\xEB" => '&#235;',
        "\xEC" => '&#279;',
        "\xED" => '&#237;',
        "\xEE" => '&#238;',
        "\xEF" => '&#299;',
        "\xF0" => '&#273;',
        "\xF1" => '&#326;',
        "\xF2" => '&#333;',
        "\xF3" => '&#311;',
        "\xF4" => '&#244;',
        "\xF5" => '&#245;',
        "\xF6" => '&#246;',
        "\xF7" => '&#247;',
        "\xF8" => '&#248;',
        "\xF9" => '&#371;',
        "\xFA" => '&#250;',
        "\xFB" => '&#251;',
        "\xFC" => '&#252;',
        "\xFD" => '&#361;',
        "\xFE" => '&#363;',
        "\xFF" => '&#729;'
    );

    $string = str_replace(array_keys($iso8859_4), array_values($iso8859_4), $string);

    return $string;
}

Added functions/decode/iso_8859_5.php.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php

/**
 * decode/iso8859-5.php
 *
 * This file contains iso-8859-5 decoding function that is needed to read
 * iso-8859-5 encoded mails in non-iso-8859-5 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT
 *
 *   Name:             ISO 8859-5:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_5.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-5 encoded string
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_5 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-5'))
        return $string;

    $iso8859_5 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#1025;',
        "\xA2" => '&#1026;',
        "\xA3" => '&#1027;',
        "\xA4" => '&#1028;',
        "\xA5" => '&#1029;',
        "\xA6" => '&#1030;',
        "\xA7" => '&#1031;',
        "\xA8" => '&#1032;',
        "\xA9" => '&#1033;',
        "\xAA" => '&#1034;',
        "\xAB" => '&#1035;',
        "\xAC" => '&#1036;',
        "\xAD" => '&#173;',
        "\xAE" => '&#1038;',
        "\xAF" => '&#1039;',
        "\xB0" => '&#1040;',
        "\xB1" => '&#1041;',
        "\xB2" => '&#1042;',
        "\xB3" => '&#1043;',
        "\xB4" => '&#1044;',
        "\xB5" => '&#1045;',
        "\xB6" => '&#1046;',
        "\xB7" => '&#1047;',
        "\xB8" => '&#1048;',
        "\xB9" => '&#1049;',
        "\xBA" => '&#1050;',
        "\xBB" => '&#1051;',
        "\xBC" => '&#1052;',
        "\xBD" => '&#1053;',
        "\xBE" => '&#1054;',
        "\xBF" => '&#1055;',
        "\xC0" => '&#1056;',
        "\xC1" => '&#1057;',
        "\xC2" => '&#1058;',
        "\xC3" => '&#1059;',
        "\xC4" => '&#1060;',
        "\xC5" => '&#1061;',
        "\xC6" => '&#1062;',
        "\xC7" => '&#1063;',
        "\xC8" => '&#1064;',
        "\xC9" => '&#1065;',
        "\xCA" => '&#1066;',
        "\xCB" => '&#1067;',
        "\xCC" => '&#1068;',
        "\xCD" => '&#1069;',
        "\xCE" => '&#1070;',
        "\xCF" => '&#1071;',
        "\xD0" => '&#1072;',
        "\xD1" => '&#1073;',
        "\xD2" => '&#1074;',
        "\xD3" => '&#1075;',
        "\xD4" => '&#1076;',
        "\xD5" => '&#1077;',
        "\xD6" => '&#1078;',
        "\xD7" => '&#1079;',
        "\xD8" => '&#1080;',
        "\xD9" => '&#1081;',
        "\xDA" => '&#1082;',
        "\xDB" => '&#1083;',
        "\xDC" => '&#1084;',
        "\xDD" => '&#1085;',
        "\xDE" => '&#1086;',
        "\xDF" => '&#1087;',
        "\xE0" => '&#1088;',
        "\xE1" => '&#1089;',
        "\xE2" => '&#1090;',
        "\xE3" => '&#1091;',
        "\xE4" => '&#1092;',
        "\xE5" => '&#1093;',
        "\xE6" => '&#1094;',
        "\xE7" => '&#1095;',
        "\xE8" => '&#1096;',
        "\xE9" => '&#1097;',
        "\xEA" => '&#1098;',
        "\xEB" => '&#1099;',
        "\xEC" => '&#1100;',
        "\xED" => '&#1101;',
        "\xEE" => '&#1102;',
        "\xEF" => '&#1103;',
        "\xF0" => '&#8470;',
        "\xF1" => '&#1105;',
        "\xF2" => '&#1106;',
        "\xF3" => '&#1107;',
        "\xF4" => '&#1108;',
        "\xF5" => '&#1109;',
        "\xF6" => '&#1110;',
        "\xF7" => '&#1111;',
        "\xF8" => '&#1112;',
        "\xF9" => '&#1113;',
        "\xFA" => '&#1114;',
        "\xFB" => '&#1115;',
        "\xFC" => '&#1116;',
        "\xFD" => '&#167;',
        "\xFE" => '&#1118;',
        "\xFF" => '&#1119;'
    );

    $string = str_replace(array_keys($iso8859_5), array_values($iso8859_5), $string);

    return $string;
}

Added functions/decode/iso_8859_6.php.





























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php

/**
 * decode/iso8859-6.php
 *
 * This file contains iso-8859-6 decoding function that is needed to read
 * iso-8859-6 encoded mails in non-iso-8859-6 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT
 *
 *   Name:             ISO 8859-6:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_6.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-6 strings
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_6 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-6'))
        return $string;

    $iso8859_6 = array(
        "\xA0" => '&#160;',
        "\xA4" => '&#164;',
        "\xAC" => '&#1548;',
        "\xAD" => '&#173;',
        "\xBB" => '&#1563;',
        "\xBF" => '&#1567;',
        "\xC1" => '&#1569;',
        "\xC2" => '&#1570;',
        "\xC3" => '&#1571;',
        "\xC4" => '&#1572;',
        "\xC5" => '&#1573;',
        "\xC6" => '&#1574;',
        "\xC7" => '&#1575;',
        "\xC8" => '&#1576;',
        "\xC9" => '&#1577;',
        "\xCA" => '&#1578;',
        "\xCB" => '&#1579;',
        "\xCC" => '&#1580;',
        "\xCD" => '&#1581;',
        "\xCE" => '&#1582;',
        "\xCF" => '&#1583;',
        "\xD0" => '&#1584;',
        "\xD1" => '&#1585;',
        "\xD2" => '&#1586;',
        "\xD3" => '&#1587;',
        "\xD4" => '&#1588;',
        "\xD5" => '&#1589;',
        "\xD6" => '&#1590;',
        "\xD7" => '&#1591;',
        "\xD8" => '&#1592;',
        "\xD9" => '&#1593;',
        "\xDA" => '&#1594;',
        "\xE0" => '&#1600;',
        "\xE1" => '&#1601;',
        "\xE2" => '&#1602;',
        "\xE3" => '&#1603;',
        "\xE4" => '&#1604;',
        "\xE5" => '&#1605;',
        "\xE6" => '&#1606;',
        "\xE7" => '&#1607;',
        "\xE8" => '&#1608;',
        "\xE9" => '&#1609;',
        "\xEA" => '&#1610;',
        "\xEB" => '&#1611;',
        "\xEC" => '&#1612;',
        "\xED" => '&#1613;',
        "\xEE" => '&#1614;',
        "\xEF" => '&#1615;',
        "\xF0" => '&#1616;',
        "\xF1" => '&#1617;',
        "\xF2" => '&#1618;'
    );

    $string = str_replace(array_keys($iso8859_6), array_values($iso8859_6), $string);

    return $string;
}

Added functions/decode/iso_8859_7.php.











































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php

/**
 * decode/iso8859-7.php
 *
 * This file contains iso-8859-7 decoding function that is needed to read
 * iso-8859-7 encoded mails in non-iso-8859-7 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT
 *
 *   Name:             ISO 8859-7:1987 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_7.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-7 encoded strings
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_7 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-7'))
        return $string;

    $iso8859_7 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#8216;',
        "\xA2" => '&#8217;',
        "\xA3" => '&#163;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAF" => '&#8213;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#900;',
        "\xB5" => '&#901;',
        "\xB6" => '&#902;',
        "\xB7" => '&#183;',
        "\xB8" => '&#904;',
        "\xB9" => '&#905;',
        "\xBA" => '&#906;',
        "\xBB" => '&#187;',
        "\xBC" => '&#908;',
        "\xBD" => '&#189;',
        "\xBE" => '&#910;',
        "\xBF" => '&#911;',
        "\xC0" => '&#912;',
        "\xC1" => '&#913;',
        "\xC2" => '&#914;',
        "\xC3" => '&#915;',
        "\xC4" => '&#916;',
        "\xC5" => '&#917;',
        "\xC6" => '&#918;',
        "\xC7" => '&#919;',
        "\xC8" => '&#920;',
        "\xC9" => '&#921;',
        "\xCA" => '&#922;',
        "\xCB" => '&#923;',
        "\xCC" => '&#924;',
        "\xCD" => '&#925;',
        "\xCE" => '&#926;',
        "\xCF" => '&#927;',
        "\xD0" => '&#928;',
        "\xD1" => '&#929;',
        "\xD3" => '&#931;',
        "\xD4" => '&#932;',
        "\xD5" => '&#933;',
        "\xD6" => '&#934;',
        "\xD7" => '&#935;',
        "\xD8" => '&#936;',
        "\xD9" => '&#937;',
        "\xDA" => '&#938;',
        "\xDB" => '&#939;',
        "\xDC" => '&#940;',
        "\xDD" => '&#941;',
        "\xDE" => '&#942;',
        "\xDF" => '&#943;',
        "\xE0" => '&#944;',
        "\xE1" => '&#945;',
        "\xE2" => '&#946;',
        "\xE3" => '&#947;',
        "\xE4" => '&#948;',
        "\xE5" => '&#949;',
        "\xE6" => '&#950;',
        "\xE7" => '&#951;',
        "\xE8" => '&#952;',
        "\xE9" => '&#953;',
        "\xEA" => '&#954;',
        "\xEB" => '&#955;',
        "\xEC" => '&#956;',
        "\xED" => '&#957;',
        "\xEE" => '&#958;',
        "\xEF" => '&#959;',
        "\xF0" => '&#960;',
        "\xF1" => '&#961;',
        "\xF2" => '&#962;',
        "\xF3" => '&#963;',
        "\xF4" => '&#964;',
        "\xF5" => '&#965;',
        "\xF6" => '&#966;',
        "\xF7" => '&#967;',
        "\xF8" => '&#968;',
        "\xF9" => '&#969;',
        "\xFA" => '&#970;',
        "\xFB" => '&#971;',
        "\xFC" => '&#972;',
        "\xFD" => '&#973;',
        "\xFE" => '&#974;'
    );

    $string = str_replace(array_keys($iso8859_7), array_values($iso8859_7), $string);

    return $string;
}

Added functions/decode/iso_8859_8.php.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php

/**
 * decode/iso8859-8.php
 *
 * This file contains iso-8859-8 decoding function that is needed to read
 * iso-8859-8 encoded mails in non-iso-8859-8 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT
 *
 *   Name:             ISO/IEC 8859-8:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.1
 *   Table format:     Format A
 *   Date:             2000-Jan-03
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_8.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-8 encoded strings
 * @param string $string Encoded string
 * @return string $string Decoded string
 */
function charset_decode_iso_8859_8 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-8'))
        return $string;

    $iso8859_8 = array(
        "\xA0" => '&#160;',
        "\xA2" => '&#162;',
        "\xA3" => '&#163;',
        "\xA4" => '&#164;',
        "\xA5" => '&#165;',
        "\xA6" => '&#166;',
        "\xA7" => '&#167;',
        "\xA8" => '&#168;',
        "\xA9" => '&#169;',
        "\xAA" => '&#215;',
        "\xAB" => '&#171;',
        "\xAC" => '&#172;',
        "\xAD" => '&#173;',
        "\xAE" => '&#174;',
        "\xAF" => '&#175;',
        "\xB0" => '&#176;',
        "\xB1" => '&#177;',
        "\xB2" => '&#178;',
        "\xB3" => '&#179;',
        "\xB4" => '&#180;',
        "\xB5" => '&#181;',
        "\xB6" => '&#182;',
        "\xB7" => '&#183;',
        "\xB8" => '&#184;',
        "\xB9" => '&#185;',
        "\xBA" => '&#247;',
        "\xBB" => '&#187;',
        "\xBC" => '&#188;',
        "\xBD" => '&#189;',
        "\xBE" => '&#190;',
        "\xDF" => '&#8215;',
        "\xE0" => '&#1488;',
        "\xE1" => '&#1489;',
        "\xE2" => '&#1490;',
        "\xE3" => '&#1491;',
        "\xE4" => '&#1492;',
        "\xE5" => '&#1493;',
        "\xE6" => '&#1494;',
        "\xE7" => '&#1495;',
        "\xE8" => '&#1496;',
        "\xE9" => '&#1497;',
        "\xEA" => '&#1498;',
        "\xEB" => '&#1499;',
        "\xEC" => '&#1500;',
        "\xED" => '&#1501;',
        "\xEE" => '&#1502;',
        "\xEF" => '&#1503;',
        "\xF0" => '&#1504;',
        "\xF1" => '&#1505;',
        "\xF2" => '&#1506;',
        "\xF3" => '&#1507;',
        "\xF4" => '&#1508;',
        "\xF5" => '&#1509;',
        "\xF6" => '&#1510;',
        "\xF7" => '&#1511;',
        "\xF8" => '&#1512;',
        "\xF9" => '&#1513;',
        "\xFA" => '&#1514;',
        "\xFD" => '&#8206;',
        "\xFE" => '&#8207;'
    );

    $string = str_replace(array_keys($iso8859_8), array_values($iso8859_8), $string);

    return $string;
}

Added functions/decode/iso_8859_9.php.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php

/**
 * decode/iso8859-9.php
 *
 * This file contains iso-8859-9 decoding function that is needed to read
 * iso-8859-9 encoded mails in non-iso-8859-9 locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT
 *
 *   Name:             ISO/IEC 8859-9:1999 to Unicode
 *   Unicode version:  3.0
 *   Table version:    1.0
 *   Table format:     Format A
 *   Date:             1999 July 27
 *   Authors:          Ken Whistler <kenw@sybase.com>
 *
 * Original copyright:
 *  Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
 *
 *  This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 *  No claims are made as to fitness for any particular purpose.  No
 *  warranties of any kind are expressed or implied.  The recipient
 *  agrees to determine applicability of information provided.  If this
 *  file has been provided on optical media by Unicode, Inc., the sole
 *  remedy for any claim will be exchange of defective media within 90
 *  days of receipt.
 *
 *  Unicode, Inc. hereby grants the right to freely use the information
 *  supplied in this file in the creation of products supporting the
 *  Unicode Standard, and to make copies of this file in any form for
 *  internal or external distribution as long as this notice remains
 *  attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_8859_9.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso8859-9 encoded strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_iso_8859_9 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-8859-9'))
        return $string;

    $iso8859_9 = array(
       "\xA0" => '&#160;',
       "\xA1" => '&#161;',
       "\xA2" => '&#162;',
       "\xA3" => '&#163;',
       "\xA4" => '&#164;',
       "\xA5" => '&#165;',
       "\xA6" => '&#166;',
       "\xA7" => '&#167;',
       "\xA8" => '&#168;',
       "\xA9" => '&#169;',
       "\xAA" => '&#170;',
       "\xAB" => '&#171;',
       "\xAC" => '&#172;',
       "\xAD" => '&#173;',
       "\xAE" => '&#174;',
       "\xAF" => '&#175;',
       "\xB0" => '&#176;',
       "\xB1" => '&#177;',
       "\xB2" => '&#178;',
       "\xB3" => '&#179;',
       "\xB4" => '&#180;',
       "\xB5" => '&#181;',
       "\xB6" => '&#182;',
       "\xB7" => '&#183;',
       "\xB8" => '&#184;',
       "\xB9" => '&#185;',
       "\xBA" => '&#186;',
       "\xBB" => '&#187;',
       "\xBC" => '&#188;',
       "\xBD" => '&#189;',
       "\xBE" => '&#190;',
       "\xBF" => '&#191;',
       "\xC0" => '&#192;',
       "\xC1" => '&#193;',
       "\xC2" => '&#194;',
       "\xC3" => '&#195;',
       "\xC4" => '&#196;',
       "\xC5" => '&#197;',
       "\xC6" => '&#198;',
       "\xC7" => '&#199;',
       "\xC8" => '&#200;',
       "\xC9" => '&#201;',
       "\xCA" => '&#202;',
       "\xCB" => '&#203;',
       "\xCC" => '&#204;',
       "\xCD" => '&#205;',
       "\xCE" => '&#206;',
       "\xCF" => '&#207;',
       "\xD0" => '&#286;',
       "\xD1" => '&#209;',
       "\xD2" => '&#210;',
       "\xD3" => '&#211;',
       "\xD4" => '&#212;',
       "\xD5" => '&#213;',
       "\xD6" => '&#214;',
       "\xD7" => '&#215;',
       "\xD8" => '&#216;',
       "\xD9" => '&#217;',
       "\xDA" => '&#218;',
       "\xDB" => '&#219;',
       "\xDC" => '&#220;',
       "\xDD" => '&#304;',
       "\xDE" => '&#350;',
       "\xDF" => '&#223;',
       "\xE0" => '&#224;',
       "\xE1" => '&#225;',
       "\xE2" => '&#226;',
       "\xE3" => '&#227;',
       "\xE4" => '&#228;',
       "\xE5" => '&#229;',
       "\xE6" => '&#230;',
       "\xE7" => '&#231;',
       "\xE8" => '&#232;',
       "\xE9" => '&#233;',
       "\xEA" => '&#234;',
       "\xEB" => '&#235;',
       "\xEC" => '&#236;',
       "\xED" => '&#237;',
       "\xEE" => '&#238;',
       "\xEF" => '&#239;',
       "\xF0" => '&#287;',
       "\xF1" => '&#241;',
       "\xF2" => '&#242;',
       "\xF3" => '&#243;',
       "\xF4" => '&#244;',
       "\xF5" => '&#245;',
       "\xF6" => '&#246;',
       "\xF7" => '&#247;',
       "\xF8" => '&#248;',
       "\xF9" => '&#249;',
       "\xFA" => '&#250;',
       "\xFB" => '&#251;',
       "\xFC" => '&#252;',
       "\xFD" => '&#305;',
       "\xFE" => '&#351;',
       "\xFF" => '&#255;'
    );

    $string = str_replace(array_keys($iso8859_9), array_values($iso8859_9), $string);

    return $string;
}

Added functions/decode/iso_ir_111.php.































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php

/**
 * decode/iso-ir-111.php
 *
 * This file contains iso-ir-111 decoding function that is needed to read
 * iso-ir-111 encoded mails in non-iso-ir-111 locale.
 *
 * Original data taken from:
 *  http://crl.nmsu.edu/~mleisher/csets/ISOIR111.TXT
 *
 * Original ID: Id: ISOIR111.TXT,v 1.2 1999/08/23 18:34:15 mleisher Exp
 *   Name:             ISO IR 111/ECMA Cyrillic to Unicode 2.1 mapping table.
 * Typed in by hand from
 *    http://www.fingertipsoft.com/ref/cyrillic/charsets.html
 * Author: Mark Leisher <mleisher@crl.nmsu.edu>
 * Date: 05 March 1998
 *
 * Original copyright:
 * Copyright 1999 Computing Research Labs, New Mexico State University
 *
 * 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: iso_ir_111.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode iso-ir-111 encoded strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_iso_ir_111 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'iso-ir-111'))
        return $string;

    $iso_ir_111 = array(
        "\xA0" => '&#160;',
        "\xA1" => '&#1106;',
        "\xA2" => '&#1107;',
        "\xA3" => '&#1105;',
        "\xA4" => '&#1108;',
        "\xA5" => '&#1109;',
        "\xA6" => '&#1110;',
        "\xA7" => '&#1111;',
        "\xA8" => '&#1112;',
        "\xA9" => '&#1113;',
        "\xAA" => '&#1114;',
        "\xAB" => '&#1115;',
        "\xAC" => '&#1116;',
        "\xAD" => '&#173;',
        "\xAE" => '&#1118;',
        "\xAF" => '&#1119;',
        "\xB0" => '&#8470;',
        "\xB1" => '&#1026;',
        "\xB2" => '&#1027;',
        "\xB3" => '&#1025;',
        "\xB4" => '&#1028;',
        "\xB5" => '&#1029;',
        "\xB6" => '&#1030;',
        "\xB7" => '&#1031;',
        "\xB8" => '&#1032;',
        "\xB9" => '&#1033;',
        "\xBA" => '&#1034;',
        "\xBB" => '&#1035;',
        "\xBC" => '&#1036;',
        "\xBD" => '&#164;',
        "\xBE" => '&#1038;',
        "\xBF" => '&#1039;',
        "\xC0" => '&#1102;',
        "\xC1" => '&#1072;',
        "\xC2" => '&#1073;',
        "\xC3" => '&#1094;',
        "\xC4" => '&#1076;',
        "\xC5" => '&#1077;',
        "\xC6" => '&#1092;',
        "\xC7" => '&#1075;',
        "\xC8" => '&#1093;',
        "\xC9" => '&#1080;',
        "\xCA" => '&#1081;',
        "\xCB" => '&#1082;',
        "\xCC" => '&#1083;',
        "\xCD" => '&#1084;',
        "\xCE" => '&#1085;',
        "\xCF" => '&#1086;',
        "\xD0" => '&#1087;',
        "\xD1" => '&#1103;',
        "\xD2" => '&#1088;',
        "\xD3" => '&#1089;',
        "\xD4" => '&#1090;',
        "\xD5" => '&#1091;',
        "\xD6" => '&#1078;',
        "\xD7" => '&#1074;',
        "\xD8" => '&#1100;',
        "\xD9" => '&#1099;',
        "\xDA" => '&#1079;',
        "\xDB" => '&#1096;',
        "\xDC" => '&#1101;',
        "\xDD" => '&#1097;',
        "\xDE" => '&#1095;',
        "\xDF" => '&#1098;',
        "\xE0" => '&#1070;',
        "\xE1" => '&#1040;',
        "\xE2" => '&#1041;',
        "\xE3" => '&#1062;',
        "\xE4" => '&#1044;',
        "\xE5" => '&#1045;',
        "\xE6" => '&#1060;',
        "\xE7" => '&#1043;',
        "\xE8" => '&#1061;',
        "\xE9" => '&#1048;',
        "\xEA" => '&#1049;',
        "\xEB" => '&#1050;',
        "\xEC" => '&#1051;',
        "\xED" => '&#1052;',
        "\xEE" => '&#1053;',
        "\xEF" => '&#1054;',
        "\xF0" => '&#1055;',
        "\xF1" => '&#1071;',
        "\xF2" => '&#1056;',
        "\xF3" => '&#1057;',
        "\xF4" => '&#1058;',
        "\xF5" => '&#1059;',
        "\xF6" => '&#1046;',
        "\xF7" => '&#1042;',
        "\xF8" => '&#1068;',
        "\xF9" => '&#1067;',
        "\xFA" => '&#1047;',
        "\xFB" => '&#1064;',
        "\xFC" => '&#1069;',
        "\xFD" => '&#1065;',
        "\xFE" => '&#1063;',
        "\xFF" => '&#1066;'
    );

    $string = str_replace(array_keys($iso_ir_111), array_values($iso_ir_111), $string);

    return $string;
}

Added functions/decode/koi8_r.php.





















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<?php

/**
 * decode/koi8-r.php
 *
 * This file contains koi8-r decoding function that is needed to read
 * koi8-r encoded mails in non-koi8-r locale.
 *
 * Original data taken from:
 *  ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT
 *
 * Name:             KOI8-R (RFC1489) to Unicode
 * Unicode version:  3.0
 * Table version:    1.0
 * Table format:     Format A
 * Date:             18 August 1999
 * Authors:          Helmut Richter <richter@lrz.de>
 *
 * Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
 *
 * This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
 * No claims are made as to fitness for any particular purpose.  No
 * warranties of any kind are expressed or implied.  The recipient
 * agrees to determine applicability of information provided.  If this
 * file has been provided on optical media by Unicode, Inc., the sole
 * remedy for any claim will be exchange of defective media within 90
 * days of receipt.
 *
 * Unicode, Inc. hereby grants the right to freely use the information
 * supplied in this file in the creation of products supporting the
 * Unicode Standard, and to make copies of this file in any form for
 * internal or external distribution as long as this notice remains
 * attached.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: koi8_r.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode koi8r strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_koi8_r ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'koi8-r'))
        return $string;

    $koi8r = array(
        "\x80" => '&#9472;',
        "\x81" => '&#9474;',
        "\x82" => '&#9484;',
        "\x83" => '&#9488;',
        "\x84" => '&#9492;',
        "\x85" => '&#9496;',
        "\x86" => '&#9500;',
        "\x87" => '&#9508;',
        "\x88" => '&#9516;',
        "\x89" => '&#9524;',
        "\x8A" => '&#9532;',
        "\x8B" => '&#9600;',
        "\x8C" => '&#9604;',
        "\x8D" => '&#9608;',
        "\x8E" => '&#9612;',
        "\x8F" => '&#9616;',
        "\x90" => '&#9617;',
        "\x91" => '&#9618;',
        "\x92" => '&#9619;',
        "\x93" => '&#8992;',
        "\x94" => '&#9632;',
        "\x95" => '&#8729;',
        "\x96" => '&#8730;',
        "\x97" => '&#8776;',
        "\x98" => '&#8804;',
        "\x99" => '&#8805;',
        "\x9A" => '&#160;',
        "\x9B" => '&#8993;',
        "\x9C" => '&#176;',
        "\x9D" => '&#178;',
        "\x9E" => '&#183;',
        "\x9F" => '&#247;',
        "\xA0" => '&#9552;',
        "\xA1" => '&#9553;',
        "\xA2" => '&#9554;',
        "\xA3" => '&#1105;',
        "\xA4" => '&#9555;',
        "\xA5" => '&#9556;',
        "\xA6" => '&#9557;',
        "\xA7" => '&#9558;',
        "\xA8" => '&#9559;',
        "\xA9" => '&#9560;',
        "\xAA" => '&#9561;',
        "\xAB" => '&#9562;',
        "\xAC" => '&#9563;',
        "\xAD" => '&#9564;',
        "\xAE" => '&#9565;',
        "\xAF" => '&#9566;',
        "\xB0" => '&#9567;',
        "\xB1" => '&#9568;',
        "\xB2" => '&#9569;',
        "\xB3" => '&#1025;',
        "\xB4" => '&#9570;',
        "\xB5" => '&#9571;',
        "\xB6" => '&#9572;',
        "\xB7" => '&#9573;',
        "\xB8" => '&#9574;',
        "\xB9" => '&#9575;',
        "\xBA" => '&#9576;',
        "\xBB" => '&#9577;',
        "\xBC" => '&#9578;',
        "\xBD" => '&#9579;',
        "\xBE" => '&#9580;',
        "\xBF" => '&#169;',
        "\xC0" => '&#1102;',
        "\xC1" => '&#1072;',
        "\xC2" => '&#1073;',
        "\xC3" => '&#1094;',
        "\xC4" => '&#1076;',
        "\xC5" => '&#1077;',
        "\xC6" => '&#1092;',
        "\xC7" => '&#1075;',
        "\xC8" => '&#1093;',
        "\xC9" => '&#1080;',
        "\xCA" => '&#1081;',
        "\xCB" => '&#1082;',
        "\xCC" => '&#1083;',
        "\xCD" => '&#1084;',
        "\xCE" => '&#1085;',
        "\xCF" => '&#1086;',
        "\xD0" => '&#1087;',
        "\xD1" => '&#1103;',
        "\xD2" => '&#1088;',
        "\xD3" => '&#1089;',
        "\xD4" => '&#1090;',
        "\xD5" => '&#1091;',
        "\xD6" => '&#1078;',
        "\xD7" => '&#1074;',
        "\xD8" => '&#1100;',
        "\xD9" => '&#1099;',
        "\xDA" => '&#1079;',
        "\xDB" => '&#1096;',
        "\xDC" => '&#1101;',
        "\xDD" => '&#1097;',
        "\xDE" => '&#1095;',
        "\xDF" => '&#1098;',
        "\xE0" => '&#1070;',
        "\xE1" => '&#1040;',
        "\xE2" => '&#1041;',
        "\xE3" => '&#1062;',
        "\xE4" => '&#1044;',
        "\xE5" => '&#1045;',
        "\xE6" => '&#1060;',
        "\xE7" => '&#1043;',
        "\xE8" => '&#1061;',
        "\xE9" => '&#1048;',
        "\xEA" => '&#1049;',
        "\xEB" => '&#1050;',
        "\xEC" => '&#1051;',
        "\xED" => '&#1052;',
        "\xEE" => '&#1053;',
        "\xEF" => '&#1054;',
        "\xF0" => '&#1055;',
        "\xF1" => '&#1071;',
        "\xF2" => '&#1056;',
        "\xF3" => '&#1057;',
        "\xF4" => '&#1058;',
        "\xF5" => '&#1059;',
        "\xF6" => '&#1046;',
        "\xF7" => '&#1042;',
        "\xF8" => '&#1068;',
        "\xF9" => '&#1067;',
        "\xFA" => '&#1047;',
        "\xFB" => '&#1064;',
        "\xFC" => '&#1069;',
        "\xFD" => '&#1065;',
        "\xFE" => '&#1063;',
        "\xFF" => '&#1066;'
    );

    $string = str_replace(array_keys($koi8r), array_values($koi8r), $string);

    return $string;
}

Added functions/decode/koi8_u.php.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?php

/**
 * decode/koi8-u.php
 *
 * This file contains koi8-u decoding function that is needed to read
 * koi8-u encoded mails in non-koi8-u locale.
 *
 * Original data taken from rfc2319
 *
 * Original copyright:
 *
 * Copyright (C) The Internet Society (1998).  All Rights Reserved.
 *
 * This document and translations of it may be copied and furnished to
 * others, and derivative works that comment on or otherwise explain it
 * or assist in its implementation may be prepared, copied, published
 * and distributed, in whole or in part, without restriction of any
 * kind, provided that the above copyright notice and this paragraph are
 * included on all such copies and derivative works.  However, this
 * document itself may not be modified in any way, such as by removing
 * the copyright notice or references to the Internet Society or other
 * Internet organizations, except as needed for the purpose of
 * developing Internet standards in which case the procedures for
 * copyrights defined in the Internet Standards process must be
 * followed, or as required to translate it into languages other than
 * English.
 *
 * The limited permissions granted above are perpetual and will not be
 * revoked by the Internet Society or its successors or assigns.
 *
 * This document and the information contained herein is provided on an
 * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
 * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
 * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: koi8_u.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode koi8-u encoded strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_koi8_u ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'koi8-u'))
        return $string;

    $koi8u = array(
        "\x80" => '&#9472;',
        "\x81" => '&#9474;',
        "\x82" => '&#9484;',
        "\x83" => '&#9488;',
        "\x84" => '&#9492;',
        "\x85" => '&#9496;',
        "\x86" => '&#9500;',
        "\x87" => '&#9508;',
        "\x88" => '&#9516;',
        "\x89" => '&#9524;',
        "\x8A" => '&#9532;',
        "\x8B" => '&#9600;',
        "\x8C" => '&#9604;',
        "\x8D" => '&#9608;',
        "\x8E" => '&#9612;',
        "\x8F" => '&#9616;',
        "\x90" => '&#9617;',
        "\x91" => '&#9618;',
        "\x92" => '&#9619;',
        "\x93" => '&#8992;',
        "\x94" => '&#9632;',
        "\x95" => '&#8729;',
        "\x96" => '&#8730;',
        "\x97" => '&#8776;',
        "\x98" => '&#8804;',
        "\x99" => '&#8805;',
        "\x9A" => '&#160;',
        "\x9B" => '&#8993;',
        "\x9C" => '&#176;',
        "\x9D" => '&#178;',
        "\x9E" => '&#183;',
        "\x9F" => '&#247;',
        "\xA0" => '&#9552;',
        "\xA1" => '&#9553;',
        "\xA2" => '&#9554;',
        "\xA3" => '&#1105;',
        "\xA4" => '&#1108;',
        "\xA5" => '&#9556;',
        "\xA6" => '&#1110;',
        "\xA7" => '&#1111;',
        "\xA8" => '&#9559;',
        "\xA9" => '&#9560;',
        "\xAA" => '&#9561;',
        "\xAB" => '&#9562;',
        "\xAC" => '&#9563;',
        "\xAD" => '&#1169;',
        "\xAE" => '&#9565;',
        "\xAF" => '&#9566;',
        "\xB0" => '&#9567;',
        "\xB1" => '&#9568;',
        "\xB2" => '&#9569;',
        "\xB3" => '&#1025;',
        "\xB4" => '&#1027;',
        "\xB5" => '&#9571;',
        "\xB6" => '&#1030;',
        "\xB7" => '&#1031;',
        "\xB8" => '&#9574;',
        "\xB9" => '&#9575;',
        "\xBA" => '&#9576;',
        "\xBB" => '&#9577;',
        "\xBC" => '&#9578;',
        "\xBD" => '&#1168;',
        "\xBE" => '&#9580;',
        "\xBF" => '&#169;',
        "\xC0" => '&#1102;',
        "\xC1" => '&#1072;',
        "\xC2" => '&#1073;',
        "\xC3" => '&#1094;',
        "\xC4" => '&#1076;',
        "\xC5" => '&#1077;',
        "\xC6" => '&#1092;',
        "\xC7" => '&#1075;',
        "\xC8" => '&#1093;',
        "\xC9" => '&#1080;',
        "\xCA" => '&#1081;',
        "\xCB" => '&#1082;',
        "\xCC" => '&#1083;',
        "\xCD" => '&#1084;',
        "\xCE" => '&#1085;',
        "\xCF" => '&#1086;',
        "\xD0" => '&#1087;',
        "\xD1" => '&#1103;',
        "\xD2" => '&#1088;',
        "\xD3" => '&#1089;',
        "\xD4" => '&#1090;',
        "\xD5" => '&#1091;',
        "\xD6" => '&#1078;',
        "\xD7" => '&#1074;',
        "\xD8" => '&#1100;',
        "\xD9" => '&#1099;',
        "\xDA" => '&#1079;',
        "\xDB" => '&#1096;',
        "\xDC" => '&#1101;',
        "\xDD" => '&#1097;',
        "\xDE" => '&#1095;',
        "\xDF" => '&#1098;',
        "\xE0" => '&#1070;',
        "\xE1" => '&#1040;',
        "\xE2" => '&#1041;',
        "\xE3" => '&#1062;',
        "\xE4" => '&#1044;',
        "\xE5" => '&#1045;',
        "\xE6" => '&#1060;',
        "\xE7" => '&#1043;',
        "\xE8" => '&#1061;',
        "\xE9" => '&#1048;',
        "\xEA" => '&#1049;',
        "\xEB" => '&#1050;',
        "\xEC" => '&#1051;',
        "\xED" => '&#1052;',
        "\xEE" => '&#1053;',
        "\xEF" => '&#1054;',
        "\xF0" => '&#1055;',
        "\xF1" => '&#1071;',
        "\xF2" => '&#1056;',
        "\xF3" => '&#1057;',
        "\xF4" => '&#1058;',
        "\xF5" => '&#1059;',
        "\xF6" => '&#1046;',
        "\xF7" => '&#1042;',
        "\xF8" => '&#1068;',
        "\xF9" => '&#1067;',
        "\xFA" => '&#1047;',
        "\xFB" => '&#1064;',
        "\xFC" => '&#1069;',
        "\xFD" => '&#1065;',
        "\xFE" => '&#1063;',
        "\xFF" => '&#1066;'
    );

    $string = str_replace(array_keys($koi8u), array_values($koi8u), $string);

    return $string;
}

Added functions/decode/ns_4551_1.php.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
<?php

/**
 * functions/decode/ns_4551_1.php
 *
 * This file contains ns_4551-1 decoding function that is needed to read
 * ns_4551-1 encoded mails in non-ns_4551-1 locale.
 *
 * This is the same as ISO-646-NO and is used by some
 * Microsoft programs when sending Norwegian characters
 *
 * @copyright 2004-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: ns_4551_1.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * ns_4551_1 decoding function
 *
 * @param string $string
 * @return string
 */
function charset_decode_ns_4551_1 ($string) {
    /*
     * These characters are:
     * Latin capital letter AE
     * Latin capital letter O with stroke
     * Latin capital letter A with ring above
     * and the same as small letters
     */
    return strtr ($string, "[\\]{|}", "");
}

Added functions/decode/tis_620.php.



















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php

/**
 * decode/tis620.php
 *
 * This file contains tis620 decoding function that is needed to read
 * tis620 encoded mails in non-tis620 locale.
 *
 * Original data taken from:
 *  http://www.inet.co.th/cyberclub/trin/thairef/tis620-iso10646.html
 *
 * Original copyright:
 *  Note: The information contained herein is provided as-is. It was
 *  complied from various references given at the end of the page.
 *  The author (trin@mozart.inet.co.th) believes all information
 *  presented here is accurate.
 *
 *     References
 *  1. [1]TIS 620-2533 Standard for Thai Character Codes for Computers
 *      (in Thai), [2]Thai Industrial Standards Institute
 *  2. [3]Thai Information Technology Standards, On-line resources at the
 *     National Electronics and Computer Technology Center (NECTEC)
 *  3. ISO/IEC 10646-1, [4]ISO/IEC JTC1/SC2
 *  4. [5]Thai block in Unicode 2.1, [6]Unicode Consortium
 *
 *  Links
 *  1. http://www.nectec.or.th/it-standards/std620/std620.htm
 *  2. http://www.tisi.go.th/
 *  3. http://www.nectec.or.th/it-standards/
 *  4. http://wwwold.dkuug.dk/JTC1/SC2/
 *  5. http://charts.unicode.org/Unicode.charts/normal/U0E00.html
 *  6. http://www.unicode.org/
 *
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: tis_620.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode tis620 encoded strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_tis_620 ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'tis-620'))
        return $string;

    $tis620 = array(
        "\xA0" => '&#65535;',
        "\xA1" => '&#3585;',
        "\xA2" => '&#3586;',
        "\xA3" => '&#3587;',
        "\xA4" => '&#3588;',
        "\xA5" => '&#3589;',
        "\xA6" => '&#3590;',
        "\xA7" => '&#3591;',
        "\xA8" => '&#3592;',
        "\xA9" => '&#3593;',
        "\xAA" => '&#3594;',
        "\xAB" => '&#3595;',
        "\xAC" => '&#3596;',
        "\xAD" => '&#3597;',
        "\xAE" => '&#3598;',
        "\xAF" => '&#3599;',
        "\xB0" => '&#3600;',
        "\xB1" => '&#3601;',
        "\xB2" => '&#3602;',
        "\xB3" => '&#3603;',
        "\xB4" => '&#3604;',
        "\xB5" => '&#3605;',
        "\xB6" => '&#3606;',
        "\xB7" => '&#3607;',
        "\xB8" => '&#3608;',
        "\xB9" => '&#3609;',
        "\xBA" => '&#3610;',
        "\xBB" => '&#3611;',
        "\xBC" => '&#3612;',
        "\xBD" => '&#3613;',
        "\xBE" => '&#3614;',
        "\xBF" => '&#3615;',
        "\xC0" => '&#3616;',
        "\xC1" => '&#3617;',
        "\xC2" => '&#3618;',
        "\xC3" => '&#3619;',
        "\xC4" => '&#3620;',
        "\xC5" => '&#3621;',
        "\xC6" => '&#3622;',
        "\xC7" => '&#3623;',
        "\xC8" => '&#3624;',
        "\xC9" => '&#3625;',
        "\xCA" => '&#3626;',
        "\xCB" => '&#3627;',
        "\xCC" => '&#3628;',
        "\xCD" => '&#3629;',
        "\xCE" => '&#3630;',
        "\xCF" => '&#3631;',
        "\xD0" => '&#3632;',
        "\xD1" => '&#3633;',
        "\xD2" => '&#3634;',
        "\xD3" => '&#3635;',
        "\xD4" => '&#3636;',
        "\xD5" => '&#3637;',
        "\xD6" => '&#3638;',
        "\xD7" => '&#3639;',
        "\xD8" => '&#3640;',
        "\xD9" => '&#3641;',
        "\xDA" => '&#3642;',
        "\xDB" => '&#65535;',
        "\xDC" => '&#65535;',
        "\xDD" => '&#65535;',
        "\xDE" => '&#65535;',
        "\xDF" => '&#3647;',
        "\xE0" => '&#3648;',
        "\xE1" => '&#3649;',
        "\xE2" => '&#3650;',
        "\xE3" => '&#3651;',
        "\xE4" => '&#3652;',
        "\xE5" => '&#3653;',
        "\xE6" => '&#3654;',
        "\xE7" => '&#3655;',
        "\xE8" => '&#3656;',
        "\xE9" => '&#3657;',
        "\xEA" => '&#3658;',
        "\xEB" => '&#3659;',
        "\xEC" => '&#3660;',
        "\xED" => '&#3661;',
        "\xEE" => '&#3662;',
        "\xEF" => '&#3663;',
        "\xF0" => '&#3664;',
        "\xF1" => '&#3665;',
        "\xF2" => '&#3666;',
        "\xF3" => '&#3667;',
        "\xF4" => '&#3668;',
        "\xF5" => '&#3669;',
        "\xF6" => '&#3670;',
        "\xF7" => '&#3671;',
        "\xF8" => '&#3672;',
        "\xF9" => '&#3673;',
        "\xFA" => '&#3674;',
        "\xFB" => '&#3675;',
        "\xFC" => '&#65535;',
        "\xFD" => '&#65535;',
        "\xFE" => '&#65535;',
        "\xFF" => '&#65535;'
        );

    $string = str_replace(array_keys($tis620), array_values($tis620), $string);

    return $string;
}

Added functions/decode/us_ascii.php.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
<?php

/**
 * functions/decode/us_ascii.php
 *
 * This file contains us-ascii decoding function that is needed to read
 * us-ascii encoded mails in non-us-ascii locale.
 *
 * Function replaces all 8bit symbols with '?' marks
 *
 * @copyright 2004-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: us_ascii.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * us-ascii decoding function.
 *
 * @param string $string string that has to be cleaned
 * @return string cleaned string
 */
function charset_decode_us_ascii ($string) {
    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'us-ascii'))
        return $string;

    $string = preg_replace("/([\201-\237])/e","'?'",$string);

    /* I don't want to use 0xA0 (\240) in any ranges. RH73 may dislike it */
    $string = str_replace("\240", '?', $string);

    $string = preg_replace("/([\241-\377])/e","'?'",$string);
    return $string;
}

Added functions/decode/utf_8.php.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php

/**
 * functions/decode/utf-8.php - utf-8 decoding functions
 *
 * This file contains utf-8 decoding function that is needed to read
 * utf-8 encoded mails in non-utf-8 locale.
 *
 * Every decoded character consists of n bytes. First byte is octal
 * 300-375, other bytes - always octals 200-277.
 *<pre>
 * Ranges (first byte):
 *                oct     dec    hex
 * Two byte   - 300-337 192-223 C0-DF
 * Three byte - 340-357 224-239 E0-EF
 * Four byte  - 360-367 240-247 F0-F7
 * Five byte  - 370-373 248-251 F8-FB
 * Six byte   - 374-375 252-253 FC-FD
 *
 * \a\b characters are decoded to html code calculated with formula:
 *  octdec(a-300)*64 + octdec(b-200)
 *
 * \a\b\c characters are decoded to html code calculated with formula:
 *  octdec(a-340)*64^2 + octdec(b-200)*64 + octdec(c-200)
 *
 * \a\b\c\d characters are decoded to html code calculated with formula:
 *  octdec(a-360)*64^3 + octdec(b-200)*64^2 +
 *  + octdec(c-200)*64 + octdec(d-200)
 *
 * \a\b\c\d\e characters are decoded to html code calculated with formula:
 *  octdec(a-370)*64^4 + octdec(b-200)*64^3 +
 *  + octdec(c-200)*64^2 + octdec(d-200)*64 + octdec(e-200)
 *
 * \a\b\c\d\e\f characters are decoded to html code calculated with formula:
 *  octdec(a-374)*64^5 + octdec(b-200)*64^4 + octdec(c-200)*64^3 +
 *  + octdec(d-200)*64^2 + octdec(e-200)*64 + octdec(f-200)
 *</pre>
 * @copyright 2003-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: utf_8.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage decode
 */

/**
 * Decode utf-8 strings
 * @param string $string Encoded string
 * @return string Decoded string
 */
function charset_decode_utf_8 ($string) {
    global $squirrelmail_language;

    // Japanese translation uses mbstring function to read utf-8
    if ($squirrelmail_language == 'ja_JP')
        return $string;

    // don't do decoding when there are no 8bit symbols
    if (! sq_is8bit($string,'utf-8'))
        return $string;

    // decode six byte unicode characters
    /* (i think currently there is no such symbol)
    $string = preg_replace("/([\374-\375])([\200-\277])([\200-\277])([\200-\277])([\200-\277])([\200-\277])/e",
    "'&#'.((ord('\\1')-252)*1073741824+(ord('\\2')-200)*16777216+(ord('\\3')-200)*262144+(ord('\\4')-128)*4096+(ord('\\5')-128)*64+(ord('\\6')-128)).';'",
    $string);
    */

    // decode five byte unicode characters
    /* (i think currently there is no such symbol)
    $string = preg_replace("/([\370-\373])([\200-\277])([\200-\277])([\200-\277])([\200-\277])/e",
    "'&#'.((ord('\\1')-248)*16777216+(ord('\\2')-200)*262144+(ord('\\3')-128)*4096+(ord('\\4')-128)*64+(ord('\\5')-128)).';'",
    $string);
    */

    // decode four byte unicode characters
    $string = preg_replace("/([\360-\367])([\200-\277])([\200-\277])([\200-\277])/e",
    "'&#'.((ord('\\1')-240)*262144+(ord('\\2')-128)*4096+(ord('\\3')-128)*64+(ord('\\4')-128)).';'",
    $string);

    // decode three byte unicode characters
    $string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e",
    "'&#'.((ord('\\1')-224)*4096+(ord('\\2')-128)*64+(ord('\\3')-128)).';'",
    $string);

    // decode two byte unicode characters
    $string = preg_replace("/([\300-\337])([\200-\277])/e",
    "'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",
    $string);

    // remove broken unicode
    $string = preg_replace("/[\200-\237]|\240|[\241-\377]/",'?',$string);

    return $string;
}

Added functions/display_messages.php.

























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?php

/**
 * display_messages.php
 *
 * This contains all messages, including information, error, and just
 * about any other message you can think of.
 *
 * @copyright 1999-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: display_messages.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 */

/**
 * including plugin functions
 */
require_once(SM_PATH . 'functions/plugin.php');

function error_message($message, $mailbox, $sort, $startMessage, $color) {

    global $default_folder_prefix;

    $urlMailbox = urlencode($mailbox);
    $string = '<tr><td align="center">' . $message . '</td></tr>'.
              '<tr><td align="center">'.
              '<a href="'.sqm_baseuri()."src/right_main.php?sort=$sort&amp;startMessage=$startMessage&amp;mailbox=$urlMailbox\">";

    if (!empty($default_folder_prefix)) {
        if (strpos($mailbox, $default_folder_prefix) === 0)
            $mailbox = substr($mailbox, strlen($default_folder_prefix));
    }
    
    $string .= sprintf (_("Click here to return to %s"),
                  sm_encode_html_special_chars(imap_utf7_decode_local($mailbox))).
              '</a></td></tr>';
    error_box($string, $color);
}

function plain_error_message($message, $color) {
    error_box($message, $color);
}

function logout_error( $errString, $errTitle = '' ) {
    global $frame_top, $org_logo, $org_name, $org_logo_width, $org_logo_height,
           $hide_sm_attributions, $version, $squirrelmail_language, 
           $color, $theme, $theme_default;

    include_once( SM_PATH . 'functions/page_header.php' );

    $base_uri = sqm_baseuri();

    $logout_link = $base_uri . 'src/login.php';

    list($junk, $errString, $errTitle, $logout_link) 
        = do_hook('logout_error', $errString, $errTitle, $logout_link);

    /* Display width and height like good little people */
    $width_and_height = '';
    if (isset($org_logo_width) && is_numeric($org_logo_width) && $org_logo_width>0) {
        $width_and_height = " width=\"$org_logo_width\"";
    }
    if (isset($org_logo_height) && is_numeric($org_logo_height) && $org_logo_height>0) {
        $width_and_height .= " height=\"$org_logo_height\"";
    }

    if (!isset($frame_top) || $frame_top == '' ) {
        $frame_top = '_top';
    }

    // load default theme if possible
    if (!isset($color) && @file_exists($theme[$theme_default]['PATH']))
        @include ($theme[$theme_default]['PATH']);

    if ( !isset( $color ) ) {
        $color = array();
        $color[0]  = '#dcdcdc';  /* light gray    TitleBar               */
        $color[1]  = '#800000';  /* red                                  */
        $color[2]  = '#cc0000';  /* light red     Warning/Error Messages */
        $color[4]  = '#ffffff';  /* white         Normal Background      */
        $color[7]  = '#0000cc';  /* blue          Links                  */
        $color[8]  = '#000000';  /* black         Normal text            */
    }

    if ( $errTitle == '' ) {
        $errTitle = $errString;
    }
    set_up_language($squirrelmail_language, true);

    displayHtmlHeader( $org_name.' - '.$errTitle, '', false );

    echo '<body text="'.$color[8].'" bgcolor="'.$color[4].'" link="'.$color[7].'" vlink="'.$color[7].'" alink="'.$color[7]."\">\n\n".
         '<center>';

    if (isset($org_logo) && ($org_logo != '')) {
        echo '<img src="'.$org_logo.'" alt="'.sprintf(_("%s Logo"), $org_name).
             "\"$width_and_height /><br />\n";
    }
    echo ( $hide_sm_attributions ? '' :
            '<small>' . sprintf (_("SquirrelMail version %s"), $version) . '<br />'.
            _("By the SquirrelMail Project Team") . "<br /></small>\n" ).
         '<table cellspacing="1" cellpadding="0" bgcolor="'.$color[1].'" width="70%">'.
         '<tr><td>'.
         '<table width="100%" border="0" bgcolor="'.$color[4].'" align="center">'.
         '<tr><td bgcolor="'.$color[0].'" align="center">'.
         '<font color="'.$color[2].'"><b>' . _("ERROR") . '</b></font>'.
         '</td></tr>'.
         '<tr><td align="center">' . $errString . '</td></tr>'.
         '<tr><td bgcolor="'.$color[0].'" align="center">'.
         '<font color="'.$color[2].'"><b>'.
         '<a href="'.$logout_link.'" target="'.$frame_top.'">'.
         _("Go to the login page") . '</a></b></font></td></tr>'.
         '</table></td></tr></table></center></body></html>';
}

function error_box($string, $color) {
    global $pageheader_sent, $org_title;

    if ( !isset( $color ) ) {
        $color = array();
        $color[0]  = '#dcdcdc';  /* light gray    TitleBar               */
        $color[1]  = '#800000';  /* red                                  */
        $color[2]  = '#cc0000';  /* light red     Warning/Error Messages */
        $color[4]  = '#ffffff';  /* white         Normal Background      */
        $color[7]  = '#0000cc';  /* blue          Links                  */
        $color[8]  = '#000000';  /* black         Normal text            */
        $color[9]  = '#ababab';  /* mid-gray      Darker version of #0   */
    }
    if ( !isset( $org_title ) ) {
        $org_title = "SquirrelMail";
    }

    $err = _("ERROR");

    $ret = concat_hook_function('error_box', $string);
    if($ret != '') {
        $string = $ret;
    }

    /* check if the page header has been sent; if not, send it! */
    if(!isset($pageheader_sent) && !$pageheader_sent) {
        /* include this just to be sure */
        include_once( SM_PATH . 'functions/page_header.php' );
        displayHtmlHeader($org_title.': '.$err);
        $pageheader_sent = TRUE;
        echo "<body text=\"$color[8]\" bgcolor=\"$color[4]\" link=\"$color[7]\" vlink=\"$color[7]\" alink=\"$color[7]\">\n\n";
    }

    echo '<table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="'.$color[9].'">'.
         '<tr><td>'.
         '<table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.$color[4].'">'.
         '<tr><td align="center" bgcolor="'.$color[0].'">'.
         '<font color="'.$color[2].'"><b>' . $err . ':</b></font>'.
         '</td></tr><tr><td>'.
         '<table cellpadding="1" cellspacing="5" align="center" border="0">'.
         '<tr>' . html_tag( 'td', $string."\n", 'left') . '</tr></table>'.
         '</td></tr></table></td></tr></table>';
}

/**
 * Adds message that informs about non fatal error that can happen while saving preferences
 * @param string $message error message
 * @since 1.5.1 and 1.4.5
 */
function error_option_save($message) {
    global $optpage_save_error;

    if (! is_array($optpage_save_error) )
        $optpage_save_error=array();

    $optpage_save_error=array_merge($optpage_save_error,array($message));
}

Added functions/encode/cp1251.php.





































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php

/**
 * cp1251 encoding functions
 *
 * takes a string of unicode entities and converts it to a cp1251 encoded string
 * Unsupported characters are replaced with ?.
 *
 * @copyright 2004-2012 The SquirrelMail Project Team
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: cp1251.php 14248 2012-01-02 00:18:17Z pdontthink $
 * @package squirrelmail
 * @subpackage encode
 */

/**
 * Converts string to cp1251
 * @param string $string text with numeric unicode entities
 * @return string cp1251 encoded text
 */
function charset_encode_cp1251 ($string) {
   // don't run encoding function, if there is no encoded characters
   if (! preg_match("'&#[0-9]+;'",$string) ) return $string;

    $string=preg_replace("/&#([0-9]+);/e","unicodetocp1251('\\1')",$string);
    // $string=preg_replace("/&#[xX]([0-9A-F]+);/e","unicodetocp1251(hexdec('\\1'))",$string);

    return $string;
}

/**
 * Return cp1251 symbol when unicode character number is provided
 *
 * This function is used internally by charset_encode_cp1251
 * function. It might be unavailable to other SquirrelMail functions.
 * Don't use it or make sure, that functions/encode/cp1251.php is
 * included.
 *
 * @param int $var decimal unicode value
 * @return string cp1251 character
 */
function unicodetocp1251($var) {

    $cp1251chars=array('160' => "\xA0",
                       '164' => "\xA4",
                       '166' => "\xA6",
                       '167' => "\xA7",
                       '169' => "\xA9",
                       '171' => "\xAB",
                       '172' => "\xAC",
                       '173' => "\xAD",
                       '174' => "\xAE",
                       '176' => "\xB0",
                       '177' => "\xB1",
                       '181' => "\xB5",
                       '182' => "\xB6",
                       '183' => "\xB7",
                       '187' => "\xBB",
                       '1025' => "\xA8",
                       '1026' => "\x80",
                       '1027' => "\x81",
                       '1028' => "\xAA",
                       '1029' => "\xBD",
                       '1030' => "\xB2",
                       '1031' => "\xAF",
                       '1032' => "\xA3",
                       '1033' => "\x8A",
                       '1034' => "\x8C",
                       '1035' => "\x8E",
                       '1036' => "\x8D",
                       '1038' => "\xA1",
                       '1039' => "\x8F",
                       '1040' => "\xC0",
                       '1041' => "\xC1",
                       '1042' => "\xC2",
                       '1043' => "\xC3",
                       '1044' => "\xC4",
                       '1045' => "\xC5",
                       '1046' => "\xC6",
                       '1047' => "\xC7",
                       '1048' => "\xC8",
                       '1049' => "\xC9",
                       '1050' => "\xCA",
                       '1051' => "\xCB",
                       '1052' => "\xCC",
                       '1053' => "\xCD",
                       '1054' => "\xCE",
                       '1055' => "\xCF",
                       '1056' => "\xD0",
                       '1057' => "\xD1",
                       '1058' => "\xD2",
                       '1059' => "\xD3",
                       '1060' => "\xD4",
                       '1061' => "\xD5",
                       '1062' => "\xD6",
                       '1063' => "\xD7",
                       '1064' => "\xD8",
                       '1065' => "\xD9",
                       '1066' => "\xDA",
                       '1067' => "\xDB",
                       '1068' => "\xDC",
                       '1069' => "\xDD",
                       '1070' => "\xDE",
                       '1071' => "\xDF",
                       '1072' => "\xE0",
                       '1073' => "\xE1",
                       '1074' => "\xE2",
                       '1075' => "\xE3",
                       '1076' => "\xE4",
                       '1077' => "\xE5",
                       '1078' => "\xE6",
                       '1079' => "\xE7",
                       '1080' => "\xE8",
                       '1081' => "\xE9",
                       '1082' => "\xEA",
                       '1083' => "\xEB",
                       '1084' => "\xEC",
                       '1085' => "\xED",
                       '1086' => "\xEE",
                       '1087' => "\xEF",
                       '1088' => "\xF0",
                       '1089' => "\xF1",
                       '1090' => "\xF2",
                       '1091' => "\xF3",
                       '1092' => "\xF4",
                       '1093' => "\xF5",
                       '1094' => "\xF6",
                       '1095' => "\xF7",
                       '1096' => "\xF8",
                       '1097' => "\xF9",
                       '1098' => "\xFA",
                       '1099' => "\xFB",
                       '1100' => "\xFC",
                       '1101' => "\xFD",
                       '1102' => "\xFE",
                       '1103' => "\xFF",
                       '1105' => "\xB8",
                       '1106' => "\x90",
                       '1107' => "\x83",
                       '1108' => "\xBA",
                       '1109' => "\xBE",