#!/usr/bin/env python
""" Python Character Mapping Codec for MS PST. The MS PST codec is
used to encode PST files (outlook local storage files) using
'compressible encryption'. This is actually a simple substitution
cipher.
"""
import codecs

### Codec APIs
class Codec(codecs.Codec):
    def encode(self,input,errors='strict'):
        return codecs.charmap_encode(input,errors,encoding_map)

    def decode(self,input,errors='strict'):
        return codecs.charmap_decode(input,errors,decoding_map)

class StreamWriter(Codec,codecs.StreamWriter):
    pass

class StreamReader(Codec,codecs.StreamReader):
    pass

### Decoding Map
## The decoding map is a simple substitution cipher.
decoding_map = codecs.make_identity_dict(range(256))
decoding_map.update( {
     0: 71,
     1: 241,
     2: 180,
     3: 230,
     4: 11,
     5: 106,
     6: 114,
     7: 72,
     8: 133,
     9: 78,
     10: 158,
     11: 235,
     12: 226,
     13: 248,
     14: 148,
     15: 83,
     16: 224,
     17: 187,
     18: 160,
     19: 2,
     20: 232,
     21: 90,
     22: 9,
     23: 171,
     24: 219,
     25: 227,
     26: 186,
     27: 198,
     28: 124,
     29: 195,
     30: 16,
     31: 221,
     32: 57,
     33: 5,
     34: 150,
     35: 48,
     36: 245,
     37: 55,
     38: 96,
     39: 130,
     40: 140,
     41: 201,
     42: 19,
     43: 74,
     44: 107,
     45: 29,
     46: 243,
     47: 251,
     48: 143,
     49: 38,
     50: 151,
     51: 202,
     52: 145,
     53: 23,
     54: 1,
     55: 196,
     56: 50,
     57: 45,
     58: 110,
     59: 49,
     60: 149,
     61: 255,
     62: 217,
     63: 35,
     64: 209,
     65: 0,
     66: 94,
     67: 121,
     68: 220,
     69: 68,
     70: 59,
     71: 26,
     72: 40,
     73: 197,
     74: 97,
     75: 87,
     76: 32,
     77: 144,
     78: 61,
     79: 131,
     80: 185,
     81: 67,
     82: 190,
     83: 103,
     84: 210,
     85: 70,
     86: 66,
     87: 118,
     88: 192,
     89: 109,
     90: 91,
     91: 126,
     92: 178,
     93: 15,
     94: 22,
     95: 41,
     96: 60,
     97: 169,
     98: 3,
     99: 84,
     100: 13,
     101: 218,
     102: 93,
     103: 223,
     104: 246,
     105: 183,
     106: 199,
     107: 98,
     108: 205,
     109: 141,
     110: 6,
     111: 211,
     112: 105,
     113: 92,
     114: 134,
     115: 214,
     116: 20,
     117: 247,
     118: 165,
     119: 102,
     120: 117,
     121: 172,
     122: 177,
     123: 233,
     124: 69,
     125: 33,
     126: 112,
     127: 12,
     128: 135,
     129: 159,
     130: 116,
     131: 164,
     132: 34,
     133: 76,
     134: 111,
     135: 191,
     136: 31,
     137: 86,
     138: 170,
     139: 46,
     140: 179,
     141: 120,
     142: 51,
     143: 80,
     144: 176,
     145: 163,
     146: 146,
     147: 188,
     148: 207,
     149: 25,
     150: 28,
     151: 167,
     152: 99,
     153: 203,
     154: 30,
     155: 77,
     156: 62,
     157: 75,
     158: 27,
     159: 155,
     160: 79,
     161: 231,
     162: 240,
     163: 238,
     164: 173,
     165: 58,
     166: 181,
     167: 89,
     168: 4,
     169: 234,
     170: 64,
     171: 85,
     172: 37,
     173: 81,
     174: 229,
     175: 122,
     176: 137,
     177: 56,
     178: 104,
     179: 82,
     180: 123,
     181: 252,
     182: 39,
     183: 174,
     184: 215,
     185: 189,
     186: 250,
     187: 7,
     188: 244,
     189: 204,
     190: 142,
     191: 95,
     192: 239,
     193: 53,
     194: 156,
     195: 132,
     196: 43,
     197: 21,
     198: 213,
     199: 119,
     200: 52,
     201: 73,
     202: 182,
     203: 18,
     204: 10,
     205: 127,
     206: 113,
     207: 136,
     208: 253,
     209: 157,
     210: 24,
     211: 65,
     212: 125,
     213: 147,
     214: 216,
     215: 88,
     216: 44,
     217: 206,
     218: 254,
     219: 36,
     220: 175,
     221: 222,
     222: 184,
     223: 54,
     224: 200,
     225: 161,
     226: 128,
     227: 166,
     228: 153,
     229: 152,
     230: 168,
     231: 47,
     232: 14,
     233: 129,
     234: 101,
     235: 115,
     236: 228,
     237: 194,
     238: 162,
     239: 138,
     240: 212,
     241: 225,
     242: 17,
     243: 208,
     244: 8,
     245: 139,
     246: 42,
     247: 242,
     248: 237,
     249: 154,
     250: 100,
     251: 63,
     252: 193,
     253: 108,
     254: 249,
     255: 236}
    )

### Encoding Map
encoding_map = codecs.make_encoding_map(decoding_map)

def encode(input,errors='strict'):
    return codecs.charmap_encode(input,errors,encoding_map)

def decode(input,errors='strict'):
    return codecs.charmap_decode(input,errors,decoding_map)

def search_function(x):
    if x=='ms-pst':
        return (encode, decode, StreamReader, StreamWriter)

## This is required to be able to use the ms-pst encoding
codecs.register(search_function)
