Source

blake / blake.h

Full commit
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
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
/*
$Id: blake.h,v 2.3.3 2008/01/27 11:37:00 overlord Exp $

Copyright (C) 2001-2008 Daybo Logic.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/*
  Blake library by David Duncan Ross Palmer
  http://www.daybologic.co.uk/mailddrp

  Blake is a protocol for talking to OverChat servers.  All clients
  should use this library to talk to the server(s).  Full documentation
  for the use of this shared library is at this address:
  http://www.daybologic.co.uk/overchat/blake.html

  Note: Above URL is no longer valid and we probably won't have
  complete documentation online for quite some time because I am too
  busy to complete it.

  Maintainer:
  David Duncan Ross Palmer <http://www.daybologic.co.uk/mailddrp>
*/
/*-------------------------------------------------------------------------*/
/* Pre-requisites for including dlstdinc.h */
#include "dlstdinc.h"
/*-------------------------------------------------------------------------*/
#ifndef INC_BLAKE_H
#define INC_BLAKE_H
/*-------------------------------------------------------------------------*/
/*
  Export/import definition for easy library building.  Do not be confused
  by BLAKE_AS_DLL.  BLAKE_AS_DLL means we are being built as a shared lib
  _OR_ dynamic link library.  You can use BLAKE_AS_DLL from overchat_config.h
  (written by confgure) to determine which you are being built as.

  Note: Don't define BLAKE_SOURCE, that is for internal use
*/

/*
  Visual C++ does this automatically for us so I might as well make use of it
*/
#if ( defined(BLAKE_EXPORTS) || defined(BLAKE_IMPORTS) )
#  ifndef BLAKE_AS_DLL
#    define BLAKE_AS_DLL
#  endif
#endif

#if ( defined(BLAKE_AS_DLL) && defined(BLAKE_SOURCE) && defined(__WIN32__) )
#  define BLAKEAPI(ret) __declspec(dllexport) ##ret __stdcall
#elif ( defined(BLAKE_AS_DLL) && !defined(BLAKE_SOURCE) && defined(__WIN32__) )
#  define BLAKEAPI(ret) __declspec(dllimport) ##ret __stdcall
#else
#  define BLAKEAPI(ret) ret
#endif

/*
  Ensure all structure packing is aligned at DWORD boundries for compatibillity
  with VB and most other 32-bit applications.
*/
#if ( defined(BLAKE_AS_DLL) && defined(__WIN32__) )
# include <pshpack4.h>
#endif

/* Ensure C++ does not treat as mangled symbols */
#ifdef __cplusplus
  extern "C" {
#endif

/*
  The Blake protocol, servers and clients rely on some fixed settings
  which everybody should be aware of globally.  They are not config-
  urable so don't change them unless rebuilding the entire OverChat
  project.  Changes to the values must then be documented in internal
  Blake documentation.
*/
#define BLAKE_NICK_LIMIT (32)
#define BLAKE_PASS_LIMIT (32)
#define BLAKE_EMAIL_LIMIT (128)
#define BLAKE_REALNAME_LIMIT (64)
#define BLAKE_JOB_LIMIT (64)
#define BLAKE_WWW_LIMIT (128)
#define BLAKE_ROOMNAME_LIMIT (20)
#define BLAKE_CHUMGROUPNAME_LIMIT (128)
#define BLAKE_MSG_LIMIT_BYTES (8192)

/*
  General common sense definitions of time
*/
#define BLAKE_MINUTE (60)               /* 60 seconds in one minute */
#define BLAKE_HOUR (3600)               /* 3,600 seconds in an hour */
#define BLAKE_DAY ((BLAKE_HOUR)*24)     /* 24 hours in a day        */
#define BLAKE_YEAR ((BLAKE_DAY)*365)    /* Typical year is 365 days */

/*
  These values aren't so hard coded as the above but their values are
  of some consequence.  For example, if the maximum packet size is
  set smaller that a real Blake packet can be, problems will occur
  (dropped packets in some clients) and TX/RX multipliers are reasonably
  tuned to hold enough packets but not waste memory per client in the
  server.  I wouldn't recommend having seperately sizes RX and TX
  buffers.  Remember that TX/RX SZ are multipliers of the packet size, not
  bytes.
*/
#define BLAKE_NET_PKTMAXSZ (10240) /* Max size in bytes of one Blake packet */
#define BLAKE_NET_TXSZ (25) /* Per connection */
#define BLAKE_NET_RXSZ (BLAKE_NET_TXSZ)

/*
  The Blake basic version information.  This should be changed just
  after a release. Ready for the new version being developed.  See also
  blake_GetVersion(), which returns this dynamically.  See also below,
  where we define the actual status of the project on release.
*/
#define BLAKE_VERMAJ   (0)
#define BLAKE_VERMIN   (2)
#define BLAKE_VERPATCH (4)

/*
  Blake extended version status information.  This is returned
  dynamically via blake_GetVersionEx().  First we define the bits, then
  combine them into a state word.  This word is 16-bits long.
*/
#define BLAKE_VEREX_DEBUG (0x1) /* Bit 0: Debug build */
#define BLAKE_VEREX_PRIVATE (0x2) /* Bit 1: Private build */
#define BLAKE_VEREX_SPECIAL (0x4) /* Bit 2: Special build */
#define BLAKE_VEREX_PRERELEASE (0x8) /* Bit 3: Pre-release */
#define BLAKE_VEREX_BETA (0x10) /* Bit 4: beta Pre-release */
#define BLAKE_VEREX_PREEMPT (0x20) /* Bit 5: Pre-emptive threads */
/* The remaining bits are undefined and must be zero until defined */
#define BLAKE_VEREX_UNDEFINED_6 (0x40)
#define BLAKE_VEREX_UNDEFINED_7 (0x80)
#define BLAKE_VEREX_UNDEFINED_8 (0x100)
#define BLAKE_VEREX_UNDEFINED_9 (0x200)
#define BLAKE_VEREX_UNDEFINED_A (0x400)
#define BLAKE_VEREX_UNDEFINED_B (0x800)
#define BLAKE_VEREX_UNDEFINED_C (0x1000)
#define BLAKE_VEREX_UNDEFINED_D (0x2000)
#define BLAKE_VEREX_UNDEFINED_E (0x4000)
#define BLAKE_VEREX_UNDEFINED_F (0x8000)

/*
  We don't want users of Blake to be dependent on hashing hardcoded lengths
  in the DayboCrypt library incase the source is not available to them,
  therefore Blake independently hard codes the well known, supported hash
  lengths in bytes.  These don't conflict with DayboCrypt and I recommend
  you use these if your code depends on Blake and not DayboCrypt's header.
  These values do not change, anybody caught changing them will be in trouble.
*/
#define BLAKE_MD2HASHLEN    (128/8)
#define BLAKE_MD4HASHLEN    (128/8)
#define BLAKE_MD5HASHLEN    (128/8)
#define BLAKE_SHA1HASHLEN   (160/8)
#define BLAKE_SHA224HASHLEN (244/8)
#define BLAKE_SHA256HASHLEN (256/8)
#define BLAKE_SHA384HASHLEN (384/8)
#define BLAKE_SHA512HASHLEN (512/8)

/*
  C and C++ mixing macros.  For any function which is a C callable function
  existing in a C++ module, OVERCHAT_C_IN_CPP must be placed _before_ the
  declaration.  In C++, void in a prototype is not expected, in C it is.
  Therefore if there are no paramters to a function, OVERCHAT_PROTOTYPE_VOID
  must be placed in place of the parameter list.  For example:
  OVERCHAT_C_IN_CPP void Function(OVERCHAT_PROTOTYPE_VOID);
*/
#ifdef __cplusplus /* C++ */
# define OVERCHAT_C_IN_CPP extern "C"
# define OVERCHAT_PROTOTYPE_VOID
#else /* C */
# define OVERCHAT_C_IN_CPP
# define OVERCHAT_PROTOTYPE_VOID void
#endif /*__cplusplus*/

/*
  These definitions are used within Blake and within the OverChat server.  You
  are welcome to use them too.
*/
#define BLAKE_MIN(a,b) ((((a)) > ((b))) ? (b) : (a)) /* Return minumum of a pair */
#define BLAKE_MAX(a,b) (((a) > (b)) ? (a) : (b))     /* Return maximum of a pair */

/*
  This MSG_BUFF_SIZE value is used for creating string buffers for
  sprintf() creation of messages.  For logging and other purposes.
  However, please remember that any new code which uses it will get
  broken.  I _do_ plan to remove this and replace it with a C based
  string class to increase stabillity/security.
*/
#define MSG_BUFF_SIZE (4096)

/*
  Any of these error codes can be returned by Blake functions:
*/
enum blakeError {
  blakeSuccess,
  blakeNotEnoughMem,          /* Not enough memory to complete the operation */
  blakeInvalidParam,          /* Passed parameters were not acceptable */
  blakeNoCallback,            /* No callback could process the packet or event */
  blakeCallbackFail,          /* The callback routine returned failure */
  blakeBufferTooSmall,        /* The buffer supplied was not large enough */
  blakeNotStarted,            /* This means blake_Init() was not called, don't rely on this, some functions may not check that blake_Init() was called. */
  blakeProtoNoSupport,        /* The network protocol is not supported */
  blakeBindFailure,           /* The sockets routine bind() failed */
  blakeConnRefused,           /* Connection to the remote end was refused. */
  blakeTimedOut,              /* The connection timed out or was firewalled */
  blakeNetDown,               /* The network is down */
  blakeUnknownNetError,       /* The network error is unknown or unhandled, report the code to DDRP */
  blakeRegAlready,            /* Something was already registered */
  blakeBadObject,             /* An unitialised or unknown/unregistered object was passed for working on */
  blakeQueueFull,             /* A fixed size queue was full, dynamic queues return NotEnoughMem instead */
  blakeUnknownFailure,        /* Catch all condition or user tampering with data structures */
  blakeQueueEmpty,            /* The queue is empty */
  blakeUnsupported,           /* The function is not supported or not written yet */
  blakeMismatch,              /* Structure alignment or version mismatch */
  blakeLimit,                 /* A hard coded limit was reached. */
  blakeDbFull,                /* The database is full. */
  blakeDbAccessWrite,         /* Unable to write to the database at this time */
  blakeDbAccessRead,          /* Unable to access the database (read) */
  blakeExclusiveFileFailure,  /* Can't open a file for exclusive access */
  blakeBadSAHandle,           /* The SafeAllocator handle is unrecognised */
  blakeDbRecordCorrupt,       /* Database record is corrupt (checksum) */
  blakeFileTruncated,         /* File is too short! */
  blakeArchivedFileError,     /* Error opening archived file */
  blakeRange,                 /* A parameter is out of range */
  blakeDbAccessOpen,          /* Cannot open a connection to the database */
  blakeSubUnsupported         /* Function dependencies cannot be met due to unsupported features */
};

/*
  NetBuffer errors
*/
enum blakeNetBufferError {
  bnbeNoError,
  bnbeCannotAccommodate,
  bnbeExtremeSize,
  bnbeBadDirection,
  bnbeSocketRegistered,
  bnbeUninitialised, /* NetBuffer not set up! */
  bnbeSocketNotRegistered, /* Only used by blake_netbuffer wrapper */
  bnbeNotEnoughMem /* Allocation/construction failed */
};

/*
  NetBuffer direction
*/
enum blakeNetBufferDirection {
  bnbdIncoming,
  bnbdOutgoing
};

/*
  Options modes.  Blake options is a versatile module which is designed to
  be extended or replaced, should we decide to start moving options to
  another form of file.  Therefore, certain Blake Options calls will
  require that you specifiy what form the options are in (and possibly
  also the relevant filename).  This enumeration specifies the form of
  the options.

  Notes:
  1) At the time of writing, only bomWindows16 is supported (September 2005).
  2) bomMySQL means that the Name parameter becomes the name of the database
     rather than the filename.  bomWindows32 will use the Name to find the
     right key in the registry, but the way this is done is not a published
     specification.
  3) bomUndefined is the default and is a valid mode, however, all calls
     will fail when in this mode.
*/
enum blakeOptionsMode {
  bomUndefined,                                 /* Default, non-valid mode */
  bomWindows16,                             /* Windows initialisation file */
  bomWindows32,                           /* Windows registration database */
  bomUnixConf,                            /* UNIX style configuration file */
  bomRaw,                     /* Not recommended, not-portable binary dump */
  bomMySQL                                 /* Use MySQL database interface */
};

/*
  Blake's language support enables use abroad by clients and servers.
  The order of the languages is important.
*/
enum blakeLang {
  langEnglish,
  langFrench,
  langSpanish,
  langGerman,
  langItalian,
  langPortuguese
};

#define OVERCHAT_NUMLANGUAGES (6) /* 6 Supported languages currently */
#define OVERCHAT_DEFLANG (langEnglish) /* In ignorance of user's language we always presume English */

enum blakeExchange {      /* AIM-like codes for different exchange virtual servers.  Used for chats */
  allRooms,               /* Not normally acceptable, works for kill */
  guestRooms,             /* Rooms reserved for guests, normal users may NOT enter this area */
  generalRooms,           /* General rooms open to all users */
  operatedRooms,          /* Guests cannot enter these areas, here, operators may kick people from rooms */
  administrativeRooms,    /* Reserved for operators, administrators and DDRP */
  debugRooms,             /* Debugging only. these rooms may be unstable and include new features or testing stuff */
  adultRooms              /* Rooms for adult content */
};

enum blakeServerCodes {      /* Codes sent from the server to the client(s) */
  bscsuspend,                /* Client should shut up until we tell it to speak */
  bscresume,                 /* Client may speak */
  bscchallenge,              /* Client must authenticate */
  bscgoterror,               /* For sending an error code to the client */
  bsclist_response,          /* For sending a list of users to a client */
  bscwhois_info,             /* For sending whois info back to a client */
  bscversioned,              /* Delivery of version info in response to a version packet */
  bscsuper,                  /* Information about Privelledge of current user */
  bsckilled,                 /* You are about to be disconnected by another user */
  bscchum_signon,            /* One of your chums just signed on */
  bscchum_signoff,           /* One of your chums just signed off */
  bscchum_idle,              /* One of your chums went into or came out of an idle state */
  bscloginreply,             /* You have have failed or succeed to authorise */
  bscisonlinereply,          /* Reply to the last IsOnline request */
  bscregisterreply           /* Reply to a client nickname registration request */
};

enum blakeClientCodes {   /* code sent from the client(s) to the server */
  bcclogin,                  /* Respond to an authentication challenge */
  bccsuper_request,          /* Get information about your current privilege */
  bccadd_enemy,              /* Block an anoying user */
  bccnot_enemy,              /* Unblock a user */
  bccjoin_chat,              /* Attempt to join a group chat (may not be suppoed by the server) */
  bcclist,                   /* Multipurpose request for a list of users */
  bcckilluser,               /* Kills a user (requires privelledges) */
  bcckillchat,               /* Somewhere along the lines of "punting chatroom" as those morons on AOL would say */
  bcckick,                   /* Kicks users from chats, server admins or room ops only */
  bccreserved0,              /* FREE SPACE, USE THIS NEXT, BEFORE ADDING TO END */
  bccreserved1,              /* FREE SPACE, USE THIS NEXT, BEFORE ADDING TO END */
  bccversion,                /* Request server version */
  bccmessage,                /* Send an instant message, offline message or notice to a user */
  bccchatmsg,                /* Send a message to a chat room (must ibe in the chat and with voice privelledge) */
  bccwhois,                  /* Get details of any user */
  bccreserved2,              /* FREE SPACE, USE THIS NEXT, BEFORE ADDING TO END */
  bccremoteshutdown,         /* Remote server maintainance code */
  bccchum_add,               /* Adds a chum to keep in contact with */
  bccchum_remove,            /* Removes a chum, terrible pitty */
  bccidle,                   /* Come out of or enter an idle state */
  bccisonline,               /* Test if a given user is online */
  bccmessage2,               /* Sub-protocol message */
  bccregister                /* Register a nickname */
};

enum blakeErrorCodes {    /* These error are returned with serverCodes::goterror type packets */
  becno_more_enemies,        /* Out of space for storing folk you wish to block */
  becyou_be_minion,          /* You are a minion.  Privileges denied */
  becchat_full,              /* You chat is full (if chat has limited space) */
  beckill_deny_greater,      /* You may not kill a user who is better than you */
  beckill_deny_code,         /* You may not kill the server programmer (DDRP) */
  becdenied,                 /* You may not perform that action, you have no privelledge */
  becnot_op,                 /* You are not channel operator */
  becserver_kill,            /* The server killed the user for an undisclosed reason */
  becprotocol_mistake,       /* The server killed you for improperly using the protocol */
  becnosuchchum,             /* The said person is not your chum */
  becchumspace,              /* No more chums may be added */
  becchumalready,            /* Said chum already a chum even if in another group */
  bec_user_offline           /* The user is not online */
};

enum blakeLoginReplyCode {
  blrSuccess,                /* Logged in successfully */
  blrNoSuchUser,             /* This user does not exist in the server's database */
  blrInvalidPassword,        /* The supplied password is not correct */
  blrAlreadyConnected,       /* You are already logged in! */
  blrConnLimitExceeded,      /* You have too many clones on your network */
  blrGlinedHost,             /* Your host has been banned from OverChat */
  blrGlinedDomain,           /* Your domain is no longer welcome on OverChat */
  blrKlinedHost,             /* Your host may not connect to this server, find another one */
  blrKlinedDomain,           /* Your domain is not welcomed by the server administrator */
  blrGeneral,                /* General failure on OverChat */
  blrUnknown,                /* Unknown login failure */
  blrOpenBlakeBannedProxy,   /* No Open Blake users from this proxy (glined) */
  blrOpenBlakeDisallowed,    /* No Open Blake user from any proxy */
  blrLegalIssues,            /* OverChat suspended due to legal issues */
  blrFinancialIssues,        /* OverChat suspended due to financial problems */
  blrAbandoned,              /* OverChat is officially abandoned */
  blrEmployment,             /* DDRP is in employment and cannot maintain OverChat */
  blrSuspendCommittee,       /* Your accounts have been suspended by order of the committee */
  blrSuspendGod,             /* Your accounts have been suspended by order of a god */
  blrUnstable,               /* The service is too unstable to use at the moment */
  blrOldClient,              /* Your client is too old to use the service */
  blrUnauthorisedClient,     /* Unauthorised client */
  blrStrangeLogin,           /* Your client passed strange login information */
  blrUnsupportedLanguage,    /* The server cannot support your language selection */
  blrMaintenance,            /* The server is undergoing maintenance */
  blrBlakeUnsupported,       /* The server no longer uses Blake */
  blrBetaTestersBanned,      /* The committee have blocked all beta testers */
  blrGodsBanned,             /* Gods are banned, use a non-priveleged account */
  blrUsersBanned,            /* Ordinary users banned */
  blrEvaluationComplete,     /* Your evulation is complete, now you must pay up */
  blrSysLoadHigh,            /* System load on the server is too high */
  blrNewTOS,                 /* You must agree to the new TOS before logging in */
  blrPurchased,              /* OverChat bought by another company, reconfirm account details */
  blrRespect,                /* OverChat is closed as a mark of respect for the dead */
  blrHoliday,                /* OverChat does not operate on this holiday */
  blr911Respect,             /* OverChat closed on aniversary of terrorist attack on USA */
  blrDatabaseFailure,        /* The server can't access the database */
  blrRecordCorrupt,          /* Return this if possible (ie. record not so corrupt we couldn't get the username) */
  blrUnknownHash,            /* The hash used to give the password to the server cannot be handled/unknown */
  blrTooManyClients          /* Too many users are connected to the server, connect to another server if one is available */
};

enum blakeRegisterReplyCode {
  brrSuccess,                /* Successful registration */
  brrOffensive,              /* The nickname is considered too offensive */
  brrEmailFaults,            /* Faults with email address */
  brrHandleError,            /* Cannot aquire a handle for the database */
  brrLockError,              /* Cannot lock the database */
  brrNickOwned,              /* The nickname is already owned by another user */
  brrMailError,              /* Registered but cannot send mail, try to recover password later */
  brrCreateError,            /* Unknown error creating the user */
  brrNickTooLong,            /* The nickname was too long */
  brrInvalidChar,            /* The nickname contained invalid characters */
  brrBeginSpace,             /* The nickname cannot begin with a space */
  brrInvalidEmail,           /* The email address does not appear valid */
  brrNoDomain,               /* The email address does not have a domain portion */
  brrDomainResolution        /* The domain does not have a primary DNS A record (may look for MX records in the future) */
};

enum blakeCipherID {
  bcidPlain,                 /* Plaintext, no cipher */
  bcidCaesar,                /* Caesar's Cipher */
  bcidTKModulator,           /* TK's modulator cipher */
  bcidFixedStreamSub         /* DDRP's fixed stream substitution cipher */
};

/*
  Note: Hashes are listed from least secure to most secure.
  The explicit numerical assignments must not be altered,
  this could break binary compatibility and clients would
  not log in successfully. Also, algorithms will be given
  the wrong names.  In other words, don't mess!
*/
enum blakeHashType {
  bhtUnknown  = 0,           /* This is reserved for special use, try not to use it if you don't have to */
  bhtMd2      = 6,           /* RSA MD2 (Rivest), (128 bits) */
  bchMd4      = 7,           /* RSA MD4 (Rivest), (128 bits) */
  bhtMd5      = 1,           /* RSA MD5 (Rivest), (128 bits) */
  bhtSha1     = 2,           /* Secure Hash Algorithm (160 bits) */
  bhtSha256   = 3,           /* Secure Hash Algorithm (256 bits) */
  bhtSha384   = 4,           /* Secure Hash Algorithm (384 bits) */
  bhtSha512   = 5,           /* Secure Hash Algorithm (512 bits) */
  bhtSha224   = 8,           /* Secure Hash Alforithm (224 bits) */
  bhtPlain    = 9            /* Not hashed */
};

/* Only authorised clients will be allowed into the system */
enum blakeClientID {
  bClientIdOberChatten,      /* DDRP's Win32 client */
  bClientIdOCTurboUNIX,      /* DDRP's UNIX version of octurbo */
  bClientIdOCLogin,          /* DDRP's test client */
  bClientIdDDRPLogin,        /* DDRP's personal client */
  bClientIdOC32,             /* Total Konfuzion's Win32 client */
  bClientIdJava,             /* Java based client */
  bClientIdSarah             /* Dagsylad's Win32 client */
};

/*
  Privileges are used internally by the server and are requested by
  clients.  Use one of the privileges here, if it corrosponds to the value
  in your account you will be awarded the privilege.  See titles.txt
  for more information of titles and privileges.
*/
/* Ordinary mortals */
#define CLEARANCE_ZERO 0
#define CLEARANCE_UNAUTHORISED CLEARANCE_ZERO
#define CLEARANCE_GUEST 1 /* May not be supported */
#define CLEARANCE_ROOKIE 2 /* almost all users! */
#define CLEARANCE_LESSER_BETA_TESTER 3
#define CLEARANCE_ROOKIE_REPRESENTITIVE 4
#define CLEARANCE_ROOKIE_WHIP 5
#define CLEARANCE_ROOKIE_WHIP_CHAIRMAN 6
#define CLEARANCE_USER_REPRESENTITVE 7
/* Officers */
#define CLEARANCE_SERVICE_CONTROLLER 108
#define CLEARANCE_HEAD_CONTROLLER 109
#define CLEARANCE_COMMITTEE 110
#define CLEARANCE_COMMITTEE_CHAIRMAN 111
#define CLEARANCE_FINANCIAL_ADVISOR 112
#define CLEARANCE_SPIRITUAL_ADVISOR 113
/* Programmers */
#define CLEARANCE_GREATER_BETA_TESTER 214
#define CLEARANCE_CODE_PATCHER 215
#define CLEARANCE_PROGRAMMER 216
#define CLEARANCE_SYSTEM_DESIGNER 217
#define CLEARANCE_DLOB_ENGINEER 218
#define CLEARANCE_BLAKE_ENGINEER 219
#define CLEARANCE_ENGINEER 220
/* The gods */
#define CLEARANCE_PROPHET 248
#define CLEARANCE_PROPHET_HEAD 249
#define CLEARANCE_FLOATING_SPECTARE 250
#define CLEARANCE_SUPERIOR_MYSTIC_CONTROLLER 251
#define CLEARANCE_HOLOGRAPHIC_DICTATOR 252
#define CLEARANCE_INVINSIBLE_ABSOLUTE_DICTATOR 253
#define CLEARANCE_SUPREME_COMMANDER 254
#define CLEARANCE_ROOT 255 /* Reserved for the system */

#define CLEARANCE_SETTING_DEFAULT CLEARANCE_ROOKIE /* New users start out life as rookies */
#define CLEARANCE_SETTING_KILLER CLEARANCE_PROPHET /* Lowest clearance necessary to kill users */

/*
  The stop codes are assigned to components and to people in ranges.
  The stop codes are numbered from 0 to 65,535.  Zero has a special
  meaning.  We define the ranges first and then define all stop codes
  as the range's base plus the number within the range.  Example:
  DDRP's personal range starts at 1, all his numbers are 0 to the top
  of his range plus his base to keep within the correct range.  Failure
  to keep within your assigned ranges will result in a beating from the
  founding father! =D
*/
/* The stop code ranges. */
#define BLAKESTOP_RANGE_DDRP (1) /* 1-499*/
#define BLAKESTOP_RANGE_TK (500) /* 500-699*/
#define BLAKESTOP_RANGE_PATER (700) /* 700-719*/
#define BLAKESTOP_RANGE_CRAIG (720) /*720-899*/
#define BLAKESTOP_RANGE_DAGSYLAD (900) /*900-999*/
#define BLAKESTOP_RANGE_OCQUERY (1000) /*1000-1079*/
#define BLAKESTOP_RANGE_DLOB (1080) /*1080-1299*/
#define BLAKESTOP_RANGE_GENERAL (1300) /*1300-1499*/
#define BLAKESTOP_RANGE_CORE (1500) /*1500-1599*/
#define BLAKESTOP_RANGE_OBERCHATTEN (1600) /*1600-1649*/
#define BLAKESTOP_RANGE_UNDEFINED (1650) /* Do not use as yet */

/* The stop codes */
#define BLAKESTOP_ZERO (0)
#define BLAKESTOP_OOPS (BLAKESTOP_ZERO)

/* DDRP's personal panics */
#define BLAKESTOP_DDRP_FAILED_MUTANT_CREATION ((BLAKESTOP_RANGE_DDRP)+0) /* Param 0 == Address of lock container, param 1 == Index if applicable  */
#define BLAKESTOP_DDRP_TEST ((BLAKESTOP_RANGE_DDRP)+1) /* No parameters */
#define BLAKESTOP_DDRP_BADCHAR ((BLAKESTOP_RANGE_DDRP)+2) /* 0=Detected @ code address, 1=Buffer base address, 2=Bytes per character, 3=Offset of character, 4=Character value (accurate only if bytes per char <= 4, 5=Length of string */
#define BLAKESTOP_DDRP_HASHBUFF_TOO_SMALL ((BLAKESTOP_RANGE_DDRP)+3) /* 0=Address of hash buffer, 1=expected size, 2=actual size */
#define BLAKESTOP_DDRP_LANG_MSGCOUNT_MISMATCH ((BLAKESTOP_RANGE_DDRP)+4) /* 0=Count of English messages, 1=Count of messages in foreign language, 2=Index of foreign language */
#define BLAKESTOP_DDRP_LANG_UNKNOWN ((BLAKESTOP_RANGE_DDRP)+5) /* 0=Detected @ code address, 1=Known language count, 2=illegal language enumeration */
#define BLAKESTOP_DDRP_LOGICASSERT ((BLAKESTOP_RANGE_DDRP)+6) /* 0=Detected @ code address, 1=Data address, 2=Data content */
#define BLAKESTOP_DDRP_UNINITED ((BLAKESTOP_RANGE_DDRP)+7) /* 0=Detected @ code address */

/* General code panics */
#define BLAKESTOP_SIGILL ((BLAKESTOP_RANGE_GENERAL)+0) /* No parameters */
#define BLAKESTOP_SIGSEGV ((BLAKESTOP_RANGE_GENERAL)+1) /* No parameters */
#define BLAKESTOP_SIGABRT ((BLAKESTOP_RANGE_GENERAL)+2) /* No parameters */
#define BLAKESTOP_SIGBUS ((BLAKESTOP_RANGE_GENERAL)+3) /* No parameters */
#define BLAKESTOP_IGNORANT_UNINSTALL ((BLAKESTOP_RANGE_GENERAL)+4) /* Parameters: 0=Detected @ code address, 1=Real callback address, 2=Bad guess at callback address */
#define BLAKESTOP_BLAKE_FUNCTION_FAILED ((BLAKESTOP_RANGE_GENERAL)+5) /* Parameters: 0=Detected @ code address, 1=Address of Blake function, 2=error code */
#define BLAKESTOP_BLAKE_MODULE_NOT_INITED ((BLAKESTOP_RANGE_GENERAL)+6) /* Parameters: 0=Detected @ code address */

/* Core failures */
#define BLAKESTOP_CORE_LLCORRUPT ((BLAKESTOP_RANGE_CORE)+0) /* Parameters: 0=Detected @ code address, 1=Base of linked list, 2=Address of node, 3=Index of node, 4=Expected checksum, 5=Actual checksum, 6=Linked list creation timestamp, 7=Node creation timestamp, 8=Associated socket or zero. */
#define BLAKESTOP_CORE_LLADDRDUP ((BLAKESTOP_RANGE_CORE)+1) /* Parameters: 0=Detected @ code address, 1=Base of linked list, 2=Address of duplicate node, 3=Count of all nodes, 4=Count of this address */
#define BLAKESTOP_CORE_LLSOCKDUP ((BLAKESTOP_RANGE_CORE)+2) /* Parameters: 0=Detected @ code address, 1=Base of linked list, 2=Address of node at which duplication was detected, 3=Count of all nodes, 4=Socket number which is duplicated, 5=Count of duplications of this socket */
#define BLAKESTOP_CORE_IMPOSSIBLE_TIMESTAMP ((BLAKESTOP_RANGE_CORE)+3) /* Parameters: 0=Detection @ code address, 1=Address of stored timestamp, 2=Current time, 3=Stored time higher than current time */
#define BLAKESTOP_CORE_CLONED ((BLAKESTOP_RANGE_CORE)+4) /* Parameters: 0=Nickname, 1=Index of instance 1, 2=Index of index 2, 3=Number of instances of this clone */

/* OberChatten client failures */
#define BLAKESTOP_OBERCHATTEN_RADIOITEM_OOR ((BLAKESTOP_RANGE_OBERCHATTEN)+0) /* Parameters: 0=Detected @ code address, 1=Address of component, 2=Address of controlling class, 3=Maximum extent, 4=Index of attempted access*/
#define BLAKESTOP_OBERCHATTEN_UNHANDLED_VALUE ((BLAKESTOP_RANGE_OBERCHATTEN)+1) /* Parameters: 0=Detected @ code address, 1=Address of controlling class, 2=Address of offending value, 3=Offending value */

/* Declaration of fixed type blake_byte_t */
typedef unsigned char blake_byte_t;
/* Declaration of fixed type blake_word8_t */
typedef unsigned char blake_word8_t;
/* Declaration of fixed type blake_byte_t */
typedef unsigned char blake_bool_t;

/* Declaration of fixed type blake_word16_t */
#ifndef USHRT_MAX
#  error ("Must have an ANSI compliant limits.h")
#else
#  if ( USHRT_MAX != 0xFFFFU )
#    error ("unsigned short is not 16-bits, visit www.daybologic.co.uk/mailddrp/")
#  else
     typedef unsigned short blake_word16_t;
#  endif
#endif

/* Declaration of fixed type blake_word32_t */
#ifndef ULONG_MAX
#  error ("Must have an ANSI compliant limits.h")
#else
#  if ( ULONG_MAX > 0xFFFFFFFFUL ) /* 64-bit */
     typedef unsigned int blake_word32_t;
#  else
     typedef unsigned long blake_word32_t;
#  endif
#endif

/* For internal number to string translations */
#if ( UINT_MAX > 4294967295UL )
# error ("Make BLAKE_UINT_CHAR_BUFF larger, www.daybologic.co.uk/mailddrp/")
#else
# define BLAKE_UINT_CHAR_BUFF (11) /* Includes NULL */
#endif

#if ( UINT_MAX > 4294967295UL )
# error ("Make BLAKE_ULONG_CHAR_BUFF larger, www.daybologic.co.uk/mailddrp - specify your machine type!")
#else
# define BLAKE_ULONG_CHAR_BUFF (11) /* Includes NULL - not big enough for 64-bit machine so will need an update when I have test machines */
#endif

/*
  IP type.  Don't access this directly, use Blake routines to promote
  porting to IPv6 when the time comes.
*/
#ifdef OVERCHAT_IPV6
# error ("I can't handle ipv6 FIXME!")
#else
  typedef struct {
    unsigned char _parts[4]; /* That's it! */
  } OVERCHAT_IP;
#endif /*OVERCHAT_IPV6*/

/*
  These binary flags are used by blakeMessage
*/
#define BLAKEMESSAGE_FLAGS1_NOTICE  (1) /* Notice, such as away, do NOT auto reply to any message marked as a notice! */
#define BLAKEMESSAGE_FLAGS1_HIDDEN  (2) /* Do not show the message to the user or respond at the receiving end */
#define BLAKEMESSAGE_FLAGS1_COMMAND (4) /* Read this as a client to client command such as /me */

struct blake_ver_t {                 /* Generic version number type */
  blake_word16_t sz;                           /* Size of structure */
  blake_word8_t major, minor, patch;
  blake_word16_t exFlags;
};

struct blakeSuspend {
  blake_word32_t dummy_time; /* Ignore, false */
};

struct blakeResume {
  blake_word32_t reserved; /* Just so this compiles really but I could use it later */
};

struct blakeChallenge {
  blake_word16_t secs; /* Maximum time for client to AUTH before client is killed */
  blake_word32_t _reserved; /* Send zero for now */
  blake_byte_t rnum[16]; /* MD5 hash of a gaurenteed random number */
};

struct blakeGotError {
  blake_word16_t errnum; /* Error code */
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* Only relevant for some errors */
};

struct blakeListResponse {
  blake_word32_t thread_id; /* A number so clients don't get confused between chats etc */
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* Any unused space should be padded with NULLs, the user is sent a user's handle */
};

struct blakeWhoisInfo {
  blake_byte_t username[BLAKE_NICK_LIMIT];
  blake_word8_t usingIpv6; /* Hopefully zero until I can handle this, most clients won't be happy if this is TRUE */
  OVERCHAT_IP ip; /* Stores an IP address, it's up to clients to DNS lookup if they want to */
  blake_word8_t clearance; /* Security clearance level */
  blake_word8_t warning; /* Percentage warning ( if too high person is killed ) */
  blake_word8_t limiter; /* Current rate limiter level */
  struct { /* normally a bitfield but too much hassle in the protocol */
    blake_word8_t invisible; /* Some users can't see this person */
    blake_word8_t invinsible; /* This person cannot be killed, this is generally reserved for internal server issues */
  } flags;
  blake_word32_t memberSince; /* Time and date that person began using the service with this nick */
  blake_word32_t onlineSince; /* Time and date that person is online since this session */
  blake_word32_t idleSince; /* Time and date that person last fired a server event, idle time can be calculated with this and onlineSince */
};

struct blakeVersioned {
  struct blake_ver_t server; /* Server's version */
  blake_byte_t os_description[256]; /* Description of operating system (usually uname -a) */
  struct blake_ver_t os; /* Operating system's version (optional) */
};

struct blakeSuper {
  blake_word8_t clearance; /* The super powers given (security clearance level) */
};

struct blakeKilled {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* The user who killed you */
  /* A message will follow after the packet from the user who killed you */
};

struct blakeChumSignon {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* The user who signed on who is your chum */
  blake_byte_t groupname[BLAKE_CHUMGROUPNAME_LIMIT]; /* The group name to which they belong (no more than one group supported per chum) */
};

struct blakeChumSignoff {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* The user who signed off who is your chum */
  blake_word32_t secs_on; /* How many seconds the user was loggedd in for */
};

struct blakeChumIdle {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* The user who went idle or came back */
  blake_byte_t back_flag; /* If this is nonzero the user came back, if zero they went idle */
  blake_word32_t idle_secs; /* Seconds idle, calculated by the server internal information regardless of the back_flag or the idle state indicator */
};

struct blakeLoginReply {
  blake_byte_t failcode; /* See blakeLoginReplyCode */
};

struct blakeIsOnlineReply {
  blake_byte_t username[BLAKE_NICK_LIMIT];
  blake_byte_t boolean; /* Whether the person is online or not */
};

struct blakeRegisterReply {
  blake_byte_t failcode; /* See blakeRegisterReplyCode */
  blake_byte_t password[BLAKE_PASS_LIMIT];
  blake_byte_t reserved[32]; /* A little leaway incase I need to do anything else */
};

/* -------- */

struct blakeLogin {                           /* Client side */
  blake_byte_t _username[BLAKE_NICK_LIMIT]; /* Your username, use padding, no NULL terminator is full length */
  blake_word8_t hashtype; /* enum blakeHashType */
  blake_byte_t _passworddigest[128]; /* Large space to allow expansion of hashtype, allows for a 1,024-bit hash */
  blake_byte_t reserved[120]; /* Reserved */
  blake_word32_t clientid; /* The client's unique identifer */
  blake_word32_t clientver; /* The version of that client */
  blake_byte_t language; /* This will be supported in the future, at the moment it's zero, meaning English (of course) */
};

struct blakeSuperRequest {
  blake_word8_t reserved; /* Do not use */
};

struct blakeAddEnemy {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* The user who you wish to block */
  blake_word32_t blocktime; /* how long to block the user (not gaurenteed absolutely accurate), retained between sessions, 0 for forever */
};

struct blakeNotEnemy {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* Remove a user from your list of blocks */
};

struct blakeJoinChat {
  blake_byte_t chatname[BLAKE_ROOMNAME_LIMIT]; /* Names the chat to join, pad with zeros, no NULL terminator */
  blake_byte_t dummy; /* Set to 0x55 */
  blake_word16_t random; /* Set to any old crap */
  blake_word16_t reserved; /* Reserved, set to zero */
  enum blakeExchange exchange; /* AIM-like exchange number */
};

struct blakeList {
  blake_word8_t type; /* 0 people, 1 chats */
  blake_word16_t meaningless; /* Ignore this */
  enum blakeExchange exchange; /* Setting to anything other than 0 when listing people will result in a kill */
  blake_byte_t chatname[BLAKE_ROOMNAME_LIMIT]; /* Names the chat to list users from, if not totally NULLs on type 0 you will be killed */
  blake_word32_t thread_id; /* Will be returned in reply */
};

struct blakeKillUser {
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* User's nick */
  OVERCHAT_IP ip; /* An alternative, preferred */
  /* Message follows fixed packet structure */
};

struct blakeKillChat {
  blake_byte_t chatname[BLAKE_ROOMNAME_LIMIT]; /* Chatroom name */
  enum blakeExchange exchange; /* the exchange on which the chat resides or allRooms */
};

struct blakeKick {
  /* To prevent false server kills if username or chatname don't exist we ignore the packet */
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* Name of user */
  blake_byte_t chatname[BLAKE_NICK_LIMIT]; /* Name of chat room on a specific... */
  enum blakeExchange exchange; /* exchange number.  May not be allRooms */
  blake_word16_t dummy; /* 0x6714 or 0x1177 */
};

struct blakeReserved0 {
  blake_byte_t reservedSpace[128]; /* Makes sure I have enough space if I ever want to use this packet */
};

struct blakeNonsense0 {
  blake_word16_t value0; /* 0x9900 */
  blake_word8_t value1; /* 15 (0xF) */
  blake_byte_t username[BLAKE_NICK_LIMIT]; /* Send any old screen name, it doesn't have to exist */
};

struct blakeVersion {
  blake_word8_t reserved;
};

struct blakeMessage {
  blake_byte_t username[BLAKE_NICK_LIMIT];
  blake_word8_t cipher; /* 0=plaintext, anything else is a code identifying a cipher */
  blake_word8_t flags1; /* These flags can be found above somewhere, prepended by BLAKEMESSAGE_FLAGS1_ */
  blake_byte_t reserved[127]; /* Should I need to add anything else */
  /* message follows as extended packet */
};

struct blakeMessage2 {
  blake_word8_t reserved0;
  blake_word8_t reserved1;
  blake_word8_t reserved2;
  /* Message follows as extended packet */
};

struct blakeChatMsg {
  blake_byte_t chatname[BLAKE_ROOMNAME_LIMIT];
  blake_word8_t spoof; /* Useless but must be 0x12 */
  enum blakeExchange exchange; /* The exchange on which the chat exists, sending to all is not allowed */
  /* Message follows as extended packet */
};

struct blakeWhois {
  blake_byte_t username[BLAKE_NICK_LIMIT];
};

struct blakeRemoteShutdown {
  blake_word8_t dorestart; /* 1=yes, 0=just kill */
};

struct blakeChumAdd {
  blake_byte_t username[BLAKE_NICK_LIMIT];
  blake_byte_t groupname[BLAKE_CHUMGROUPNAME_LIMIT];
};

struct blakeChumRemove {
  blake_byte_t username[BLAKE_NICK_LIMIT];
};

struct blakeIdle {
  blake_byte_t idle_flag; /* If nonzero you go idle, if zero coming back */
};

struct blakeIsOnline {
  blake_byte_t username[BLAKE_NICK_LIMIT];
};

struct blakeRegister {
  blake_byte_t username[BLAKE_NICK_LIMIT];
  blake_byte_t email[BLAKE_EMAIL_LIMIT];
  blake_byte_t reserved[64];
};

/* What a packet looks like */
struct blakePacket {
  blake_word16_t len; /* Length of complete packet and extended packet, including self */
  blake_word8_t server; /* If nonzero use serverCode, if zero use clientCode */
  union {
    enum blakeServerCodes serverCode;
    enum blakeClientCodes clientCode;
  } code;
  union { /* info (packet dependent) */
    /* ---- server side type packets ---- */
    struct blakeSuspend _suspend;
    struct blakeResume _resume;
    struct blakeChallenge _challenge;
    struct blakeGotError _goterror;
    struct blakeListResponse _listresponse;
    struct blakeWhoisInfo _whoisinfo;
    struct blakeVersioned _versioned;
    struct blakeSuper _super;
    struct blakeKilled _killed;
    struct blakeChumSignon _chumsignon;
    struct blakeChumSignoff _chumsignoff;
    struct blakeChumIdle _chumidle;
    struct blakeLoginReply _loginreply;
    struct blakeIsOnlineReply _isonlinereply;
    struct blakeRegisterReply _registerreply;
    /* ---- client side type packets ---- */
    struct blakeLogin _login;
    struct blakeSuperRequest _superrequest;
    struct blakeAddEnemy _addenemy;
    struct blakeNotEnemy _notenemy;
    struct blakeJoinChat _joinchat;
    struct blakeList _list;
    struct blakeKillUser _killuser;
    struct blakeKillChat _killchat;
    struct blakeKick _kick;
    struct blakeVersion _version;
    struct blakeMessage _message;
    struct blakeMessage2 _message2;
    struct blakeChatMsg _chatmsg;
    struct blakeWhois _whois;
    struct blakeRemoteShutdown _remoteshutdown;
    struct blakeChumAdd _chumadd;
    struct blakeChumRemove _chumremove;
    struct blakeIdle _idle;
    struct blakeIsOnline _isonline;
    struct blakeRegister _register;
  } info; /* Packet dependent portion */
  blake_word16_t extendedPacketLength; /* If any data follows the packet's fixed structure it's length is here, read on for dynamic messages such as IM */
};

/*
  Before calling any functions in the DLL, each process wishing to use
  Blake's offerings _must_ call blake_Init().  Failure to do so may
  result in behaviour being undefined.  The function will return false
  on an error.  Note: Technically Win32 is capable of dealing with this
  initialisation automatically.  However, if you rely on this and don't
  call this function, the code won't port to other platforms.  This only
  applies when Blake is built as a DLL anyway.  Please make sure you
  call the function.

  Thread information: As of OverChat 0.1.8, the threads and mutants code
  has been stripped into a separate library called DayboThreads.  DayboThreads
  _must_ be initialised _before_ the call to blake_Init().
*/
BLAKEAPI(blake_bool_t) blake_Init(void);

/*
  Before a process exits, it is expected to call blake_Cleanup() as a matter
  of respect for Blake.  If they do not, memory leaks will result.
  The function could fail under unknown circumstances, this will be documented
  better at a leter date. Note: Technically Win32 is capable of dealing
  with this cleanup automatically.  However, if you rely on this and don't
  call this function, the code won't port to other platforms.

  Thread information: As of OverChat 0.1.8, the thread and mutant code has
  been stripped from Blake and is now in a separate library called
  DayboThreads.  blake_Cleanup() will no longer shut down threads.  The thread
  library should only be shut down _after_ Blake has been cleaned up.
*/
BLAKEAPI(blake_bool_t) blake_Cleanup(void);

/*
  This function is available to check whether the Blake library has been
  initialised successfully and is ready for use.  It is provided for
  convenience to code which cannot determine whether Blake is already running.
  It is not safe to use this as a thread safe mechanism.  A blake cleanup
  may have already been invoked.
*/
BLAKEAPI(blake_bool_t) blake_Verify(void);

/*
  This function returns a pointer to a string which contains the
  date when Blake was built.  This is considered to be the "OverChat
  build date".  The string should not be modified.
*/
BLAKEAPI(const char*) blake_GetBuildDateString(void);

/*
  This function returns a pointer to a string which contains the
  time at which Blake was built.  This is considered to be the
  "OverChat build time".  The string should not be modified.
*/
BLAKEAPI(const char*) blake_GetBuildTimeString(void);

/*
  This function returns (via pointers supplied by the caller),
  the version information contained in OVERCHAT_VERMAJ,
  OVERCHAT_VERMIN and OVERCHAT_VERPATCH respectively.  This allows
  one to _ensure_ the library matches the header.  In cases where
  this is not so important, use the definitions themselves, as this
  is of course more efficient.  Note: All pointers are optional,
  supplying NULL is fine.
*/
BLAKEAPI(void) blake_GetVersion(
  blake_word16_t *PMajor,
  blake_word16_t *PMinor,
  blake_word16_t *PPatch
);

/*
  This function returns the same information as blake_GetVersion(),
  but returns it via a blake_ver_t structure, including any extended
  version state flags it may contain.
*/
BLAKEAPI(enum blakeError) blake_GetVersionEx(
  struct blake_ver_t *PVerInfo
);

/*
  When blakeError codes are returned from the Blake library and the
  caller cannot handle them in code or wants to log them.  Get a more
  human readable string of the error by calling this function.  When
  called with NULL arguments (either one) it simply returns the length
  of the string which would have been returned, this allows the caller
  to allocate a buffer to copy the string.
*/
BLAKEAPI(unsigned int) blake_GetErrorMessage(
  const enum blakeError BlakeError,
  char *Buff,
  size_t MaxSize,
  enum blakeLang Language
);

/*
  In order for code to dynamically determine the number of error messages
  which are actually in Blake and returnable by blake_GetErrorMessage()
  one should call this.  One could then cast integers from zero to the
  return value minus one to enum blakeError and print the entire error
  set for a given language.  Note: All languages have the same amount of
  errors and are at the same indexes or error numbers so this function
  doesn't accept a language modifier.  It is not possible to enumerate
  all languages presently.
*/
BLAKEAPI(unsigned int) blake_GetNumberOfErrorMessages(void);

/*
  blake_GetErrorMessageMnemonic() is useful for debugging.  Call the function
  to be given a pointer to a string which is the source-level version of
  the mnemonic.  This is useful for printing diagnostic messages.  If the
  function returns NULL, print a simple integer instead.
*/
BLAKEAPI(const char*) blake_GetErrorMessageMnemonic(
  const enum blakeError Err
);

/*
  OverChat; being a very large project often gets confusing and is hard
  to debug.  Whether your code responsibilities are Blake itself,
  the server, the protocol implementation or simply an official client,
  call this function wherever you do not know if code is executing or not.
  Use the macro blake_Trace( ), not the direct call to blake_dTrace( ).
*/
BLAKEAPI(void) blake_dTrace(
  const char *File,
  const unsigned int Line,
  const char *Message
);

#define blake_Trace(msg) \
          blake_dTrace(__FILE__, __LINE__, (msg))

/*
  This nil handle is used for static initialisation of a generic,
  opaque handle.
*/
#ifdef BLAKE_THREADS
# define BLAKE_INVALID_HANDLE (DAYBOTHREADS_INVALID_HANDLE)
#else
# define BLAKE_INVALID_HANDLE (0U)
#endif /*BLAKE_THREADS*/

/*
  This is a linked list based on pointers, it's used for all sorts
  of things inside the Blake library but is also offered to outsiders
  if you cannot be bothered to code your own linked list in.
  It is also used by the OverChat server.  Very few functions are
  truely exported, the rest are done via pointers in the object.
*/
struct blake_link_ptrs_node /* A generic node, you don't need to touch this */
{
  void* ptr;
  struct blake_link_ptrs_node* next;
};

struct blake_link_ptrs /* The linked list object */
{
  size_t size; /* Size of this structure in bytes */
  struct blake_link_ptrs_node* head; /* Linked list base, do not touch */
  struct blake_link_ptrs_node* tail; /* Linked list tail (cached) */
  size_t nodeSize; /* Do not touch this from outside! */
  unsigned int count; /* Don't alter the count from outside, it is used to make the count a lot faster than following the list */
  enum blakeError (*AddToHead)(struct blake_link_ptrs* Obj, const void* Node); /* Adds a node to the head/base (this will change positions of the nodes which follow) */
  enum blakeError (*AddToTail)(struct blake_link_ptrs* Obj, const void* Node); /* Adds a node to the tail end (typical)*/
  enum blakeError (*Del)(struct blake_link_ptrs* Obj, const void* Node);
  enum blakeError (*DelByPos)(struct blake_link_ptrs* Obj, const unsigned int Pos);
  void (*DelAll)(struct blake_link_ptrs* Obj); /* Delete's everything, can be called anytime... but MUST be called before you discard the object */
  unsigned int (*Count)(const struct blake_link_ptrs* Obj);
  enum blakeError (*Find)(struct blake_link_ptrs* Obj, const void* Node, unsigned int* PPos); /* Finds the node, PPos is optional if you want to recover the position */
  enum blakeError (*Set)(struct blake_link_ptrs* Obj, const unsigned int Pos, const void* Node);
  enum blakeError (*Get)(const struct blake_link_ptrs* Obj, const unsigned int Pos, void* Node);
  size_t (*NodeSize)(const struct blake_link_ptrs* Obj);
};

/*
  When using a linked list, it must be initialised, there is no matching
  cleanup, all that is neccersary is that DelAll() be called or the object
  is empty anyway.  All nodes are a fixed size and are copied into the linked
  list based on pointers, however, zero sized NodeSizes are logically
  corrected to prevent a crash to 1 byte.  From Blake version 1.0 onwards, ensure
  the size element of the structure is set to the correct sizeof() else the function
  will fail, reporting blakeBadObject.
*/
BLAKEAPI(enum blakeError) blake_InitLinkPtrs(
  struct blake_link_ptrs *Obj,
  size_t NodeSize
);

BLAKEAPI(enum blakeError) blake_DebugInitLinkPtrs(
  const char *SourceFile,
  const unsigned int SourceLine,
  struct blake_link_ptrs *Obj,
  size_t NodeSize
);

#if ( defined(DEBUG) && !defined(BLAKE_LL_SOURCE) )
# define blake_InitLinkPtrs(o, ns) \
           blake_DebugInitLinkPtrs(__FILE__, __LINE__, (o), (ns))
#endif

#ifdef DEBUG
/*
  This call is only available in debug builds so use with care,
  it will print to stdout all information about linked lists, it
  is not guarenteed to be accurate and was an add on to the linked
  list after the design was long since finished.
*/
BLAKEAPI(void) blake_DebugDumpLinkLists(void);
#endif /*DEBUG*/

/*
  This structure is the internal workings of a fast queue.
  It is recommended that none of the elements are touched
  direvtly by outsiders and that the functions below it
  are used exclusively to manipulate it.  It is called a fast
  queue because it is a fixed size nad may not be resized
  on the fly.
*/
struct blakeFastQueueInternal {
  blake_bool_t Used;
  void* Dataptr;
};

struct blakeFastQueue {
  unsigned int InitSig; /* Signature indicating initialisation */
  unsigned int UBound; /* Uppermost bound to prevent overruns */
  size_t ElemSize; /* Size of one element */
  unsigned int Count; /* Current used items */
  struct blakeFastQueueInternal* Base;
  void* MemoryDebugger; /* This is used by the Blake memory debugger, do not touch */
#ifdef BLAKE_THREADS
  dtlock_t Lock; /* This DayboThreads lock is used by the fast queue internally.  Do not  tamper with it */
  blake_bool_t LockCreated; /* Internally used to prevent direct access to the above */
#endif /*BLAKE_THREADS*/
};

/*
  Please initialise a queue with this dynamic constructor.
  Anything manually changed in the structure before this call
  will be destroyed (ignored).  The function can fail and return
  an error, those are likely to be blakeNotStarted, blakeInvalidParam,
  or blakeNotEnoughMem.  blakeNotEnoughMem can also occur when
  the DLL is a debug version and the memory debugger runs out
  of slots to track the process, this can happen even if there is
  a ton of free memory.  Please use your own structure and pass a pointer
  to it but don't ever touch the logically opaque data in the structure.
  The UBound is the upper boundry, for example, to make a ten element
  queue specify 9.  The minimum is of course, zero.  The ElemSize
  is the size of an element in the queue, normally the result from a
  sizeof() of whatever you plan to store in the queue. Specifying
  too little will truncate storage of elements.  Specifying too large
  a value will result in a crash when data is being copied from the user
  later.  Do not over do any of these values or blakeNotEnoughMem will
  return.
*/
BLAKEAPI(enum blakeError) blake_InitFastQueue(
  struct blakeFastQueue *PQueue,
  const unsigned int UBound,
  const size_t ElemSize
);

/*
  To add an item to the back of the queue call this function.
  The function can fail if the queue is full, bad parameters are
  passed or the library is not started.  If the queue is full
  blakeQueueFull is returned.  Make sure the queue has been
  initialised, it's hard to tell if it has not been initialised.
  If possible, the function will return blakeBadObject but it's not
  always possible and could crash.  The new item is copied on a raw
  data basis into the back of the queue.  It shall not be topped
  until all other pending items in front of it have been popped.
*/
BLAKEAPI(enum blakeError) blake_PushFastQueue(
  struct blakeFastQueue *PQueue,
  const void *NewItem
);

/*
  To "top" a fast queue, call this function with a pointer to the
  fast queue and a pointer to a position to copy the top element
  of the queue into.  To try to make this safer pass the size of
  the element to copy too.  This function generally succeeds if used
  correctly.  If there is nothing in the queue. blakeQueueEmpty
  is returned and the element is cleared.  The same element will
  always be returned until the queue is popped.
*/
BLAKEAPI(enum blakeError) blake_TopFastQueue(
  struct blakeFastQueue *PQueue,
  void *PReceiveItem,
  const size_t SizeItem
);

/*
  This function "pops" a queue.  What that means is that the element
  at the front of the queue is discarded, normally done after "topping"
  the queue.
*/
BLAKEAPI(enum blakeError) blake_PopFastQueue(
  struct blakeFastQueue *PQueue
);

/*
  This functions is a simple call which does not return extended
  error information if it fails and simply returns the count of the
  number of items which are in the list.  It's possible to read this
  with the Count variable but is inadvisable, CountFastQueue()
  follows proper locking symantics.
*/
BLAKEAPI(unsigned int) blake_CountFastQueue(
  struct blakeFastQueue *PQueue
);

/*
  In order to free the resources allocated inside a fast queue
  this function must be called on it.  Please ensure the queue
  was initialised before attempting to destroy it and that no
  code is working with the list and no code could possibly have
  it locked.  If initialisation of a queue failed do not attempt
  to destroy it, partial initialisation of a queue is always destroyed
  before the initialialiser returns and there could be nothing left
  to free.  This function will fail gracefully with a blakeBadObject
  if you try it.
*/
BLAKEAPI(enum blakeError) blake_DestroyFastQueue(
  struct blakeFastQueue *PQueue
);

/*
  If a client receives data from the server, it contains a raw stream (TCOP)
  normally.  However, if the tag <blake=n> is received all data following
  it should be sent to Blake is one go from a buffer up until </blake>.
  The tags themselves must not be passed to this function.  This function
  cracks the packet and calls the appropriate callbacks the client has
  registered.  If the client has not registered a callback the packet is
  dropped.  The same mechanism is used by the server.  Zero is returned if
  the callback was not installed and the packet was dropped.  One is returned
  if the callback was executed but failed for whatever reason.  Two is
  returned if the callback was called and reported success.
*/
BLAKEAPI(enum blakeError) blake_CrackPacket(
  int Socket,
  const void *PacketBuffer,
  const size_t BufferLength
);

/*
  In order to handle logging messages which Blake sometimes
  puts out (not overly often but it happens), install a handler
  to capture them.  This is a per-process thing.  To stop handling
  messages again call this again with the argument NULL.
*/
BLAKEAPI(void) blake_InstallLogger(void (*Handler)(const char* Message));

/*
  When a packet has been received by the server or the client and has
  been cracked by Blake, callbacks will be executed.  To ensure all
  packets that can be processed are handled install a callback for
  every possible client code (or server code in the case of the server)
  by calling this function many times within a a setup function before
  cracking any packets.  IsServer should be set by clients.  The Code
  should be cast from an enum blakeClientCode.  The callback should be
  able to accept a void pointer.  The void pointer is in reality the
  correct structure for that type of callback and should be cast to
  one of the structures in this file.  In addition, the int Sock is the
  socket of the relevant caller connection (user). Callbacks should report
  failure by returning zero or false.  If the installer reports an error,
  display it to the user as this is a-typical.
*/
BLAKEAPI(enum blakeError) blake_InstallCallback(
  blake_bool_t IsServer,
  WORD Code,
  blake_bool_t (*UserCallback)(int, const void*, const void*)
);

/*
  Networking
  ----------
  These work for TCP/IP.  Not all functions might work with UDP/IP but
  I don't know a lot about that.  These are implemented on BSD sockets
  for UNIX porting, Winsock for Windows and Open Transport on MacOS
  so they help the server and/or the client port.
*/

/*
  The broken pipe signal only exists on UNIX, clients and the server must
  ignore the signal or handle it with a handler which does nothing.
  If it is not ignored the process will exit with a Broken pipe message.
  When SIGPIPE is ignored or under systems which don't support the signal
  anyway, calls to the sockets API will result in an error indicating
  connection closed by the remote end or broken pipe.  In order to trap
  these install a callback which can take the socket identifier with
  this function.  When a socket is received via your callback, close it
  and do whatever you have to do to such as logging the broken
  connection.  This function does not generally fail, unless Blake has
  not been initialised.
*/
BLAKEAPI(enum blakeError) network_InstallBrokenPipeCallback(
  void (*NewCallback)(int SockDesc)
);

/*
  To close a socket previously created by network_CreateSocket(), call
  this function.  The function returns no value.  This is way to
  break a connection to the server/client.
*/
BLAKEAPI(void) network_CloseSocket(int SocketDesc);

/*
  To create a net socket of type int call network_CreateSocket().
  The socket integer returned is not gaurenteed to be interactable
  with the sockets API avoiding Blake.  It is for now but may change
  in the future.  The socket returned should only be used with the
  Blake network library.  IPv6 is not currently supports by Blake
  and will return an error (-1).  Datagram means UDP and not TCP.
  A datagram socket is not compatible with Blake but is supported
  for other purposes.  NonBlocking means that the socket will
  return from calls whether there has been data processed or not.
  See other manuals for in depth conversation on this.
  On failure the function returns -1.
*/
BLAKEAPI(int) network_CreateSocket(
  blake_bool_t IPv6,
  blake_bool_t Datagram,
  blake_bool_t NonBlocking
);


/*
  When a client wants to connect to the server it should do so with a
  blocking socket, it makes my life a lot easier.  However, Blake
  designed as it is wants you to specify whether a socket should block
  or not when it is created.  In order to make a blocking socket,
  connect it to the server and then switch to non-blocking mode,
  I have provided this nice, portable way of switching the socket
  mode.
*/
BLAKEAPI(void) network_MakeNonBlocking(
  int SocketDesc
);

/*
  The traditonal resolvers for UNIX and WinSock were not thread safe,
  nowadays there is a thread safe version of the resolver but it is
  not always present in all Unices and sometimes only exists in
  threaded builds.  network_Resolve() is far safer for us to use as it
  uses the traditional resolver but will only resolve one address at a
  time via mutual exclusion.  The function will not fail on DNS resolution
  failure.  It will take a pointer to the hostname and copy the IP address
  into the provided structure.  If the name cannot be looked up the IP
  is zeroed and the function still reports blakeSuccess.  The function
  can fail for other reasons such as bad parameters or library not
  initialised.
*/
BLAKEAPI(enum blakeError) network_Resolve(
  const char *HostNameIn,
  OVERCHAT_IP *IPOut
);

/*
  It is simple to determine whether an IP is zero or not but this
  function has been supplied so that clients can safely test the value
  without knowing whether Blake is still using IPv4 or IPv6.  The function
  returns false if the IP is OK.  It returns true if no address is passed
  or the IP is zero (for example 0.0.0.0).
*/
BLAKEAPI(blake_bool_t) network_IsZeroIP(
  const OVERCHAT_IP *PIP
);

/*
  This function is experimental, it prints an IP to stdout but may be
  scrapped as it is of limited use, it might be better to use the Get
  IP as string function.
*/
BLAKEAPI(void) network_PrintIP(
  const OVERCHAT_IP *IP
);

/*
  This function compares two IPs and returns true if they are the same,
  if one or both of the arguments are NULL it will behave in a logical manner,
  that is, NULL and NULL match (true), NULL and an IP, even if that IP is
  zero, do not match (false).
*/
BLAKEAPI(blake_bool_t) network_CompareIP(
  const OVERCHAT_IP *IP1,
  const OVERCHAT_IP *IP2
);

/*
  This function cracks a traditional IP (32-bit value), IPv4 from a
  DWORD into the structure which allows it's passing to other
  functions such as get as string.  It splits apart the DWORD into the
  four byte portions ready for dotted notation.
*/
BLAKEAPI(enum blakeError) network_CrackIPv4(
  const DWORD dwIPIn,
  OVERCHAT_IP *IPOut
);

/*
  See the above cracker, this function re-concatinates the IP into
  a DWORD for easy and smaller storage and for network interaction.
*/
BLAKEAPI(enum blakeError) network_DecrackIPv4(
  const OVERCHAT_IP *IPIn,
  DWORD *dwIPOut
);

/*
  This function connects a client to the server.  A socket open on the
  client side should be passed.  The socket should have been returned
  from network_CreateSocket() to be honest.  IPv6 will currently fail
  and is reserved for future use.  Port is generally 3277 or whatever
  the client is configured to connect on.  Certainly the official server
  runs on port 3277 at overchat.daybologic.com.  The IP is generally
  overchat.daybologic.com after it comes back from the resolver.  There
  is no need for anything interested to return.  If the function
  returns blakeSuccess then the socket has been successfully connected to
  the server, congratulation.
*/
BLAKEAPI(enum blakeError) network_Connect(
  int Socket,
  blake_bool_t IPv6,
  const unsigned short int Port,
  const OVERCHAT_IP *IP
);

/*
  To allow your program to be called when raw data arrives on a socket,
  a special raw data callback must be installed.  Simply pass the number
  of a socket which was previously created to this function along with
  the address of a function which should be called everytime data arrives
  on the socket.  Your callback can then use network_Read() to obtain
  the pending data.  Attention!  You must call blake_PendingLoop()
  somewhere in the client/server for this to work.  Preferably in the
  message loop or a time executing frequently.  Pending loop can also
  be configured to not return until the end of the program, then it
  can be run from an independent thread for maximum usabillity.  The
  pending loop may be given other tasks in the future but for now all
  it does is make sure that raw data is delivered to client/server via
  this raw data callback mechanisim.  Warning!  Whilst in the data
  callback you must return as soon as possible as you will be stalling
  the pending loop.  The function can fail if there is already an
  assosiated callback.  To remove a callback first pass NULL.  Passing
  -1 and NULL removes all callbacks, passing -1 and an address of an
  existing call-back is illegal.  Passing -1 and a new callback causes
  the callback to be called for all sockets Blake knows about.
  Note: The callback returns nothing and accepts the socket number.
*/
BLAKEAPI(enum blakeError) network_InstallIncomingCallback(
  int Socket,
  void (*DataReader)(int S)
);

/*
  Attention: This is an import function, one outgoing callback is allowed per
  process.  In it's early days, Blake did network output itself.  It does not
  do this any longer.  A client (and the server for that matter) need to be
  able to send data based around a select() loop.  They should support their
  own TX buffer and only write out of the buffer when select() says a socket
  is ready.  Therefore, when Blake is instructed to send data it purely
  sends _ALL_ data to the callback function.  The user (client or server) of
  Blake is expected to insert this data into the TX buffer.  If you fail to
  install a callback with this function, Blake will send NO data to the network!
  The callback does not need removing.  The function can fail with one of these
  errors:
    blakeInvalidParam - NULL passed.
    blakeRegAlready - This already was the callback (redundant)
    blakeNotStarted - Blake was not started
*/
BLAKEAPI(enum blakeError) network_InstallOutgoingCallback(
  void (*Sender)(int Socket, const void* RawData, size_t RawDataSize)
);

/*
  This function returns the next available socket for writing.  It returns
  -1 if no socket is ready for writing or no sockets are owned by the
  process.  In order for Blake to know which sockets to test for writabillty,
  the process must have installed them with network_InstallIncomingCallback( ).
*/
BLAKEAPI(int) network_ReturnWritableSocket(void);

/*
  This function initialises the IP, effectively a call to network_LoadIP()
  with NULL as a source.  Do not use with IPv6 IPs
*/
BLAKEAPI(enum blakeError) network_InitIPv4(
  OVERCHAT_IP *PIP
);

/*
  This is the Blake pending loop.  It must be called frequently in order
  to process data coming from over the network.  Either run this from
  a thread and tell it never to return (until the process shuts down)
  or tell it to return every loop and call it from a message loop (preferred)
  or timer.  The pending loop is mutually exclusive.  Careless calling
  from inside any callback such as those installed by
  network_InstallRawCallback() can deadlock the thread.
*/
BLAKEAPI(void) blake_PendingLoop(
  blake_bool_t RunForever
);

/*
  When the pending loop is running in 'RunForever' mode it should
  be cancelled before the process is cleaned up.  To do this
  simply call this function.  After the next loop, PendingLoop
  will return.  When pending loop is used is not running in
  'RunForever' mode, this function has no effect whatsoever.
*/
BLAKEAPI(void) blake_CancelPendingLoop(void);

BLAKEAPI(blake_bool_t) network_Write(
  int SocketDesc,
  const void *Buffer,
  const size_t BufferSize
);

/*
  This works the same way as recv()
*/
BLAKEAPI(int) network_Read(
  int SocketDesc,
  void *Buffer,
  const size_t BufferSize
);

/*
  Copies an IP address, NULL as PSource maybe used to init an IP address
*/
BLAKEAPI(void) network_LoadIP(
  OVERCHAT_IP *PDest,
  OVERCHAT_IP *PSource
);

/*
  Loads the IP holder with the IP when given the socket descriptor for
  the user
*/
BLAKEAPI(void) network_GetIPOnSocket(
  OVERCHAT_IP *PDest,
  int SocketDesc
);

/*
  Get IP as a string for printing
*/
BLAKEAPI(void) network_GetIPAsString(
  char *DestBuff,
  UINT DestMaxLen,
  OVERCHAT_IP *IPStore
);

/*
  Change byte order for network
*/
BLAKEAPI(unsigned long int) network_HostToNetLong(
  unsigned long int Value
);

BLAKEAPI(unsigned short int) network_HostToNetShort(
  unsigned short int Value
);

/*
  Change byte order from network
*/
BLAKEAPI(unsigned long int) network_NetToHostLong(
  unsigned long int Value
);

BLAKEAPI(unsigned short int) network_NetToHostShort(
  unsigned short int Value
);

/*
  Writes a string to the socket
*/
BLAKEAPI(blake_bool_t) network_WriteString(
  int SocketDesc,
  const char *Str
);

/*
  Faster if you only have one byte to write
*/
BLAKEAPI(blake_bool_t) network_WriteChar(
  int SocketDesc,
  char Char
);

/*
  This function is for incoming connections to the server.  This
  installs a socket collector callback.  The socket collector callback is
  called everytime a new connection arrives at the server.  This
  function is useless to clients.  The function will accept any function
  pointer, including NULL if no connections will be accepted.  Note that
  not accepting connections is not equivilant to blocking them, it's just
  a bad technique, you _must_ accept connections.  There is no function
  is Blake (yet) for temporarily denying connections.  The callback simply
  is given the socket of the client who has connection.  You may be wondering
  how to set this up, how to get program control to work.  Make sure you call
  the blake_PendingLoop() or Ccb() will never be called.  The function
  doesn't fail, that is not to say that it cannot.  It certainly fails if the
  Blake library is not initialised.  The port socket is the socket prepared
  for listening with network_StartListening().
*/
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) network_InstallCC(
    int PortSocket,
    void Ccb(int SocketNumber)
  );
#endif /*BLAKE_SERVER*/

/*
  The start listening function takes a socket returned by
  network_CreateSocket() and prepares the socket for listening.  It takes a
  call to the pending loop catalyst (as much as possible) to actually grab
  those callers which are coming in.  It also takes a function installed
  with network_InstallCC() to get those socket numbers of the connections.
  However, before a socket has been prepared for listening, the port is not
  open and it is impossible for for callers to connect.  You'll generally
  only call this once.  It can only work once per port number unless the
  port is closed with network_CloseSocket().  OverChat has one port
  (port 3277 as of writing).  Two ports don't have a purpose at this time
  but may later.  Presently, this function is only useful for the server
  not the client.  That may change if direct instant message connection
  becomes possible.
*/
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) network_StartListening(
    int PortSocket,
    unsigned short PortNumber
  );
#endif /*BLAKE_SERVER*/

/*
  Packet transmision
  ------------------
  All calls to transmit packets may result in a FALSE return,
  if this happens, wait, the buffers are full!
  Server side calls such as challenges are not exported from the DLL
  and are not even in the DLL code for client builds of the DLL.
  At library build time the define BLAKE_SERVER is expected to be defined
  or all server specific code is stripped to prevent crackers gaining
  more knowledge about server activities.
  The first of these server side packets is called Blake challenge, this
  asks a client to login with an amount of time.
*/
#ifdef BLAKE_SERVER
  BLAKEAPI(blake_bool_t) blake_Challenge(
    int Sock,
    USHORT MaxSecs,
    const unsigned char ChallengeDigest[BLAKE_MD5HASHLEN]
  );

  BLAKEAPI(blake_bool_t) blake_LoginReply(
    int Sock,
    enum blakeLoginReplyCode LoginReplyCode
  );
#endif /*BLAKE_SERVER*/
/*
  To login normally pass Username and Password, to login as a guest pass NULL
  as Username (Password would be ignored anyway).  System for determining your
  own username when assigned as a guest has not been completed.
  So this will presently fail.  A true return does not indicate successful
  login, just that the packet was successfully sent.  The language generally
  defaults to langEnglish.  Other languages are supported by the server
  and will affect all OverChat system messages being passed to a user.
  OverChat cannot convert foreign user's languages so that you can talk to
  them.  The challenge digest will have been received when you got the challenge,
  you must know it in order for blake_Login() to generate the correct secure
  hash for passing the password to the server.  As of tree 0.1.5, the
  login hash type has to be passed, if the server returns an error because
  the login hash is not supported, re-call blake_Login( ) with another hash
  from the most secure to the least secure until the server accepts you.
  NOTE: Hashes are listed by enum blakeHashType from the least secure to
  the most secure.
  The client ID and version are required for securing the system against
  unauthorised clients.  They must be correct or later security questions by
  the server will fail.
*/
BLAKEAPI(blake_bool_t) blake_Login(
  int Sock,
  const char *Username,
  const char *Password,
  enum blakeLang Language,
  const unsigned char ChallengeDigest[BLAKE_MD5HASHLEN],
  const enum blakeClientID ClientID,
  const unsigned long ClientVersion,
  enum blakeHashType LoginHashType
);

/*
  Functions called by the server to make the client "shaddup" occasionally.
  Listen to the server when you receive these packets!  Else the server
  will kill you!
*/
#ifdef BLAKE_SERVER
  /*
    if Seconds == 0UL client waits for a resume
  */
  BLAKEAPI(blake_bool_t) blake_Suspend(
    int Sock,
    const unsigned long Seconds
  );

  BLAKEAPI(blake_bool_t) blake_Resume(
    int Sock
  );
#endif /*BLAKE_SERVER*/

/*
  blake_Msg() is the function to use to message a user.  Pass the socket
  you are using as usual then the nickname of the person you are messaging,
  blake_Msg() does not need you to pass your own nickname, it already
  knows who you are ;-).  Then pass the message.  The message for the said
  person will be queued for you.  It is also now neccersary to pass a code
  identifiying the encryption cipher the message has been encoded with, note
  that I recommend plain text is never used over the internet.  Flags1
  is usually 0, check the BLAKEMESSAGE_FLAGS1_ flags for more information,
  always use BLAKEMESSAGE_FLAGS1_NOTICE for notices such as away messages.
*/
BLAKEAPI(enum blakeError) blake_Msg(
  int Sock,
  const char *NickName,
  const char *Msg,
  enum blakeCipherID BCID,
  blake_word8_t Flags1
);

/*
  blake_Msg2() is the function which doesn't message a user, it is very
  similar to blake_Msg(), except that it messages the server (or the client).
  Bi-directional just like IM type messages.
*/
BLAKEAPI(enum blakeError) blake_Msg2(
  int Sock,
  const char *Msg
);

/*
  blake_Whois() is a function which requests whois info about a person who
  is logged in.  Offline people are not currently supported.
  Daybo Logic have plans ahead to support this via a seperate database server
  which will be authoritiatve for everything, users on or offline.
  When a whois is requested, a whois info is returned, so ensure you
  have a callback to collect the data when it comes through.
*/
BLAKEAPI(enum blakeError) blake_Whois(
  int Sock,
  const char *NickName
);

/*
  blake_WhoisInfo() is a server side only function which is used to reply
  to a whois query.  It is not available to clients.  Nothing about the
  structure is modified.
*/
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_WhoisInfo(
    int Sock,
    const struct blakeWhoisInfo *PWhoisInfo
  );
#endif /*BLAKE_SERVER*/

/*
  This function requests version information from the server.
  A client has access to information about it's own library version
  through the blake_GetVersion() call but blake_Version() is a request
  to the server for it's own library version plus other information.
  You should have a callback installed for blake_Versioned, which will
  be the answer to this request.
*/
BLAKEAPI(enum blakeError) blake_Version(
  int Sock
);

#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_Versioned(
    int Sock,
    const struct blakeVersioned *PVersioned
  );
#endif /*BLAKE_SERVER*/

/*
  This function can be used to determine whether or not a specific
  user is online at any given time.
*/
BLAKEAPI(enum blakeError) blake_IsOnline(
  int Sock,
  const char *NickName
);

#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_IsOnlineReply(
    int Sock,
    const char *NickName,
    blake_bool_t Yes
  );
#endif /*BLAKE_SERVER*/

/*
  These two functions enable a client to request it's current privilege
  (clearance) level and the server to reply with the privilege.
  Set reserved to zero.
*/
BLAKEAPI(enum blakeError) blake_SuperRequest(
  int Sock,
  blake_word8_t Reserved
);
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_Super(
    int Sock,
    blake_word8_t Clearance
  );
#endif /*BLAKE_SERVER*/

/*
  These two functions are used for one of the most evil functions of
  OverChat.  /kill (grin).  Kill is used to disconnect another user
  and is only available to gods of the service.  Anybody else trying
  to use it will just be returned one of the standard error codes.
  Via the typical blake error reporting packet, the same one which
  is used when somebody you're messing isn't online, etc.  Note:
  The Sneer is used to tell the user they are a loser generally.
*/
BLAKEAPI(enum blakeError) blake_Kill(
  int Sock,
  const char *NickName,
  const char *Sneer
);

#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_Killed(
    int Sock,
    const char *NickOfKiller,
    const char *Sneer
  );
#endif /*BLAKE_SERVER*/

/*
  These two functions are for the purpose of registering users.  Generally
  a client will allow a user to register a few nicknames per session.
  It would be appreciated if client developers disable their registration
  commands after about three nicknames and re-enable them in a few hours
  to prevent abuse.  This is a measure to protect the registration system
  while the server developer(s) find a way to block abuse on the server side.
*/
BLAKEAPI(enum blakeError) blake_Register(
  int Sock,
  const char *Nick,
  const char *Email
);
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_RegisterReply(
    int Sock,
    const enum blakeRegisterReplyCode ReplyCode,
    const char *Password
  );
#endif /*BLAKE_SERVER*/

/*
  This function is server-side only.  It sends a client an error code
  for various conditions such as messaging a user who is offline or
  doesn't exist.  The Nick parameter is optional and can be useful
  for pointing out any nickname revelant to the error.
*/
#ifdef BLAKE_SERVER
  BLAKEAPI(enum blakeError) blake_GotError(
    int Sock,
    const enum blakeErrorCodes ErrorCode,
    const char *Nick
  );
#endif /*BLAKE_SERVER*/

/*
  blake_RecalculateRealPktSz() is a function to calculate the size of
  a Blake packet.  In code we know that the structure including unions
  is the same size as it's largest members but when transferred over then
  network, it is often valuable to know the true size.  The true size
  can be written to the packet's len member so that the other side of
  the conversation can read the packet and know when it truely ends.
*/
BLAKEAPI(blake_word16_t) blake_RecalculateRealPktSz(
  struct blakePacket *PPacket
);

/*
  This function may do nothing depending on what version of Blake
  you are using.  It is intended to give a dump of all memory
  allocated on behalf of the process by Blake.  The FileName is
  an empty or already existing text file in which text about
  the memory in use is dumped.  The file can then be read with
  an ordinary text editor.  If you need help discovering whether
  memory has been leaked by Blake or if you cannot find a resource
  leak in your own program with the data supplied contact me.  The
  information is in relation to Blake source & not to the host
  program's source, so it isn't always easy to discover the problem.
  The general theory is, however, that is you have a filename
  indicated as having memory allocated by the name of blake_fastqueue.c
  you know a queue is allocated etc.
*/
BLAKEAPI(void) blake_DebugDump(
  const char *FileName
);

/*
  This function is useful for when functions have to receive parameters
  to remain compatible with other interfaces which offer greater
  functionallity.  A lot of Blake protocol stuff uses this to accept
  extended packets because a few packets _do_ support extended packets
  even though most don't.  It is also useful for passing RCS id strings
  which state when a file was last modified and by whom.  It stops
  optimising compilers deleting those strings and prevents warnings.

  Note: Change in version 0.1.8, the function name was blake_Unused(),
  now the function name is blake_UnusedVar() and blake_Unused() is a
  macro which calls blake_UnusedVar().
*/
BLAKEAPI(void) blake_UnusedVar(
  const void *UnusedParam,
  blake_bool_t Recursed
);
#define blake_Unused(v) \
  blake_UnusedVar((v), 0)

/*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % This section deals with time and date functions.  Stored in      %
  % blake_time.c   When converting between types, we try to rely on  %
  % the C library where possible, to avoid pitfalls I may have missed%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  The following function converts an SQL format date/time string, which
  looks like this: "YYYY-MM-DD HH:MM:SS", to a time_t (UNIX format)
  which is the number of seconds since the epoch or the beginning of time
  as we know it.  January 1st 1970.
*/

BLAKEAPI(enum blakeError) blake_SQLToUnixTime(
  time_t *const PUnixTimeOut,
  const char *const PSQLTimeIn
);

/*
The following function converts an SQL format date/time string, which
  looks like this: "YYYY-MM-DD HH:MM:SS", to a a struct tm, which is
  well known to C programmers as an easily disectible, informative
  date/time representation structure.
*/

BLAKEAPI(enum blakeError) blake_SQLToTM(
  struct tm *const PTMOut,
  const char *const PSQLTimeIn
);

/*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % This section deals with OverChat database registration (locally  %
  % not remotely.  The atomic, physical process of adding, changing  %
  % and removing a person (a user) from the database.  Don't worry   %
  % about aquiring any locks, the whole process is always atomic per %
  % database.                                                        %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  This structure defines a user, their total information.  Many of the
  database functions expect a pointer to such a structure but many only
  use certain information and ignore those parts which are not required
  in the current context.  In revision 2 of the database these are actually
  stored like this in binary format in the file.  In version three, they
  are stored in multiple formats, MySQL is the most common.
*/
struct blake_db_user {
  unsigned long int id;
  unsigned long int uid;
  char username[BLAKE_NICK_LIMIT+1];
  char password[BLAKE_PASS_LIMIT+1];
  char realname[BLAKE_REALNAME_LIMIT+1];
  char email[BLAKE_EMAIL_LIMIT+1];
  blake_word16_t clearance; /* May use a bitfield of perms in future */
  char job[BLAKE_JOB_LIMIT+1];
  char www[BLAKE_WWW_LIMIT+1];
  char secretq[BLAKE_EMAIL_LIMIT+1];
  char secreta[BLAKE_EMAIL_LIMIT+1];
  time_t time_reg;
  time_t time_rec;
  time_t time_last;
  blake_word8_t deleted;
  blake_word8_t enabled;
  blake_word8_t online;
  blake_word32_t login_count;
  blake_word16_t warning_level;
  blake_word32_t kick_count;
  blake_word16_t kill_count;
  blake_word32_t brownie_points;
  blake_word16_t rate_limiter;
  blake_word8_t password_hash;
  blake_word16_t checksum; /* All fields but self, summed */
};
#define BLAKE_DB_USERSZ ( (BLAKE_NICK_LIMIT)+1 + (BLAKE_PASS_LIMIT)+1 + (BLAKE_EMAIL_LIMIT)+1 + 2 + (4 * 3) + 4 + 2 + 2 + 4 + 4 + 2 + 1 + 1 + 2 + 1 + 124)

/*
  This structure describes the header inside the database and is only used
  when the server reads the database, is is no use the clients.  Attention
  should be paid to the signature and revision to avoid reading the wrong
  file or an outdated file.
*/
struct blake_db_legacy_header {
  blake_word32_t Sig;
  blake_word16_t Revision;
  char Copyright[250];
};
#define BLAKE_DB_LEGACY_HEADERSZ ( 4 + 2 + 250 )

/*
  This enumeration specifies the system, db2 (legacy database) or
  mysql.  Support for other databases will only be added if the job
  demands it.  The numbers are fixed (useful to know if you are not using
  C to call any of the interfaces.
*/
enum blake_db_system {
  bdbSysDB2 = 0,
  bdbSysMySQL = 1,
  bdbSysPostGRESQL = 2
};

/* Some of the values which are always the same in the above header */
#define BLAKE_DB_LEGACY_HEADER_SIG (0x5692fc33)
#define BLAKE_DB_LEGACY_HEADER_REVISION (3)
#define BLAKE_DB_LEGACY_HEADER_COPYRIGHT "OverChat Database revision 2 (C)2002 Daybo Logic, all rights reserved.  www.overchat.org"

/*
  This type, BLAKE_DATABASE_HANDLE, is a handle which is used to access
  all databases, internally, it seperates filenames and the locks
  which should be used to access those files.
*/
typedef unsigned int BLAKE_DATABASE_HANDLE;

/*
  blake_db_CreateHandle( )
  Before accessing any database, a handle must be created for it,
  this is so that locks can be managed for the database.  This is
  enforced.  A return value of BLAKE_INVALID_HANDLE may be returned
  though the pointer and an error code returned if things go wrong.
  Always ensure the handle is unlocked before releasing it.  Releasing
  is done by blake_db_DestroyHandle( ).  Note that when a legacy database
  is used, InName becomes the filename containing the database and all
  other input parameters are ignored.
*/
BLAKEAPI(enum blakeError) blake_db_CreateHandle(
  const char *InHost,
  const char *InName,
  const char *InUser,
  const char *InPass,
  const char *InTable,
  BLAKE_DATABASE_HANDLE *PHandleOut
);

BLAKEAPI(enum blakeError) blake_db_legacy_CreateHandle(
  const char *InFileName,
  BLAKE_DATABASE_HANDLE *PHandleOut
);

BLAKEAPI(enum blakeError) blake_db_mysql_CreateHandle(
  const char *InHost,
  const char *InName, /* Or schema */
  const char *InUser,
  const char *InPass,
  const char *InTable,
  BLAKE_DATABASE_HANDLE *PHandleOut
);

BLAKEAPI(enum blakeError) blake_db_postgresql_CreateHandle(
  const char *InHost,
  const char *InName,
  const char *InUser,
  const char *InPass,
  const char *InTable,
  BLAKE_DATABASE_HANDLE *PHandleOut
);

/*
  blake_db_DestroyHandle( )
  Database handle destruction must be done only once the handle is
  unlocked and not in use.  You should destroy the handle before
  program clean up or whenever the database will be no longer required.
  Failure to do so will leak memory.
*/
BLAKEAPI(enum blakeError) blake_db_DestroyHandle(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_legacy_DestroyHandle(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_mysql_DestroyHandle(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_postgresql_DestroyHandle(
  BLAKE_DATABASE_HANDLE DBHandle
);

/*
  blake_db_LockTable( )
  The function provides mutual exclusion of database files.  Before
  accessing a database via it's handle, lock it with this function.
  Now you can be sure that the database is in a constant state and is not
  being accessed by other threads or processes.  To ensure consistency
  between operations it should be locked.  Once the database is unlocked
  it's content should be considered unknown.
  Use of these functions is mandatory, file is kept open in a locked
  state during this call as well as an internal mutant state change.
  Misuse of locking functions will cause a failure.  In the remote 'SQL'
  versions of the database, we will start a transaction on the table and
  the table will be locked until blake_db_UnlockTable( ) is called.
*/
BLAKEAPI(enum blakeError) blake_db_LockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_legacy_LockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_mysql_LockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(enum blakeError) blake_db_postgresql_LockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

/*
  blake_db_UnlockTable( )
  In remote 'SQL' databases, we will end the transaction, committing
  changes to disk (we never rollback).  In the legacy (file) database,
  this releases a file-system lock.
  Ensure you unlock a database which has been locked as soon as possible.
  Once it is unlocked it's contents should be considered unknown and it should
  not be accessed until a lock is re-aquired.  Failure to release a lock
  may result in deadlock and will lead to a locked file which can no longer
  be accessed.
*/
BLAKEAPI(void) blake_db_UnlockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(void) blake_db_legacy_UnlockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(void) blake_db_mysql_UnlockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(void) blake_db_postgresql_UnlockTable(
  BLAKE_DATABASE_HANDLE DBHandle
);

/*
  blakedb_Checksum16() returns a 16-bit checksum for a record.  It is not
  normally useful as the normal database functions always calculate this on
  a record's saving and check it on it's retrieval.  However, it may be useful
  for repair tools.  This function is not presently used on remote 'SQL'
  versions of the database to allow web-site code (generally PHP) to more
  easily manipulate and modify the records.
*/
BLAKEAPI(blake_word16_t) blake_db_Checksum16(
  const struct blake_db_user *UserRecord
);

/*
  blake_db_GetUserData( )
  This function takes as input, the user ID of a user.  It returns _all_
  information about the user from the database.  To check if the user
  did not exist, test TimeOf.Creation.  A zero time is the fastest way to
  detect that the user does not really exist at all.  Always test the return
  code for errors.  If a checksum was stored with a record (later versions
  only), the function may return blakeDbRecordCorrupt.  Should this happen,
  take evasive action, the best thing to do is to delete the user.
  Valid Uids are 1 through UINT_MAX.  Zero is not a valid Uid.
  Note that previous versions of the library allowed zero and called this
  a user index.  Passing zero will not result in blakeInvalidParam.
*/
BLAKEAPI(enum blakeError) blake_db_GetUserData(
  BLAKE_DATABASE_HANDLE DBH,
  unsigned int Uid,
  struct blake_db_user *PUserData,
  size_t SizeOfUserData
);

BLAKEAPI(enum blakeError) blake_db_legacy_GetUserData(
  BLAKE_DATABASE_HANDLE DBH,
  unsigned int Uid,
  struct blake_db_user *PUserData,
  size_t SizeOfUserData
);

BLAKEAPI(enum blakeError) blake_db_mysql_GetUserData(
  BLAKE_DATABASE_HANDLE DBH,
  unsigned int Uid,
  struct blake_db_user *PUserData,
  size_t SizeOfUserData
);

BLAKEAPI(enum blakeError) blake_db_postgresql_GetUserData(
  BLAKE_DATABASE_HANDLE DBH,
  unsigned int Uid,
  struct blake_db_user *PUserData,
  size_t SizeOfUserData
);

/*
  blake_db_CreateUser( )
  This call is used to create a new user.  They will be assigned the next
  free index, which will be returned.  You should test before creating
  the user, that a user with the same name does not already exist, otherwise
  you will make a duplicate and that will be nasty.  To tell if a user
  exists, use blake_db_GetUserIndex( ) and then blake_db_GetUserData( ) on the
  index.  PNewUserDataIn will be modified with a creation time/date.  On new
  users, checksums will be stored as a part of the record, it is unnecessary
  for the caller to worry about this.  Any checksum sent to the creator will
  be disregarded and overwritten.
*/
BLAKEAPI(enum blakeError) blake_db_CreateUser(
  BLAKE_DATABASE_HANDLE DBH,
  struct blake_db_user *PNewUserDataIn,
  unsigned int *PUserIndexOut
);

BLAKEAPI(enum blakeError) blake_db_legacy_CreateUser(
  BLAKE_DATABASE_HANDLE DBH,
  struct blake_db_user *PNewUserDataIn,
  unsigned int *PUserIndexOut
);

BLAKEAPI(enum blakeError) blake_db_mysql_CreateUser(
  BLAKE_DATABASE_HANDLE DBH,
  struct blake_db_user *PNewUserDataIn,
  unsigned int *PUserIndexOut
);

BLAKEAPI(enum blakeError) blake_db_postgresql_CreateUser(
  BLAKE_DATABASE_HANDLE DBH,
  struct blake_db_user *PNewUserDataIn,
  unsigned int *PUserIndexOut
);

/*
  blake_db_GetUserIndex( )
  Returns the numeric index of a user within the database by nickname.
  To ensure consistency the database must be locked during the call
  to this function and to the call(s) which rely on the result, as once
  unlocked, indexes could in theory be changed.  In reality they won't...
  but that's using a dangerous assumption that I will always use the
  current system for storing people in an INI file, I may in future
  start reassigning indexes if a user is deleted so don't rely on this
  behaviour.  Just because an index is returned, it does not mean that
  user exists.  The index exists and should be tested with GetUserData()
  to see if the person you're looking for is real.  NickName is not
  case sensitive.  Warning: This function really does return the index
  of the user within the database, that index may not be related to their
  user ID.
*/
BLAKEAPI(unsigned int) blake_db_GetUserIndex(
  BLAKE_DATABASE_HANDLE DBHandle,
  const char *NickName
);

BLAKEAPI(unsigned int) blake_db_legacy_GetUserIndex(
  BLAKE_DATABASE_HANDLE DBHandle,
  const char *NickName
);

BLAKEAPI(unsigned int) blake_db_mysql_GetUserIndex(
  BLAKE_DATABASE_HANDLE DBHandle,
  const char *NickName
);

BLAKEAPI(unsigned int) blake_db_postgresql_GetUserIndex(
  BLAKE_DATABASE_HANDLE DBHandle,
  const char *NickName
);

/*
  This simple function initialises a blake_db_User structure.
*/
BLAKEAPI(enum blakeError) blake_db_InitUser(
  struct blake_db_user *PUserData,
  size_t UserDataSz
);

/*
  This function sets an exisitng user record with updated data.
  Make sure you're overwriting the correct record or you will cause some evil
  side effects and user annoyance!  On new records, checksums are stored.
  The Checksum field in the user record will be automatically recalculated
  before it is stored, there is no need to manually change this field.
  Note: In the 'SQL' remote server version of the code, shortcuts may be
  used, using the user ID to prevent looping through the entire database
  and thus leaving the logic to the backend database.  The consequence of
  this is that the index may be ignored and cannot be considered valid
  after the call.  It is kept for compatibility with the legacy database
  only.
*/
BLAKEAPI(enum blakeError) blake_db_UpdateUser(
  BLAKE_DATABASE_HANDLE DBHandle,
  unsigned int Index,
  struct blake_db_user *NewUserRecord,
  size_t UserRecordSz
);

BLAKEAPI(enum blakeError) blake_db_legacy_UpdateUser(
  BLAKE_DATABASE_HANDLE DBHandle,
  unsigned int Index,
  struct blake_db_user *NewUserRecord,
  size_t UserRecordSz
);

BLAKEAPI(enum blakeError) blake_db_mysql_UpdateUser(
  BLAKE_DATABASE_HANDLE DBHandle,
  unsigned int Index,
  struct blake_db_user *NewUserRecord,
  size_t UserRecordSz
);

BLAKEAPI(enum blakeError) blake_db_postgresql_UpdateUser(
  BLAKE_DATABASE_HANDLE DBHandle,
  unsigned int Index,
  struct blake_db_user *NewUserRecord,
  size_t UserRecordSz
);

/*
  This function allows one to retrieve the header of the database.  Usually
  people don't bother with this.  Calling this function when not using
  a legacy file based database will result in an error code being returned.
*/
BLAKEAPI(enum blakeError) blake_db_GetLegacyHeader(
  BLAKE_DATABASE_HANDLE DBHandle,
  struct blake_db_legacy_header *PHeaderOut
);

/*
  This function allows one to set the header of the database.  No details of
  the database will be verified, it is effectively a raw write to the header
  (with endian and other basic issues dealt with).  Writing bad information
  here will make tools which deal with the database or further reads of the
  database fail if the information is not valid.  So leave it alone unless
  you're sure you're doing the right thing!

  Note: Calling this function on a database which is not actually a legacy
  file database will result in an error code being returned and no
  action will take place.
*/
BLAKEAPI(enum blakeError) blake_db_PutLegacyHeader(
  BLAKE_DATABASE_HANDLE DBHandle,
  const struct blake_db_legacy_header *PHeaderIn
);

/*
  For more refined writing of a header, call blake_db_InitLegacyHeader()
  which will fill a header structure full of the correct data in for you,
  then call blake_db_PutLegacyHeader() above.
*/
BLAKEAPI(enum blakeError) blake_db_InitLegacyHeader(
  struct blake_db_legacy_header *PHeader
);

/*
  This function allows one to count how many users have been registered,
  it a handle should be aquired, the database locked open, then this can
  be called, don't forget to release lock(s) as soon as possible.
  The function will not list corrupted or deleted records.  The function
  will end when the first record with no registration time and with no deleted
  flag is found, this is the virtual record which signifies the end of the
  database (it doesn't really exist), don't forget these rules when using
  the database yourself.  In 'SQL' versions of the database, a statement
  is executed which will count all rows which are not marked as deleted.
*/
BLAKEAPI(unsigned long int) blake_db_CountUsers(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(unsigned long int) blake_db_legacy_CountUsers(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(unsigned long int) blake_db_mysql_CountUsers(
  BLAKE_DATABASE_HANDLE DBHandle
);

BLAKEAPI(unsigned long int) blake_db_postgresql_CountUsers(
  BLAKE_DATABASE_HANDLE DBHandle
);

/*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % This section of Blake deals with nicknames (shortened to nicks)%
  % Always use these routines.  Not your own fast replcements or   %
  % inline hacks.  These must be used to ensure that any new rules %
  % work correctly.                                                %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/

/*
  blake_NickTest( ) should return true.  If it returns a character,
  via a pointer it means that character was deemed illegal for inside
  a nickname.  If the function returns a space (' ') as illegal,
  it does not mean space is illegal... but to have _only_ space
  (no other alphanumerics) or if the nick begins with a space, then it
  is illegal.
  If the nick is too long the TooLong flag is set.
*/
BLAKEAPI(blake_bool_t) blake_NickTest(
  const char *Nickname,
  blake_bool_t *PTooLong,
  char *PSingleInvalidCharacter
);

/*
  This function works in exactly the same way as the nickname tester but it
  is designed for passwords.
*/
BLAKEAPI(blake_bool_t) blake_PassTest(
  const char *Password,
  blake_bool_t *PTooLong,
  char *PSingleInvalidCharacter
);

/*
  blake_NickCompare( ) returns true if the nicks are the same false if
  they are not.  "Toad" and "t   oaD" are deemed the same nick.
  "David" and "dA v1d" are not.
*/
BLAKEAPI(blake_bool_t) blake_NickCompare(
  const char *Nick1,
  const char *Nick2
);
#define blake_ChatCompare(cr1, cr2) \
          blake_NickCompare((cr1), (cr2))

/*
  blake_EmailCompare( ) returns true if the email addresses are the same
  and false if they are not the same.  It is a very safe compare which
  converts to uppercase for the comparision and strips and trailing or
  leading space.
*/
BLAKEAPI(blake_bool_t) blake_EmailCompare(
  const char *Email1,
  const char *Email2
);

/*
  blake_NickRude( ) returns true if a nickname is considered to be rude.
  This function can only work when the path/filename or just the filename
  of a file containing strings which are deemed unacceptable is passed.
  The file contains strings such as fuck, shit and cunt.  Thus meaning
  that substring using nicks like: fucktard, shitfaced and cuntbreath
  cannot be used.
*/
BLAKEAPI(blake_bool_t) blake_NickRude(
  const char *RudeFileName,
  const char *Nick
);

/*
  blake_RandPass( ) returns a password of random length containing
  random nonsense.  No spaces will be inserted.  This password generator
  was written by Total Konfuzion of OC32 fame.  <totalk@daybologic.co.uk>
  Reinit is used to determine whether Blake reseeds the random number
  generator.  It takes five seconds to seed the generator.
*/
BLAKEAPI(enum blakeError) blake_RandPass(
  char *BufferOut,
  size_t BuffSize,
  blake_bool_t Reinit
);

/*
  This function normalises nicknames to a consistant state, useful for
  log files and the like.  "D D    Rp"  will become "ddrp".  The MaxBuffSz
  must be the size of the buffer 'Normalised'.  'Normalised' must be
  enough to hold the un-normalised nickname, a buffer of the same size
  as Nickname is most cases.
*/
BLAKEAPI(enum blakeError) blake_NormNick(
  const char *Nickname,
  char *Normalised,
  const size_t MaxBuffSz
);

/*
  The following function destructively modifies the original string.
  The password 'blah' will become '****'
*/
BLAKEAPI(char *) blake_PassMask(
  char *Password
);

/*
  This function is used to convert a security clearance level into a user
  readable string.  It returns the length of the string so that memory can
  be allocated.  The length is in characters excluding the NULL terminator.
  When calling for the second time, the number of bytes of memory allocated
  should be passed so the function can avoid overwriting a buffer which is
  not large enough.
*/
BLAKEAPI(unsigned int) blake_GetClearanceString(
  unsigned int Level,
  char *Buff,
  size_t MaxBuffSize
);

/*
  This function works in exactly the same way as blake_GetClearanceString,
  however, the string returned is not a user friendly string, it is the
  programmers' mnemonic symbol.
*/
BLAKEAPI(unsigned int) blake_GetClearanceMnemonic(
  unsigned int Level,
  char *Buff,
  size_t MaxBuffSize
);

/*
  This function is designed to convert a mnemonic such as CLEARANCE_UNAUTHORISED
  to it's equivillent integer representation which most functions expect.
  -1 is returned on failue.
*/
BLAKEAPI(int) blake_GetClearanceNumeric(
  const char *Mnemonic
);

/*
  Elite script kiddies like to speak in a silly way.  It's a load of hassle
  to master.  You can use this function in a client to allow the user to
  use it automatically.  The source message is modified, there is no reliable
  way to reverse the effect.
*/
BLAKEAPI(enum blakeError) blake_13375p34k(
  char *Message
);

/*
  Blake has some ANSI replacements for things which aren't natively available
  to clients, the server or Blake itself.  These calls can be called without
  worrying that the functions may not exist on the target machine.
  They work exactly the same as the normal non-ANSI C equivilants.
*/
BLAKEAPI(int) blake_stricmp(
  const char *s1,
  const char *s2
);

BLAKEAPI(char*) blake_strlwr(
  char *s
);

BLAKEAPI(char*) blake_strupr(
  char *s
);

BLAKEAPI(char*) blake_strdup(
  const char *s
);

/*
  The Str buffer must be at least (8*sizeof(int))+1) which supports the
  lowest possible radix (2, binary).  Note that presently I only support
  radix 8, 10 and 16.  Other radixes will be supported when they are
  required by somebody.  The function returns NULL is an unsupported radix
  is used or other failures.
  FIXME NOTE: This only currently uses radix 10
*/
BLAKEAPI(char*) blake_itoa(
  int Value,
  char *Str,
  int Radix
);

/*
  Raw strip manipulation functions which have never been in C languages
  to my knowledge.
*/
BLAKEAPI(void) blake_LTrim(
  char *Str
);

BLAKEAPI(void) blake_RTrim(
  char *Str
);

BLAKEAPI(void) blake_Trim(
  char *Str
);

/************************************************************************
  Blake non-portable file system support.  Internally, these things are
  very different for each operating system.  So it makes sense for Blake
  to offer the abstracted interface to everybody.
*************************************************************************/

/*
  Open a file for exclusive access.  This will ensure other processes fail
  when opening the file.  On UNIX there are many different ways of locking
  files, I cannot gaurentee exclusitivy but if you use this interface for
  all processes likely to access the file you will ensure that it works
  correctly on all operating systems.  FileName gives the name of the file.
  NeedWrite must be set true if you want write access to the file, otherwise
  only read access is granted.  Note: Files are dealt with in binary mode.
  The pointer to the file stream is returned through a pointer to a pointer.
  Ensure your FILE* is NULL and then pass the address of your pointer to
  the function.  Always check the return value before checking values.
  If anything other than blakeSuccess, do not close the handle.
*/
BLAKEAPI(enum blakeError) blake_ExclusiveFileOpen(
  const char *FileName,
  blake_bool_t NeedWrite,
  FILE **PHandle
);

/*
  This function must only be used on handles returned from
  blake_ExclusiveFileOpen().  It releases the lock on the file and
  closes it.  NOTE: On UNIX I don't think I need unlock, only close the
  handle but I need more information on this.  I presently do not unlock
  on UNIX.
*/
BLAKEAPI(void) blake_ExclusiveFileClose(
  FILE *Handle
);

/*
  Language features (blake_lang.c).
  Use these to help support new languages when they come along rather than
  using your own strings to decide on the language name.  New: Portable
  interface to an external strings file.
*/

/*
  blake_LangShortcut() reutrns the simple two letter string which
  identifies a language.  en, fr for English, French etc.  Do
  not modify the returned pointer as it it part of a Blake internal
  array.  If the language is unknown, NULL is returned.
*/
BLAKEAPI(const char*) blake_LangShortcut(
  enum blakeLang LangCode
);

/*
  blake_LangName() returns the name of the language in the language
  requested.  For example, the French don't call French French, so it's
  good to use their version of the word.  Pass firstly the language code
  you want to get the string of and then the lsnguage the string should
  be in.  Do not modify the returned pointer as it is part of an internal
  Blake table.  IF the language is unknown, the simple string "unknown
  language" is returned in whatever language you select.  If both languages
  are unknown, the message "unknown language" is returned in English.
*/
BLAKEAPI(const char*) blake_LangName(
  enum blakeLang LangCode,
  enum blakeLang InLanguage
);

/*
  blake_LangSetFile() should be used before calling blake_LangGetString(),
  it indicates the file which contains the strings in the supported languages
  the file is an RTTB format file containing plain text files which
  name the language by the language's two letter code.  Obviously because
  of the split up between these functions, only one file is supported
  per process.  Threads can't use different strings.  Strings are cached
  by Blake and are not re-read unless blake_LangCacheFlush() is called.
*/
BLAKEAPI(enum blakeError) blake_LangSetFile(
  const char *LanguageFile
);

BLAKEAPI(const char*) blake_LangGetString(
  int StringID,
  enum blakeLang Language,
  enum blakeError *PBlakeErrorOut
);

BLAKEAPI(enum blakeError) blake_LangCacheFlush(
  OVERCHAT_PROTOTYPE_VOID
);

/***********************************************************************
  OverChat safe memory allocations section.  Use this in your clients
  or in the server.  The portions of memory are protected unless a direct
  pointer is requested to prevent new programmers from messing up memory.
 ***********************************************************************/

typedef unsigned long int BLAKE_SA_HANDLE; /* User mode handle for their blocks */
typedef unsigned char BLAKE_SA_FLAGS; /* Flags for allocating new blocks */

/* Values for BLAKE_SA_FLAGS (bitmask) */
#define BLAKE_SA_FLAGS_VIRTUAL (1) /* Use swapfile */
#define BLAKE_SA_FLAGS_PRIVATEVIRTUAL (2) /* Use a private swapfile (requires VIRTUAL) */
#define BLAKE_SA_FLAGS_VIOLATIONKILL (4) /* Kill program on boundry violation */
#define BLAKE_SA_FLAGS_USEMINLIMIT (8) /* Use minimum size limit */
#define BLAKE_SA_FLAGS_USEMAXLIMIT (16) /* Use maximum size limit */
#define BLAKE_SA_FLAGS_GROW (32) /* Self growing block */

#define BLAKE_SA_FLAGS_DEFAULT ( 0 | (BLAKE_SA_FLAGS_VIOLATIONKILL) )

typedef struct {
  unsigned long int CurrentUsedSize; /* Actual bytes used */
  unsigned long int HardLimit; /* 0 or the absolute limit (depending on growth/limit) */
  unsigned long int NextLimit; /* 0 or the next boundry which will execute growth */
  BLAKE_SA_FLAGS Flags; /* Just the typical flags */
  unsigned long int AccessCount; /* Number of times the memory has been accessed */
  unsigned long int MinSize;
  time_t CreationTime; /* Time at which this block was allocated */
} BLAKE_SA_LSTATS;

typedef struct {
  unsigned long int Count; /* Number of blocks */
  unsigned long int Bytes; /* Number of bytes in use */
  unsigned long int ActualBytes; /* Bytes plus any growth factor */
  BLAKE_SA_LSTATS EarliestBlock; /* First block allocated by user */
  BLAKE_SA_LSTATS LatestBlock; /* Latest block allocated by user */
  BLAKE_SA_LSTATS SmallestBlock; /* Full info about smallest block */
  BLAKE_SA_LSTATS LargestBlock; /* Full info about largest block */
} BLAKE_SA_GSTATS;

/*
  The growth should be reasonable for self-growing blocks, otherwise time
  is wasted, use blake_SetSafeAllocateGrowthFactor() to change it on a per
  block basis.
*/
#define BLAKE_SA_DEFAULTGROWTH (256)

/*
  Trap codes are used generally internally to indicate a user fault.
  Except User which is used for custom stuff by users.
*/
enum blakeSAtrapCode {
  blakeSAtrapCodeUser, /* User mode trap for user strange reason */
  blakeSAtrapCodeBoundingViolation, /* Typical overrun, you die! */
  blakeSAtrapCodeCorruption, /* Checksum mismatch */
  blakeSAtrapCodeBadHandle /* Handle is crap or already released */
};

/*
  Flags may only be specified when a block is created and recovered with this
  function, it's not possible to change flags because Blake won't start
  treating the block differently (virtual/real) and the file might be already
  outside limits.
*/
BLAKEAPI(enum blakeError) blake_SafeAllocateGetBlockFlags(
  BLAKE_SA_HANDLE Handle,
  BLAKE_SA_FLAGS *PFlagsOut
);

/*
  Safe allocator's main function to allocate new memory.  The memory which
  is allocated for the user is protected and is not exposed to the caller
  unless requested.  Use the handle with all other SafeAllocate functions to
  handle the memory.  If the flags specify use of limits, defaults are applied
  until limit modifiers are applied to the block with other functions.
  Always use BLAKE_SA_FLAGS_DEFAULT as the flags unless you know what
  you're doing.  That function will apply defaults to the flags.
*/
BLAKEAPI(enum blakeError) blake_SafeAllocate(
  unsigned long int Size,
  BLAKE_SA_FLAGS Flags,
  BLAKE_SA_HANDLE *PHandleOut
);

/*
  Safe allocate limits only matter if the block was created with
  BLAKE_SA_FLAGS_USEMINLIMIT, BLAKE_SA_FLAGS_USEMAXLIMIT or both.
  A minimum size is useful for speed, I recommend using this for virtual
  files, it's useless otherwise.  The maximum limiter stops you growing
  a self growing array to a stupid size, if not using growable arrays
  it is useless.
*/
BLAKEAPI(enum blakeError) blake_SetSafeAllocateLimits(
  BLAKE_SA_HANDLE Handle,
  unsigned long int Minimum,
  unsigned long int Maximum
);

/*
  To free a block which has been allocated earlier use this function, it
  is essential that it is used.  Blake will trap anything not freed with a
  fatal crash.  Blake will fire a fatal trap if the handle is invalid.
*/
BLAKEAPI(void) blake_SafeFree(
  BLAKE_SA_HANDLE Handle
);

/*
  To get global statistics about safe allocations use this function and point
  to your structure to receive the data.
*/
BLAKEAPI(enum blakeError) blake_GetSafeAllocateGlobalStats(
  BLAKE_SA_GSTATS *PGlobalOut
);

/*
  To get local statistics for a specific block use this local stats grabber.
*/
BLAKEAPI(enum blakeError) blake_GetSafeAllocateLocalStats(
  BLAKE_SA_HANDLE Handle,
  BLAKE_SA_LSTATS *PLocalOut
);

/*
  Sets the growth factor for a block, this is useful only of the block
  supports growth.  That is decided by the flags sent by the caller when
  creating the block.  This function will fail if the block does not
  support growth. The default growth factor is BLAKE_SA_DEFAULTGROWTH.
*/
BLAKEAPI(enum blakeError) blake_SetSafeAllocateGrowthFactor(
  BLAKE_SA_HANDLE Handle,
  unsigned int NewGrowthFactor
);

/*
  The following is a last resort and should not be used if you can avoid it.
  If there is something you'd like to be able to use with the safe wrappers
  which can't be done, contact DDRP and see if he can do something about it
  before resorting to this emergency way to recover the _actual_ hidden
  pointer to the memory.  Once you alter data manually you _must_ call
  blake_SafeAllocateResetSum() on the data!  Ottherwise corruption will
  be reported!
*/
BLAKEAPI(void*) blake_SafeAllocateExposePointer(
  BLAKE_SA_HANDLE Handle
);

/*
  Manual traps are useful if you _know_ something is wrong, I can't think of
  a good example but if you need to use this feature do so.  It is recommended
  that the TrapCode be blakeSAtrapCodeUser only to prevent confusion with
  Blake generated traps.
*/
BLAKEAPI(void) blake_SafeAllocateTrap(
  BLAKE_SA_HANDLE Handle,
  enum blakeSAtrapCode TrapCode,
  const char *Description
);

/*
  This is called internally everytime any operation is performed on a block
  of data, users only need to call this if they manually expose the pointer
  and change data themselves.  It reset the internal checksum which keeps an
  eye out for corruption.
*/
BLAKEAPI(void) blake_SafeAllocateResetSum(
  BLAKE_SA_HANDLE Handle
);

/*
  This is used to copy data into a block from a raw pointer.
  If the block is self growing the size up may fail, if it is fixed size
  or limited it's possible that a trap may occur, crashing the program.
*/
BLAKEAPI(enum blakeError) blake_SafeAllocateRawToBlock(
  BLAKE_SA_HANDLE Handle,
  const void *SourceData,
  unsigned int DestinationIndex
);

/*
  The opposite of the above, copying out of the block back into a raw memory
  pointer
*/
BLAKEAPI(void) blake_SafeAllocateBlockToRaw(
  BLAKE_SA_HANDLE Handle,
  unsigned int SourceIndex,
  void *DestinationPointer
);

/*
  This clears the current contents of a block of memory under the control
  of the safe allocator.
*/
BLAKEAPI(void) blake_SafeAllocateClear(
  BLAKE_SA_HANDLE Handle
);

/*
  *******************************************************************
  * Blake's general purpose panic function.  Terminates the process *
  * Please use this rather than assert().  Include stopcodes.h for  *
  * the list of codes, the codes are assigned to project members    *
  * in ranges or to project components specifically.  The first par-*
  * ameter is the source filename, the second is the line number.   *
  * The third is the stop code from stopcodes.h and the remaining   *
  * parameters are stop code specific.  Notes in stopcodes.h reveal *
  * the meaning of these parameters.  Ensure you get the count of   *
  * parameters right or Panic() will overrun!                       *
  * Panic does not return.                                          *
  *******************************************************************
*/
typedef unsigned short int BLAKE_STOPCODE;

BLAKEAPI(void) blake_Panic(
  const char *File,
  unsigned int Line,
  BLAKE_STOPCODE StopCode,
  unsigned int ParamCount,
  blake_word32_t Params[]
);
#define PANIC(sc, pm, params) \
  blake_Panic(__FILE__, __LINE__, (sc), (pm), (params))

/*
  This function is simple and returns the macro name associated with a define
  macro for a stop code.  For example if a stop code has the string macro
  BLAKESTOP_CORE_LIST_CORRUPT and that translates to number 4 (example only),
  this function will return "BLAKESTOP_CORE_LIST_CORRUPT"
*/
BLAKEAPI(const char*) blake_StopCodeString(
  BLAKE_STOPCODE StopCode
);

/*
  This function returns a pointer to a useful descriptive string for the
  error.  Seeing as all the programmers speak English, I haven't bothered
  with language support.  Users shouldn't see these strings in general
  operation and they are only of use to nerds.
*/
BLAKEAPI(const char*) blake_StopCodeDescription(
  BLAKE_STOPCODE StopCode
);

/* Hash based security features. */

/*
  The MD5 hash comparison function is a wrapper for the DayboCrypt
  MD5 digest comparison function, it returns true if the both MD5 hashes
  are the same and false if they differ.  It is safe against NULL pointers
  and works in a logical fashion with them.
*/
BLAKEAPI(blake_bool_t) blake_MD5CompareDigests(
  const unsigned char Digest0[BLAKE_MD5HASHLEN],
  const unsigned char Digest1[BLAKE_MD5HASHLEN]
);

/*
  This functions works in exactly the same way as MD5CompareDigests()
  but it is designed for the SHA-1 algorithm.
*/
BLAKEAPI(blake_bool_t) blake_SHA1CompareDigests(
  const unsigned char Digest0[BLAKE_SHA1HASHLEN],
  const unsigned char Digest1[BLAKE_SHA1HASHLEN]
);

/*
  The random hash function returns a securely random MD5 hash which is
  total garbage and highly unlikely to repeat, the resulting hash value
  can be used to send to clients in order to make their password hashes
  securely dynamic within a second hash of the password hash + the random
  hash.
*/
BLAKEAPI(unsigned char*) blake_MD5SecureRandomHash(
  unsigned char HashOut[BLAKE_MD5HASHLEN]
);

/*
  The double password hash creates a hash based on a random hash and a password,
  so that (I pontificate) it will take several months in a specific cracker
  (not an automated program) to find the password.  If users change their
  passwords every three months this is secure.  HashOut is the effective
  return value (the real return value is the standard Blake error number),
  Password is the cleartext password, HashIn is expected to be a hash
  returned by blake_MD5SecureRandomHash() and both sides of the conversation
  must know it in order to generate the same hash for comparison.  Remember,
  this is a one way hash, it is computionally difficult to get the password
  back from this function and should take several months to complete.
*/
BLAKEAPI(enum blakeError) blake_MD5SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_MD5HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function does the same job as
  blake_MD5SecureRandomHash() but it has been designed for clients
  who wish to log in via the SHA-1 algorithm.
*/
BLAKEAPI(enum blakeError) blake_SHA1SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_SHA1HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function does the same job as
  blake_MD5SecureRandomHash() but it has been designed for clients
  who wish to log in via the SHA-224 algorithm
*/
BLAKEAPI(enum blakeError) blake_SHA224SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_SHA224HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function does the same job as
  blake_MD5SecureRandomHash() but it has been designed for clients
  who wish to log in via the SHA-256 algorithm
*/
BLAKEAPI(enum blakeError) blake_SHA256SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_SHA256HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function does the same job as
  blake_MD5SecureRandomHash() but it has been designed for clients
  who wish to log in via the SHA-384 algorithm
*/
BLAKEAPI(enum blakeError) blake_SHA384SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_SHA384HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function does the same job as
  blake_MD5SecureRandomHash() but it has been designed for clients
  who wish to log in via the SHA-512 algorithm
*/
BLAKEAPI(enum blakeError) blake_SHA512SecureDoublePasswordHash(
  unsigned char HashOut[BLAKE_SHA512HASHLEN],
  const char *Password,
  const unsigned char HashIn[BLAKE_MD5HASHLEN]
);

/*
  This function returns the official name of a hash from it's code.
*/
BLAKEAPI(const char*) blake_HashTypeName(
  const enum blakeHashType HashType
);

/*
  Checksumming features.  Please use these instead of writing
  your own routines to keep overhead down.  I'm using pointers
  for these, this provides us for expansion for other types
  such as 64-bit support on systems which won't allow us to pass
  a 64-bit value.  64-bit will of course return via a second
  parameter.
*/
BLAKEAPI(blake_word16_t) blake_Sum16OfWord8(
  const blake_word8_t *PWord8
);

BLAKEAPI(blake_word16_t) blake_Sum16OfWord16(
  const blake_word16_t *PWord16
);

BLAKEAPI(blake_word16_t) blake_Sum16OfWord32(
  const blake_word32_t *PWord32
);

BLAKEAPI(blake_word32_t) blake_Sum32OfWord8(
  const blake_word8_t *PWord8
);

BLAKEAPI(blake_word32_t) blake_Sum32OfWord16(
  const blake_word16_t *PWord16
);

BLAKEAPI(blake_word32_t) blake_Sum32OfWord32(
  const blake_word32_t *PWord32
);

/*
  This function returns the address of the caller.  Please don't rely on it
  for calculations or critical things, just use it for debugging purposes
  or logging.  I don't know how portable it is across different systems.
  Cast the return value to an void* if you want to dereference it for some
  reason.  The variable 'x' can be anything, just pass 0, it's used for internal
  stack logic and it's value doesn't matter, just it's position on the stack.
*/
BLAKEAPI(unsigned int) blake_Here(
  unsigned int x
);

/*
  Functions for dealing with the new client/server authentication scheme
  (used to lock unauthorised clients out).
  There are mostly for the server only.
*/

/*
  This function returns the desription of an authorised client of OverChat.
  The length is the return value and you must allocate emough memory
  to get the string on the second call.
*/
BLAKEAPI(unsigned int) blake_GetClientIDString(
  const enum blakeClientID ClientID,
  char *PBuffOut,
  const size_t MaxBuffSz
);

/*
  ***********************************
  * Blake Benchmarking - testing if *
  * systems are adequate.           *
  ***********************************
*/

/*
  blake_LoopBenchmarkGetIndex() returns either -1 (clock skew), which means
  the user changed the clock to an earlier time during the test (in which
  case the test should be repeated), 0, for a very slow computer which did
  not complete the test or between 1 and 10, where 10 is the fastest
  computer.  If the test does not return -1, the result is cached so that
  time is not wasted if the function is called multiple times during
  the same execution.  It is recommended that the program save the result
  in a configuration file to avoid calling this, during program init-
  ialisation, call blake_LoopBenchmarkSetIndex() with the benchmark you
  got on the first program execution.  How long this function takes to
  return depends on the speed of the computer, the maximum time the test
  is allowed to take is 120 seconds (two minutes), at which time the
  function returns zero.
*/
BLAKEAPI(int) blake_LoopBenchmarkGetIndex(void);

/*
  blake_LoopBenchmarkSetIndex() is used to initialise the benchmark so
  that the real benchmark is not performed when it is got by the above
  function.  A value above 10 will be assumed to be 10.  A warning will
  be printed to stderr if a value above 10 is used.  The function returns
  the previous value, which is probally -1, as this is the internal value
  to represent that the benchmark has not yet been run.  Unless you have
  called this function before of course.  Calling this function with a
  value of -1 will allow GetIndex() to run the benchmark again, for real.
*/
BLAKEAPI(int) blake_LoopBenchmarkSetIndex(
  const int OldIndex
);

/*
  **********************************************
  * Contact info - this is available so that   *
  * clients can display who to contact incase  *
  * of failures.  Or perhaps in the credits.   *
  * Of course, the credits for the client      *
  * will have to be added manually, as I can't *
  * really add them here.                      *
  **********************************************
*/

enum blakeContactInfoType {
  blakeCitEmail, /* Email addresss or webform */
  blakeCitName,  /* Nickname or realname information */
  blakeCitTasks  /* Tasks and responsibillities */
};

/*
  blake_GetContactInfo() returns the strings related to a particular
  item of contact info.  Index begins at zero the user should increment
  the Index until the function returns blakeRange, which means that
  the range of indexies has been exceeded.  blakeBufferTooSmall will
  be returned if the buffer supplied is too small.  Partial contact
  details aren't returned.  If you do not know the length of a contact
  info, you could call blake_GetContactInfoLen().  The maximum length of
  any item of contact information is obtainable by calling
  blake_GetContactInfoMaxLen(), which will run a loop to determine the
  maximum length you'll need to allocate the first time it is run, caching
  the result on any further calls.  The contact info blakeCitTasks returns
  a string seperated like this: "task\0task\0task\0\0", the final task
  ending in two NULLs and needs special handling.  It's length is understood
  to be the same as "task\0task\0task\0" (15)
*/
BLAKEAPI(enum blakeError) blake_GetContactInfo(
  const enum blakeContactInfoType ContactInfoType,
  const unsigned int Index,
  char *OutBuff,
  const size_t MaxBuffSz
);

/*
  This function works in the same way as the above but returns the length of
  the item rather than the item itself.  The length is returned via a pointer.
  (PLen).
*/
BLAKEAPI(enum blakeError) blake_GetContactInfoLen(
  const enum blakeContactInfoType ContactInfoType,
  const unsigned int Index,
  unsigned int *PLen
);

/*
  This function returns the maximum length that will need to be allocated to
  a buffer that will receive a contact-info string.  It does this by counting
  the lengths of all strings and returning the length of the longest string.
  Since this is static at compile time, the result is cached, so this
  function can be called as many times as is neccersary.  It's result will
  not change and it will not cycle through all strings after the first call.
  Remember that the value returned (*PLen) is the length in characters of the
  longest string, not the number of bytes which need to be allocated.  The
  number of bytes to allocate is the ((*Plen)+1) * sizeof(char) where char
  represents one character.
*/
BLAKEAPI(enum blakeError) blake_GetContactInfoMaxLen(
  unsigned int *PLen
);

/*
  ****************************************
  * NetBuffer, the code which handles    *
  * packets, probally the most annoying  *
  * thing I had to code in the entire    *
  * system.                              *
  ****************************************
*/

/*
  netbuffer_GetErrorMessage() returns am error string in the language
  specified when an error occurs with the NetBuffer.  See
  blake_GetErrorMessage() for details on how this works.
*/
BLAKEAPI(unsigned int) netbuffer_GetErrorMessage(
  const enum blakeNetBufferError NetBufferError,
  char *Buff,
  size_t MaxSize,
  enum blakeLang Language
);

/*
  When you need to convert a NetBuffer error into a debugging symbol, for
  use in a panic or debug dump perhaps, use this function, it returns the
  relevant symbol as a string.  Do not modify this string as you will
  corrupt Blake's memory.
*/
BLAKEAPI(const char*) netbuffer_GetErrorMessageMnemonic(
  const enum blakeNetBufferError NetBufferError
);

/*
  netbuffer_Close() deregisters a socket from the NetBuffer system
  and then calls network_Close() on the socket.  The socket is no longer
  valid after this call.  The socket must have been registered earlier
  with netbuffer_Open().
*/
BLAKEAPI(void) netbuffer_Close(
  int Socket
);

/*
  netbuffer_Push() adds data to a socket in the incoming or outgoing
  direction.  Of course, it still takes callbacks on the socket to
  actually do anything with this data.  When a whole packet has been
  pushed, the NetBuffer object for the socket you are working with
  calls the Blake packet cracker on your behalf.  Quite frankly, the
  system is complex, see an example client if you are confused.
*/
BLAKEAPI(enum blakeNetBufferError) netbuffer_Push(
  int Socket,
  enum blakeNetBufferDirection Direction,
  const void *Data,
  const size_t DataSize
);

/*
  netbuffer_Pop() takes data from a socket's managed buffer in either
  direction it is destined for.  It is expected that this data is then
  processed/sent to the network depending on direction.  Because of the
  complexity and crucialness of this activity, it is recommended that
  the reader refer to an example client to see how this is used.
*/
BLAKEAPI(size_t) netbuffer_Pop(
  int Socket,
  enum blakeNetBufferDirection,
  void *Data,
  const size_t MaxDataSize,
  enum blakeNetBufferError *PNetError
);

/*
  netbuffer_Open() takes an existing, created socket and constructs
  a NetBuffer object around it.  This object can then be automatically
  used with the rest of the netbuffer functions above just by supplying
  the socket number.  netbuffer_Close() must be called afterwards and
  that will close the socket as well as destroy the associated internal
  NetBuffer object for that socket.
*/
BLAKEAPI(enum blakeNetBufferError) netbuffer_Open(
  int Socket
);

/*
  blake_Chomp() is a function for removing a possible newline character ('\n')
  from the end of a string.  It must be the vest last character in a string
  and if it is not there the function will not change the string.  If a
  string looks like this: "ddrp\n\0", the function will returb "ddrp\0\0".
  The return value is Str, it is only returned so that it can easily be used
  in expressions.
*/
BLAKEAPI(char*) blake_Chomp(
  char *Str
);

/*
  ***********************************************
  * The Blake Options module.  A multi-purpose  *
  * options storage interface.  All config      *
  * files and persistant settings should be     *
  * handled via this new interface from October *
  * 2005 -- D. D. R. Palmer                     *
  ***********************************************
*/
/*
  The options module will work in one of several different modes
  but it will only operate in any one mode at any one given time.
  To change the mode of opration, call this function.  It will
  return either blakeSuccess or blakeUnsupported.  There is no
  gaurentee that any of the modes defined in this header will be
  supported by any given build of Blake.

  Note: You must specify a mode before using any of these functions,
  failure to do so will result in failure of all functions which
  rely on knowing which mode the module is in.
*/
BLAKEAPI(enum blakeError) blake_OptionsSetMode(
  const enum blakeOptionsMode NewMode
);

/*
  To see what mode the module is currently in, call this function
*/
BLAKEAPI(enum blakeOptionsMode) blake_OptionsGetMode(
  void
);

/*
  To check whether a given mode is valid for this build of the library,
  call blake_OptionsIsSupportedMode().  The function will return true
  for any supported modes.  It will return false for any unknown modes,
  whether they were defined in this header or not.
*/
BLAKEAPI(blake_bool_t) blake_OptionsIsSupportedMode(
  const enum blakeOptionsMode Mode
);

/*
  To read a simple integer via the options module, use this interface.
  The Name is interpreted differently depending on the mode, the Subject
  is generally a section, if they are supported (they may not be in some
  modes) and the Option is the actual name of the option in the file.
  If the function sucueeds, the result is returned via a pointer
*/
BLAKEAPI(enum blakeError) blake_OptionsGetInteger(
  const char *Name,
  const char *Subject,
  const char *Option,
  int *PResult
);

/* Restore C++ naming */
#ifdef __cplusplus
  }
#endif

/*
  Restore alignment
*/
#if ( defined(BLAKE_AS_DLL) && defined(__WIN32__) )
# include <poppack.h>
#endif
/*-------------------------------------------------------------------------*/
#endif /*!INC_BLAKE_H*/