1<?php
2
3/*
4 *  pgn4web javascript chessboard
5 *  copyright (C) 2009-2012 Paolo Casaschi
6 *  see README file and http://pgn4web.casaschi.net
7 *  for credits, license and more details
8 *
9 *  Huffman encoding/decoding derived from code at http://rumkin.com/tools/compression/compress_huff.php
10 */
11
12function BitsToBytes($i) {
13  global $encodingCharSet, $encodingVersion;
14
15  $o = 0;
16  if (substr($i, 0, 1) == '1') { $o += 32; }
17  if (substr($i, 1, 1) == '1') { $o += 16; }
18  if (substr($i, 2, 1) == '1') { $o +=  8; }
19  if (substr($i, 3, 1) == '1') { $o +=  4; }
20  if (substr($i, 4, 1) == '1') { $o +=  2; }
21  if (substr($i, 5, 1) == '1') { $o +=  1; }
22
23  return substr($encodingCharSet, $o, 1);
24}
25
26function EncodePGN($ov) {
27
28  global $encodingCharSet, $encodingVersion;
29  $encodingCharSet = "$0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
30  $encodingVersion = 1;
31  /*
32   * version 1 of PGN encoding:
33   *   encodedPGN = nnn$xxx0
34   *   nnn = number representing bytes length of the decoded message
35   *   $ = dollar char (delimiter for length info)
36   *   xxx = encoded text (using $LetterCodes below)
37   *   0 = zero char (version marker)
38   */
39
40  $LetterCodes[0]   = '00111111111111110';
41  $LetterCodes[1]   = '0101101';
42  $LetterCodes[2]   = '00111111111111111';
43  $LetterCodes[3]   = '00111111111111100';
44  $LetterCodes[4]   = '00111111111111101';
45  $LetterCodes[5]   = '000011111111111010';
46  $LetterCodes[6]   = '000011111111111011';
47  $LetterCodes[7]   = '000011111111111000';
48  $LetterCodes[8]   = '000011111111111001';
49  $LetterCodes[9]   = '000011111111111110';
50  $LetterCodes[10]  = '0101100';
51  $LetterCodes[11]  = '000011111111111111';
52  $LetterCodes[12]  = '000011111111111100';
53  $LetterCodes[13]  = '0011100';
54  $LetterCodes[14]  = '000011111111111101';
55  $LetterCodes[15]  = '000011111111110010';
56  $LetterCodes[16]  = '000011111111110011';
57  $LetterCodes[17]  = '000011111111110000';
58  $LetterCodes[18]  = '000011111111110001';
59  $LetterCodes[19]  = '000011111111110110';
60  $LetterCodes[20]  = '000011111111110111';
61  $LetterCodes[21]  = '000011111111110100';
62  $LetterCodes[22]  = '000011111111110101';
63  $LetterCodes[23]  = '1111111111110101010';
64  $LetterCodes[24]  = '1111111111110101011';
65  $LetterCodes[25]  = '1111111111110101000';
66  $LetterCodes[26]  = '1111111111110101001';
67  $LetterCodes[27]  = '1111111111110101110';
68  $LetterCodes[28]  = '1111111111110101111';
69  $LetterCodes[29]  = '1111111111110101100';
70  $LetterCodes[30]  = '1111111111110101101';
71  $LetterCodes[31]  = '1111111111110100010';
72  $LetterCodes[32]  = '1000';
73  $LetterCodes[33]  = '101111111110';
74  $LetterCodes[34]  = '00010';
75  $LetterCodes[35]  = '11111111110';
76  $LetterCodes[36]  = '0011111111110';
77  $LetterCodes[37]  = '1011111111110';
78  $LetterCodes[38]  = '00001111111110';
79  $LetterCodes[39]  = '00111111110';
80  $LetterCodes[40]  = '0011101';
81  $LetterCodes[41]  = '111111110';
82  $LetterCodes[42]  = '11001111111110';
83  $LetterCodes[43]  = '1111110';
84  $LetterCodes[44]  = '000011110';
85  $LetterCodes[45]  = '0011110';
86  $LetterCodes[46]  = '00000';
87  $LetterCodes[47]  = '0110110';
88  $LetterCodes[48]  = '010100';
89  $LetterCodes[49]  = '00110';
90  $LetterCodes[50]  = '01000';
91  $LetterCodes[51]  = '01100';
92  $LetterCodes[52]  = '11000';
93  $LetterCodes[53]  = '11010';
94  $LetterCodes[54]  = '11100';
95  $LetterCodes[55]  = '001010';
96  $LetterCodes[56]  = '011100';
97  $LetterCodes[57]  = '0001110';
98  $LetterCodes[58]  = '001111111110';
99  $LetterCodes[59]  = '1111111111100';
100  $LetterCodes[60]  = '10111111110';
101  $LetterCodes[61]  = '1100110100';
102  $LetterCodes[62]  = '000011111110';
103  $LetterCodes[63]  = '00011110';
104  $LetterCodes[64]  = '1100111111110';
105  $LetterCodes[65]  = '110011100';
106  $LetterCodes[66]  = '000010';
107  $LetterCodes[67]  = '10111110';
108  $LetterCodes[68]  = '00111110';
109  $LetterCodes[69]  = '0010110';
110  $LetterCodes[70]  = '110011101';
111  $LetterCodes[71]  = '110011110';
112  $LetterCodes[72]  = '1100110101';
113  $LetterCodes[73]  = '0010111110';
114  $LetterCodes[74]  = '11001111110';
115  $LetterCodes[75]  = '101110';
116  $LetterCodes[76]  = '1100111110';
117  $LetterCodes[77]  = '101111110';
118  $LetterCodes[78]  = '000110';
119  $LetterCodes[79]  = '0101110';
120  $LetterCodes[80]  = '1011110';
121  $LetterCodes[81]  = '011101';
122  $LetterCodes[82]  = '11101';
123  $LetterCodes[83]  = '11001100';
124  $LetterCodes[84]  = '001111110';
125  $LetterCodes[85]  = '0000111110';
126  $LetterCodes[86]  = '1111111110';
127  $LetterCodes[87]  = '11111110';
128  $LetterCodes[88]  = '110011111110';
129  $LetterCodes[89]  = '0000111111110';
130  $LetterCodes[90]  = '1011111110';
131  $LetterCodes[91]  = '10010';
132  $LetterCodes[92]  = '00111111111110';
133  $LetterCodes[93]  = '10011';
134  $LetterCodes[94]  = '11001111111111';
135  $LetterCodes[95]  = '11111111111010';
136  $LetterCodes[96]  = '10111111111110';
137  $LetterCodes[97]  = '11110';
138  $LetterCodes[98]  = '011010';
139  $LetterCodes[99]  = '10100';
140  $LetterCodes[100] = '11011';
141  $LetterCodes[101] = '00100';
142  $LetterCodes[102] = '010010';
143  $LetterCodes[103] = '010011';
144  $LetterCodes[104] = '011110';
145  $LetterCodes[105] = '0000110';
146  $LetterCodes[106] = '00001111110';
147  $LetterCodes[107] = '00001110';
148  $LetterCodes[108] = '110010';
149  $LetterCodes[109] = '000111110';
150  $LetterCodes[110] = '010101';
151  $LetterCodes[111] = '111110';
152  $LetterCodes[112] = '0110111';
153  $LetterCodes[113] = '1100110110';
154  $LetterCodes[114] = '0111110';
155  $LetterCodes[115] = '0111111';
156  $LetterCodes[116] = '10110';
157  $LetterCodes[117] = '0101111';
158  $LetterCodes[118] = '00101110';
159  $LetterCodes[119] = '000111111';
160  $LetterCodes[120] = '10101';
161  $LetterCodes[121] = '001011110';
162  $LetterCodes[122] = '1100110111';
163  $LetterCodes[123] = '0010111111';
164  $LetterCodes[124] = '001111111111110';
165  $LetterCodes[125] = '0011111110';
166  $LetterCodes[126] = '111111111110110';
167  $LetterCodes[127] = '1111111111110100011';
168  $LetterCodes[128] = '1111111111110100000';
169  $LetterCodes[129] = '1111111111110100001';
170  $LetterCodes[130] = '1111111111110100110';
171  $LetterCodes[131] = '1111111111110100111';
172  $LetterCodes[132] = '1111111111110100100';
173  $LetterCodes[133] = '1111111111110100101';
174  $LetterCodes[134] = '1111111111110111010';
175  $LetterCodes[135] = '1111111111110111011';
176  $LetterCodes[136] = '1111111111110111000';
177  $LetterCodes[137] = '1111111111110111001';
178  $LetterCodes[138] = '1111111111110111110';
179  $LetterCodes[139] = '1111111111110111111';
180  $LetterCodes[140] = '1111111111110111100';
181  $LetterCodes[141] = '1111111111110111101';
182  $LetterCodes[142] = '1111111111110110010';
183  $LetterCodes[143] = '1111111111110110011';
184  $LetterCodes[144] = '1111111111110110000';
185  $LetterCodes[145] = '1111111111110110001';
186  $LetterCodes[146] = '1111111111110110110';
187  $LetterCodes[147] = '1111111111110110111';
188  $LetterCodes[148] = '1111111111110110100';
189  $LetterCodes[149] = '1111111111110110101';
190  $LetterCodes[150] = '1111111111110001010';
191  $LetterCodes[151] = '1111111111110001011';
192  $LetterCodes[152] = '1111111111110001000';
193  $LetterCodes[153] = '1111111111110001001';
194  $LetterCodes[154] = '1111111111110001110';
195  $LetterCodes[155] = '1111111111110001111';
196  $LetterCodes[156] = '1111111111110001100';
197  $LetterCodes[157] = '1111111111110001101';
198  $LetterCodes[158] = '1111111111110000010';
199  $LetterCodes[159] = '1111111111110000011';
200  $LetterCodes[160] = '1111111111110000000';
201  $LetterCodes[161] = '1111111111110000001';
202  $LetterCodes[162] = '1111111111110000110';
203  $LetterCodes[163] = '1111111111110000111';
204  $LetterCodes[164] = '1111111111110000100';
205  $LetterCodes[165] = '1111111111110000101';
206  $LetterCodes[166] = '1111111111110011010';
207  $LetterCodes[167] = '1111111111110011011';
208  $LetterCodes[168] = '1111111111110011000';
209  $LetterCodes[169] = '1111111111110011001';
210  $LetterCodes[170] = '1111111111110011110';
211  $LetterCodes[171] = '1111111111110011111';
212  $LetterCodes[172] = '1111111111110011100';
213  $LetterCodes[173] = '1111111111110011101';
214  $LetterCodes[174] = '1111111111110010010';
215  $LetterCodes[175] = '1111111111110010011';
216  $LetterCodes[176] = '1111111111110010000';
217  $LetterCodes[177] = '1111111111110010001';
218  $LetterCodes[178] = '1111111111110010110';
219  $LetterCodes[179] = '1111111111110010111';
220  $LetterCodes[180] = '1111111111110010100';
221  $LetterCodes[181] = '1111111111110010101';
222  $LetterCodes[182] = '1111111111111101010';
223  $LetterCodes[183] = '1111111111111101011';
224  $LetterCodes[184] = '1111111111111101000';
225  $LetterCodes[185] = '1111111111111101001';
226  $LetterCodes[186] = '1111111111111101110';
227  $LetterCodes[187] = '1111111111111101111';
228  $LetterCodes[188] = '1111111111111101100';
229  $LetterCodes[189] = '1111111111111101101';
230  $LetterCodes[190] = '1111111111111100010';
231  $LetterCodes[191] = '1111111111111100011';
232  $LetterCodes[192] = '1111111111111100000';
233  $LetterCodes[193] = '1111111111111100001';
234  $LetterCodes[194] = '1111111111111100110';
235  $LetterCodes[195] = '1111111111111100111';
236  $LetterCodes[196] = '1111111111111100100';
237  $LetterCodes[197] = '1111111111111100101';
238  $LetterCodes[198] = '1111111111111111010';
239  $LetterCodes[199] = '1111111111111111011';
240  $LetterCodes[200] = '1111111111111111000';
241  $LetterCodes[201] = '1111111111111111001';
242  $LetterCodes[202] = '1111111111111111110';
243  $LetterCodes[203] = '1111111111111111111';
244  $LetterCodes[204] = '1111111111111111100';
245  $LetterCodes[205] = '1111111111111111101';
246  $LetterCodes[206] = '1111111111111110010';
247  $LetterCodes[207] = '1111111111111110011';
248  $LetterCodes[208] = '1111111111111110000';
249  $LetterCodes[209] = '1111111111111110001';
250  $LetterCodes[210] = '1111111111111110110';
251  $LetterCodes[211] = '1111111111111110111';
252  $LetterCodes[212] = '1111111111111110100';
253  $LetterCodes[213] = '1111111111111110101';
254  $LetterCodes[214] = '1111111111111001010';
255  $LetterCodes[215] = '1111111111111001011';
256  $LetterCodes[216] = '1111111111111001000';
257  $LetterCodes[217] = '1111111111111001001';
258  $LetterCodes[218] = '1111111111111001110';
259  $LetterCodes[219] = '1111111111111001111';
260  $LetterCodes[220] = '1111111111111001100';
261  $LetterCodes[221] = '1111111111111001101';
262  $LetterCodes[222] = '1111111111111000010';
263  $LetterCodes[223] = '1111111111111000011';
264  $LetterCodes[224] = '1111111111111000000';
265  $LetterCodes[225] = '1111111111111000001';
266  $LetterCodes[226] = '1111111111111000110';
267  $LetterCodes[227] = '1111111111111000111';
268  $LetterCodes[228] = '1111111111111000100';
269  $LetterCodes[229] = '1111111111111000101';
270  $LetterCodes[230] = '1111111111111011010';
271  $LetterCodes[231] = '1111111111111011011';
272  $LetterCodes[232] = '1111111111111011000';
273  $LetterCodes[233] = '1111111111111011001';
274  $LetterCodes[234] = '1111111111111011110';
275  $LetterCodes[235] = '1111111111111011111';
276  $LetterCodes[236] = '1111111111111011100';
277  $LetterCodes[237] = '1111111111111011101';
278  $LetterCodes[238] = '1111111111111010010';
279  $LetterCodes[239] = '1111111111111010011';
280  $LetterCodes[240] = '1111111111111010000';
281  $LetterCodes[241] = '1111111111111010001';
282  $LetterCodes[242] = '1111111111111010110';
283  $LetterCodes[243] = '1111111111111010111';
284  $LetterCodes[244] = '1111111111111010100';
285  $LetterCodes[245] = '1111111111111010101';
286  $LetterCodes[246] = '10111111111111010';
287  $LetterCodes[247] = '10111111111111011';
288  $LetterCodes[248] = '10111111111111000';
289  $LetterCodes[249] = '10111111111111001';
290  $LetterCodes[250] = '10111111111111110';
291  $LetterCodes[251] = '10111111111111111';
292  $LetterCodes[252] = '10111111111111100';
293  $LetterCodes[253] = '10111111111111101';
294  $LetterCodes[254] = '1111111111101110';
295  $LetterCodes[255] = '1111111111101111';
296
297  # Build resulting data stream
298  # The bits string could get very large
299  $bits = "";
300  $bytes = strlen($ov) . "$";
301  for ($i = 0; $i < strlen($ov); $i++) {
302    # converts ASCII chars above 255 to a star (code 42) avoiding decoding failure
303    if (ord(substr($ov, $i, 1)) > 255) { $bits = $bits . $LetterCodes[42]; }
304    else { $bits = $bits . $LetterCodes[ord(substr($ov, $i, 1))]; }
305    while (strlen($bits) > 5) {
306      $bytes = $bytes . BitsToBytes($bits);
307      $bits = substr($bits, 6);
308    }
309  }
310  $bytes = $bytes . BitsToBytes($bits);
311
312  $bytes = $bytes . substr($encodingCharSet, $encodingVersion, 1);
313
314  return $bytes;
315}
316
317?>
318