comparison src/libpst.c @ 230:42b38d65f7e4

patches from Justin Greer
author Carl Byington <carl@five-ten-sg.com>
date Thu, 10 Sep 2009 13:01:08 -0700
parents fef2214083a4
children fe64279df92b
comparison
equal deleted inserted replaced
229:e7f363452178 230:42b38d65f7e4
63 63
64 64
65 typedef struct pst_holder { 65 typedef struct pst_holder {
66 char **buf; 66 char **buf;
67 FILE *fp; 67 FILE *fp;
68 int base64; 68 int base64; // bool, are we encoding into base64
69 int base64_line_count; // base64 bytes emitted on the current line
70 size_t base64_extra; // count of bytes held in base64_extra_chars
71 char base64_extra_chars[2]; // up to two pending unencoded bytes
69 } pst_holder; 72 } pst_holder;
70 73
71 74
72 typedef struct pst_subblock { 75 typedef struct pst_subblock {
73 char *buf; 76 char *buf;
250 0x27, 0x3b, 0xda, 0xba, 0xd7, 0xc2, 0x26, 0xd4, 0x91, 0x1d, 0xd2, 0x1c, 0x22, 0x33, 0xf8, 0xfa, 253 0x27, 0x3b, 0xda, 0xba, 0xd7, 0xc2, 0x26, 0xd4, 0x91, 0x1d, 0xd2, 0x1c, 0x22, 0x33, 0xf8, 0xfa,
251 0xf1, 0x5a, 0xef, 0xcf, 0x90, 0xb6, 0x8b, 0xb5, 0xbd, 0xc0, 0xbf, 0x08, 0x97, 0x1e, 0x6c, 0xe2, 254 0xf1, 0x5a, 0xef, 0xcf, 0x90, 0xb6, 0x8b, 0xb5, 0xbd, 0xc0, 0xbf, 0x08, 0x97, 0x1e, 0x6c, 0xe2,
252 0x61, 0xe0, 0xc6, 0xc1, 0x59, 0xab, 0xbb, 0x58, 0xde, 0x5f, 0xdf, 0x60, 0x79, 0x7e, 0xb2, 0x8a 255 0x61, 0xe0, 0xc6, 0xc1, 0x59, 0xab, 0xbb, 0x58, 0xde, 0x5f, 0xdf, 0x60, 0x79, 0x7e, 0xb2, 0x8a
253 }; 256 };
254 257
258 static size_t pst_append_holder(pst_holder *h, size_t size, char **buf, size_t z);
255 static int pst_build_desc_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val); 259 static int pst_build_desc_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val);
256 static pst_id2_tree* pst_build_id2(pst_file *pf, pst_index_ll* list); 260 static pst_id2_tree* pst_build_id2(pst_file *pf, pst_index_ll* list);
257 static int pst_build_id_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val); 261 static int pst_build_id_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val);
258 static int pst_chr_count(char *str, char x); 262 static int pst_chr_count(char *str, char x);
259 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size); 263 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size);
260 static size_t pst_ff_getIDblock(pst_file *pf, uint64_t i_id, char** buf); 264 static size_t pst_ff_getIDblock(pst_file *pf, uint64_t i_id, char** buf);
261 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf); 265 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf);
262 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h); 266 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h);
267 static size_t pst_finish_cleanup_holder(pst_holder *h, size_t size);
263 static void pst_free_attach(pst_item_attach *attach); 268 static void pst_free_attach(pst_item_attach *attach);
264 static void pst_free_desc (pst_desc_tree *head); 269 static void pst_free_desc (pst_desc_tree *head);
265 static void pst_free_id2(pst_id2_tree * head); 270 static void pst_free_id2(pst_id2_tree * head);
266 static void pst_free_id (pst_index_ll *head); 271 static void pst_free_id (pst_index_ll *head);
267 static void pst_free_list(pst_mapi_object *list); 272 static void pst_free_list(pst_mapi_object *list);
535 540
536 541
537 pst_binary pst_attach_to_mem(pst_file *pf, pst_item_attach *attach) { 542 pst_binary pst_attach_to_mem(pst_file *pf, pst_item_attach *attach) {
538 pst_index_ll *ptr; 543 pst_index_ll *ptr;
539 pst_binary rc; 544 pst_binary rc;
540 pst_holder h = {&rc.data, NULL, 0}; 545 pst_holder h = {&rc.data, NULL, 0, 0, 0};
541 rc.size = 0; 546 rc.size = 0;
542 rc.data = NULL; 547 rc.data = NULL;
543 DEBUG_ENT("pst_attach_to_mem"); 548 DEBUG_ENT("pst_attach_to_mem");
544 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) { 549 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) {
545 ptr = pst_getID(pf, attach->i_id); 550 ptr = pst_getID(pf, attach->i_id);
558 } 563 }
559 564
560 565
561 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) { 566 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) {
562 pst_index_ll *ptr; 567 pst_index_ll *ptr;
563 pst_holder h = {NULL, fp, 0}; 568 pst_holder h = {NULL, fp, 0, 0, 0};
564 size_t size = 0; 569 size_t size = 0;
565 DEBUG_ENT("pst_attach_to_file"); 570 DEBUG_ENT("pst_attach_to_file");
566 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) { 571 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) {
567 ptr = pst_getID(pf, attach->i_id); 572 ptr = pst_getID(pf, attach->i_id);
568 if (ptr) { 573 if (ptr) {
582 } 587 }
583 588
584 589
585 size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp) { 590 size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp) {
586 pst_index_ll *ptr; 591 pst_index_ll *ptr;
587 pst_holder h = {NULL, fp, 1}; 592 pst_holder h = {NULL, fp, 1, 0, 0};
588 size_t size = 0; 593 size_t size = 0;
589 DEBUG_ENT("pst_attach_to_file_base64"); 594 DEBUG_ENT("pst_attach_to_file_base64");
590 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) { 595 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) {
591 ptr = pst_getID(pf, attach->i_id); 596 ptr = pst_getID(pf, attach->i_id);
592 if (ptr) { 597 if (ptr) {
939 944
940 945
941 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf); 946 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf);
942 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf) { 947 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf) {
943 size_t r; 948 size_t r;
949 DEBUG_ENT("pst_decode_type3");
944 if (pf->do_read64) { 950 if (pf->do_read64) {
945 DEBUG_INFO(("Decoding table3 64\n")); 951 DEBUG_INFO(("Decoding table3 64\n"));
946 DEBUG_HEXDUMPC(buf, sizeof(pst_table3_rec), 0x10); 952 DEBUG_HEXDUMPC(buf, sizeof(pst_table3_rec), 0x10);
947 memcpy(table3_rec, buf, sizeof(pst_table3_rec)); 953 memcpy(table3_rec, buf, sizeof(pst_table3_rec));
948 LE64_CPU(table3_rec->id); 954 LE64_CPU(table3_rec->id);
954 memcpy(&table3_rec32, buf, sizeof(pst_table3_rec32)); 960 memcpy(&table3_rec32, buf, sizeof(pst_table3_rec32));
955 LE32_CPU(table3_rec32.id); 961 LE32_CPU(table3_rec32.id);
956 table3_rec->id = table3_rec32.id; 962 table3_rec->id = table3_rec32.id;
957 r = sizeof(pst_table3_rec32); 963 r = sizeof(pst_table3_rec32);
958 } 964 }
965 DEBUG_RET();
959 return r; 966 return r;
960 } 967 }
961 968
962 969
963 /** Process the index1 b-tree from the pst file and create the 970 /** Process the index1 b-tree from the pst file and create the
3909 3916
3910 3917
3911 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf) { 3918 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf) {
3912 size_t ret; 3919 size_t ret;
3913 pst_id2_tree* ptr; 3920 pst_id2_tree* ptr;
3914 pst_holder h = {buf, NULL, 0}; 3921 pst_holder h = {buf, NULL, 0, 0, 0};
3915 DEBUG_ENT("pst_ff_getID2block"); 3922 DEBUG_ENT("pst_ff_getID2block");
3916 ptr = pst_getID2(id2_head, id2); 3923 ptr = pst_getID2(id2_head, id2);
3917 3924
3918 if (!ptr) { 3925 if (!ptr) {
3919 DEBUG_WARN(("Cannot find id2 value %#"PRIi64"\n", id2)); 3926 DEBUG_WARN(("Cannot find id2 value %#"PRIi64"\n", id2));
3924 DEBUG_RET(); 3931 DEBUG_RET();
3925 return ret; 3932 return ret;
3926 } 3933 }
3927 3934
3928 3935
3936 /** find the actual data from an i_id and send it to the destination
3937 * specified by the pst_holder h. h must be a new empty destination.
3938 *
3939 * @param pf PST file structure
3940 * @param ptr
3941 * @param h specifies the output destination (buffer, file, encoding)
3942 * @return updated size of the output
3943 */
3929 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h) { 3944 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h) {
3930 size_t ret; 3945 size_t ret;
3931 char *b = NULL, *t; 3946 char *b = NULL;
3932 DEBUG_ENT("pst_ff_getID2data"); 3947 DEBUG_ENT("pst_ff_getID2data");
3933 if (!(ptr->i_id & 0x02)) { 3948 if (!(ptr->i_id & 0x02)) {
3934 ret = pst_ff_getIDblock_dec(pf, ptr->i_id, &b); 3949 ret = pst_ff_getIDblock_dec(pf, ptr->i_id, &b);
3935 if (h->buf) { 3950 ret = pst_append_holder(h, (size_t)0, &b, ret);
3936 *(h->buf) = b; 3951 free(b);
3937 } else if ((h->base64 == 1) && h->fp) {
3938 t = pst_base64_encode(b, ret);
3939 if (t) {
3940 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
3941 free(t); // caught by valgrind
3942 }
3943 free(b);
3944 } else if (h->fp) {
3945 (void)pst_fwrite(b, (size_t)1, ret, h->fp);
3946 free(b);
3947 } else {
3948 // h-> does not specify any output
3949 }
3950
3951 } else { 3952 } else {
3952 // here we will assume it is a block that points to others 3953 // here we will assume it is an indirection block that points to others
3953 DEBUG_INFO(("Assuming it is a multi-block record because of it's id\n")); 3954 DEBUG_INFO(("Assuming it is a multi-block record because of it's id\n"));
3954 ret = pst_ff_compile_ID(pf, ptr->i_id, h, (size_t)0); 3955 ret = pst_ff_compile_ID(pf, ptr->i_id, h, (size_t)0);
3955 } 3956 }
3957 ret = pst_finish_cleanup_holder(h, ret);
3956 DEBUG_RET(); 3958 DEBUG_RET();
3957 return ret; 3959 return ret;
3958 } 3960 }
3959 3961
3960 3962
3963 /** find the actual data from an indirection i_id and send it to the destination
3964 * specified by the pst_holder.
3965 *
3966 * @param pf PST file structure
3967 * @param i_id ID of the block to read
3968 * @param h specifies the output destination (buffer, file, encoding)
3969 * @param size number of bytes of data already sent to h
3970 * @return updated size of the output
3971 */
3961 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size) { 3972 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size) {
3962 size_t z, a; 3973 size_t z, a;
3963 uint16_t count, y; 3974 uint16_t count, y;
3964 char *buf3 = NULL, *buf2 = NULL, *t; 3975 char *buf3 = NULL;
3965 char *b_ptr; 3976 char *buf2 = NULL;
3966 int line_count = 0; 3977 char *b_ptr;
3967 char base64_extra_chars[3]; 3978 int line_count = 0;
3968 uint32_t base64_extra = 0;
3969 pst_block_hdr block_hdr; 3979 pst_block_hdr block_hdr;
3970 pst_table3_rec table3_rec; //for type 3 (0x0101) blocks 3980 pst_table3_rec table3_rec; //for type 3 (0x0101) blocks
3971 3981
3972 DEBUG_ENT("pst_ff_compile_ID"); 3982 DEBUG_ENT("pst_ff_compile_ID");
3973 a = pst_ff_getIDblock(pf, i_id, &buf3); 3983 a = pst_ff_getIDblock(pf, i_id, &buf3);
3981 LE16_CPU(block_hdr.index_offset); 3991 LE16_CPU(block_hdr.index_offset);
3982 LE16_CPU(block_hdr.type); 3992 LE16_CPU(block_hdr.type);
3983 LE32_CPU(block_hdr.offset); 3993 LE32_CPU(block_hdr.offset);
3984 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#x)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset)); 3994 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#x)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
3985 3995
3996 count = block_hdr.type;
3997 b_ptr = buf3 + 8;
3998
3999 // For indirect lookups through a table of i_ids, just recurse back into this
4000 // function, letting it concatenate all the data together, and then return the
4001 // total size of the data.
4002 if (block_hdr.index_offset == (uint16_t)0x0201) { // Indirect lookup (depth 2).
4003 for (y=0; y<count; y++) {
4004 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
4005 size = pst_ff_compile_ID(pf, table3_rec.id, h, size);
4006 }
4007 free(buf3);
4008 DEBUG_RET();
4009 return size;
4010 }
4011
3986 if (block_hdr.index_offset != (uint16_t)0x0101) { //type 3 4012 if (block_hdr.index_offset != (uint16_t)0x0101) { //type 3
3987 DEBUG_WARN(("WARNING: not a type 0x0101 buffer, Treating as normal buffer\n")); 4013 DEBUG_WARN(("WARNING: not a type 0x0101 buffer, Treating as normal buffer\n"));
3988 if (pf->encryption) (void)pst_decrypt(i_id, buf3, a, pf->encryption); 4014 if (pf->encryption) (void)pst_decrypt(i_id, buf3, a, pf->encryption);
3989 if (h->buf) 4015 size = pst_append_holder(h, size, &buf3, a);
3990 *(h->buf) = buf3; 4016 free(buf3);
3991 else if (h->base64 == 1 && h->fp) {
3992 t = pst_base64_encode(buf3, a);
3993 if (t) {
3994 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
3995 free(t); // caught by valgrind
3996 }
3997 free(buf3);
3998 } else if (h->fp) {
3999 (void)pst_fwrite(buf3, (size_t)1, a, h->fp);
4000 free(buf3);
4001 } else {
4002 // h-> does not specify any output
4003 }
4004 DEBUG_RET(); 4017 DEBUG_RET();
4005 return a; 4018 return size;
4006 } 4019 }
4007 count = block_hdr.type; 4020
4008 b_ptr = buf3 + 8;
4009 line_count = 0;
4010 for (y=0; y<count; y++) { 4021 for (y=0; y<count; y++) {
4011 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr); 4022 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
4012 z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2); 4023 z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
4013 if (!z) { 4024 if (!z) {
4014 DEBUG_WARN(("call to getIDblock returned zero %i\n", z)); 4025 DEBUG_WARN(("call to getIDblock returned zero %i\n", z));
4015 if (buf2) free(buf2); 4026 if (buf2) free(buf2);
4016 free(buf3); 4027 free(buf3);
4017 DEBUG_RET(); 4028 DEBUG_RET();
4018 return z; 4029 return z;
4019 } 4030 }
4020 if (h->buf) { 4031 size = pst_append_holder(h, size, &buf2, z);
4021 *(h->buf) = realloc(*(h->buf), size+z+1); 4032 }
4022 DEBUG_INFO(("appending read data of size %i onto main buffer from pos %i\n", z, size)); 4033
4023 memcpy(&((*(h->buf))[size]), buf2, z); 4034 free(buf3);
4024 } else if ((h->base64 == 1) && h->fp) { 4035 if (buf2) free(buf2);
4025 if (base64_extra) { 4036 DEBUG_RET();
4026 // include any bytes left over from the last encoding 4037 return size;
4027 buf2 = (char*)realloc(buf2, z+base64_extra); 4038 }
4028 memmove(buf2+base64_extra, buf2, z); 4039
4029 memcpy(buf2, base64_extra_chars, base64_extra); 4040
4030 z += base64_extra; 4041 /** append (buf,z) data to the output destination (h,size)
4031 } 4042 *
4032 4043 * @param h specifies the output destination (buffer, file, encoding)
4033 // find out how many bytes will be left over after this encoding and save them 4044 * @param size number of bytes of data already sent to h
4034 base64_extra = z % 3; 4045 * @param buf reference to a pointer to the buffer to be appended to the destination
4035 if (base64_extra) { 4046 * @param z number of bytes in buf
4036 z -= base64_extra; 4047 * @return updated size of the output, buffer pointer possibly reallocated
4037 memcpy(base64_extra_chars, buf2+z, base64_extra); 4048 */
4038 } 4049 static size_t pst_append_holder(pst_holder *h, size_t size, char **buf, size_t z) {
4039 4050 char *t;
4040 // encode this chunk 4051 DEBUG_ENT("pst_append_holder");
4041 t = pst_base64_encode_multiple(buf2, z, &line_count); 4052
4042 if (t) { 4053 // raw append to a buffer
4043 DEBUG_INFO(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size)); 4054 if (h->buf) {
4044 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp); 4055 *(h->buf) = realloc(*(h->buf), size+z+1);
4045 free(t); // caught by valgrind 4056 DEBUG_INFO(("appending read data of size %i onto main buffer from pos %i\n", z, size));
4046 } 4057 memcpy(*(h->buf)+size, *buf, z);
4047 } else if (h->fp) { 4058
4048 DEBUG_INFO(("writing %i bytes to file. Currently %i\n", z, size)); 4059 // base64 encoding to a file
4049 (void)pst_fwrite(buf2, (size_t)1, z, h->fp); 4060 } else if ((h->base64 == 1) && h->fp) {
4050 } else { 4061 //
4051 // h-> does not specify any output 4062 if (h->base64_extra) {
4052 } 4063 // include any bytes left over from the last encoding
4053 size += z; 4064 *buf = (char*)realloc(*buf, z+h->base64_extra);
4054 } 4065 memmove(*buf+h->base64_extra, *buf, z);
4055 if ((h->base64 == 1) && h->fp && base64_extra) { 4066 memcpy(*buf, h->base64_extra_chars, h->base64_extra);
4067 z += h->base64_extra;
4068 }
4069
4070 // find out how many bytes will be left over after this encoding and save them
4071 h->base64_extra = z % 3;
4072 if (h->base64_extra) {
4073 z -= h->base64_extra;
4074 memcpy(h->base64_extra_chars, *buf+z, h->base64_extra);
4075 }
4076
4077 // encode this chunk
4078 t = pst_base64_encode_multiple(*buf, z, &h->base64_line_count);
4079 if (t) {
4080 DEBUG_INFO(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
4081 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
4082 free(t); // caught by valgrind
4083 }
4084
4085 // raw append to a file
4086 } else if (h->fp) {
4087 DEBUG_INFO(("writing %i bytes to file. Currently %i\n", z, size));
4088 (void)pst_fwrite(*buf, (size_t)1, z, h->fp);
4089
4090 // null output
4091 } else {
4092 // h-> does not specify any output
4093 }
4094 DEBUG_RET();
4095 return size+z;
4096 }
4097
4098
4099 /** finish cleanup for base64 encoding to a file with extra bytes left over
4100 *
4101 * @param h specifies the output destination (buffer, file, encoding)
4102 * @param size number of bytes of data already sent to h
4103 * @return updated size of the output
4104 */
4105 static size_t pst_finish_cleanup_holder(pst_holder *h, size_t size) {
4106 char *t;
4107 DEBUG_ENT("pst_finish_cleanup_holder");
4108 if ((h->base64 == 1) && h->fp && h->base64_extra) {
4056 // need to encode any bytes left over 4109 // need to encode any bytes left over
4057 t = pst_base64_encode_multiple(base64_extra_chars, (size_t)base64_extra, &line_count); 4110 t = pst_base64_encode_multiple(h->base64_extra_chars, h->base64_extra, &h->base64_line_count);
4058 if (t) { 4111 if (t) {
4059 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp); 4112 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
4060 free(t); // caught by valgrind 4113 free(t); // caught by valgrind
4061 } 4114 }
4062 } 4115 size += h->base64_extra;
4063 free(buf3); 4116 }
4064 if (buf2) free(buf2);
4065 DEBUG_RET(); 4117 DEBUG_RET();
4066 return size; 4118 return size;
4067 } 4119 }
4068 4120
4069 4121
4244 static const char* codepage(int cp, int buflen, char* result) { 4296 static const char* codepage(int cp, int buflen, char* result) {
4245 switch (cp) { 4297 switch (cp) {
4246 case 932 : return "iso-2022-jp"; 4298 case 932 : return "iso-2022-jp";
4247 case 936 : return "gb2313"; 4299 case 936 : return "gb2313";
4248 case 950 : return "big5"; 4300 case 950 : return "big5";
4301 case 1200 : return "ucs-2le";
4302 case 1201 : return "ucs-2be";
4249 case 20127 : return "us-ascii"; 4303 case 20127 : return "us-ascii";
4250 case 20269 : return "iso-6937"; 4304 case 20269 : return "iso-6937";
4251 case 20865 : return "iso-8859-15"; 4305 case 20865 : return "iso-8859-15";
4252 case 20866 : return "koi8-r"; 4306 case 20866 : return "koi8-r";
4253 case 21866 : return "koi8-u"; 4307 case 21866 : return "koi8-u";